<commit_before>/** @file
 *
 * @ingroup dspSoundFileLib
 *
 * @brief Loads soundfile data into a sample matrix
 *
 * @details This object collaborates with #TTSampleMatrix to load values from a sound file into the sample matrix.
 *
 * @see TTSampleMatrix
 *
 * @authors Nathan Wolek
 *
 * @copyright Copyright © 2013 by Nathan Wolek @n
 * This code is licensed under the terms of the "New BSD License" @n
 * http://creativecommons.org/licenses/BSD/
 */

#include "TTSoundfileLoader.h"

#define thisTTClass			TTSoundfileLoader
#define thisTTClassName		"soundfile.loader"
#define thisTTClassTags		"audio, soundfile, buffer"

TTObjectBasePtr TTSoundfileLoader::instantiate(TTSymbol& name, TTValue& arguments)
{
	return new TTSoundfileLoader(arguments);
}

extern "C" void TTSoundfileLoader::registerClass()
{
	TTClassRegister(thisTTClassName, thisTTClassTags, TTSoundfileLoader::instantiate);
}

TTSoundfileLoader::TTSoundfileLoader(TTValue& arguments) :
TTSoundfile(arguments),
mTargetMatrix(NULL)
{
    // add the attributes and messages here
    //addMessageWithArguments(load);

    // initialize happens as part of the load
}

TTSoundfileLoader::~TTSoundfileLoader()
{
	mTargetMatrix = NULL; // reset to NULL for reference counting
}

/**	Internal method that sets the class's pointer to the target sample matrix for loading sound file data. Because only TTMatrixPtr is allowed to be passed using TTValue, we perform a test to ensure that it is indeed a TTSampleMatrix before setting the new pointer.
 @param     newTargetMatrix     pointer to the new matrix
 @return    TTErr               kTTErrNone if the pointer was updated. kTTErrInvalidValue is the pointer was not to a TTSampleMatrix.
 */
TTErr TTSoundfileLoader::setTargetMatrix(const TTMatrixPtr newTargetMatrix)
{
    if (newTargetMatrix->getName() != "samplematrix")
    {
        return kTTErrInvalidValue;
    } else {
        mTargetMatrix = (TTSampleMatrixPtr)&newTargetMatrix;
        return kTTErrNone;
    }
}

/**	Public method used to trigger the load process. Copies samples from a sound file on the hard drive into a TTSampleMatrix.
 @param[in]     input           requires 2 items: TTSymbol containing the file path, TTMatrixPtr to the target matrix.
 @param[out]    unusedOutput    not used
 @return        TTErr           kTTErrNone load was successful. kTTErrInvalidFilepath if the filepath was invalid. kTTErrInvalidValue if the pointer to TTSampleMatrix was invalid.
 */
TTErr TTSoundfileLoader::load(const TTValueRef input, TTValueRef unusedOutput)
{
    // sort out the two input values
    TTValue newFilePath = input[0];
    TTMatrixPtr newTargetMatrix = input[1];
    TTErr err = kTTErrNone;

    // set the mFilePath
    err = setFilePath(newFilePath);

    // set the mTargetMatrix
    if (!err)
        err = setTargetMatrix(newTargetMatrix);

    // set the start and end points in source file

    // set the start and end points in mTargetMatrix

    // copy the samples (one at a time initially, to be optimized later)

    // QUESTIONS to consider
    // how will we handle multi channels?
    // should the sample rate get copied across?
    // if the size is different, what is the desired behavior?

    // reset? should mFilePath & mTargetMatrix be reset at the conclusion?

    return err;
}<commit_msg>first functioning code for TTSoundfileLoader:load()<commit_after>/** @file
 *
 * @ingroup dspSoundFileLib
 *
 * @brief Loads soundfile data into a sample matrix
 *
 * @details This object collaborates with #TTSampleMatrix to load values from a sound file into the sample matrix.
 *
 * @see TTSampleMatrix
 *
 * @authors Nathan Wolek
 *
 * @copyright Copyright © 2013 by Nathan Wolek @n
 * This code is licensed under the terms of the "New BSD License" @n
 * http://creativecommons.org/licenses/BSD/
 */

#include "TTSoundfileLoader.h"

#define thisTTClass			TTSoundfileLoader
#define thisTTClassName		"soundfile.loader"
#define thisTTClassTags		"audio, soundfile, buffer"

TTObjectBasePtr TTSoundfileLoader::instantiate(TTSymbol& name, TTValue& arguments)
{
	return new TTSoundfileLoader(arguments);
}

extern "C" void TTSoundfileLoader::registerClass()
{
	TTClassRegister(thisTTClassName, thisTTClassTags, TTSoundfileLoader::instantiate);
}

TTSoundfileLoader::TTSoundfileLoader(TTValue& arguments) :
TTSoundfile(arguments),
mTargetMatrix(NULL)
{
    // add the attributes and messages here
    //addMessageWithArguments(load);

    // initialize happens as part of the load
}

TTSoundfileLoader::~TTSoundfileLoader()
{
	mTargetMatrix = NULL; // reset to NULL for reference counting
}

/**	Internal method that sets the class's pointer to the target sample matrix for loading sound file data. Because only TTMatrixPtr is allowed to be passed using TTValue, we perform a test to ensure that it is indeed a TTSampleMatrix before setting the new pointer.
 @param     newTargetMatrix     pointer to the new matrix
 @return    TTErr               kTTErrNone if the pointer was updated. kTTErrInvalidValue is the pointer was not to a TTSampleMatrix.
 */
TTErr TTSoundfileLoader::setTargetMatrix(const TTMatrixPtr newTargetMatrix)
{
    if (newTargetMatrix->getName() != "samplematrix")
    {
        return kTTErrInvalidValue;
    } else {
        mTargetMatrix = (TTSampleMatrixPtr)&newTargetMatrix;
        return kTTErrNone;
    }
}

/**	Public method used to trigger the load process. Copies samples from a sound file on the hard drive into a TTSampleMatrix.
 @param[in]     input           requires 2 items: TTSymbol containing the file path, TTMatrixPtr to the target matrix.
 @param[out]    unusedOutput    not used
 @return        TTErr           kTTErrNone load was successful. kTTErrInvalidFilepath if the filepath was invalid. kTTErrInvalidValue if the pointer to TTSampleMatrix was invalid.
 */
TTErr TTSoundfileLoader::load(const TTValueRef input, TTValueRef unusedOutput)
{
    // sort out the two input values
    TTValue newFilePath = input[0];
    TTMatrixPtr newTargetMatrix = input[1];
    TTErr err = kTTErrNone;

    // set the mFilePath
    err = setFilePath(newFilePath);

    // set the mTargetMatrix
    if (!err)
        err = setTargetMatrix(newTargetMatrix);

    // set the start and end points in source file

    // set the start and end points in mTargetMatrix

    // copy the samples (one at a time initially, to be optimized later)
    // NOTE: we will temporarily assume that channel counts match
    TTUInt32 targetMatrixLength = mTargetMatrix->getComponentCount();

    if (this->getLengthInSamples() < targetMatrixLength)
    {
        // we will throw an error because we are only interested in completely filling the SampleMartix, for now
        err = kTTErrGeneric;
    } else {
        TTSampleValue valueToMove;

        for (int sample=0;sample<targetMatrixLength;sample++)
        {
            // TTSoundfile:peek() -> TTSampleMatrix:poke()
            this->peek(sample,0,valueToMove);
            mTargetMatrix->poke(sample,0,valueToMove);
        }
    }

    // QUESTIONS to consider
    // how will we handle multi channels?
    // should the sample rate get copied across?
    // if the size is different, what is the desired behavior?

    // reset? should mFilePath & mTargetMatrix be reset at the conclusion?

    return err;
}<|endoftext|>


<commit_before><commit_msg>For touch implement a simpler add bookmark until new Views based widgets are available<commit_after><|endoftext|>


<commit_before>/*****************************************************************************
 * VLC backend for the Phonon library                                        *
 * Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>               *
 * Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>                *
 * Copyright (C) 2009 Fathi Boudra <fabo@kde.org>                            *
 *                                                                           *
 * This program 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 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         *
 * Lesser General Public License for more details.                           *
 *                                                                           *
 * You should have received a copy of the GNU Lesser General Public          *
 * License along with this package; if not, write to the Free Software       *
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA *
 *****************************************************************************/

#include "vlcloader.h"

#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QLibrary>
#include <QtCore/QSettings>
#include <QtCore/QString>
#include <QtCore/QStringList>

// Global variables
libvlc_instance_t *vlc_instance = 0;
libvlc_media_player_t *vlc_current_media_player = 0;

namespace Phonon
{
namespace VLC {

bool vlcInit()
{
    // Global variables
    vlc_instance = 0;

    QString path = vlcPath();
    if (!path.isEmpty()) {
        QString pluginsPath = QString("--plugin-path=") + QDir::toNativeSeparators(QFileInfo(vlcPath()).dir().path());
#if defined(Q_OS_UNIX)
        pluginsPath.append("/vlc");
#elif defined(Q_OS_WIN)
        pluginsPath.append("\\plugins");
#endif
        QByteArray p = path.toLatin1();
        QByteArray pp = pluginsPath.toLatin1();
        // VLC command line options. See vlc --full-help
        const char *vlcArgs[] = {
            p.constData(),
            pp.constData(),
            "--verbose=2",
            "--intf=dummy",
            "--extraintf=logger",
            "--ignore-config",
            "--reset-plugins-cache",
            "--no-media-library",
            "--no-one-instance",
            "--no-osd",
            "--no-stats",
            "--no-video-title-show"
        };

        // Create and initialize a libvlc instance (it should be done only once)
        vlc_instance = libvlc_new(sizeof(vlcArgs) / sizeof(*vlcArgs), vlcArgs);
        if(!vlc_instance)
            qDebug() << "libvlc exception:" << libvlc_errmsg();

        return true;
    } else {
        return false;
    }
}

void vlcRelease()
{
    libvlc_release(vlc_instance);
    vlcUnload();
}

#if defined(Q_OS_UNIX)
static bool libGreaterThan(const QString &lhs, const QString &rhs)
{
    QStringList lhsparts = lhs.split(QLatin1Char('.'));
    QStringList rhsparts = rhs.split(QLatin1Char('.'));
    Q_ASSERT(lhsparts.count() > 1 && rhsparts.count() > 1);

    for (int i = 1; i < rhsparts.count(); ++i) {
        if (lhsparts.count() <= i)
            // left hand side is shorter, so it's less than rhs
            return false;

        bool ok = false;
        int b = 0;
        int a = lhsparts.at(i).toInt(&ok);
        if (ok)
            b = rhsparts.at(i).toInt(&ok);
        if (ok) {
            // both toInt succeeded
            if (a == b)
                continue;
            return a > b;
        } else {
            // compare as strings;
            if (lhsparts.at(i) == rhsparts.at(i))
                continue;
            return lhsparts.at(i) > rhsparts.at(i);
        }
    }

    // they compared strictly equally so far
    // lhs cannot be less than rhs
    return true;
}
#endif

static QStringList findAllLibVlc()
{
    QStringList paths;
#if defined(Q_OS_UNIX)
    paths = QString::fromLatin1(qgetenv("LD_LIBRARY_PATH"))
            .split(QLatin1Char(':'), QString::SkipEmptyParts);
    paths << QLatin1String(PHONON_LIB_INSTALL_DIR) << QLatin1String("/usr/lib") << QLatin1String("/usr/local/lib");

    QStringList foundVlcs;
    foreach (const QString &path, paths) {
        QDir dir = QDir(path);
        QStringList entryList = dir.entryList(QStringList() << QLatin1String("libvlc.*"), QDir::Files);

        qSort(entryList.begin(), entryList.end(), libGreaterThan);
        foreach (const QString &entry, entryList)
            foundVlcs << path + QLatin1Char('/') + entry;
    }

    return foundVlcs;
#elif defined(Q_OS_WIN)
     // Read VLC version and installation directory from Windows registry
    QSettings settings(QSettings::SystemScope, "VideoLAN", "VLC");
    QString vlcVersion = settings.value("Version").toString();
    QString vlcInstallDir = settings.value("InstallDir").toString();
    if (vlcVersion.startsWith("1.0") && !vlcInstallDir.isEmpty()) {
        paths << vlcInstallDir + QLatin1Char('\\') + "libvlc.dll";
        return paths;
    }else{
        //If nothing is found in the registry try %PATH%
    QStringList searchPaths = QString::fromLatin1(qgetenv("PATH"))
            .split(QLatin1Char(';'), QString::SkipEmptyParts);
    QStringList foundVlcs;
    foreach (const QString &sp, searchPaths) {
        QDir dir = QDir(sp);
        QStringList entryList = dir.entryList(QStringList() << QLatin1String("libvlc.dll"), QDir::Files);
        foreach (const QString &entry, entryList)
            foundVlcs << sp + QLatin1Char('\\') + entry;
    }
    paths<<foundVlcs;
    return paths;
  }
#endif
}

static QLibrary *vlcLibrary = 0;

QString vlcPath()
{
    static QString path;
    if (!path.isEmpty()) {
        return path;
    }

    vlcLibrary = new QLibrary();
    QStringList paths = findAllLibVlc();
    foreach(path, paths) {
        vlcLibrary->setFileName(path);

        if (vlcLibrary->resolve("libvlc_get_version")) {
            //TODO:call libvlc_get_version to test version?
            return path;
        } else {
            qDebug("Cannot resolve the symbol or load VLC library");
        }
        qWarning() << vlcLibrary->errorString();
    }

    vlcUnload();

    return QString();
}

void vlcUnload()
{
    vlcLibrary->unload();
    delete vlcLibrary;
    vlcLibrary = 0;
}

}
} // Namespace Phonon::VLC
<commit_msg>changes in libvlc validation<commit_after>/*****************************************************************************
 * VLC backend for the Phonon library                                        *
 * Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>               *
 * Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>                *
 * Copyright (C) 2009 Fathi Boudra <fabo@kde.org>                            *
 *                                                                           *
 * This program 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 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         *
 * Lesser General Public License for more details.                           *
 *                                                                           *
 * You should have received a copy of the GNU Lesser General Public          *
 * License along with this package; if not, write to the Free Software       *
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA *
 *****************************************************************************/

#include "vlcloader.h"

#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QLibrary>
#include <QtCore/QSettings>
#include <QtCore/QString>
#include <QtCore/QStringList>

// Global variables
libvlc_instance_t *vlc_instance = 0;
libvlc_media_player_t *vlc_current_media_player = 0;

namespace Phonon
{
namespace VLC {

bool vlcInit()
{
    // Global variables
    vlc_instance = 0;

    QString path = vlcPath();
    if (!path.isEmpty()) {
        QString pluginsPath = QString("--plugin-path=") + QDir::toNativeSeparators(QFileInfo(vlcPath()).dir().path());
#if defined(Q_OS_UNIX)
        pluginsPath.append("/vlc");
#elif defined(Q_OS_WIN)
        pluginsPath.append("\\plugins");
#endif
        QByteArray p = path.toLatin1();
        QByteArray pp = pluginsPath.toLatin1();
        // VLC command line options. See vlc --full-help
        const char *vlcArgs[] = {
            p.constData(),
            pp.constData(),
            "--verbose=2",
            "--intf=dummy",
            "--extraintf=logger",
            "--ignore-config",
            "--reset-plugins-cache",
            "--no-media-library",
            "--no-one-instance",
            "--no-osd",
            "--no-stats",
            "--no-video-title-show"
        };

        // Create and initialize a libvlc instance (it should be done only once)
        vlc_instance = libvlc_new(sizeof(vlcArgs) / sizeof(*vlcArgs), vlcArgs);
        if(!vlc_instance)
            qDebug() << "libvlc exception:" << libvlc_errmsg();

        return true;
    } else {
        return false;
    }
}

void vlcRelease()
{
    libvlc_release(vlc_instance);
    vlcUnload();
}

#if defined(Q_OS_UNIX)
static bool libGreaterThan(const QString &lhs, const QString &rhs)
{
    QStringList lhsparts = lhs.split(QLatin1Char('.'));
    QStringList rhsparts = rhs.split(QLatin1Char('.'));
    Q_ASSERT(lhsparts.count() > 1 && rhsparts.count() > 1);

    for (int i = 1; i < rhsparts.count(); ++i) {
        if (lhsparts.count() <= i)
            // left hand side is shorter, so it's less than rhs
            return false;

        bool ok = false;
        int b = 0;
        int a = lhsparts.at(i).toInt(&ok);
        if (ok)
            b = rhsparts.at(i).toInt(&ok);
        if (ok) {
            // both toInt succeeded
            if (a == b)
                continue;
            return a > b;
        } else {
            // compare as strings;
            if (lhsparts.at(i) == rhsparts.at(i))
                continue;
            return lhsparts.at(i) > rhsparts.at(i);
        }
    }

    // they compared strictly equally so far
    // lhs cannot be less than rhs
    return true;
}
#endif

static QStringList findAllLibVlc()
{
    QStringList paths;
#if defined(Q_OS_UNIX)
    paths = QString::fromLatin1(qgetenv("LD_LIBRARY_PATH"))
            .split(QLatin1Char(':'), QString::SkipEmptyParts);
    paths << QLatin1String(PHONON_LIB_INSTALL_DIR) << QLatin1String("/usr/lib") << QLatin1String("/usr/local/lib");

    QStringList foundVlcs;
    foreach (const QString &path, paths) {
        QDir dir = QDir(path);
        QStringList entryList = dir.entryList(QStringList() << QLatin1String("libvlc.*"), QDir::Files);

        qSort(entryList.begin(), entryList.end(), libGreaterThan);
        foreach (const QString &entry, entryList)
            foundVlcs << path + QLatin1Char('/') + entry;
    }

    return foundVlcs;
#elif defined(Q_OS_WIN)
     // Read VLC version and installation directory from Windows registry
    QSettings settings(QSettings::SystemScope, "VideoLAN", "VLC");
    QString vlcVersion = settings.value("Version").toString();
    QString vlcInstallDir = settings.value("InstallDir").toString();
    if (vlcVersion.startsWith("1.0") && !vlcInstallDir.isEmpty()) {
        paths << vlcInstallDir + QLatin1Char('\\') + "libvlc.dll";
        return paths;
    }else{
        //If nothing is found in the registry try %PATH%
    QStringList searchPaths = QString::fromLatin1(qgetenv("PATH"))
            .split(QLatin1Char(';'), QString::SkipEmptyParts);
    QStringList foundVlcs;
    foreach (const QString &sp, searchPaths) {
        QDir dir = QDir(sp);
        QStringList entryList = dir.entryList(QStringList() << QLatin1String("libvlc.dll"), QDir::Files);
        foreach (const QString &entry, entryList)
            foundVlcs << sp + QLatin1Char('\\') + entry;
    }
    paths<<foundVlcs;
    return paths;
  }
#endif
}

static QLibrary *vlcLibrary = 0;

QString vlcPath()
{
    static QString path;
    if (!path.isEmpty()) {
        return path;
    }

    vlcLibrary = new QLibrary();
    QStringList paths = findAllLibVlc();
    foreach(path, paths) {
        vlcLibrary->setFileName(path);

        if (!vlcLibrary->resolve("libvlc_exception_init")) {//"libvlc_exception_init" not contained in 1.1+
            return path;
        } else {
            qDebug("Cannot resolve the symbol or load VLC library");
        }
        qWarning() << vlcLibrary->errorString();
    }

    vlcUnload();

    return QString();
}

void vlcUnload()
{
    vlcLibrary->unload();
    delete vlcLibrary;
    vlcLibrary = 0;
}

}
} // Namespace Phonon::VLC
<|endoftext|>


<commit_before>/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include <stdint.h>

#include "tensorflow/lite/c/builtin_op_data.h"
#include "tensorflow/lite/c/common.h"
#include "tensorflow/lite/kernels/internal/optimized/optimized_ops.h"
#include "tensorflow/lite/kernels/internal/reference/reference_ops.h"
#include "tensorflow/lite/kernels/internal/tensor.h"
#include "tensorflow/lite/kernels/internal/tensor_ctypes.h"
#include "tensorflow/lite/kernels/internal/types.h"
#include "tensorflow/lite/kernels/kernel_util.h"

namespace tflite {
namespace ops {
namespace builtin {
namespace split {

struct OpContext {
  OpContext(TfLiteContext* context, TfLiteNode* node) {
    params = reinterpret_cast<TfLiteSplitParams*>(node->builtin_data);
    axis = GetInput(context, node, 0);
    input = GetInput(context, node, 1);
  }
  TfLiteSplitParams* params;
  const TfLiteTensor* axis;
  const TfLiteTensor* input;
};

TfLiteStatus UseDynamicOutputTensors(TfLiteContext* context, TfLiteNode* node) {
  for (int i = 0; i < NumOutputs(node); ++i) {
    TfLiteTensor* tensor;
    TF_LITE_ENSURE_OK(context, GetOutputSafe(context, node, i, &tensor));
    SetTensorToDynamic(tensor);
  }
  return kTfLiteOk;
}

TfLiteStatus ResizeOutputTensors(TfLiteContext* context, TfLiteNode* node,
                                 const TfLiteTensor* axis,
                                 const TfLiteTensor* input, int num_splits) {
  int axis_value = GetTensorData<int>(axis)[0];
  if (axis_value < 0) {
    axis_value += NumDimensions(input);
  }

  TF_LITE_ENSURE(context, axis_value >= 0);
  TF_LITE_ENSURE(context, axis_value < NumDimensions(input));

  const int input_size = SizeOfDimension(input, axis_value);
  TF_LITE_ENSURE_MSG(context, input_size % num_splits == 0,
                     "Not an even split");
  const int slice_size = input_size / num_splits;

  for (int i = 0; i < NumOutputs(node); ++i) {
    TfLiteIntArray* output_dims = TfLiteIntArrayCopy(input->dims);
    output_dims->data[axis_value] = slice_size;
    TfLiteTensor* output;
    TF_LITE_ENSURE_OK(context, GetOutputSafe(context, node, i, &output));
    TF_LITE_ENSURE_STATUS(context->ResizeTensor(context, output, output_dims));
  }

  return kTfLiteOk;
}

TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) {
  TF_LITE_ENSURE_EQ(context, NumInputs(node), 2);

  OpContext op_context(context, node);

  TF_LITE_ENSURE_EQ(context, NumOutputs(node), op_context.params->num_splits);

  auto input_type = op_context.input->type;
  TF_LITE_ENSURE(context,
                 input_type == kTfLiteFloat32 || input_type == kTfLiteUInt8 ||
                     input_type == kTfLiteInt8 || input_type == kTfLiteInt16 ||
                     input_type == kTfLiteInt32);
  for (int i = 0; i < NumOutputs(node); ++i) {
    TfLiteTensor* tensor;
    TF_LITE_ENSURE_OK(context, GetOutputSafe(context, node, i, &tensor));
    tensor->type = input_type;
  }

  // If we know the contents of the 'axis' tensor, resize all outputs.
  // Otherwise, wait until Eval().
  if (IsConstantTensor(op_context.axis)) {
    return ResizeOutputTensors(context, node, op_context.axis, op_context.input,
                               op_context.params->num_splits);
  } else {
    return UseDynamicOutputTensors(context, node);
  }
}

TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
  OpContext op_context(context, node);

  // When the 'axis' tensor is non-const we can't resize output tensors in
  // Prepare(), and we have to do it now.
  if (!IsConstantTensor(op_context.axis)) {
    TF_LITE_ENSURE_OK(
        context,
        ResizeOutputTensors(context, node, op_context.axis, op_context.input,
                            op_context.params->num_splits));
  }

  int axis_value = GetTensorData<int>(op_context.axis)[0];
  if (axis_value < 0) {
    axis_value += NumDimensions(op_context.input);
  }

  TF_LITE_ENSURE(context, axis_value >= 0);
  TF_LITE_ENSURE(context, axis_value < NumDimensions(op_context.input));

  // TODO(b/173221795): Our usage of VectorOfTensors could be optimized by
  // calculating it in Prepare, unless we defer shape calculation.
  // We can improve the optimized_ops version to handle other
  // cases too.
#define TF_LITE_SPLIT(scalar)                                       \
  VectorOfTensors<scalar> all_outputs(*context, *node->outputs);    \
  tflite::SplitParams op_params;                                    \
  op_params.num_split = NumOutputs(node);                           \
  op_params.axis = axis_value;                                      \
  reference_ops::Split(op_params, GetTensorShape(op_context.input), \
                       GetTensorData<scalar>(op_context.input),     \
                       all_outputs.shapes(), all_outputs.data());

  switch (op_context.input->type) {
    case kTfLiteFloat32: {
      TF_LITE_SPLIT(float);
      break;
    }
    case kTfLiteUInt8: {
      TF_LITE_SPLIT(uint8_t);
      break;
    }
    case kTfLiteInt8: {
      TF_LITE_SPLIT(int8_t);
      break;
    }
    case kTfLiteInt16: {
      TF_LITE_SPLIT(int16_t);
      break;
    }
    case kTfLiteInt32: {
      TF_LITE_SPLIT(int32_t);
      break;
    }
    default:
      context->ReportError(context, "Type %s currently not supported.",
                           TfLiteTypeGetName(op_context.input->type));
      return kTfLiteError;
  }
#undef TF_LITE_SPLIT

  return kTfLiteOk;
}

}  // namespace split

TfLiteRegistration* Register_SPLIT() {
  static TfLiteRegistration r = {nullptr, nullptr, split::Prepare, split::Eval};
  return &r;
}

}  // namespace builtin
}  // namespace ops
}  // namespace tflite
<commit_msg>Prevent division by 0<commit_after>/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include <stdint.h>

#include "tensorflow/lite/c/builtin_op_data.h"
#include "tensorflow/lite/c/common.h"
#include "tensorflow/lite/kernels/internal/optimized/optimized_ops.h"
#include "tensorflow/lite/kernels/internal/reference/reference_ops.h"
#include "tensorflow/lite/kernels/internal/tensor.h"
#include "tensorflow/lite/kernels/internal/tensor_ctypes.h"
#include "tensorflow/lite/kernels/internal/types.h"
#include "tensorflow/lite/kernels/kernel_util.h"

namespace tflite {
namespace ops {
namespace builtin {
namespace split {

struct OpContext {
  OpContext(TfLiteContext* context, TfLiteNode* node) {
    params = reinterpret_cast<TfLiteSplitParams*>(node->builtin_data);
    axis = GetInput(context, node, 0);
    input = GetInput(context, node, 1);
  }
  TfLiteSplitParams* params;
  const TfLiteTensor* axis;
  const TfLiteTensor* input;
};

TfLiteStatus UseDynamicOutputTensors(TfLiteContext* context, TfLiteNode* node) {
  for (int i = 0; i < NumOutputs(node); ++i) {
    TfLiteTensor* tensor;
    TF_LITE_ENSURE_OK(context, GetOutputSafe(context, node, i, &tensor));
    SetTensorToDynamic(tensor);
  }
  return kTfLiteOk;
}

TfLiteStatus ResizeOutputTensors(TfLiteContext* context, TfLiteNode* node,
                                 const TfLiteTensor* axis,
                                 const TfLiteTensor* input, int num_splits) {
  int axis_value = GetTensorData<int>(axis)[0];
  if (axis_value < 0) {
    axis_value += NumDimensions(input);
  }

  TF_LITE_ENSURE(context, axis_value >= 0);
  TF_LITE_ENSURE(context, axis_value < NumDimensions(input));

  const int input_size = SizeOfDimension(input, axis_value);
  TF_LITE_ENSURE(context, num_splits != 0);
  TF_LITE_ENSURE_MSG(context, input_size % num_splits == 0,
                     "Not an even split");
  const int slice_size = input_size / num_splits;

  for (int i = 0; i < NumOutputs(node); ++i) {
    TfLiteIntArray* output_dims = TfLiteIntArrayCopy(input->dims);
    output_dims->data[axis_value] = slice_size;
    TfLiteTensor* output;
    TF_LITE_ENSURE_OK(context, GetOutputSafe(context, node, i, &output));
    TF_LITE_ENSURE_STATUS(context->ResizeTensor(context, output, output_dims));
  }

  return kTfLiteOk;
}

TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) {
  TF_LITE_ENSURE_EQ(context, NumInputs(node), 2);

  OpContext op_context(context, node);

  TF_LITE_ENSURE_EQ(context, NumOutputs(node), op_context.params->num_splits);

  auto input_type = op_context.input->type;
  TF_LITE_ENSURE(context,
                 input_type == kTfLiteFloat32 || input_type == kTfLiteUInt8 ||
                     input_type == kTfLiteInt8 || input_type == kTfLiteInt16 ||
                     input_type == kTfLiteInt32);
  for (int i = 0; i < NumOutputs(node); ++i) {
    TfLiteTensor* tensor;
    TF_LITE_ENSURE_OK(context, GetOutputSafe(context, node, i, &tensor));
    tensor->type = input_type;
  }

  // If we know the contents of the 'axis' tensor, resize all outputs.
  // Otherwise, wait until Eval().
  if (IsConstantTensor(op_context.axis)) {
    return ResizeOutputTensors(context, node, op_context.axis, op_context.input,
                               op_context.params->num_splits);
  } else {
    return UseDynamicOutputTensors(context, node);
  }
}

TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
  OpContext op_context(context, node);

  // When the 'axis' tensor is non-const we can't resize output tensors in
  // Prepare(), and we have to do it now.
  if (!IsConstantTensor(op_context.axis)) {
    TF_LITE_ENSURE_OK(
        context,
        ResizeOutputTensors(context, node, op_context.axis, op_context.input,
                            op_context.params->num_splits));
  }

  int axis_value = GetTensorData<int>(op_context.axis)[0];
  if (axis_value < 0) {
    axis_value += NumDimensions(op_context.input);
  }

  TF_LITE_ENSURE(context, axis_value >= 0);
  TF_LITE_ENSURE(context, axis_value < NumDimensions(op_context.input));

  // TODO(b/173221795): Our usage of VectorOfTensors could be optimized by
  // calculating it in Prepare, unless we defer shape calculation.
  // We can improve the optimized_ops version to handle other
  // cases too.
#define TF_LITE_SPLIT(scalar)                                       \
  VectorOfTensors<scalar> all_outputs(*context, *node->outputs);    \
  tflite::SplitParams op_params;                                    \
  op_params.num_split = NumOutputs(node);                           \
  op_params.axis = axis_value;                                      \
  reference_ops::Split(op_params, GetTensorShape(op_context.input), \
                       GetTensorData<scalar>(op_context.input),     \
                       all_outputs.shapes(), all_outputs.data());

  switch (op_context.input->type) {
    case kTfLiteFloat32: {
      TF_LITE_SPLIT(float);
      break;
    }
    case kTfLiteUInt8: {
      TF_LITE_SPLIT(uint8_t);
      break;
    }
    case kTfLiteInt8: {
      TF_LITE_SPLIT(int8_t);
      break;
    }
    case kTfLiteInt16: {
      TF_LITE_SPLIT(int16_t);
      break;
    }
    case kTfLiteInt32: {
      TF_LITE_SPLIT(int32_t);
      break;
    }
    default:
      context->ReportError(context, "Type %s currently not supported.",
                           TfLiteTypeGetName(op_context.input->type));
      return kTfLiteError;
  }
#undef TF_LITE_SPLIT

  return kTfLiteOk;
}

}  // namespace split

TfLiteRegistration* Register_SPLIT() {
  static TfLiteRegistration r = {nullptr, nullptr, split::Prepare, split::Eval};
  return &r;
}

}  // namespace builtin
}  // namespace ops
}  // namespace tflite
<|endoftext|>


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

/**
 * @file
 **/

#include "modules/planning/tasks/traffic_decider/traffic_decider.h"

#include "modules/common/configs/vehicle_config_helper.h"
#include "modules/common/vehicle_state/vehicle_state.h"
#include "modules/planning/common/planning_gflags.h"

namespace apollo {
namespace planning {
using apollo::common::Status;

TrafficDecider::TrafficDecider(const std::string &name) : Task(name) {}

PathObstacle *TrafficDecider::CreateDestinationObstacle() {
  // set destination point
  const auto &routing_response = frame_->routing_response();
  if (!routing_response.routing_request().has_end()) {
    ADEBUG << "routing_request has no end";
    return nullptr;
  }
  common::math::Vec2d destination;
  destination.set_x(routing_response.routing_request().end().pose().x());
  destination.set_y(routing_response.routing_request().end().pose().y());

  // check if destination point is in planning range
  common::SLPoint destination_sl;
  const auto &reference_line = reference_line_info_->reference_line();
  reference_line.get_point_in_frenet_frame(destination, &destination_sl);
  double destination_s = destination_sl.s();
  if (destination_s < 0 || destination_s > reference_line.length()) {
    AINFO << "destination(s[:" << destination_sl.s()
          << "]) out of planning range. Skip";
    return nullptr;
  }

  // adjust destination based on adc_front_s
  common::SLPoint adc_sl;
  auto &adc_position = common::VehicleState::instance()->pose().position();
  reference_line.get_point_in_frenet_frame({adc_position.x(), adc_position.y()},
                                           &adc_sl);
  const auto &vehicle_param =
      common::VehicleConfigHelper::instance()->GetConfig().vehicle_param();
  double adc_front_s = adc_sl.s() + vehicle_param.front_edge_to_center();
  if (destination_sl.s() <= adc_front_s) {
    destination_s = adc_front_s + FLAGS_destination_adjust_distance_buffer;
  }

  const std::string id =
      FLAGS_destination_obstacle_id + "_" + reference_line_info_->Id();
  std::unique_ptr<Obstacle> obstacle_ptr =
      reference_line_info_->CreateVirtualObstacle(
          id, destination_s, FLAGS_virtual_stop_wall_length,
          FLAGS_virtual_stop_wall_width, FLAGS_virtual_stop_wall_height);
  const auto *obstacle = obstacle_ptr.get();
  if (!frame_->AddObstacle(std::move(obstacle_ptr))) {
    AERROR << "Failed to add destination obstacle: " << id;
    return nullptr;
  }
  auto *ptr = reference_line_info_->AddObstacle(obstacle);
  if (!ptr) {
    AERROR << "Failed to add destination obstacle: " << id << "'s projection";
    return nullptr;
  }
  return ptr;
}

apollo::common::Status TrafficDecider::Optimize(
    Frame *frame, ReferenceLineInfo *reference_line_info) {
  frame_ = frame;
  reference_line_info_ = reference_line_info;

  // 1. add destination stop
  if (!MakeDestinationStopDecision()) {
    AINFO << "There is no destination stop";
  } else {
    AINFO << "destination is created";
  }
  return Status::OK();
}

bool TrafficDecider::MakeDestinationStopDecision() {
  auto *path_obstacle = CreateDestinationObstacle();
  if (!path_obstacle) {
    AINFO << "The path obstacle is not found";
    return false;
  }
  const auto &obstacle = path_obstacle->Obstacle();
  const auto &reference_line = reference_line_info_->reference_line();

  // check stop_posision on reference line
  auto stop_position = obstacle->Perception().position();
  common::SLPoint stop_line_sl;
  reference_line.get_point_in_frenet_frame(
      {stop_position.x(), stop_position.x()}, &stop_line_sl);
  if (!reference_line.is_on_road(stop_line_sl)) {
    return false;
  }

  // check stop_line_s vs adc_s. stop_line_s must be ahead of adc_front_s
  common::SLPoint adc_sl;
  auto &adc_position = common::VehicleState::instance()->pose().position();
  reference_line.get_point_in_frenet_frame({adc_position.x(), adc_position.y()},
                                           &adc_sl);
  const auto &vehicle_param =
      common::VehicleConfigHelper::instance()->GetConfig().vehicle_param();
  double adc_front_s = adc_sl.s() + vehicle_param.front_edge_to_center();
  if (stop_line_sl.s() <= adc_front_s) {
    ADEBUG << "skip: object:" << obstacle->Id() << " fence route_s["
           << stop_line_sl.s() << "] behind adc_front_s[" << adc_front_s << "]";
    return false;
  }

  ObjectDecisionType object_stop;
  ObjectStop *object_stop_ptr = object_stop.mutable_stop();
  object_stop_ptr->set_distance_s(FLAGS_stop_line_min_distance);
  object_stop_ptr->set_reason_code(StopReasonCode::STOP_REASON_DESTINATION);

  auto stop_ref_point =
      reference_line.get_reference_point(stop_position.x(), stop_position.y());
  object_stop_ptr->mutable_stop_point()->set_x(stop_ref_point.x());
  object_stop_ptr->mutable_stop_point()->set_y(stop_ref_point.y());
  object_stop_ptr->set_stop_heading(stop_ref_point.heading());

  reference_line_info_->path_decision()->AddLongitudinalDecision(
      "Destination", obstacle->Id(), object_stop);

  return true;
}

}  // namespace planning
}  // namespace apollo
<commit_msg>fix a bug in Destination Stop<commit_after>/******************************************************************************
 * Copyright 2017 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

/**
 * @file
 **/

#include "modules/planning/tasks/traffic_decider/traffic_decider.h"

#include "modules/common/configs/vehicle_config_helper.h"
#include "modules/common/vehicle_state/vehicle_state.h"
#include "modules/planning/common/planning_gflags.h"

namespace apollo {
namespace planning {
using apollo::common::Status;

TrafficDecider::TrafficDecider(const std::string &name) : Task(name) {}

PathObstacle *TrafficDecider::CreateDestinationObstacle() {
  // set destination point
  const auto &routing_response = frame_->routing_response();
  if (!routing_response.routing_request().has_end()) {
    ADEBUG << "routing_request has no end";
    return nullptr;
  }
  common::math::Vec2d destination;
  destination.set_x(routing_response.routing_request().end().pose().x());
  destination.set_y(routing_response.routing_request().end().pose().y());

  // check if destination point is in planning range
  common::SLPoint destination_sl;
  const auto &reference_line = reference_line_info_->reference_line();
  reference_line.get_point_in_frenet_frame(destination, &destination_sl);
  double destination_s = destination_sl.s();
  if (destination_s < 0 || destination_s > reference_line.length()) {
    AINFO << "destination(s[:" << destination_sl.s()
          << "]) out of planning range. Skip";
    return nullptr;
  }

  // adjust destination based on adc_front_s
  common::SLPoint adc_sl;
  auto &adc_position = common::VehicleState::instance()->pose().position();
  reference_line.get_point_in_frenet_frame({adc_position.x(), adc_position.y()},
                                           &adc_sl);
  const auto &vehicle_param =
      common::VehicleConfigHelper::instance()->GetConfig().vehicle_param();
  double adc_front_s = adc_sl.s() + vehicle_param.front_edge_to_center();
  if (destination_sl.s() <= adc_front_s) {
    destination_s = adc_front_s + FLAGS_destination_adjust_distance_buffer;
  }

  const std::string id =
      FLAGS_destination_obstacle_id + "_" + reference_line_info_->Id();
  std::unique_ptr<Obstacle> obstacle_ptr =
      reference_line_info_->CreateVirtualObstacle(
          id, destination_s, FLAGS_virtual_stop_wall_length,
          FLAGS_virtual_stop_wall_width, FLAGS_virtual_stop_wall_height);
  const auto *obstacle = obstacle_ptr.get();
  if (!frame_->AddObstacle(std::move(obstacle_ptr))) {
    AERROR << "Failed to add destination obstacle: " << id;
    return nullptr;
  }
  auto *ptr = reference_line_info_->AddObstacle(obstacle);
  if (!ptr) {
    AERROR << "Failed to add destination obstacle: " << id << "'s projection";
    return nullptr;
  }
  return ptr;
}

apollo::common::Status TrafficDecider::Optimize(
    Frame *frame, ReferenceLineInfo *reference_line_info) {
  frame_ = frame;
  reference_line_info_ = reference_line_info;

  // 1. add destination stop
  if (!MakeDestinationStopDecision()) {
    AINFO << "There is no destination stop";
  } else {
    AINFO << "destination is created";
  }
  return Status::OK();
}

bool TrafficDecider::MakeDestinationStopDecision() {
  auto *path_obstacle = CreateDestinationObstacle();
  if (!path_obstacle) {
    AINFO << "The path obstacle is not found";
    return false;
  }
  const auto &obstacle = path_obstacle->Obstacle();
  const auto &reference_line = reference_line_info_->reference_line();

  // check stop_posision on reference line
  auto stop_position = obstacle->Perception().position();
  common::SLPoint stop_line_sl;
  reference_line.get_point_in_frenet_frame(
      {stop_position.x(), stop_position.y()}, &stop_line_sl);
  if (!reference_line.is_on_road(stop_line_sl)) {
    return false;
  }

  // check stop_line_s vs adc_s. stop_line_s must be ahead of adc_front_s
  common::SLPoint adc_sl;
  auto &adc_position = common::VehicleState::instance()->pose().position();
  reference_line.get_point_in_frenet_frame({adc_position.x(), adc_position.y()},
                                           &adc_sl);
  const auto &vehicle_param =
      common::VehicleConfigHelper::instance()->GetConfig().vehicle_param();
  double adc_front_s = adc_sl.s() + vehicle_param.front_edge_to_center();
  if (stop_line_sl.s() <= adc_front_s) {
    ADEBUG << "skip: object:" << obstacle->Id() << " fence route_s["
           << stop_line_sl.s() << "] behind adc_front_s[" << adc_front_s << "]";
    return false;
  }

  ObjectDecisionType object_stop;
  ObjectStop *object_stop_ptr = object_stop.mutable_stop();
  object_stop_ptr->set_distance_s(FLAGS_stop_line_min_distance);
  object_stop_ptr->set_reason_code(StopReasonCode::STOP_REASON_DESTINATION);

  auto stop_ref_point =
      reference_line.get_reference_point(stop_position.x(), stop_position.y());
  object_stop_ptr->mutable_stop_point()->set_x(stop_ref_point.x());
  object_stop_ptr->mutable_stop_point()->set_y(stop_ref_point.y());
  object_stop_ptr->set_stop_heading(stop_ref_point.heading());

  reference_line_info_->path_decision()->AddLongitudinalDecision(
      "Destination", obstacle->Id(), object_stop);

  return true;
}

}  // namespace planning
}  // namespace apollo
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "spatial_resampler.h"

namespace webrtc {

VPMSimpleSpatialResampler::VPMSimpleSpatialResampler()
:
_resamplingMode(kFastRescaling),
_targetWidth(0),
_targetHeight(0),
_scaler()
{
}

VPMSimpleSpatialResampler::~VPMSimpleSpatialResampler()
{
  //
}

WebRtc_Word32
VPMSimpleSpatialResampler::SetTargetFrameSize(WebRtc_Word32 width,
                                              WebRtc_Word32 height)
{
  if (_resamplingMode == kNoRescaling)  {
    return VPM_OK;
  }

  if (width < 1 || height < 1)  {
    return VPM_PARAMETER_ERROR;
  }

  _targetWidth = width;
  _targetHeight = height;

  return VPM_OK;
}

void
VPMSimpleSpatialResampler::SetInputFrameResampleMode(VideoFrameResampling
                                                     resamplingMode)
{
  _resamplingMode = resamplingMode;
}

void
VPMSimpleSpatialResampler::Reset()
{
  _resamplingMode = kFastRescaling;
  _targetWidth = 0;
  _targetHeight = 0;
}

WebRtc_Word32
VPMSimpleSpatialResampler::ResampleFrame(const I420VideoFrame& inFrame,
                                         I420VideoFrame* outFrame)
{
  if (_resamplingMode == kNoRescaling)
     return outFrame->CopyFrame(inFrame);
  // Check if re-sampling is needed
  if ((inFrame.width() == _targetWidth) &&
    (inFrame.height() == _targetHeight))  {
    return outFrame->CopyFrame(inFrame);
  }

  // Setting scaler
  // TODO(mikhal/marpan): Should we allow for setting the filter mode in
  // _scale.Set() with |_resamplingMode|?
  int retVal = 0;
  retVal = _scaler.Set(inFrame.width(), inFrame.height(),
                       _targetWidth, _targetHeight, kI420, kI420, kScaleBox);
  if (retVal < 0)
    return retVal;

  // Setting time parameters to the output frame - all the rest will be
  // set by the scaler.
  outFrame->set_timestamp(inFrame.timestamp());
  outFrame->set_render_time_ms(inFrame.render_time_ms());

  retVal = _scaler.Scale(inFrame, outFrame);
  if (retVal == 0)
    return VPM_OK;
  else
    return VPM_SCALE_ERROR;
}

WebRtc_Word32
VPMSimpleSpatialResampler::TargetHeight()
{
  return _targetHeight;
}

WebRtc_Word32
VPMSimpleSpatialResampler::TargetWidth()
{
  return _targetWidth;
}

bool
VPMSimpleSpatialResampler::ApplyResample(WebRtc_Word32 width,
                                         WebRtc_Word32 height)
{
  if ((width == _targetWidth && height == _targetHeight) ||
       _resamplingMode == kNoRescaling)
    return false;
  else
    return true;
}

} //namespace
<commit_msg>Fix a bug in spatial_resampler where we should set the timestamp after Scale.<commit_after>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "spatial_resampler.h"

namespace webrtc {

VPMSimpleSpatialResampler::VPMSimpleSpatialResampler()
:
_resamplingMode(kFastRescaling),
_targetWidth(0),
_targetHeight(0),
_scaler()
{
}

VPMSimpleSpatialResampler::~VPMSimpleSpatialResampler()
{
  //
}

WebRtc_Word32
VPMSimpleSpatialResampler::SetTargetFrameSize(WebRtc_Word32 width,
                                              WebRtc_Word32 height)
{
  if (_resamplingMode == kNoRescaling)  {
    return VPM_OK;
  }

  if (width < 1 || height < 1)  {
    return VPM_PARAMETER_ERROR;
  }

  _targetWidth = width;
  _targetHeight = height;

  return VPM_OK;
}

void
VPMSimpleSpatialResampler::SetInputFrameResampleMode(VideoFrameResampling
                                                     resamplingMode)
{
  _resamplingMode = resamplingMode;
}

void
VPMSimpleSpatialResampler::Reset()
{
  _resamplingMode = kFastRescaling;
  _targetWidth = 0;
  _targetHeight = 0;
}

WebRtc_Word32
VPMSimpleSpatialResampler::ResampleFrame(const I420VideoFrame& inFrame,
                                         I420VideoFrame* outFrame)
{
  if (_resamplingMode == kNoRescaling)
     return outFrame->CopyFrame(inFrame);
  // Check if re-sampling is needed
  if ((inFrame.width() == _targetWidth) &&
    (inFrame.height() == _targetHeight))  {
    return outFrame->CopyFrame(inFrame);
  }

  // Setting scaler
  // TODO(mikhal/marpan): Should we allow for setting the filter mode in
  // _scale.Set() with |_resamplingMode|?
  int retVal = 0;
  retVal = _scaler.Set(inFrame.width(), inFrame.height(),
                       _targetWidth, _targetHeight, kI420, kI420, kScaleBox);
  if (retVal < 0)
    return retVal;

  retVal = _scaler.Scale(inFrame, outFrame);

  // Setting time parameters to the output frame.
  // Timestamp will be reset in Scale call above, so we should set it after.
  outFrame->set_timestamp(inFrame.timestamp());
  outFrame->set_render_time_ms(inFrame.render_time_ms());

  if (retVal == 0)
    return VPM_OK;
  else
    return VPM_SCALE_ERROR;
}

WebRtc_Word32
VPMSimpleSpatialResampler::TargetHeight()
{
  return _targetHeight;
}

WebRtc_Word32
VPMSimpleSpatialResampler::TargetWidth()
{
  return _targetWidth;
}

bool
VPMSimpleSpatialResampler::ApplyResample(WebRtc_Word32 width,
                                         WebRtc_Word32 height)
{
  if ((width == _targetWidth && height == _targetHeight) ||
       _resamplingMode == kNoRescaling)
    return false;
  else
    return true;
}

} //namespace
<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2014.  All rights reserved
 */
#include    "../../StroikaPreComp.h"

#include    "../../../Foundation/Characters/String_Constant.h"
#include    "../../../Foundation/Characters/String2Float.h"
#include    "../../../Foundation/Containers/Mapping.h"
#include    "../../../Foundation/Containers/Sequence.h"
#include    "../../../Foundation/Containers/Set.h"
#include    "../../../Foundation/Debug/Assertions.h"
#include    "../../../Foundation/Debug/Trace.h"
#include    "../../../Foundation/DataExchange/CharacterDelimitedLines/Reader.h"
#include    "../../../Foundation/IO/FileSystem/BinaryFileInputStream.h"
#include    "../../../Foundation/Streams/BinaryInputStream.h"

#include    "../CommonMeasurementTypes.h"

#include    "Memory.h"

using   namespace   Stroika::Foundation;
using   namespace   Stroika::Foundation::Containers;
using   namespace   Stroika::Foundation::DataExchange;
using   namespace   Stroika::Foundation::Memory;

using   namespace   Stroika::Frameworks;
using   namespace   Stroika::Frameworks::SystemPerformance;

using   Characters::Character;
using   Characters::String_Constant;
using   Containers::Mapping;
using   Containers::Sequence;
using   Containers::Set;

// Comment this in to turn on aggressive noisy DbgTrace in this module
//#define   USE_NOISY_TRACE_IN_THIS_MODULE_       1

namespace {
    template <typename T>
    void    ReadX_ (Optional<T>* result, const String& n, const Sequence<String>& line)
    {
        if (line.size () >= 3 and line[0] == n) {
            String  unit = line[2];
            double  factor = (unit == L"kB") ? 1024 : 1;
            *result = static_cast<T> (round (Characters::String2Float<double> (line[1]) * factor));
#if     USE_NOISY_TRACE_IN_THIS_MODULE_
            DbgTrace (L"Set %s = %ld", n.c_str (), static_cast<long> (**result));
#endif
        }
    }
    Instruments::Memory::Info capture_ ()
    {
#if     USE_NOISY_TRACE_IN_THIS_MODULE_
        Debug::TraceContextBumper ctx (SDKSTR ("Instruments::Memory::Info capture_"));
#endif
        Instruments::Memory::Info   result;
#if     qPlatform_POSIX
        DataExchange::CharacterDelimitedLines::Reader reader {{ ':', ' ', '\t' }};
        const   String_Constant kProcMemInfoFileName_ { L"/proc/meminfo" };
        //const String_Constant kProcMemInfoFileName_ { L"c:\\Sandbox\\VMSharedFolder\\meminfo" };
        for (Sequence<String> line : reader.ReadAs2DArray (IO::FileSystem::BinaryFileInputStream (kProcMemInfoFileName_))) {
#if     USE_NOISY_TRACE_IN_THIS_MODULE_
            DbgTrace (L"***in Instruments::Memory::Info capture_ linesize=%d, line[0]=%s", line.size(), line.empty () ? L"" : line[0].c_str ());
#endif
            ReadX_ (&result.fFreePhysicalMemory, String_Constant (L"MemFree"), line);
            ReadX_ (&result.fTotalVirtualMemory, String_Constant (L"VmallocTotal"), line);
            ReadX_ (&result.fUsedVirtualMemory, String_Constant (L"VmallocUsed"), line);
            ReadX_ (&result.fLargestAvailableVirtualChunk, String_Constant (L"VmallocChunk"), line);
        }
#elif   qPlatform_Windows
#endif
        return result;
    }
}

const   MeasurementType Instruments::Memory::kSystemMemoryMeasurement = MeasurementType (String_Constant (L"System-Memory"));

/*
 ********************************************************************************
 ******************** Instruments::Memory::GetObjectVariantMapper ***************
 ********************************************************************************
 */
ObjectVariantMapper Instruments::Memory::GetObjectVariantMapper ()
{
    using   StructureFieldInfo = ObjectVariantMapper::StructureFieldInfo;
    ObjectVariantMapper sMapper_ = [] () -> ObjectVariantMapper {
        ObjectVariantMapper mapper;
        mapper.AddCommonType<Optional<uint64_t>> ();
        mapper.AddCommonType<Optional<double>> ();
        DISABLE_COMPILER_CLANG_WARNING_START("clang diagnostic ignored \"-Winvalid-offsetof\"");   // Really probably an issue, but not to debug here -- LGP 2014-01-04
        DISABLE_COMPILER_GCC_WARNING_START("GCC diagnostic ignored \"-Winvalid-offsetof\"");       // Really probably an issue, but not to debug here -- LGP 2014-01-04
        mapper.AddClass<Info> (initializer_list<StructureFieldInfo> {
            { Stroika_Foundation_DataExchange_ObjectVariantMapper_FieldInfoKey (Info, fFreePhysicalMemory), String_Constant (L"Free-Physical-Memory") },
            { Stroika_Foundation_DataExchange_ObjectVariantMapper_FieldInfoKey (Info, fTotalVirtualMemory), String_Constant (L"Total-Virtual-Memory") },
            { Stroika_Foundation_DataExchange_ObjectVariantMapper_FieldInfoKey (Info, fUsedVirtualMemory), String_Constant (L"UsedV-irtual-Memory") },
            { Stroika_Foundation_DataExchange_ObjectVariantMapper_FieldInfoKey (Info, fLargestAvailableVirtualChunk), String_Constant (L"Largest-Available-Virtual-Chunk") },
            { Stroika_Foundation_DataExchange_ObjectVariantMapper_FieldInfoKey (Info, fMajorPageFaultsSinceBoot), String_Constant (L"Major-Page-Faults-Since-Boot") },
            { Stroika_Foundation_DataExchange_ObjectVariantMapper_FieldInfoKey (Info, fMinorPageFaultsSinceBoot), String_Constant (L"Minor-Page-Faults-Since-Boot") },
            { Stroika_Foundation_DataExchange_ObjectVariantMapper_FieldInfoKey (Info, fMajorPageFaultsPerSecond), String_Constant (L"Major-Page-Faults-Per-Second") },
            { Stroika_Foundation_DataExchange_ObjectVariantMapper_FieldInfoKey (Info, fMinorPageFaultsPerSecond), String_Constant (L"Minor-Page-Faults-Per-Second") },
        });
        DISABLE_COMPILER_GCC_WARNING_END("GCC diagnostic ignored \"-Winvalid-offsetof\"");
        DISABLE_COMPILER_CLANG_WARNING_END("clang diagnostic ignored \"-Winvalid-offsetof\"");
        return mapper;
    } ();
    return sMapper_;
}

/*
 ********************************************************************************
 ******************* Instruments::Memory::GetInstrument *************************
 ********************************************************************************
 */
Instrument  SystemPerformance::Instruments::Memory::GetInstrument ()
{
    static  Instrument  kInstrument_    = Instrument (
            InstrumentNameType (String_Constant (L"Memory")),
    [] () -> MeasurementSet {
        MeasurementSet    results;
        DateTime    before = DateTime::Now ();
        Instruments::Memory::Info rawMeasurement = capture_ ();
        results.fMeasuredAt = DateTimeRange (before, DateTime::Now ());
        Measurement m;
        m.fValue = GetObjectVariantMapper ().FromObject (rawMeasurement);
        m.fType = kSystemMemoryMeasurement;
        results.fMeasurements.Add (m);
        return results;
    },
    {kMemoryUsage}
                                          );
    return kInstrument_;
}
<commit_msg>fixed problem reading /proc/meminfo - must avoid SEEK! - use trick of BufferedBinaryInputStream for now to avoid, but must fix better<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2014.  All rights reserved
 */
#include    "../../StroikaPreComp.h"

#include    "../../../Foundation/Characters/String_Constant.h"
#include    "../../../Foundation/Characters/String2Float.h"
#include    "../../../Foundation/Containers/Mapping.h"
#include    "../../../Foundation/Containers/Sequence.h"
#include    "../../../Foundation/Containers/Set.h"
#include    "../../../Foundation/Debug/Assertions.h"
#include    "../../../Foundation/Debug/Trace.h"
#include    "../../../Foundation/DataExchange/CharacterDelimitedLines/Reader.h"
#include    "../../../Foundation/IO/FileSystem/BinaryFileInputStream.h"
#include    "../../../Foundation/Streams/BinaryInputStream.h"
#include    "../../../Foundation/Streams/BufferedBinaryInputStream.h"

#include    "../CommonMeasurementTypes.h"

#include    "Memory.h"

using   namespace   Stroika::Foundation;
using   namespace   Stroika::Foundation::Containers;
using   namespace   Stroika::Foundation::DataExchange;
using   namespace   Stroika::Foundation::Memory;

using   namespace   Stroika::Frameworks;
using   namespace   Stroika::Frameworks::SystemPerformance;

using   Characters::Character;
using   Characters::String_Constant;
using   Containers::Mapping;
using   Containers::Sequence;
using   Containers::Set;

// Comment this in to turn on aggressive noisy DbgTrace in this module
//#define   USE_NOISY_TRACE_IN_THIS_MODULE_       1

namespace {
    template <typename T>
    void    ReadX_ (Optional<T>* result, const String& n, const Sequence<String>& line)
    {
        if (line.size () >= 3 and line[0] == n) {
            String  unit = line[2];
            double  factor = (unit == L"kB") ? 1024 : 1;
            *result = static_cast<T> (round (Characters::String2Float<double> (line[1]) * factor));
#if     USE_NOISY_TRACE_IN_THIS_MODULE_
            DbgTrace (L"Set %s = %ld", n.c_str (), static_cast<long> (**result));
#endif
        }
    }
    Instruments::Memory::Info capture_ ()
    {
#if     USE_NOISY_TRACE_IN_THIS_MODULE_
        Debug::TraceContextBumper ctx (SDKSTR ("Instruments::Memory::Info capture_"));
#endif
        Instruments::Memory::Info   result;
#if     qPlatform_POSIX
        DataExchange::CharacterDelimitedLines::Reader reader {{ ':', ' ', '\t' }};
        const   String_Constant kProcMemInfoFileName_ { L"/proc/meminfo" };
        //const String_Constant kProcMemInfoFileName_ { L"c:\\Sandbox\\VMSharedFolder\\meminfo" };

        // @todo - NOTE - MUST use Streams::BufferedBinaryInputStream because otherwise code will SEEK. REAL fix is to add attributes to BinaryFileInputStream saying if seekable, and /proc/xx files are NOT

        for (Sequence<String> line : reader.ReadAs2DArray (Streams::BufferedBinaryInputStream (IO::FileSystem::BinaryFileInputStream (kProcMemInfoFileName_)))) {
#if     USE_NOISY_TRACE_IN_THIS_MODULE_
            DbgTrace (L"***in Instruments::Memory::Info capture_ linesize=%d, line[0]=%s", line.size(), line.empty () ? L"" : line[0].c_str ());
#endif
            ReadX_ (&result.fFreePhysicalMemory, String_Constant (L"MemFree"), line);
            ReadX_ (&result.fTotalVirtualMemory, String_Constant (L"VmallocTotal"), line);
            ReadX_ (&result.fUsedVirtualMemory, String_Constant (L"VmallocUsed"), line);
            ReadX_ (&result.fLargestAvailableVirtualChunk, String_Constant (L"VmallocChunk"), line);
        }
#elif   qPlatform_Windows
#endif
        return result;
    }
}

const   MeasurementType Instruments::Memory::kSystemMemoryMeasurement = MeasurementType (String_Constant (L"System-Memory"));

/*
 ********************************************************************************
 ******************** Instruments::Memory::GetObjectVariantMapper ***************
 ********************************************************************************
 */
ObjectVariantMapper Instruments::Memory::GetObjectVariantMapper ()
{
    using   StructureFieldInfo = ObjectVariantMapper::StructureFieldInfo;
    ObjectVariantMapper sMapper_ = [] () -> ObjectVariantMapper {
        ObjectVariantMapper mapper;
        mapper.AddCommonType<Optional<uint64_t>> ();
        mapper.AddCommonType<Optional<double>> ();
        DISABLE_COMPILER_CLANG_WARNING_START("clang diagnostic ignored \"-Winvalid-offsetof\"");   // Really probably an issue, but not to debug here -- LGP 2014-01-04
        DISABLE_COMPILER_GCC_WARNING_START("GCC diagnostic ignored \"-Winvalid-offsetof\"");       // Really probably an issue, but not to debug here -- LGP 2014-01-04
        mapper.AddClass<Info> (initializer_list<StructureFieldInfo> {
            { Stroika_Foundation_DataExchange_ObjectVariantMapper_FieldInfoKey (Info, fFreePhysicalMemory), String_Constant (L"Free-Physical-Memory") },
            { Stroika_Foundation_DataExchange_ObjectVariantMapper_FieldInfoKey (Info, fTotalVirtualMemory), String_Constant (L"Total-Virtual-Memory") },
            { Stroika_Foundation_DataExchange_ObjectVariantMapper_FieldInfoKey (Info, fUsedVirtualMemory), String_Constant (L"UsedV-irtual-Memory") },
            { Stroika_Foundation_DataExchange_ObjectVariantMapper_FieldInfoKey (Info, fLargestAvailableVirtualChunk), String_Constant (L"Largest-Available-Virtual-Chunk") },
            { Stroika_Foundation_DataExchange_ObjectVariantMapper_FieldInfoKey (Info, fMajorPageFaultsSinceBoot), String_Constant (L"Major-Page-Faults-Since-Boot") },
            { Stroika_Foundation_DataExchange_ObjectVariantMapper_FieldInfoKey (Info, fMinorPageFaultsSinceBoot), String_Constant (L"Minor-Page-Faults-Since-Boot") },
            { Stroika_Foundation_DataExchange_ObjectVariantMapper_FieldInfoKey (Info, fMajorPageFaultsPerSecond), String_Constant (L"Major-Page-Faults-Per-Second") },
            { Stroika_Foundation_DataExchange_ObjectVariantMapper_FieldInfoKey (Info, fMinorPageFaultsPerSecond), String_Constant (L"Minor-Page-Faults-Per-Second") },
        });
        DISABLE_COMPILER_GCC_WARNING_END("GCC diagnostic ignored \"-Winvalid-offsetof\"");
        DISABLE_COMPILER_CLANG_WARNING_END("clang diagnostic ignored \"-Winvalid-offsetof\"");
        return mapper;
    } ();
    return sMapper_;
}

/*
 ********************************************************************************
 ******************* Instruments::Memory::GetInstrument *************************
 ********************************************************************************
 */
Instrument  SystemPerformance::Instruments::Memory::GetInstrument ()
{
    static  Instrument  kInstrument_    = Instrument (
            InstrumentNameType (String_Constant (L"Memory")),
    [] () -> MeasurementSet {
        MeasurementSet    results;
        DateTime    before = DateTime::Now ();
        Instruments::Memory::Info rawMeasurement = capture_ ();
        results.fMeasuredAt = DateTimeRange (before, DateTime::Now ());
        Measurement m;
        m.fValue = GetObjectVariantMapper ().FromObject (rawMeasurement);
        m.fType = kSystemMemoryMeasurement;
        results.fMeasurements.Add (m);
        return results;
    },
    {kMemoryUsage}
                                          );
    return kInstrument_;
}
<|endoftext|>


<commit_before>/*
 Copyright (c) 2009, The Barbarian Group
 All rights reserved.

 Redistribution and use in source and binary forms, with or without modification, are permitted provided that
 the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, this list of conditions and
	the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
	the following disclaimer in the documentation and/or other materials provided with the distribution.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 POSSIBILITY OF SUCH DAMAGE.
*/

#include "cinder/Serial.h"
#include "cinder/Timer.h"
#include "cinder/Thread.h"
#include "cinder/Utilities.h"

#include <string>
#include <iostream>
#include <fcntl.h>

#if defined( CINDER_MAC )
	#include <termios.h>
	#include <sys/ioctl.h>
	#include <getopt.h>
	#include <dirent.h>
#elif defined( CINDER_MSW )
	#include <setupapi.h>
	#pragma comment(lib, "setupapi.lib")
#endif

#include <map>
using namespace std;

namespace cinder {

bool							Serial::sDevicesInited = false;
std::vector<Serial::Device>		Serial::sDevices;

Serial::Serial( const Serial::Device &device, int baudRate )
	: mObj( new Obj( device, baudRate ) )
{
}

Serial::Obj::Obj( const Serial::Device &device, int baudRate )
	: mDevice( device )
{
#if defined( CINDER_MAC )
	mFd = open( ( "/dev/" + device.getName() ).c_str(), O_RDWR | O_NOCTTY | O_NONBLOCK );
	if( mFd == -1 ) {
		throw SerialExcOpenFailed();
	}

	termios options;
	tcgetattr( mFd, &mSavedOptions );
	options = mSavedOptions;
	map<int,int> baudToConstant;
	baudToConstant[300] = B300;
	baudToConstant[1200] = B1200;
	baudToConstant[2400] = B2400;
	baudToConstant[4800] = B4800;
	baudToConstant[9600] = B9600;
	baudToConstant[19200] = B19200;
	baudToConstant[28800] = B28800;
	baudToConstant[38400] = B38400;
	baudToConstant[57600] = B57600;
	baudToConstant[115200] = B115200;
	baudToConstant[230400] = B230400;

	int rateConstant = B9600;
	if( baudToConstant.find( baudRate ) != baudToConstant.end() )
		rateConstant = baudToConstant[baudRate];

	::cfsetispeed( &options, rateConstant );
	::cfsetospeed( &options, rateConstant );

	options.c_cflag |= (CLOCAL | CREAD);
	options.c_cflag &= ~PARENB;
	options.c_cflag &= ~CSTOPB;
	options.c_cflag &= ~CSIZE;
	options.c_cflag |= CS8;
	::tcsetattr( mFd, TCSANOW, &options );
#elif defined( CINDER_MSW )
	mDeviceHandle = ::CreateFileA( mDevice.getPath().c_str(), GENERIC_READ|GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0 );
	if( mDeviceHandle == INVALID_HANDLE_VALUE ) {
		throw SerialExcOpenFailed();
	}

	::COMMCONFIG config;
	::DWORD configSize = sizeof( ::COMMCONFIG );
	::GetCommConfig( mDeviceHandle, &config, &configSize );

	string settingsStr = string("baud=") + toString( baudRate ) + " parity=N data=8 stop=1";
	if( ! ::BuildCommDCBA( settingsStr.c_str(), &config.dcb ) ) {
		throw SerialExcOpenFailed();
	}

	if( ! ::SetCommState( mDeviceHandle, &config.dcb ) ) {
		throw SerialExcOpenFailed();
	}

	::GetCommTimeouts( mDeviceHandle, &mSavedTimeouts );
	::COMMTIMEOUTS timeOuts( mSavedTimeouts );

	timeOuts.ReadIntervalTimeout = MAXDWORD;
	timeOuts.ReadTotalTimeoutMultiplier = 0;
	timeOuts.ReadTotalTimeoutConstant = 0;
	::SetCommTimeouts( mDeviceHandle, &timeOuts );
#endif
}

Serial::Device Serial::findDeviceByName( const std::string &name, bool forceRefresh )
{
	const std::vector<Serial::Device> &devices = getDevices( forceRefresh );
	for( std::vector<Serial::Device>::const_iterator deviceIt = devices.begin(); deviceIt != devices.end(); ++deviceIt ) {
		if( deviceIt->getName() == name )
			return *deviceIt;
	}

	return Serial::Device();
}

Serial::Device Serial::findDeviceByNameContains( const std::string &searchString, bool forceRefresh )
{
	const std::vector<Serial::Device> &devices = getDevices( forceRefresh );
	for( std::vector<Serial::Device>::const_iterator deviceIt = devices.begin(); deviceIt != devices.end(); ++deviceIt ) {
		if( deviceIt->getName().find( searchString ) != std::string::npos )
			return *deviceIt;
	}

	return Serial::Device();
}

const std::vector<Serial::Device>& Serial::getDevices( bool forceRefresh )
{
	if( ( ! forceRefresh ) && ( sDevicesInited ) )
		return sDevices;

	sDevices.clear();

#if defined( CINDER_MAC )
	::DIR *dir;
	::dirent *entry;
	dir = ::opendir( "/dev" );

	if( ! dir ) {
		throw SerialExcDeviceEnumerationFailed();
	}
	else {
		while( ( entry = ::readdir( dir ) ) != NULL ) {
			std::string str( (char *)entry->d_name );
			if( ( str.substr( 0, 4 ) == "tty." ) || ( str.substr( 0, 3 ) == "cu." ) ) {
				sDevices.push_back( Serial::Device( str ) );
			}
		}
	}

#elif defined( CINDER_MSW )
	::HDEVINFO devInfoSet;
	::DWORD devCount = 0;
	::SP_DEVINFO_DATA devInfo;
	::SP_DEVICE_INTERFACE_DATA devInterface;
	DWORD size = 0;

	devInfoSet = ::SetupDiGetClassDevs( &GUID_SERENUM_BUS_ENUMERATOR, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE );
	if( devInfoSet == INVALID_HANDLE_VALUE )
		throw SerialExcDeviceEnumerationFailed();

	devInterface.cbSize = sizeof( ::SP_DEVICE_INTERFACE_DATA );
	while( ::SetupDiEnumDeviceInterfaces( devInfoSet, 0, &GUID_SERENUM_BUS_ENUMERATOR, devCount++, &devInterface ) ) {
		// See how large a buffer we require for the device interface details
		::SetupDiGetDeviceInterfaceDetail( devInfoSet, &devInterface, 0, 0, &size, 0 );
		devInfo.cbSize = sizeof( ::SP_DEVINFO_DATA );
		shared_ptr<::SP_DEVICE_INTERFACE_DETAIL_DATA> interfaceDetail( (::SP_DEVICE_INTERFACE_DETAIL_DATA*)calloc( 1, size ), free );
		if( interfaceDetail ) {
			interfaceDetail->cbSize = sizeof( ::SP_DEVICE_INTERFACE_DETAIL_DATA );
			devInfo.cbSize = sizeof( ::SP_DEVINFO_DATA );
			if( ! ::SetupDiGetDeviceInterfaceDetail( devInfoSet, &devInterface, interfaceDetail.get(), size, 0, &devInfo ) ) {
				continue;
			}

			char friendlyName[2048];
			size = sizeof( friendlyName );
			friendlyName[0] = 0;
			::DWORD propertyDataType;
			if( ! ::SetupDiGetDeviceRegistryPropertyA( devInfoSet, &devInfo, SPDRP_FRIENDLYNAME, &propertyDataType, (LPBYTE)friendlyName, size, 0 ) ) {
				continue;
			}

			sDevices.push_back( Serial::Device( string( friendlyName ), toUtf8( interfaceDetail->DevicePath ) ) );
		}
	}

	::SetupDiDestroyDeviceInfoList(devInfoSet);

#endif

	sDevicesInited = true;
	return sDevices;
}

Serial::Obj::~Obj()
{
#if defined( CINDER_MAC )
	// restore the termios from before we opened the port
	::tcsetattr( mFd, TCSANOW, &mSavedOptions );
	::close( mFd );
#elif defined( CINDER_MSW )
	::SetCommTimeouts( mDeviceHandle, &mSavedTimeouts );
	::CloseHandle( mDeviceHandle );
#endif
}

const Serial::Device& Serial::getDevice() const
{
	return mObj->mDevice;
}

void Serial::writeBytes( const void *data, size_t numBytes )
{
	size_t totalBytesWritten = 0;

	while( totalBytesWritten < numBytes ) {
#if defined( CINDER_MAC )
		int bytesWritten = ::write( mObj->mFd, data, numBytes - totalBytesWritten );
		if( ( bytesWritten == -1 ) && ( errno != EAGAIN ) )
			throw SerialExcReadFailure();
#elif defined( CINDER_MSW )
		::DWORD bytesWritten;
		if( ! ::WriteFile( mObj->mDeviceHandle, data, numBytes - totalBytesWritten, &bytesWritten, 0 ) )
			throw SerialExcWriteFailure();
#endif
		totalBytesWritten += bytesWritten;
	}
}

void Serial::readBytes( void *data, size_t numBytes )
{
	size_t totalBytesRead = 0;
	while( totalBytesRead < numBytes ) {
#if defined( CINDER_MAC )
		int bytesRead = ::read( mObj->mFd, data, numBytes - totalBytesRead );
		if( ( bytesRead == -1 ) && ( errno != EAGAIN ) )
			throw SerialExcReadFailure();
#elif defined( CINDER_MSW )
		::DWORD bytesRead = 0;
		if( ! ::ReadFile( mObj->mDeviceHandle, data, numBytes - totalBytesRead, &bytesRead, 0 ) )
			throw SerialExcReadFailure();
#endif
		totalBytesRead += bytesRead;

		// yield thread time to the system
		this_thread::yield();
	}
}

size_t Serial::readAvailableBytes( void *data, size_t maximumBytes )
{
#if defined( CINDER_MAC )
	int bytesRead = ::read( mObj->mFd, data, maximumBytes );
#elif defined( CINDER_MSW )
	::DWORD bytesRead = 0;
	if( ! ::ReadFile( mObj->mDeviceHandle, data, maximumBytes, &bytesRead, 0 ) )
		throw SerialExcReadFailure();
#endif

	if( bytesRead < 0 )
		bytesRead = 0;

	return (size_t)bytesRead;
}

void Serial::writeByte( uint8_t data )
{
	writeBytes( &data, 1 );
}

uint8_t Serial::readByte()
{
	uint8_t result;
	readBytes( &result, 1 );
	return result;
}

std::string Serial::readStringUntil( char token, size_t maxLength, double timeoutSeconds )
{
	size_t bufferSize = 1024, bufferOffset = 0;
	shared_ptr<char> buffer( (char*)malloc( bufferSize ), free );

	bool useMaxLength = maxLength > 0;
	bool useTimer = timeoutSeconds > 0;
	Timer timer;
	if( useTimer )
		timer.start();

	bool done = false;
	while( ! done ) {
		char v = readChar();
		buffer.get()[bufferOffset++] = v;
		if( v == token ) {
			done = true;
		}
		else if( useMaxLength && ( bufferOffset == maxLength ) ) {
			done = true;
		}
		else if( useTimer && ( timer.getSeconds() > timeoutSeconds ) )
			throw SerialTimeoutExc();

		// we need to reallocate even if this happens to be the last byte, because we need room for a null-terminator
		if( bufferOffset == bufferSize ) {
			char *newBuffer = (char*)malloc( bufferSize * 2 );
			memcpy( newBuffer, buffer.get(), bufferSize );
			bufferSize *= 2;
			buffer = shared_ptr<char>( newBuffer, free );
		}
	}

	buffer.get()[bufferOffset] = 0; // need to null terminate this thing
	std::string result( buffer.get() );

	return result;
}

void Serial::writeString( const std::string &str )
{
	for( string::const_iterator strIt = str.begin(); strIt != str.end(); ++strIt )
		writeByte( *strIt );
}

size_t Serial::getNumBytesAvailable() const
{
	int result;

#if defined( CINDER_MAC )
	::ioctl( mObj->mFd, FIONREAD, &result );
#elif defined( CINDER_MSW )
	::COMSTAT status;
	::DWORD error;
	if( ! ::ClearCommError( mObj->mDeviceHandle, &error, &status ) )
		throw SerialExc();
	else
		result = status.cbInQue;
#endif

	return result;
}

void Serial::flush( bool input, bool output )
{
#if defined( CINDER_MAC )
	int queue;
	if( input && output )
		queue = TCIOFLUSH;
	else if( input )
		queue = TCIFLUSH;
	else if( output )
		queue = TCOFLUSH;
	else
		return;

	::tcflush( mObj->mFd, queue );
#elif defined( CINDER_MSW )
	::DWORD flags = 0;
	flags |= ( input ) ? PURGE_RXCLEAR : 0;
	flags |= ( output ) ? PURGE_TXCLEAR : 0;

	if( input || output )
		::PurgeComm( mObj->mDeviceHandle, flags );
#endif
}

} // namespace cinder<commit_msg>Fixing Mac serial issue when ReadFile returns EAGAIN<commit_after>/*
 Copyright (c) 2009, The Barbarian Group
 All rights reserved.

 Redistribution and use in source and binary forms, with or without modification, are permitted provided that
 the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, this list of conditions and
	the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
	the following disclaimer in the documentation and/or other materials provided with the distribution.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 POSSIBILITY OF SUCH DAMAGE.
*/

#include "cinder/Serial.h"
#include "cinder/Timer.h"
#include "cinder/Thread.h"
#include "cinder/Utilities.h"

#include <string>
#include <iostream>
#include <fcntl.h>

#if defined( CINDER_MAC )
	#include <termios.h>
	#include <sys/ioctl.h>
	#include <getopt.h>
	#include <dirent.h>
#elif defined( CINDER_MSW )
	#include <setupapi.h>
	#pragma comment(lib, "setupapi.lib")
#endif

#include <map>
using namespace std;

namespace cinder {

bool							Serial::sDevicesInited = false;
std::vector<Serial::Device>		Serial::sDevices;

Serial::Serial( const Serial::Device &device, int baudRate )
	: mObj( new Obj( device, baudRate ) )
{
}

Serial::Obj::Obj( const Serial::Device &device, int baudRate )
	: mDevice( device )
{
#if defined( CINDER_MAC )
	mFd = open( ( "/dev/" + device.getName() ).c_str(), O_RDWR | O_NOCTTY | O_NONBLOCK );
	if( mFd == -1 ) {
		throw SerialExcOpenFailed();
	}

	termios options;
	tcgetattr( mFd, &mSavedOptions );
	options = mSavedOptions;
	map<int,int> baudToConstant;
	baudToConstant[300] = B300;
	baudToConstant[1200] = B1200;
	baudToConstant[2400] = B2400;
	baudToConstant[4800] = B4800;
	baudToConstant[9600] = B9600;
	baudToConstant[19200] = B19200;
	baudToConstant[28800] = B28800;
	baudToConstant[38400] = B38400;
	baudToConstant[57600] = B57600;
	baudToConstant[115200] = B115200;
	baudToConstant[230400] = B230400;

	int rateConstant = B9600;
	if( baudToConstant.find( baudRate ) != baudToConstant.end() )
		rateConstant = baudToConstant[baudRate];

	::cfsetispeed( &options, rateConstant );
	::cfsetospeed( &options, rateConstant );

	options.c_cflag |= (CLOCAL | CREAD);
	options.c_cflag &= ~PARENB;
	options.c_cflag &= ~CSTOPB;
	options.c_cflag &= ~CSIZE;
	options.c_cflag |= CS8;
	::tcsetattr( mFd, TCSANOW, &options );
#elif defined( CINDER_MSW )
	mDeviceHandle = ::CreateFileA( mDevice.getPath().c_str(), GENERIC_READ|GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0 );
	if( mDeviceHandle == INVALID_HANDLE_VALUE ) {
		throw SerialExcOpenFailed();
	}

	::COMMCONFIG config;
	::DWORD configSize = sizeof( ::COMMCONFIG );
	::GetCommConfig( mDeviceHandle, &config, &configSize );

	string settingsStr = string("baud=") + toString( baudRate ) + " parity=N data=8 stop=1";
	if( ! ::BuildCommDCBA( settingsStr.c_str(), &config.dcb ) ) {
		throw SerialExcOpenFailed();
	}

	if( ! ::SetCommState( mDeviceHandle, &config.dcb ) ) {
		throw SerialExcOpenFailed();
	}

	::GetCommTimeouts( mDeviceHandle, &mSavedTimeouts );
	::COMMTIMEOUTS timeOuts( mSavedTimeouts );

	timeOuts.ReadIntervalTimeout = MAXDWORD;
	timeOuts.ReadTotalTimeoutMultiplier = 0;
	timeOuts.ReadTotalTimeoutConstant = 0;
	::SetCommTimeouts( mDeviceHandle, &timeOuts );
#endif
}

Serial::Device Serial::findDeviceByName( const std::string &name, bool forceRefresh )
{
	const std::vector<Serial::Device> &devices = getDevices( forceRefresh );
	for( std::vector<Serial::Device>::const_iterator deviceIt = devices.begin(); deviceIt != devices.end(); ++deviceIt ) {
		if( deviceIt->getName() == name )
			return *deviceIt;
	}

	return Serial::Device();
}

Serial::Device Serial::findDeviceByNameContains( const std::string &searchString, bool forceRefresh )
{
	const std::vector<Serial::Device> &devices = getDevices( forceRefresh );
	for( std::vector<Serial::Device>::const_iterator deviceIt = devices.begin(); deviceIt != devices.end(); ++deviceIt ) {
		if( deviceIt->getName().find( searchString ) != std::string::npos )
			return *deviceIt;
	}

	return Serial::Device();
}

const std::vector<Serial::Device>& Serial::getDevices( bool forceRefresh )
{
	if( ( ! forceRefresh ) && ( sDevicesInited ) )
		return sDevices;

	sDevices.clear();

#if defined( CINDER_MAC )
	::DIR *dir;
	::dirent *entry;
	dir = ::opendir( "/dev" );

	if( ! dir ) {
		throw SerialExcDeviceEnumerationFailed();
	}
	else {
		while( ( entry = ::readdir( dir ) ) != NULL ) {
			std::string str( (char *)entry->d_name );
			if( ( str.substr( 0, 4 ) == "tty." ) || ( str.substr( 0, 3 ) == "cu." ) ) {
				sDevices.push_back( Serial::Device( str ) );
			}
		}
	}

#elif defined( CINDER_MSW )
	::HDEVINFO devInfoSet;
	::DWORD devCount = 0;
	::SP_DEVINFO_DATA devInfo;
	::SP_DEVICE_INTERFACE_DATA devInterface;
	DWORD size = 0;

	devInfoSet = ::SetupDiGetClassDevs( &GUID_SERENUM_BUS_ENUMERATOR, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE );
	if( devInfoSet == INVALID_HANDLE_VALUE )
		throw SerialExcDeviceEnumerationFailed();

	devInterface.cbSize = sizeof( ::SP_DEVICE_INTERFACE_DATA );
	while( ::SetupDiEnumDeviceInterfaces( devInfoSet, 0, &GUID_SERENUM_BUS_ENUMERATOR, devCount++, &devInterface ) ) {
		// See how large a buffer we require for the device interface details
		::SetupDiGetDeviceInterfaceDetail( devInfoSet, &devInterface, 0, 0, &size, 0 );
		devInfo.cbSize = sizeof( ::SP_DEVINFO_DATA );
		shared_ptr<::SP_DEVICE_INTERFACE_DETAIL_DATA> interfaceDetail( (::SP_DEVICE_INTERFACE_DETAIL_DATA*)calloc( 1, size ), free );
		if( interfaceDetail ) {
			interfaceDetail->cbSize = sizeof( ::SP_DEVICE_INTERFACE_DETAIL_DATA );
			devInfo.cbSize = sizeof( ::SP_DEVINFO_DATA );
			if( ! ::SetupDiGetDeviceInterfaceDetail( devInfoSet, &devInterface, interfaceDetail.get(), size, 0, &devInfo ) ) {
				continue;
			}

			char friendlyName[2048];
			size = sizeof( friendlyName );
			friendlyName[0] = 0;
			::DWORD propertyDataType;
			if( ! ::SetupDiGetDeviceRegistryPropertyA( devInfoSet, &devInfo, SPDRP_FRIENDLYNAME, &propertyDataType, (LPBYTE)friendlyName, size, 0 ) ) {
				continue;
			}

			sDevices.push_back( Serial::Device( string( friendlyName ), toUtf8( interfaceDetail->DevicePath ) ) );
		}
	}

	::SetupDiDestroyDeviceInfoList(devInfoSet);

#endif

	sDevicesInited = true;
	return sDevices;
}

Serial::Obj::~Obj()
{
#if defined( CINDER_MAC )
	// restore the termios from before we opened the port
	::tcsetattr( mFd, TCSANOW, &mSavedOptions );
	::close( mFd );
#elif defined( CINDER_MSW )
	::SetCommTimeouts( mDeviceHandle, &mSavedTimeouts );
	::CloseHandle( mDeviceHandle );
#endif
}

const Serial::Device& Serial::getDevice() const
{
	return mObj->mDevice;
}

void Serial::writeBytes( const void *data, size_t numBytes )
{
	size_t totalBytesWritten = 0;

	while( totalBytesWritten < numBytes ) {
#if defined( CINDER_MAC )
		int bytesWritten = ::write( mObj->mFd, data, numBytes - totalBytesWritten );
		if( ( bytesWritten == -1 ) && ( errno != EAGAIN ) )
			throw SerialExcReadFailure();
#elif defined( CINDER_MSW )
		::DWORD bytesWritten;
		if( ! ::WriteFile( mObj->mDeviceHandle, data, numBytes - totalBytesWritten, &bytesWritten, 0 ) )
			throw SerialExcWriteFailure();
#endif
		totalBytesWritten += bytesWritten;
	}
}

void Serial::readBytes( void *data, size_t numBytes )
{
	size_t totalBytesRead = 0;
	while( totalBytesRead < numBytes ) {
#if defined( CINDER_MAC )
		int bytesRead = ::read( mObj->mFd, data, numBytes - totalBytesRead );
		if( ( bytesRead == -1 ) && ( errno != EAGAIN ) )
			throw SerialExcReadFailure();
#elif defined( CINDER_MSW )
		::DWORD bytesRead = 0;
		if( ! ::ReadFile( mObj->mDeviceHandle, data, numBytes - totalBytesRead, &bytesRead, 0 ) )
			throw SerialExcReadFailure();
#endif
		if( bytesRead != -1 )
			totalBytesRead += bytesRead;

		// yield thread time to the system
		this_thread::yield();
	}
}

size_t Serial::readAvailableBytes( void *data, size_t maximumBytes )
{
#if defined( CINDER_MAC )
	int bytesRead = ::read( mObj->mFd, data, maximumBytes );
#elif defined( CINDER_MSW )
	::DWORD bytesRead = 0;
	if( ! ::ReadFile( mObj->mDeviceHandle, data, maximumBytes, &bytesRead, 0 ) )
		throw SerialExcReadFailure();
#endif

	if( bytesRead < 0 )
		bytesRead = 0;

	return (size_t)bytesRead;
}

void Serial::writeByte( uint8_t data )
{
	writeBytes( &data, 1 );
}

uint8_t Serial::readByte()
{
	uint8_t result;
	readBytes( &result, 1 );
	return result;
}

std::string Serial::readStringUntil( char token, size_t maxLength, double timeoutSeconds )
{
	size_t bufferSize = 1024, bufferOffset = 0;
	shared_ptr<char> buffer( (char*)malloc( bufferSize ), free );

	bool useMaxLength = maxLength > 0;
	bool useTimer = timeoutSeconds > 0;
	Timer timer;
	if( useTimer )
		timer.start();

	bool done = false;
	while( ! done ) {
		char v = readChar();
		buffer.get()[bufferOffset++] = v;
		if( v == token ) {
			done = true;
		}
		else if( useMaxLength && ( bufferOffset == maxLength ) ) {
			done = true;
		}
		else if( useTimer && ( timer.getSeconds() > timeoutSeconds ) )
			throw SerialTimeoutExc();

		// we need to reallocate even if this happens to be the last byte, because we need room for a null-terminator
		if( bufferOffset == bufferSize ) {
			char *newBuffer = (char*)malloc( bufferSize * 2 );
			memcpy( newBuffer, buffer.get(), bufferSize );
			bufferSize *= 2;
			buffer = shared_ptr<char>( newBuffer, free );
		}
	}

	buffer.get()[bufferOffset] = 0; // need to null terminate this thing
	std::string result( buffer.get() );

	return result;
}

void Serial::writeString( const std::string &str )
{
	for( string::const_iterator strIt = str.begin(); strIt != str.end(); ++strIt )
		writeByte( *strIt );
}

size_t Serial::getNumBytesAvailable() const
{
	int result;

#if defined( CINDER_MAC )
	::ioctl( mObj->mFd, FIONREAD, &result );
#elif defined( CINDER_MSW )
	::COMSTAT status;
	::DWORD error;
	if( ! ::ClearCommError( mObj->mDeviceHandle, &error, &status ) )
		throw SerialExc();
	else
		result = status.cbInQue;
#endif

	return result;
}

void Serial::flush( bool input, bool output )
{
#if defined( CINDER_MAC )
	int queue;
	if( input && output )
		queue = TCIOFLUSH;
	else if( input )
		queue = TCIFLUSH;
	else if( output )
		queue = TCOFLUSH;
	else
		return;

	::tcflush( mObj->mFd, queue );
#elif defined( CINDER_MSW )
	::DWORD flags = 0;
	flags |= ( input ) ? PURGE_RXCLEAR : 0;
	flags |= ( output ) ? PURGE_TXCLEAR : 0;

	if( input || output )
		::PurgeComm( mObj->mDeviceHandle, flags );
#endif
}

} // namespace cinder<|endoftext|>


<commit_before>/*****************************************************************************
 * Copyright (C) 2013 Michael Krufky
 *
 * Author: Michael Krufky <mkrufky@linuxtv.org>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * version 2 as published by the Free Software Foundation.
 *
 * 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
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "hlsinput.h"

int main(int argc, char *argv[])
{
  int opt;
  bool feed_stdout = false;
  char url[2048] = { 0 };

  while ((opt = getopt(argc, argv, "i:o")) != -1) {
    switch (opt) {
    case 'i':
      if (!optarg) {
        fprintf(stderr, "missing argument\n");
        return -1;
      }
      strncpy(url, optarg, sizeof(url));
      break;
    case 'o':
      feed_stdout = true;
      break;
    }
  }

  hlsinput hls(feed_stdout);
  hls.get(url);
}
<commit_msg>walk_hls: tiny whitespace cleanup<commit_after>/*****************************************************************************
 * Copyright (C) 2013 Michael Krufky
 *
 * Author: Michael Krufky <mkrufky@linuxtv.org>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * version 2 as published by the Free Software Foundation.
 *
 * 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
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "hlsinput.h"

int main(int argc, char *argv[])
{
  int opt;
  bool feed_stdout = false;
  char url[2048] = { 0 };

  while ((opt = getopt(argc, argv, "i:o")) != -1) {
    switch (opt) {
    case 'i':
      if (!optarg) {
	fprintf(stderr, "missing argument\n");
	return -1;
      }
      strncpy(url, optarg, sizeof(url));
      break;
    case 'o':
      feed_stdout = true;
      break;
    }
  }

  hlsinput hls(feed_stdout);
  hls.get(url);
}
<|endoftext|>


<commit_before>/**
 * Test suite for the iterator_concepts_ordering.hpp header.
 */

#include <duck/detail/iterator_concepts_ordering.hpp>

#include <boost/mpl/assert.hpp>

BOOST_MPL_ASSERT((duck::is_more_specific_than<
                    duck::BidirectionalIterator,
                    duck::RandomAccessIterator>));

BOOST_MPL_ASSERT((duck::is_more_specific_than<
                    duck::IncrementableIterator,
                    duck::RandomAccessIterator>));

BOOST_MPL_ASSERT_NOT((duck::is_more_specific_than<
                        duck::RandomAccessIterator,
                        duck::BidirectionalIterator>));

BOOST_MPL_ASSERT_NOT((duck::is_more_specific_than<
                        duck::RandomAccessIterator,
                        duck::IncrementableIterator>));

BOOST_MPL_ASSERT_NOT((duck::is_more_specific_than<
                        duck::ForwardIterator,
                        duck::ForwardIterator>));
<commit_msg>Add more iterator concept ordering tests.<commit_after>/**
 * Test suite for the iterator_concepts_ordering.hpp header.
 */

#include <duck/detail/iterator_concepts_ordering.hpp>

#include <boost/mpl/assert.hpp>

BOOST_MPL_ASSERT((duck::is_more_specific_than<
                    duck::BidirectionalIterator,
                    duck::RandomAccessIterator>));

BOOST_MPL_ASSERT((duck::is_more_specific_than<
                    duck::IncrementableIterator,
                    duck::RandomAccessIterator>));

BOOST_MPL_ASSERT((duck::is_more_specific_than<
                    duck::ForwardIterator,
                    duck::RandomAccessIterator>));

BOOST_MPL_ASSERT_NOT((duck::is_more_specific_than<
                        duck::RandomAccessIterator,
                        duck::BidirectionalIterator>));

BOOST_MPL_ASSERT_NOT((duck::is_more_specific_than<
                        duck::RandomAccessIterator,
                        duck::IncrementableIterator>));

BOOST_MPL_ASSERT_NOT((duck::is_more_specific_than<
                        duck::ForwardIterator,
                        duck::ForwardIterator>));

BOOST_MPL_ASSERT_NOT((duck::is_more_specific_than<
                        duck::RandomAccessIterator,
                        duck::ForwardIterator>));
<|endoftext|>