<commit_before>// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include "blueprintresolver.h"
#include "blueprintfactory.h"
#include "featurenameparser.h"
#include <vespa/vespalib/util/stringfmt.h>
#include <stack>
#include <cassert>

#include <vespa/log/log.h>
LOG_SETUP(".fef.blueprintresolver");

namespace search::fef {

namespace {

using Accept = Blueprint::AcceptInput;

bool is_compatible(bool is_object, Accept accept_type) {
    return ((accept_type == Accept::ANY) ||
            ((accept_type == Accept::OBJECT) == (is_object)));
}

const char *type_str(bool is_object) {
    return (is_object ? "object" : "number");
}

const char *accept_type_str(Accept accept_type) {
    switch (accept_type) {
    case Accept::NUMBER: return "number";
    case Accept::OBJECT: return "object";
    case Accept::ANY:    return "any";
    }
    return "(not reached)";
}

struct Compiler : public Blueprint::DependencyHandler {
    using ExecutorSpec = BlueprintResolver::ExecutorSpec;
    using ExecutorSpecList = BlueprintResolver::ExecutorSpecList;
    using FeatureRef = BlueprintResolver::FeatureRef;
    using FeatureMap = BlueprintResolver::FeatureMap;

    struct Frame {
        ExecutorSpec spec;
        const FeatureNameParser &parser;
        Frame(Blueprint::SP blueprint, const FeatureNameParser &parser_in)
            : spec(std::move(blueprint)), parser(parser_in) {}
    };
    using Stack = std::vector<Frame>;

    struct FrameGuard {
        Stack &stack;
        explicit FrameGuard(Stack &stack_in) : stack(stack_in) {}
        ~FrameGuard() { stack.pop_back(); }
    };

    const BlueprintFactory  &factory;
    const IIndexEnvironment &index_env;
    bool                     compile_error;
    Stack                    resolve_stack;
    ExecutorSpecList        &spec_list;
    FeatureMap              &feature_map;

    Compiler(const BlueprintFactory &factory_in,
             const IIndexEnvironment &index_env_in,
             ExecutorSpecList &spec_list_out,
             FeatureMap &feature_map_out)
        : factory(factory_in),
          index_env(index_env_in),
          compile_error(false),
          resolve_stack(),
          spec_list(spec_list_out),
          feature_map(feature_map_out) {}

    Frame &self() { return resolve_stack.back(); }

    FeatureRef failed(const vespalib::string &feature_name, const vespalib::string &reason) {
        if (!compile_error) {
            LOG(warning, "invalid rank feature: '%s' (%s)", feature_name.c_str(), reason.c_str());
            for (size_t i = resolve_stack.size(); i > 0; --i) {
                const auto &frame = resolve_stack[i - 1];
                if (&frame != &self()) {
                    LOG(warning, "  ... needed by rank feature '%s'", frame.parser.featureName().c_str());
                }
            }
            compile_error = true;
        }
        return FeatureRef();
    }

    void fixup_feature_map() {
        auto itr = feature_map.begin();
        while (itr != feature_map.end()) {
            if (itr->second.executor >= spec_list.size()) {
                itr = feature_map.erase(itr);
            } else {
                ++itr;
            }
        }
    }

    FeatureRef verify_type(const FeatureNameParser &parser, FeatureRef ref, Accept accept_type) {
        const auto &spec = spec_list[ref.executor];
        bool is_object = spec.output_types[ref.output];
        if (!is_compatible(is_object, accept_type)) {
            return failed(parser.featureName(),
                          vespalib::make_string("output '%s' has wrong type: was %s, expected %s",
                                  parser.output().c_str(), type_str(is_object), accept_type_str(accept_type)));
        }
        return ref;
    }

    FeatureRef setup_feature(const FeatureNameParser &parser, Accept accept_type) {
        Blueprint::SP blueprint = factory.createBlueprint(parser.baseName());
        if ( ! blueprint) {
            return failed(parser.featureName(),
                          vespalib::make_string("unknown basename: '%s'", parser.baseName().c_str()));
        }
        resolve_stack.emplace_back(std::move(blueprint), parser);
        FrameGuard frame_guard(resolve_stack);
        self().spec.blueprint->setName(parser.executorName());
        self().spec.blueprint->attach_dependency_handler(*this);
        if (!self().spec.blueprint->setup(index_env, parser.parameters())) {
            fixup_feature_map();
            return failed(parser.featureName(), "invalid parameters");
        }
        if (parser.output().empty() && self().spec.output_types.empty()) {
            fixup_feature_map();
            return failed(parser.featureName(), "has no output value");
        }
        const auto &feature = feature_map.find(parser.featureName());
        if (feature == feature_map.end()) {
            fixup_feature_map();
            return failed(parser.featureName(),
                          vespalib::make_string("unknown output: '%s'", parser.output().c_str()));
        }
        spec_list.push_back(self().spec);
        return verify_type(parser, feature->second, accept_type);
    }

    FeatureRef resolve_feature(const vespalib::string &feature_name, Accept accept_type) {
        FeatureNameParser parser(feature_name);
        if (!parser.valid()) {
            return failed(feature_name, "malformed name");
        }
        const auto &feature = feature_map.find(parser.featureName());
        if (feature != feature_map.end()) {
            return verify_type(parser, feature->second, accept_type);
        }
        if ((resolve_stack.size() + 1) > BlueprintResolver::MAX_DEP_DEPTH) {
            return failed(parser.featureName(), "dependency graph too deep");
        }
        for (const Frame &frame: resolve_stack) {
            if (frame.parser.executorName() == parser.executorName()) {
                return failed(parser.featureName(), "dependency cycle detected");
            }
        }
        return setup_feature(parser, accept_type);
    }

    const FeatureType &resolve_input(const vespalib::string &feature_name, Accept accept_type) override {
        assert(self().spec.output_types.empty()); // require: 'resolve inputs' before 'define outputs'
        auto ref = resolve_feature(feature_name, accept_type);
        if (!ref.valid()) {
            return FeatureType::number();
        }
        self().spec.inputs.push_back(ref);
        return spec_list[ref.executor].output_types[ref.output];
    }

    void define_output(const vespalib::string &output_name, const FeatureType &type) override {
        vespalib::string feature_name = self().parser.executorName();
        if (!output_name.empty()) {
            feature_name.push_back('.');
            feature_name.append(output_name);
        }
        FeatureRef output_ref(spec_list.size(), self().spec.output_types.size());
        if (output_ref.output == 0) {
            feature_map.emplace(self().parser.executorName(), output_ref);
        }
        feature_map.emplace(feature_name, output_ref);
        self().spec.output_types.push_back(type);
    }
};

} // namespace search::fef::<unnamed>

BlueprintResolver::ExecutorSpec::ExecutorSpec(Blueprint::SP blueprint_in)
    : blueprint(std::move(blueprint_in)),
      inputs(),
      output_types()
{ }

BlueprintResolver::ExecutorSpec::~ExecutorSpec() = default;
BlueprintResolver::~BlueprintResolver() = default;

BlueprintResolver::BlueprintResolver(const BlueprintFactory &factory,
                                     const IIndexEnvironment &indexEnv)
    : _factory(factory),
      _indexEnv(indexEnv),
      _seeds(),
      _executorSpecs(),
      _featureMap(),
      _seedMap()
{
}

void
BlueprintResolver::addSeed(vespalib::stringref feature)
{
    _seeds.emplace_back(feature);
}

bool
BlueprintResolver::compile()
{
    assert(_executorSpecs.empty()); // only one compilation allowed
    Compiler compiler(_factory, _indexEnv, _executorSpecs, _featureMap);
    for (const auto &seed: _seeds) {
        auto ref = compiler.resolve_feature(seed, Blueprint::AcceptInput::ANY);
        if (compiler.compile_error) {
            return false;
        }
        _seedMap.emplace(FeatureNameParser(seed).featureName(), ref);
    }
    return true;
}

const BlueprintResolver::ExecutorSpecList &
BlueprintResolver::getExecutorSpecs() const
{
    return _executorSpecs;
}

const BlueprintResolver::FeatureMap &
BlueprintResolver::getFeatureMap() const
{
    return _featureMap;
}

const BlueprintResolver::FeatureMap &
BlueprintResolver::getSeedMap() const
{
    return _seedMap;
}

}
<commit_msg>Call fixup_feature_map() from failed() method.<commit_after>// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include "blueprintresolver.h"
#include "blueprintfactory.h"
#include "featurenameparser.h"
#include <vespa/vespalib/util/stringfmt.h>
#include <stack>
#include <cassert>

#include <vespa/log/log.h>
LOG_SETUP(".fef.blueprintresolver");

namespace search::fef {

namespace {

using Accept = Blueprint::AcceptInput;

bool is_compatible(bool is_object, Accept accept_type) {
    return ((accept_type == Accept::ANY) ||
            ((accept_type == Accept::OBJECT) == (is_object)));
}

const char *type_str(bool is_object) {
    return (is_object ? "object" : "number");
}

const char *accept_type_str(Accept accept_type) {
    switch (accept_type) {
    case Accept::NUMBER: return "number";
    case Accept::OBJECT: return "object";
    case Accept::ANY:    return "any";
    }
    return "(not reached)";
}

struct Compiler : public Blueprint::DependencyHandler {
    using ExecutorSpec = BlueprintResolver::ExecutorSpec;
    using ExecutorSpecList = BlueprintResolver::ExecutorSpecList;
    using FeatureRef = BlueprintResolver::FeatureRef;
    using FeatureMap = BlueprintResolver::FeatureMap;

    struct Frame {
        ExecutorSpec spec;
        const FeatureNameParser &parser;
        Frame(Blueprint::SP blueprint, const FeatureNameParser &parser_in)
            : spec(std::move(blueprint)), parser(parser_in) {}
    };
    using Stack = std::vector<Frame>;

    struct FrameGuard {
        Stack &stack;
        explicit FrameGuard(Stack &stack_in) : stack(stack_in) {}
        ~FrameGuard() { stack.pop_back(); }
    };

    const BlueprintFactory  &factory;
    const IIndexEnvironment &index_env;
    bool                     compile_error;
    Stack                    resolve_stack;
    ExecutorSpecList        &spec_list;
    FeatureMap              &feature_map;

    Compiler(const BlueprintFactory &factory_in,
             const IIndexEnvironment &index_env_in,
             ExecutorSpecList &spec_list_out,
             FeatureMap &feature_map_out)
        : factory(factory_in),
          index_env(index_env_in),
          compile_error(false),
          resolve_stack(),
          spec_list(spec_list_out),
          feature_map(feature_map_out) {}

    Frame &self() { return resolve_stack.back(); }

    FeatureRef failed(const vespalib::string &feature_name, const vespalib::string &reason) {
        if (!compile_error) {
            LOG(warning, "invalid rank feature: '%s' (%s)", feature_name.c_str(), reason.c_str());
            for (size_t i = resolve_stack.size(); i > 0; --i) {
                const auto &frame = resolve_stack[i - 1];
                if (&frame != &self()) {
                    LOG(warning, "  ... needed by rank feature '%s'", frame.parser.featureName().c_str());
                }
            }
            compile_error = true;
        }
        fixup_feature_map();
        return FeatureRef();
    }

    void fixup_feature_map() {
        auto itr = feature_map.begin();
        while (itr != feature_map.end()) {
            if (itr->second.executor >= spec_list.size()) {
                itr = feature_map.erase(itr);
            } else {
                ++itr;
            }
        }
    }

    FeatureRef verify_type(const FeatureNameParser &parser, FeatureRef ref, Accept accept_type) {
        const auto &spec = spec_list[ref.executor];
        bool is_object = spec.output_types[ref.output];
        if (!is_compatible(is_object, accept_type)) {
            return failed(parser.featureName(),
                          vespalib::make_string("output '%s' has wrong type: was %s, expected %s",
                                  parser.output().c_str(), type_str(is_object), accept_type_str(accept_type)));
        }
        return ref;
    }

    FeatureRef setup_feature(const FeatureNameParser &parser, Accept accept_type) {
        Blueprint::SP blueprint = factory.createBlueprint(parser.baseName());
        if ( ! blueprint) {
            return failed(parser.featureName(),
                          vespalib::make_string("unknown basename: '%s'", parser.baseName().c_str()));
        }
        resolve_stack.emplace_back(std::move(blueprint), parser);
        FrameGuard frame_guard(resolve_stack);
        self().spec.blueprint->setName(parser.executorName());
        self().spec.blueprint->attach_dependency_handler(*this);
        if (!self().spec.blueprint->setup(index_env, parser.parameters())) {
            return failed(parser.featureName(), "invalid parameters");
        }
        if (parser.output().empty() && self().spec.output_types.empty()) {
            return failed(parser.featureName(), "has no output value");
        }
        const auto &feature = feature_map.find(parser.featureName());
        if (feature == feature_map.end()) {
            return failed(parser.featureName(),
                          vespalib::make_string("unknown output: '%s'", parser.output().c_str()));
        }
        spec_list.push_back(self().spec);
        return verify_type(parser, feature->second, accept_type);
    }

    FeatureRef resolve_feature(const vespalib::string &feature_name, Accept accept_type) {
        FeatureNameParser parser(feature_name);
        if (!parser.valid()) {
            return failed(feature_name, "malformed name");
        }
        const auto &feature = feature_map.find(parser.featureName());
        if (feature != feature_map.end()) {
            return verify_type(parser, feature->second, accept_type);
        }
        if ((resolve_stack.size() + 1) > BlueprintResolver::MAX_DEP_DEPTH) {
            return failed(parser.featureName(), "dependency graph too deep");
        }
        for (const Frame &frame: resolve_stack) {
            if (frame.parser.executorName() == parser.executorName()) {
                return failed(parser.featureName(), "dependency cycle detected");
            }
        }
        return setup_feature(parser, accept_type);
    }

    const FeatureType &resolve_input(const vespalib::string &feature_name, Accept accept_type) override {
        assert(self().spec.output_types.empty()); // require: 'resolve inputs' before 'define outputs'
        auto ref = resolve_feature(feature_name, accept_type);
        if (!ref.valid()) {
            return FeatureType::number();
        }
        self().spec.inputs.push_back(ref);
        return spec_list[ref.executor].output_types[ref.output];
    }

    void define_output(const vespalib::string &output_name, const FeatureType &type) override {
        vespalib::string feature_name = self().parser.executorName();
        if (!output_name.empty()) {
            feature_name.push_back('.');
            feature_name.append(output_name);
        }
        FeatureRef output_ref(spec_list.size(), self().spec.output_types.size());
        if (output_ref.output == 0) {
            feature_map.emplace(self().parser.executorName(), output_ref);
        }
        feature_map.emplace(feature_name, output_ref);
        self().spec.output_types.push_back(type);
    }
};

} // namespace search::fef::<unnamed>

BlueprintResolver::ExecutorSpec::ExecutorSpec(Blueprint::SP blueprint_in)
    : blueprint(std::move(blueprint_in)),
      inputs(),
      output_types()
{ }

BlueprintResolver::ExecutorSpec::~ExecutorSpec() = default;
BlueprintResolver::~BlueprintResolver() = default;

BlueprintResolver::BlueprintResolver(const BlueprintFactory &factory,
                                     const IIndexEnvironment &indexEnv)
    : _factory(factory),
      _indexEnv(indexEnv),
      _seeds(),
      _executorSpecs(),
      _featureMap(),
      _seedMap()
{
}

void
BlueprintResolver::addSeed(vespalib::stringref feature)
{
    _seeds.emplace_back(feature);
}

bool
BlueprintResolver::compile()
{
    assert(_executorSpecs.empty()); // only one compilation allowed
    Compiler compiler(_factory, _indexEnv, _executorSpecs, _featureMap);
    for (const auto &seed: _seeds) {
        auto ref = compiler.resolve_feature(seed, Blueprint::AcceptInput::ANY);
        if (compiler.compile_error) {
            return false;
        }
        _seedMap.emplace(FeatureNameParser(seed).featureName(), ref);
    }
    return true;
}

const BlueprintResolver::ExecutorSpecList &
BlueprintResolver::getExecutorSpecs() const
{
    return _executorSpecs;
}

const BlueprintResolver::FeatureMap &
BlueprintResolver::getFeatureMap() const
{
    return _featureMap;
}

const BlueprintResolver::FeatureMap &
BlueprintResolver::getSeedMap() const
{
    return _seedMap;
}

}
<|endoftext|>


<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <string>

#include "build/build_config.h"
#include "chrome/test/ui/ui_test.h"
#include "net/base/net_util.h"

class GPUTest : public UITest {
 protected:
  GPUTest() {
  }

  virtual void SetUp() {
    UITest::SetUp();
    gpu_test_dir_ = test_data_directory_.AppendASCII("gpu");
  }

  FilePath gpu_test_dir_;
};

// TODO(apatrick): Other pending changes will fix this for mac.
#if defined(OS_MACOSX) || defined(OS_LINUX)
#define MAYBE_UITestLaunchedWithOSMesa FAILS_UITestLaunchedWithOSMesa
#else
#define MAYBE_UITestLaunchedWithOSMesa FLAKY_UITestLaunchedWithOSMesa
#endif

TEST_F(GPUTest, MAYBE_UITestLaunchedWithOSMesa) {
  // Check the webgl test reports success and that the renderer was OSMesa.
  // We use OSMesa for tests in order to get consistent results across a
  // variety of boxes.
  NavigateToURL(
      net::FilePathToFileURL(gpu_test_dir_.AppendASCII("webgl.html")));

  EXPECT_EQ(std::wstring(L"SUCCESS: Mesa OffScreen"), GetActiveTabTitle());
}
<commit_msg>Flagged GPUTest.UITestLaunchedWithOSMesa as DISABLED.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <string>

#include "build/build_config.h"
#include "chrome/test/ui/ui_test.h"
#include "net/base/net_util.h"

class GPUTest : public UITest {
 protected:
  GPUTest() {
  }

  virtual void SetUp() {
    UITest::SetUp();
    gpu_test_dir_ = test_data_directory_.AppendASCII("gpu");
  }

  FilePath gpu_test_dir_;
};

// TODO(apatrick): Other pending changes will fix this for mac and linux.
#if defined(OS_MACOSX) || defined(OS_LINUX)
#define MAYBE_UITestLaunchedWithOSMesa DISABLED_UITestLaunchedWithOSMesa
#else
#define MAYBE_UITestLaunchedWithOSMesa FLAKY_UITestLaunchedWithOSMesa
#endif

TEST_F(GPUTest, MAYBE_UITestLaunchedWithOSMesa) {
  // Check the webgl test reports success and that the renderer was OSMesa.
  // We use OSMesa for tests in order to get consistent results across a
  // variety of boxes.
  NavigateToURL(
      net::FilePathToFileURL(gpu_test_dir_.AppendASCII("webgl.html")));

  EXPECT_EQ(std::wstring(L"SUCCESS: Mesa OffScreen"), GetActiveTabTitle());
}
<|endoftext|>


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

// Interface header.
#include "objectcollectionitem.h"

// appleseed.studio headers.
#include "mainwindow/project/assemblyitem.h"
#include "mainwindow/project/itemregistry.h"
#include "mainwindow/project/objectitem.h"
#include "mainwindow/project/projectbuilder.h"
#include "mainwindow/rendering/renderingmanager.h"
#include "utility/interop.h"
#include "utility/settingskeys.h"

// appleseed.renderer headers.
#include "renderer/api/utility.h"

// appleseed.foundation headers.
#include "foundation/math/transform.h"
#include "foundation/utility/containers/dictionary.h"
#include "foundation/utility/autoreleaseptr.h"
#include "foundation/utility/searchpaths.h"
#include "foundation/utility/uid.h"

// Qt headers.
#include <QDir>
#include <QFileDialog>
#include <QMenu>
#include <QString>
#include <QStringList>

// boost headers.
#include "boost/filesystem/path.hpp"

// Standard headers.
#include <cassert>
#include <cstddef>

using namespace boost;
using namespace foundation;
using namespace renderer;
using namespace std;

namespace appleseed {
namespace studio {

namespace
{
    const UniqueID g_class_uid = new_guid();
}

ObjectCollectionItem::ObjectCollectionItem(
    ObjectContainer&    objects,
    Assembly&           parent,
    AssemblyItem*       parent_item,
    ProjectBuilder&     project_builder,
    ParamArray&         settings)
  : CollectionItemBase<Object>(g_class_uid, "Objects", project_builder)
  , m_parent(parent)
  , m_parent_item(parent_item)
  , m_settings(settings)
{
    add_items(objects);
}

QMenu* ObjectCollectionItem::get_single_item_context_menu() const
{
    QMenu* menu = CollectionItemBase<Object>::get_single_item_context_menu();

    menu->addSeparator();
    menu->addAction("Import Objects...", this, SLOT(slot_import_objects()));

    return menu;
}

void ObjectCollectionItem::slot_import_objects()
{
    QFileDialog::Options options;
    QString selected_filter;

    const QStringList filepaths =
        QFileDialog::getOpenFileNames(
            treeWidget(),
            "Import Objects...",
            m_settings.get_path_optional<QString>(LAST_DIRECTORY_SETTINGS_KEY),
            "Geometry Files (*.abc; *.obj);;All Files (*.*)",
            &selected_filter,
            options);

    if (filepaths.empty())
        return;

    const filesystem::path path(
        QDir::toNativeSeparators(filepaths.first()).toStdString());

    m_settings.insert_path(
        LAST_DIRECTORY_SETTINGS_KEY,
        path.parent_path().string());

    if (m_project_builder.get_rendering_manager().is_rendering())
        schedule_import_objects(filepaths);
    else import_objects(filepaths);

}

namespace
{
    class ImportObjectsDelayedAction
      : public RenderingManager::IDelayedAction
    {
      public:
        ImportObjectsDelayedAction(
            ObjectCollectionItem*   parent,
            const QStringList&      filepaths)
          : m_parent(parent)
          , m_filepaths(filepaths)
        {
        }

        virtual void operator()(
            MasterRenderer&         master_renderer,
            Project&                project) OVERRIDE
        {
            m_parent->import_objects(m_filepaths);
        }

      private:
        ObjectCollectionItem*       m_parent;
        const QStringList           m_filepaths;
    };
}

void ObjectCollectionItem::schedule_import_objects(const QStringList& filepaths)
{
    m_project_builder.get_rendering_manager().push_delayed_action(
        auto_ptr<RenderingManager::IDelayedAction>(
            new ImportObjectsDelayedAction(this, filepaths)));

    m_project_builder.get_rendering_manager().reinitialize_rendering();
}

void ObjectCollectionItem::import_objects(const QStringList& filepaths)
{
    for (int i = 0; i < filepaths.size(); ++i)
        insert_objects(QDir::toNativeSeparators(filepaths[i]).toStdString());
}

void ObjectCollectionItem::insert_objects(const string& path) const
{
    const string base_object_name =
        filesystem::path(path).replace_extension().filename().string();

    ParamArray params;
    params.insert("filename", path);

    SearchPaths search_paths;
    MeshObjectArray mesh_objects;

    if (!MeshObjectReader().read(
            search_paths,
            base_object_name.c_str(),
            params,
            mesh_objects))
        return;

    for (size_t i = 0; i < mesh_objects.size(); ++i)
    {
        MeshObject* object = mesh_objects[i];

        m_parent_item->add_item(object);

        m_parent.objects().insert(auto_release_ptr<Object>(object));

        const string object_instance_name = string(object->get_name()) + "_inst";

        auto_release_ptr<ObjectInstance> object_instance(
            ObjectInstanceFactory::create(
                object_instance_name.c_str(),
                ParamArray(),
                object->get_name(),
                Transformd::identity(),
                StringDictionary()));

        m_parent_item->add_item(object_instance.get());

        m_parent.object_instances().insert(object_instance);
    }

    if (!mesh_objects.empty())
    {
        m_parent.bump_version_id();
        m_project_builder.notify_project_modification();
    }
}

ItemBase* ObjectCollectionItem::create_item(Object* object)
{
    assert(object);

    ItemBase* item =
        new ObjectItem(
            object,
            m_parent,
            m_parent_item,
            m_project_builder);

    m_project_builder.get_item_registry().insert(object->get_uid(), item);

    return item;
}

}   // namespace studio
}   // namespace appleseed
<commit_msg>the Import Objects file dialog now show *.binarymesh files.<commit_after>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010-2013 Francois Beaune, Jupiter Jazz Limited
// Copyright (c) 2014 Francois Beaune, The appleseedhq Organization
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// Interface header.
#include "objectcollectionitem.h"

// appleseed.studio headers.
#include "mainwindow/project/assemblyitem.h"
#include "mainwindow/project/itemregistry.h"
#include "mainwindow/project/objectitem.h"
#include "mainwindow/project/projectbuilder.h"
#include "mainwindow/rendering/renderingmanager.h"
#include "utility/interop.h"
#include "utility/settingskeys.h"

// appleseed.renderer headers.
#include "renderer/api/utility.h"

// appleseed.foundation headers.
#include "foundation/math/transform.h"
#include "foundation/utility/containers/dictionary.h"
#include "foundation/utility/autoreleaseptr.h"
#include "foundation/utility/searchpaths.h"
#include "foundation/utility/uid.h"

// Qt headers.
#include <QDir>
#include <QFileDialog>
#include <QMenu>
#include <QString>
#include <QStringList>

// boost headers.
#include "boost/filesystem/path.hpp"

// Standard headers.
#include <cassert>
#include <cstddef>

using namespace boost;
using namespace foundation;
using namespace renderer;
using namespace std;

namespace appleseed {
namespace studio {

namespace
{
    const UniqueID g_class_uid = new_guid();
}

ObjectCollectionItem::ObjectCollectionItem(
    ObjectContainer&    objects,
    Assembly&           parent,
    AssemblyItem*       parent_item,
    ProjectBuilder&     project_builder,
    ParamArray&         settings)
  : CollectionItemBase<Object>(g_class_uid, "Objects", project_builder)
  , m_parent(parent)
  , m_parent_item(parent_item)
  , m_settings(settings)
{
    add_items(objects);
}

QMenu* ObjectCollectionItem::get_single_item_context_menu() const
{
    QMenu* menu = CollectionItemBase<Object>::get_single_item_context_menu();

    menu->addSeparator();
    menu->addAction("Import Objects...", this, SLOT(slot_import_objects()));

    return menu;
}

void ObjectCollectionItem::slot_import_objects()
{
    QFileDialog::Options options;
    QString selected_filter;

    const QStringList filepaths =
        QFileDialog::getOpenFileNames(
            treeWidget(),
            "Import Objects...",
            m_settings.get_path_optional<QString>(LAST_DIRECTORY_SETTINGS_KEY),
            "Geometry Files (*.abc; *.binarymesh; *.obj);;All Files (*.*)",
            &selected_filter,
            options);

    if (filepaths.empty())
        return;

    const filesystem::path path(
        QDir::toNativeSeparators(filepaths.first()).toStdString());

    m_settings.insert_path(
        LAST_DIRECTORY_SETTINGS_KEY,
        path.parent_path().string());

    if (m_project_builder.get_rendering_manager().is_rendering())
        schedule_import_objects(filepaths);
    else import_objects(filepaths);

}

namespace
{
    class ImportObjectsDelayedAction
      : public RenderingManager::IDelayedAction
    {
      public:
        ImportObjectsDelayedAction(
            ObjectCollectionItem*   parent,
            const QStringList&      filepaths)
          : m_parent(parent)
          , m_filepaths(filepaths)
        {
        }

        virtual void operator()(
            MasterRenderer&         master_renderer,
            Project&                project) OVERRIDE
        {
            m_parent->import_objects(m_filepaths);
        }

      private:
        ObjectCollectionItem*       m_parent;
        const QStringList           m_filepaths;
    };
}

void ObjectCollectionItem::schedule_import_objects(const QStringList& filepaths)
{
    m_project_builder.get_rendering_manager().push_delayed_action(
        auto_ptr<RenderingManager::IDelayedAction>(
            new ImportObjectsDelayedAction(this, filepaths)));

    m_project_builder.get_rendering_manager().reinitialize_rendering();
}

void ObjectCollectionItem::import_objects(const QStringList& filepaths)
{
    for (int i = 0; i < filepaths.size(); ++i)
        insert_objects(QDir::toNativeSeparators(filepaths[i]).toStdString());
}

void ObjectCollectionItem::insert_objects(const string& path) const
{
    const string base_object_name =
        filesystem::path(path).replace_extension().filename().string();

    ParamArray params;
    params.insert("filename", path);

    SearchPaths search_paths;
    MeshObjectArray mesh_objects;

    if (!MeshObjectReader().read(
            search_paths,
            base_object_name.c_str(),
            params,
            mesh_objects))
        return;

    for (size_t i = 0; i < mesh_objects.size(); ++i)
    {
        MeshObject* object = mesh_objects[i];

        m_parent_item->add_item(object);

        m_parent.objects().insert(auto_release_ptr<Object>(object));

        const string object_instance_name = string(object->get_name()) + "_inst";

        auto_release_ptr<ObjectInstance> object_instance(
            ObjectInstanceFactory::create(
                object_instance_name.c_str(),
                ParamArray(),
                object->get_name(),
                Transformd::identity(),
                StringDictionary()));

        m_parent_item->add_item(object_instance.get());

        m_parent.object_instances().insert(object_instance);
    }

    if (!mesh_objects.empty())
    {
        m_parent.bump_version_id();
        m_project_builder.notify_project_modification();
    }
}

ItemBase* ObjectCollectionItem::create_item(Object* object)
{
    assert(object);

    ItemBase* item =
        new ObjectItem(
            object,
            m_parent,
            m_parent_item,
            m_project_builder);

    m_project_builder.get_item_registry().insert(object->get_uid(), item);

    return item;
}

}   // namespace studio
}   // namespace appleseed
<|endoftext|>


<commit_before>// ROS Libraries
#include <ros/ros.h>
#include <sensor_msgs/Joy.h>
#include <geometry_msgs/Twist.h>
// Standard Libraries
#include <stdlib.h>
#include <math.h>

double linear_x=0;
double angular_z=0;

// Defines
#define Joystick_Buttons_Left_Right msg->axes[4]
#define Joystick_Buttons_Up_Down msg->axes[5]
#define Joystick_AnalogLeft_Left_Right msg->axes[0]
#define Joystick_AnalogLeft_Up_Down msg->axes[1]

// Callback Functions
void Joy_Callback (const sensor_msgs::Joy::ConstPtr& msg)
{
/*    for (unsigned i = 0; i < msg->axes.size(); ++i) {
      ROS_INFO("Axis %d is now at position %f", i, msg->axes[i]);
    }
*/

    // Joystick Buttons pressed?
    if (Joystick_Buttons_Left_Right==1) {
        angular_z=Joystick_Buttons_Left_Right;
    }
    if (Joystick_Buttons_Left_Right==-1) {
        angular_z=Joystick_Buttons_Left_Right;
    }
    if (Joystick_Buttons_Up_Down==1) {
        linear_x=Joystick_Buttons_Up_Down;
    }
    if (Joystick_Buttons_Up_Down==-1) {
        linear_x=Joystick_Buttons_Up_Down;
    }
    if (Joystick_Buttons_Up_Down==0) {
        linear_x=Joystick_Buttons_Up_Down;
    }
    if (Joystick_Buttons_Left_Right==0) {
        angular_z=Joystick_Buttons_Up_Down;
    }

    // Joystick Analog pressed?
    if (Joystick_AnalogLeft_Left_Right>0) {
        angular_z=Joystick_AnalogLeft_Left_Right;
    }
    if (Joystick_AnalogLeft_Left_Right<0) {
        angular_z=Joystick_AnalogLeft_Left_Right;
    }
    if (Joystick_AnalogLeft_Up_Down>0) {
        linear_x=Joystick_AnalogLeft_Up_Down;
    }
    if (Joystick_AnalogLeft_Up_Down<0) {
        linear_x=Joystick_AnalogLeft_Up_Down;
    }
    if (Joystick_AnalogLeft_Up_Down==0) {
        linear_x=Joystick_AnalogLeft_Up_Down;
    }
    if (Joystick_AnalogLeft_Left_Right==0) {
        angular_z=Joystick_AnalogLeft_Left_Right;
    }

}

void onExit( void )
{
    // Run cleanup code here!
    ROS_INFO("joystick_driver: Exit node");
}

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

    atexit(onExit);

    ros::init(argc, argv, "joystick_driver");
  ros::NodeHandle n;
  ros::Subscriber sub = n.subscribe("joy", 100, Joy_Callback);
  ros::Publisher cmd_vel_pub = n.advertise<geometry_msgs::Twist>("/cmd_vel", 100);
  ros::Rate loop_rate(50);                                                  //Sets the loop to publish at a rate of 10Hz
  geometry_msgs::Twist cmd_vel_msg;                                         //Declares the message to be sent

  while (n.ok()){

      if ((cmd_vel_msg.linear.x != linear_x) || (cmd_vel_msg.angular.z != angular_z)){
          cmd_vel_msg.linear.x=linear_x;
          cmd_vel_msg.angular.z=angular_z;
          cmd_vel_pub.publish(cmd_vel_msg);
          ROS_INFO("linear.x = %f angular.z = %f",cmd_vel_msg.linear.x,cmd_vel_msg.angular.z);
      }

    ros::spinOnce();
    loop_rate.sleep();
  }//end.mainloop

  return 0;
}//end.main

<commit_msg>update joystick_driver<commit_after>// ROS Libraries
#include <ros/ros.h>
#include <sensor_msgs/Joy.h>
#include <geometry_msgs/Twist.h>
// Standard Libraries
#include <stdlib.h>
#include <math.h>

float linear_x_button=0;
float angular_z_button=0;
float linear_x_stick=0;
float angular_z_stick=0;

bool stick_up_down_pressed=false;
bool stick_left_right_pressed=false;
bool button_up_down_pressed=false;
bool button_left_right_pressed=false;

// Defines
#define Joystick_Stick_Left_Right msg->axes[4]
#define Joystick_Stick_Up_Down msg->axes[5]
#define Joystick_Button_Left_Right msg->axes[0]
#define Joystick_Button_Up_Down msg->axes[1]

// Callback Functions
void Joy_Callback (const sensor_msgs::Joy::ConstPtr& msg)
{
//  for (unsigned i = 0; i < msg->axes.size(); ++i) {
//      ROS_INFO("Axis %d is now at position %f", i, msg->axes[i]);
//  }

    // Test if joystick buttons are pressed?
    if (Joystick_Button_Left_Right>0) {
        angular_z_button=Joystick_Button_Left_Right;
        button_left_right_pressed=true;
    }
    if (Joystick_Button_Left_Right<0) {
        angular_z_button=Joystick_Button_Left_Right;
        button_left_right_pressed=true;
    }
    if (Joystick_Button_Up_Down>0) {
        linear_x_button=Joystick_Button_Up_Down/5;
        button_up_down_pressed=true;
    }
    if (Joystick_Button_Up_Down<0) {
        linear_x_button=Joystick_Button_Up_Down/5;
        button_up_down_pressed=true;
    }
    if (Joystick_Button_Up_Down==0) {
        linear_x_button=Joystick_Button_Up_Down;
        button_up_down_pressed=false;
    }
    if (Joystick_Button_Left_Right==0) {
        angular_z_button=Joystick_Button_Left_Right;
        button_left_right_pressed=false;
    }

    // Test if joystick stick is pressed?
    if (Joystick_Stick_Left_Right>0) {
        angular_z_stick=Joystick_Stick_Left_Right;
        stick_left_right_pressed=true;
    }
    if (Joystick_Stick_Left_Right<0) {
        angular_z_stick=Joystick_Stick_Left_Right;
        stick_left_right_pressed=true;
    }
    if (Joystick_Stick_Up_Down>0) {
        linear_x_stick=Joystick_Stick_Up_Down/5;
        stick_up_down_pressed=true;
    }
    if (Joystick_Stick_Up_Down<0) {
        linear_x_stick=Joystick_Stick_Up_Down/5;
        stick_up_down_pressed=true;
    }
    if (Joystick_Stick_Up_Down==0) {
        linear_x_stick=Joystick_Stick_Up_Down;
        stick_up_down_pressed=false;
    }
    if (Joystick_Stick_Left_Right==0) {
        angular_z_stick=Joystick_Stick_Left_Right;
        stick_left_right_pressed=false;
    }

}

void onExit( void )
{
    // Run cleanup code here!
    ROS_INFO("joystick_driver: Exit node");
}

int main(int argc, char **argv)
{
  atexit(onExit);
  ros::init(argc, argv, "joystick_driver");
  ros::NodeHandle n;
  ros::Subscriber sub = n.subscribe("joy", 100, Joy_Callback);
  ros::Publisher cmd_vel_pub = n.advertise<geometry_msgs::Twist>("/cmd_vel", 100);
  ros::Rate loop_rate(50);                                                  //Sets the loop to publish at a rate of 10Hz
  geometry_msgs::Twist cmd_vel_msg;                                         //Declares the message to be sent
  while (n.ok()){

    if ((stick_left_right_pressed==false) && (stick_up_down_pressed==false))
    {
        if ((cmd_vel_msg.linear.x != linear_x_button) || (cmd_vel_msg.angular.z != angular_z_button)){
          cmd_vel_msg.linear.x=linear_x_button;
          cmd_vel_msg.angular.z=angular_z_button;
          cmd_vel_pub.publish(cmd_vel_msg);
          ROS_INFO("linear.x = %f angular.z = %f",cmd_vel_msg.linear.x,cmd_vel_msg.angular.z);
        }
    }
    if ((button_left_right_pressed==false) && (button_up_down_pressed==false))
    {
        if ((cmd_vel_msg.linear.x != linear_x_stick) || (cmd_vel_msg.angular.z != angular_z_stick)){
          cmd_vel_msg.linear.x=linear_x_stick;
          cmd_vel_msg.angular.z=angular_z_stick;
          cmd_vel_pub.publish(cmd_vel_msg);
          ROS_INFO("linear.x = %f angular.z = %f",cmd_vel_msg.linear.x,cmd_vel_msg.angular.z);
        }
    }

    ros::spinOnce();
    loop_rate.sleep();
  }//end.mainloop
  return 0;
}//end.main

<|endoftext|>


<commit_before>#pragma once

// TODO: Move all constants into generic, hotreloadable constants file
#include "Graphics/RendererTypes.hpp" // For NUM_SHADOW_CASCADES

namespace flex
{
	class BaseCamera
	{
	public:
		BaseCamera(const std::string& cameraName, bool bIsGameplayCam, real FOV = glm::radians(45.0f),
			real zNear = 0.5f, real zFar = 350.0f);
		virtual ~BaseCamera();

		virtual void Initialize();
		virtual void Update();
		virtual void Destroy();

		virtual void OnSceneChanged();

		virtual void OnPossess();
		virtual void OnDepossess();

		virtual void DrawImGuiObjects();

		void SetFOV(real FOV);
		real GetFOV() const;
		void SetZNear(real zNear);
		real GetZNear() const;
		void SetZFar(real zFar);
		real GetZFar() const;
		glm::mat4 GetViewProjection() const;
		glm::mat4 GetView() const;
		glm::mat4 GetProjection() const;

		// speed: Lerp amount to new rotation
		void LookAt(glm::vec3 point, real speed = 1.0f);

		void Translate(glm::vec3 translation);
		void SetPosition(glm::vec3 position);
		glm::vec3 GetPosition() const;

		void SetViewDirection(real yawRad, real pitchRad);

		glm::vec3 GetRight() const;
		glm::vec3 GetUp() const;
		glm::vec3 GetForward() const;

		void ResetPosition();
		void ResetOrientation();

		void SetYaw(real rawRad);
		real GetYaw() const;
		void SetPitch(real pitchRad);
		real GetPitch() const;

		void SetMoveSpeed(real moveSpeed);
		real GetMoveSpeed() const;
		void SetRotationSpeed(real rotationSpeed);
		real GetRotationSpeed() const;

		std::string GetName() const;

		void CalculateExposure();

		// Exposure control
		real aperture = 1.0f; // f-stops
		real shutterSpeed = 1.0f / 8.0f; // seconds
		real lightSensitivity = 800.0f; // ISO
		real exposure = 0.0f;

		bool bIsGameplayCam;
		bool bDEBUGCyclable = true;

	protected:
		// Sets m_Right, m_Up, and m_Forward based on m_Yaw and m_Pitch
		void CalculateAxisVectorsFromPitchAndYaw();
		void CalculateYawAndPitchFromForward();
		void RecalculateViewProjection();

		void JitterMatrix(glm::mat4& matrix);
		void ClampPitch();

		// Exposure calculations taken from Google's Filament rendering engine
		// Computes the camera's EV100
		// aperture measured in f-stops
		// shutterSpeed measured in seconds
		// sensitivity measured in ISO
		static real CalculateEV100(real aperture, real shutterSpeed, real sensitivity);

		// Computes the exposure normalization factor from the camera's EV100
		static real ComputeExposureNormFactor(real EV100);

		bool m_bInitialized = false;

		std::string m_Name;

		glm::mat4 m_View;
		glm::mat4 m_Proj;
		glm::mat4 m_ViewProjection;

		real m_FOV = 0.0f;
		real m_ZNear = 0.0f;
		real m_ZFar = 0.0f;

		real m_MoveSpeed = 0.0f;				// WASD or gamepad left stick
		real m_PanSpeed = 0.0f;					// MMB
		real m_DragDollySpeed = 0.0f;			// RMB
		real m_ScrollDollySpeed = 0.0f;			// Scroll wheel
		real m_OrbitingSpeed = 0.0f;			// Alt-LMB drag
		real m_MouseRotationSpeed = 0.0f;		// LMB drag
		real m_GamepadRotationSpeed = 0.0f;		// Gamepad right stick
		real m_MoveSpeedFastMultiplier = 0.0f;
		real m_MoveSpeedSlowMultiplier = 0.0f;
		real m_TurnSpeedFastMultiplier = 0.0f;
		real m_TurnSpeedSlowMultiplier = 0.0f;
		real m_PanSpeedFastMultiplier = 0.0f;
		real m_PanSpeedSlowMultiplier = 0.0f;
		real m_RollRestorationSpeed = 0.0f;

		glm::vec3 m_Position;

		real m_Yaw;
		real m_Pitch;
		real m_Roll;
		glm::vec3 m_Forward;
		glm::vec3 m_Up;
		glm::vec3 m_Right;

		glm::mat4 m_ShadowProjectionMats[NUM_SHADOW_CASCADES];
	};
} // namespace flex
<commit_msg>Set better initial camera far plane value<commit_after>#pragma once

// TODO: Move all constants into generic, hotreloadable constants file
#include "Graphics/RendererTypes.hpp" // For NUM_SHADOW_CASCADES

namespace flex
{
	class BaseCamera
	{
	public:
		BaseCamera(const std::string& cameraName, bool bIsGameplayCam, real FOV = glm::radians(45.0f),
			real zNear = 0.5f, real zFar = 1000.0f);
		virtual ~BaseCamera();

		virtual void Initialize();
		virtual void Update();
		virtual void Destroy();

		virtual void OnSceneChanged();

		virtual void OnPossess();
		virtual void OnDepossess();

		virtual void DrawImGuiObjects();

		void SetFOV(real FOV);
		real GetFOV() const;
		void SetZNear(real zNear);
		real GetZNear() const;
		void SetZFar(real zFar);
		real GetZFar() const;
		glm::mat4 GetViewProjection() const;
		glm::mat4 GetView() const;
		glm::mat4 GetProjection() const;

		// speed: Lerp amount to new rotation
		void LookAt(glm::vec3 point, real speed = 1.0f);

		void Translate(glm::vec3 translation);
		void SetPosition(glm::vec3 position);
		glm::vec3 GetPosition() const;

		void SetViewDirection(real yawRad, real pitchRad);

		glm::vec3 GetRight() const;
		glm::vec3 GetUp() const;
		glm::vec3 GetForward() const;

		void ResetPosition();
		void ResetOrientation();

		void SetYaw(real rawRad);
		real GetYaw() const;
		void SetPitch(real pitchRad);
		real GetPitch() const;

		void SetMoveSpeed(real moveSpeed);
		real GetMoveSpeed() const;
		void SetRotationSpeed(real rotationSpeed);
		real GetRotationSpeed() const;

		std::string GetName() const;

		void CalculateExposure();

		// Exposure control
		real aperture = 1.0f; // f-stops
		real shutterSpeed = 1.0f / 8.0f; // seconds
		real lightSensitivity = 800.0f; // ISO
		real exposure = 0.0f;

		bool bIsGameplayCam;
		bool bDEBUGCyclable = true;

	protected:
		// Sets m_Right, m_Up, and m_Forward based on m_Yaw and m_Pitch
		void CalculateAxisVectorsFromPitchAndYaw();
		void CalculateYawAndPitchFromForward();
		void RecalculateViewProjection();

		void JitterMatrix(glm::mat4& matrix);
		void ClampPitch();

		// Exposure calculations taken from Google's Filament rendering engine
		// Computes the camera's EV100
		// aperture measured in f-stops
		// shutterSpeed measured in seconds
		// sensitivity measured in ISO
		static real CalculateEV100(real aperture, real shutterSpeed, real sensitivity);

		// Computes the exposure normalization factor from the camera's EV100
		static real ComputeExposureNormFactor(real EV100);

		bool m_bInitialized = false;

		std::string m_Name;

		glm::mat4 m_View;
		glm::mat4 m_Proj;
		glm::mat4 m_ViewProjection;

		real m_FOV = 0.0f;
		real m_ZNear = 0.0f;
		real m_ZFar = 0.0f;

		real m_MoveSpeed = 0.0f;				// WASD or gamepad left stick
		real m_PanSpeed = 0.0f;					// MMB
		real m_DragDollySpeed = 0.0f;			// RMB
		real m_ScrollDollySpeed = 0.0f;			// Scroll wheel
		real m_OrbitingSpeed = 0.0f;			// Alt-LMB drag
		real m_MouseRotationSpeed = 0.0f;		// LMB drag
		real m_GamepadRotationSpeed = 0.0f;		// Gamepad right stick
		real m_MoveSpeedFastMultiplier = 0.0f;
		real m_MoveSpeedSlowMultiplier = 0.0f;
		real m_TurnSpeedFastMultiplier = 0.0f;
		real m_TurnSpeedSlowMultiplier = 0.0f;
		real m_PanSpeedFastMultiplier = 0.0f;
		real m_PanSpeedSlowMultiplier = 0.0f;
		real m_RollRestorationSpeed = 0.0f;

		glm::vec3 m_Position;

		real m_Yaw;
		real m_Pitch;
		real m_Roll;
		glm::vec3 m_Forward;
		glm::vec3 m_Up;
		glm::vec3 m_Right;

		glm::mat4 m_ShadowProjectionMats[NUM_SHADOW_CASCADES];
	};
} // namespace flex
<|endoftext|>


<commit_before>// Copyright (c) 2010, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Helper program for the linux_dumper class, which creates a bunch of
// threads. The first word of each thread's stack is set to the thread
// id.

#include <pthread.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/syscall.h>
#include <unistd.h>

#include "third_party/lss/linux_syscall_support.h"

#if defined(__ARM_EABI__)
#define TID_PTR_REGISTER "r3"
#elif defined(__i386)
#define TID_PTR_REGISTER "ecx"
#elif defined(__x86_64)
#define TID_PTR_REGISTER "rcx"
#else
#error This test has not been ported to this platform.
#endif

void *thread_function(void *data) {
  volatile pid_t thread_id = syscall(__NR_gettid);
  register volatile pid_t *thread_id_ptr asm(TID_PTR_REGISTER) = &thread_id;
  while (true)
    asm volatile ("" : : "r" (thread_id_ptr));
  return NULL;
}

int main(int argc, char *argv[]) {
  if (argc < 2) {
    fprintf(stderr,
            "usage: linux_dumper_unittest_helper <pipe fd> <# of threads\n");
    return 1;
  }
  int pipefd = atoi(argv[1]);
  int num_threads = atoi(argv[2]);
  if (num_threads < 1) {
    fprintf(stderr, "ERROR: number of threads is 0");
    return 1;
  }
  pthread_t threads[num_threads];
  pthread_attr_t thread_attributes;
  pthread_attr_init(&thread_attributes);
  pthread_attr_setdetachstate(&thread_attributes, PTHREAD_CREATE_DETACHED);
  for (int i = 1; i < num_threads; i++) {
    pthread_create(&threads[i], &thread_attributes, &thread_function, NULL);
  }
  // Signal parent that this process has started all threads.
  uint8_t byte = 1;
  write(pipefd, &byte, sizeof(byte));
  thread_function(NULL);
  return 0;
}
<commit_msg>Fix several issues in linux_dumper_unittest_helper Patch by Chris Dearman <chris@mips.com> R=ted at http://breakpad.appspot.com/369001/<commit_after>// Copyright (c) 2010, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Helper program for the linux_dumper class, which creates a bunch of
// threads. The first word of each thread's stack is set to the thread
// id.

#include <pthread.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/syscall.h>
#include <unistd.h>

#include "third_party/lss/linux_syscall_support.h"

#if defined(__ARM_EABI__)
#define TID_PTR_REGISTER "r3"
#elif defined(__i386)
#define TID_PTR_REGISTER "ecx"
#elif defined(__x86_64)
#define TID_PTR_REGISTER "rcx"
#else
#error This test has not been ported to this platform.
#endif

void *thread_function(void *data) {
  volatile pid_t thread_id = syscall(__NR_gettid);
  register volatile pid_t *thread_id_ptr asm(TID_PTR_REGISTER) = &thread_id;
  while (true)
    asm volatile ("" : : "r" (thread_id_ptr));
  return NULL;
}

int main(int argc, char *argv[]) {
  if (argc < 3) {
    fprintf(stderr,
            "usage: linux_dumper_unittest_helper <pipe fd> <# of threads>\n");
    return 1;
  }
  int pipefd = atoi(argv[1]);
  int num_threads = atoi(argv[2]);
  if (num_threads < 1) {
    fprintf(stderr, "ERROR: number of threads is 0");
    return 1;
  }
  pthread_t threads[num_threads];
  pthread_attr_t thread_attributes;
  pthread_attr_init(&thread_attributes);
  pthread_attr_setdetachstate(&thread_attributes, PTHREAD_CREATE_DETACHED);
  for (int i = 1; i < num_threads; i++) {
    pthread_create(&threads[i], &thread_attributes, &thread_function, NULL);
  }
  // Signal parent that this process has started all threads.
  uint8_t byte = 1;
  if (write(pipefd, &byte, sizeof(byte)) != sizeof(byte)) {
    perror("ERROR: parent notification failed");
    return 1;
  }
  thread_function(NULL);
  return 0;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: appdata.cxx,v $
 *
 *  $Revision: 1.28 $
 *
 *  last change: $Author: obo $ $Date: 2008-01-04 15:09:12 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, 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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sfx2.hxx"
#ifndef _CACHESTR_HXX //autogen
#include <tools/cachestr.hxx>
#endif
#ifndef _CONFIG_HXX
#include <tools/config.hxx>
#endif
#ifndef _INETSTRM_HXX //autogen
#include <svtools/inetstrm.hxx>
#endif
#ifndef _SFXSTRITEM_HXX //autogen
#include <svtools/stritem.hxx>
#endif

#define _SVSTDARR_STRINGS
#include <svtools/svstdarr.hxx>
#include <vos/mutex.hxx>

#include <vcl/menu.hxx>

#ifndef _LOGINERR_HXX
#include <svtools/loginerr.hxx>
#endif
#ifndef _SV_MSGBOX_HXX
#include <vcl/msgbox.hxx>
#endif
#ifndef _DATETIMEITEM_HXX //autogen
#include <svtools/dateitem.hxx>
#endif
#ifndef _SV_MENU_HXX
#include <vcl/menu.hxx>
#endif
#ifndef _SV_WRKWIN_HXX
#include <vcl/wrkwin.hxx>
#endif
#include "comphelper/processfactory.hxx"

#include <sfx2/viewfrm.hxx>
#include "appdata.hxx"
#include <sfx2/dispatch.hxx>
#include <sfx2/event.hxx>
#include "sfxtypes.hxx"
#include <sfx2/doctempl.hxx>
#include "arrdecl.hxx"
#include <sfx2/docfac.hxx>
#include <sfx2/docfile.hxx>
#include <sfx2/request.hxx>
#include "referers.hxx"
#include "app.hrc"
#include "sfxresid.hxx"
#include "objshimp.hxx"
#include <sfx2/appuno.hxx>
#include "imestatuswindow.hxx"
#include "appbaslib.hxx"

#include <basic/basicmanagerrepository.hxx>
#include <basic/basmgr.hxx>

using ::basic::BasicManagerRepository;
using ::basic::BasicManagerCreationListener;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::frame::XModel;

class SfxBasicManagerCreationListener : public ::basic::BasicManagerCreationListener
{
private:
    SfxAppData_Impl& m_rAppData;

public:
    SfxBasicManagerCreationListener( SfxAppData_Impl& _rAppData ) :m_rAppData( _rAppData ) { }

    virtual void onBasicManagerCreated( const Reference< XModel >& _rxForDocument, BasicManager& _rBasicManager );
};

void SfxBasicManagerCreationListener::onBasicManagerCreated( const Reference< XModel >& _rxForDocument, BasicManager& _rBasicManager )
{
    if ( _rxForDocument == NULL )
        m_rAppData.OnApplicationBasicManagerCreated( _rBasicManager );
}

SfxAppData_Impl::SfxAppData_Impl( SfxApplication* pApp ) :
        pDdeService( 0 ),
        pDocTopics( 0 ),
        pTriggerTopic(0),
        pDdeService2(0),
        pFactArr(0),
        pTopFrames( new SfxFrameArr_Impl ),
        pInitLinkList(0),
        pMatcher( 0 ),
        pCancelMgr( 0 ),
        pLabelResMgr( 0 ),
        pAppDispatch(NULL),
        pTemplates( 0 ),
        pPool(0),
        pEventConfig(0),
        pDisabledSlotList( 0 ),
        pSecureURLs(0),
        pMiscConfig(0),
        pSaveOptions( 0 ),
        pUndoOptions( 0 ),
        pHelpOptions( 0 ),
        m_xThisDocument( ),
        pProgress(0),
        pTemplateCommon( 0 ),
        nDocModalMode(0),
        nAutoTabPageId(0),
        nBasicCallLevel(0),
        nRescheduleLocks(0),
        nInReschedule(0),
        nAsynchronCalls(0),
        m_xImeStatusWindow(new sfx2::appl::ImeStatusWindow(
                               *pApp, comphelper::getProcessServiceFactory()))
    , pTbxCtrlFac(0)
    , pStbCtrlFac(0)
    , pViewFrames(0)
    , pObjShells(0)
    , pSfxResManager(0)
    , pOfaResMgr(0)
    , pSimpleResManager(0)
    , pBasicManager( new SfxBasicManagerHolder )
    , pBasMgrListener( new SfxBasicManagerCreationListener( *this ) )
    , pViewFrame( 0 )
    , pSlotPool( 0 )
    , pResMgr( 0 )
    , pAppDispat( 0 )
    , pInterfaces( 0 )
    , nDocNo(0)
    , nInterfaces( 0 )
    , bDowning( sal_True )
    , bInQuit( sal_False )
    , bInvalidateOnUnlock( sal_False )
    , bODFVersionWarningLater( sal_False )

{
    BasicManagerRepository::registerCreationListener( *pBasMgrListener );
}

SfxAppData_Impl::~SfxAppData_Impl()
{
    DeInitDDE();
    delete pTopFrames;
    delete pCancelMgr;
    delete pSecureURLs;
    delete pBasicManager;

    BasicManagerRepository::revokeCreationListener( *pBasMgrListener );
    delete pBasMgrListener;
}

void SfxAppData_Impl::UpdateApplicationSettings( sal_Bool bDontHide )
{
    AllSettings aAllSet = Application::GetSettings();
    StyleSettings aStyleSet = aAllSet.GetStyleSettings();
    sal_uInt32 nStyleOptions = aStyleSet.GetOptions();
    if ( bDontHide )
        nStyleOptions &= ~STYLE_OPTION_HIDEDISABLED;
    else
        nStyleOptions |= STYLE_OPTION_HIDEDISABLED;
    aStyleSet.SetOptions( nStyleOptions );
    aAllSet.SetStyleSettings( aStyleSet );
    Application::SetSettings( aAllSet );
}

SfxDocumentTemplates* SfxAppData_Impl::GetDocumentTemplates()
{
    if ( !pTemplates )
        pTemplates = new SfxDocumentTemplates;
    else
        pTemplates->ReInitFromComponent();
    return pTemplates;
}

void SfxAppData_Impl::OnApplicationBasicManagerCreated( BasicManager& _rBasicManager )
{
    pBasicManager->reset( &_rBasicManager );

    // global constants, additionally to the ones already added by createApplicationBasicManager:
    // ThisComponent
    Reference< XModel > xCurrentDoc;
    SfxObjectShell* pDoc = SfxObjectShell::Current();
    if ( pDoc )
        xCurrentDoc = pDoc->GetModel();
    _rBasicManager.InsertGlobalUNOConstant( "ThisComponent", makeAny( xCurrentDoc ) );
    m_xThisDocument = xCurrentDoc;
}
<commit_msg>INTEGRATION: CWS odbmacros2 (1.27.2); FILE MERGED 2008/02/04 13:15:28 fs 1.27.2.4: RESYNC: (1.27-1.28); FILE MERGED 2007/12/19 14:51:24 fs 1.27.2.3: #i49133# BasicManager::Insert/set/ResetGlobalUNOConstant superseded by SetGlobalUNOConstant 2007/12/18 21:15:35 fs 1.27.2.2: #i49133# m_xThisDocument is superfluous, it is always the same as SfxObjectShell's WorkingDocument (which has just been renamed to CurrentComponent) 2007/12/12 14:42:09 fs 1.27.2.1: #i49133# use SfxObjectShell::GetWorkingDocument as ThisComponent, not SfxObjectShell::Current<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: appdata.cxx,v $
 *
 *  $Revision: 1.29 $
 *
 *  last change: $Author: kz $ $Date: 2008-03-06 19:49:18 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, 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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sfx2.hxx"
#ifndef _CACHESTR_HXX //autogen
#include <tools/cachestr.hxx>
#endif
#ifndef _CONFIG_HXX
#include <tools/config.hxx>
#endif
#ifndef _INETSTRM_HXX //autogen
#include <svtools/inetstrm.hxx>
#endif
#ifndef _SFXSTRITEM_HXX //autogen
#include <svtools/stritem.hxx>
#endif

#define _SVSTDARR_STRINGS
#include <svtools/svstdarr.hxx>
#include <vos/mutex.hxx>

#include <vcl/menu.hxx>

#ifndef _LOGINERR_HXX
#include <svtools/loginerr.hxx>
#endif
#ifndef _SV_MSGBOX_HXX
#include <vcl/msgbox.hxx>
#endif
#ifndef _DATETIMEITEM_HXX //autogen
#include <svtools/dateitem.hxx>
#endif
#ifndef _SV_MENU_HXX
#include <vcl/menu.hxx>
#endif
#ifndef _SV_WRKWIN_HXX
#include <vcl/wrkwin.hxx>
#endif
#include "comphelper/processfactory.hxx"

#include <sfx2/viewfrm.hxx>
#include "appdata.hxx"
#include <sfx2/dispatch.hxx>
#include <sfx2/event.hxx>
#include "sfxtypes.hxx"
#include <sfx2/doctempl.hxx>
#include "arrdecl.hxx"
#include <sfx2/docfac.hxx>
#include <sfx2/docfile.hxx>
#include <sfx2/request.hxx>
#include "referers.hxx"
#include "app.hrc"
#include "sfxresid.hxx"
#include "objshimp.hxx"
#include <sfx2/appuno.hxx>
#include "imestatuswindow.hxx"
#include "appbaslib.hxx"

#include <basic/basicmanagerrepository.hxx>
#include <basic/basmgr.hxx>

using ::basic::BasicManagerRepository;
using ::basic::BasicManagerCreationListener;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::frame::XModel;
using ::com::sun::star::uno::XInterface;

class SfxBasicManagerCreationListener : public ::basic::BasicManagerCreationListener
{
private:
    SfxAppData_Impl& m_rAppData;

public:
    SfxBasicManagerCreationListener( SfxAppData_Impl& _rAppData ) :m_rAppData( _rAppData ) { }

    virtual void onBasicManagerCreated( const Reference< XModel >& _rxForDocument, BasicManager& _rBasicManager );
};

void SfxBasicManagerCreationListener::onBasicManagerCreated( const Reference< XModel >& _rxForDocument, BasicManager& _rBasicManager )
{
    if ( _rxForDocument == NULL )
        m_rAppData.OnApplicationBasicManagerCreated( _rBasicManager );
}

SfxAppData_Impl::SfxAppData_Impl( SfxApplication* pApp ) :
        pDdeService( 0 ),
        pDocTopics( 0 ),
        pTriggerTopic(0),
        pDdeService2(0),
        pFactArr(0),
        pTopFrames( new SfxFrameArr_Impl ),
        pInitLinkList(0),
        pMatcher( 0 ),
        pCancelMgr( 0 ),
        pLabelResMgr( 0 ),
        pAppDispatch(NULL),
        pTemplates( 0 ),
        pPool(0),
        pEventConfig(0),
        pDisabledSlotList( 0 ),
        pSecureURLs(0),
        pMiscConfig(0),
        pSaveOptions( 0 ),
        pUndoOptions( 0 ),
        pHelpOptions( 0 ),
        pProgress(0),
        pTemplateCommon( 0 ),
        nDocModalMode(0),
        nAutoTabPageId(0),
        nBasicCallLevel(0),
        nRescheduleLocks(0),
        nInReschedule(0),
        nAsynchronCalls(0),
        m_xImeStatusWindow(new sfx2::appl::ImeStatusWindow(
                               *pApp, comphelper::getProcessServiceFactory()))
    , pTbxCtrlFac(0)
    , pStbCtrlFac(0)
    , pViewFrames(0)
    , pObjShells(0)
    , pSfxResManager(0)
    , pOfaResMgr(0)
    , pSimpleResManager(0)
    , pBasicManager( new SfxBasicManagerHolder )
    , pBasMgrListener( new SfxBasicManagerCreationListener( *this ) )
    , pViewFrame( 0 )
    , pSlotPool( 0 )
    , pResMgr( 0 )
    , pAppDispat( 0 )
    , pInterfaces( 0 )
    , nDocNo(0)
    , nInterfaces( 0 )
    , bDowning( sal_True )
    , bInQuit( sal_False )
    , bInvalidateOnUnlock( sal_False )
    , bODFVersionWarningLater( sal_False )

{
    BasicManagerRepository::registerCreationListener( *pBasMgrListener );
}

SfxAppData_Impl::~SfxAppData_Impl()
{
    DeInitDDE();
    delete pTopFrames;
    delete pCancelMgr;
    delete pSecureURLs;
    delete pBasicManager;

    BasicManagerRepository::revokeCreationListener( *pBasMgrListener );
    delete pBasMgrListener;
}

void SfxAppData_Impl::UpdateApplicationSettings( sal_Bool bDontHide )
{
    AllSettings aAllSet = Application::GetSettings();
    StyleSettings aStyleSet = aAllSet.GetStyleSettings();
    sal_uInt32 nStyleOptions = aStyleSet.GetOptions();
    if ( bDontHide )
        nStyleOptions &= ~STYLE_OPTION_HIDEDISABLED;
    else
        nStyleOptions |= STYLE_OPTION_HIDEDISABLED;
    aStyleSet.SetOptions( nStyleOptions );
    aAllSet.SetStyleSettings( aStyleSet );
    Application::SetSettings( aAllSet );
}

SfxDocumentTemplates* SfxAppData_Impl::GetDocumentTemplates()
{
    if ( !pTemplates )
        pTemplates = new SfxDocumentTemplates;
    else
        pTemplates->ReInitFromComponent();
    return pTemplates;
}

void SfxAppData_Impl::OnApplicationBasicManagerCreated( BasicManager& _rBasicManager )
{
    pBasicManager->reset( &_rBasicManager );

    // global constants, additionally to the ones already added by createApplicationBasicManager:
    // ThisComponent
    Reference< XInterface > xCurrentComponent = SfxObjectShell::GetCurrentComponent();
    _rBasicManager.SetGlobalUNOConstant( "ThisComponent", makeAny( xCurrentComponent ) );
}
<|endoftext|>


<commit_before>// Copyright 2014 The Chromium Authors. All rights reserved.
// Inspired by Chromium video capture interface
// Simplified and stripped from internal base code

#include "s3d/video/capture/video_capture_device_decklink.h"
#include "s3d/video/capture/decklink.h"

// inspiration: https://forum.blackmagicdesign.com/viewtopic.php?f=12&t=33269
// todo: should verify which pixel format we need (BGRA or RGBA)
// todo: should test int64_t instead of long
class RGB8VideoFrame : public IDeckLinkVideoFrame {
 public:
  static const int kNbBytesPixel = 4;
  static const BMDPixelFormat kPixelFormat = bmdFormat8BitBGRA;

  RGB8VideoFrame(int64_t width, int64_t height, BMDPixelFormat pixelFormat, BMDFrameFlags flags);

  // override these methods for virtual
  int64_t GetWidth() override;
  int64_t GetHeight() override;
  int64_t GetRowBytes() override;
  BMDPixelFormat GetPixelFormat() override;
  BMDFrameFlags GetFlags() override;
  HRESULT GetBytes(/* out */ void** buffer) override;

  void resize(int64_t width, int64_t height);

  // Dummy implementations of remaining virtual methods
  HRESULT GetTimecode(BMDTimecodeFormat /*format*/, IDeckLinkTimecode** /*timecode*/) override {
    return E_NOINTERFACE;
  }

  HRESULT GetAncillaryData(IDeckLinkVideoFrameAncillary** /*ancillary*/) override {
    return E_NOINTERFACE;
  }

  //
  // IUnknown interface (dummy implementation)
  //
  HRESULT QueryInterface(REFIID /*iid*/, LPVOID* /*ppv*/) override { return E_NOINTERFACE; }
  ULONG AddRef() override { return 1; }
  ULONG Release() override { return 1; }

 private:
  int64_t width_;
  int64_t height_;
  BMDPixelFormat pixelFormat_;
  BMDFrameFlags frameFlags_;
  std::vector<uint8_t> bufferPointer_;
};

RGB8VideoFrame::RGB8VideoFrame(int64_t width,
                               int64_t height,
                               BMDPixelFormat pixelFormat,
                               BMDFrameFlags flags)
    : width_{width}, height_{height}, pixelFormat_{pixelFormat}, frameFlags_{flags} {
  assert(pixelFormat == kPixelFormat);
  bufferPointer_.resize(static_cast<size_t>(width_ * kNbBytesPixel * height_));
}

int64_t RGB8VideoFrame::GetWidth() {
  return width_;
}

int64_t RGB8VideoFrame::GetHeight() {
  return height_;
}

int64_t RGB8VideoFrame::GetRowBytes() {
  return width_ * kNbBytesPixel;
}

BMDPixelFormat RGB8VideoFrame::GetPixelFormat() {
  return pixelFormat_;
}

BMDFrameFlags RGB8VideoFrame::GetFlags() {
  return frameFlags_;
}

HRESULT RGB8VideoFrame::GetBytes(/* out */ void** buffer) {
  *buffer = static_cast<void*>(&bufferPointer_[0]);
  return S_OK;
}

void RGB8VideoFrame::resize(int64_t width, int64_t height) {
  width_ = width;
  height_ = height;
  bufferPointer_.resize(static_cast<size_t>(width_ * height_ * kNbBytesPixel));
}

// todo: better consistency between DeckLink and decklink (camel case?)
class DecklinkCaptureDelegate : public IDeckLinkInputCallback {
 public:
  DecklinkCaptureDelegate(const VideoCaptureDeviceDescriptor& device_descriptor,
                          VideoCaptureDeviceDecklink* frameReceiver);

  ~DecklinkCaptureDelegate() override = default;

  void AllocateAndStart(const VideoCaptureFormat& params);
  void StopAndDeAllocate();

  const VideoCaptureDeviceDescriptor& getDeviceDescriptor() { return device_descriptor_; }

  static bool supportedFormat(const VideoCaptureFormat& format);

  void ResetVideoCaptureDeviceReference() { frameReceiver_ = nullptr; }

 private:
  // IDeckLinkInputCallback interface implementation.
  HRESULT VideoInputFormatChanged(BMDVideoInputFormatChangedEvents notification_events,
                                  IDeckLinkDisplayMode* new_display_mode,
                                  BMDDetectedVideoInputFormatFlags detected_signal_flags) override;
  HRESULT VideoInputFrameArrived(IDeckLinkVideoInputFrame* videoFrameLeft,
                                 IDeckLinkAudioInputPacket* audio_packet) override;

  ULONG STDMETHODCALLTYPE AddRef() override { return ++refCount_; }
  ULONG STDMETHODCALLTYPE Release() override { return --refCount_; }  // accepted memory leak
  HRESULT STDMETHODCALLTYPE QueryInterface(REFIID /*iid*/, LPVOID* /*ppv*/) override {
    return E_NOINTERFACE;
  }

  // Forwarder to VideoCaptureDeviceDeckLinkMac::SendErrorString().
  void SendErrorString(const std::string& reason);
  // Forwarder to VideoCaptureDeviceDeckLinkMac::SendLogString().
  void SendLogString(const std::string& message);

  const VideoCaptureDeviceDescriptor device_descriptor_;
  VideoCaptureFormat captureFormat_;

  // Weak reference to the captured frames client, used also for error messages
  // and logging. Initialized on construction and used until cleared by calling
  // ResetVideoCaptureDeviceReference().
  VideoCaptureDeviceDecklink* frameReceiver_;
  // This is used to control the video capturing device input interface.
  SmartDecklinkPtr<IDeckLinkInput> deckLinkInput_;
  // |decklink_| represents a physical device attached to the host.
  SmartDecklinkPtr<IDeckLink> deckLink_;

  SmartDecklinkPtr<IDeckLinkVideoConversion> videoConversion_;
  std::unique_ptr<RGB8VideoFrame> rgbFrameLeft_;
  std::unique_ptr<RGB8VideoFrame> rgbFrameRight_;

  size_t refCount_;

  std::chrono::high_resolution_clock::time_point firstRefTime_;
};

DecklinkCaptureDelegate::DecklinkCaptureDelegate(
    const VideoCaptureDeviceDescriptor& device_descriptor,
    VideoCaptureDeviceDecklink* frameReceiver)
    : device_descriptor_{device_descriptor},
      captureFormat_{{0, 0}, 0.0f, VideoPixelFormat::UNKNOWN},
      frameReceiver_{frameReceiver},
      rgbFrameLeft_{new RGB8VideoFrame(0, 0, RGB8VideoFrame::kPixelFormat, bmdFrameFlagDefault)},
      rgbFrameRight_{new RGB8VideoFrame(0, 0, RGB8VideoFrame::kPixelFormat, bmdFrameFlagDefault)} {}

void DecklinkCaptureDelegate::AllocateAndStart(const VideoCaptureFormat& params) {
  // Only 1920x1080, 30fps, BGRA, 2D or 3D supported
  // todo: is it BGRA or ARGB?
  if (!supportedFormat(params)) {
    // todo: this seems like another type of exception, or a bug?
    throw VideoCaptureDeviceAllocationException("Requested format not supported");
  }

  IDeckLinkIterator* deckLinkIterator = CreateDeckLinkIteratorInstance();
  if (deckLinkIterator == nullptr) {
    throw VideoCaptureDeviceAllocationException("Error creating DeckLink iterator");
  }

  IDeckLink* deckLink;
  if (deckLinkIterator->Next(&deckLink) != S_OK) {
    throw VideoCaptureDeviceAllocationException("No DeckLink device found");
  }

  auto deckLinkInput = make_decklink_ptr<IDeckLinkInput>(deckLink);
  deckLinkInput->SetCallback(this);

  // Check if display mode is supported
  BMDDisplayModeSupport displayModeSupported;

  // todo: set from capture format
  BMDDisplayMode displayMode = bmdModeHD1080p30;
  BMDPixelFormat pixelFormat = bmdFormat8BitYUV;
  BMDVideoInputFlags videoInputFlag =
      params.stereo3D ? bmdVideoInputDualStream3D : bmdVideoInputFlagDefault;

  HRESULT result = deckLinkInput->DoesSupportVideoMode(displayMode, pixelFormat, videoInputFlag,
                                                       &displayModeSupported, nullptr);
  if (result != S_OK) {
    throw VideoCaptureDeviceAllocationException("Display mode not supported");
  }

  // 3D settings for video capture
  if (params.stereo3D) {
    auto decklinkConfiguration = make_decklink_ptr<IDeckLinkConfiguration>(deckLink);
    if (decklinkConfiguration->SetFlag(bmdDeckLinkConfigSDIInput3DPayloadOverride, true) != S_OK) {
      throw VideoCaptureDeviceAllocationException("Cannot set 3D payload override flag");
    }
  }

  // create decklink conversion for YUV -> RGB
  videoConversion_.reset(CreateVideoConversionInstance());

  // Enable Video Input
  if (deckLinkInput->EnableVideoInput(displayMode, pixelFormat, videoInputFlag) != S_OK) {
    throw VideoCaptureDeviceAllocationException("Cannot enable video input");
  }

  // todo: now it's hardcoded to 1080p, 30fps, BGRA
  captureFormat_ = {params.frameSize, params.frameRate, params.pixelFormat, params.stereo3D};
  deckLink_.reset(deckLink);
  deckLinkInput_.swap(deckLinkInput);

  if (deckLinkInput_->StartStreams() != S_OK) {
    throw VideoCaptureDeviceAllocationException("Cannot start capture stream");
  }
}

HRESULT DecklinkCaptureDelegate::VideoInputFormatChanged(
    BMDVideoInputFormatChangedEvents /*notification_events*/,
    IDeckLinkDisplayMode* /*new_display_mode*/,
    BMDDetectedVideoInputFormatFlags /*detected_signal_flags*/) {
  return S_OK;
}

HRESULT DecklinkCaptureDelegate::VideoInputFrameArrived(
    IDeckLinkVideoInputFrame* videoFrameLeft,
    IDeckLinkAudioInputPacket* /*audio_packet*/) {
  if ((videoFrameLeft->GetFlags() & bmdFrameHasNoInputSource) != 0u) {  // todo: verify this != 0u
    SendErrorString("Left frame, no input signal");
    return S_FALSE;
  }

  void* raw_data_left = nullptr;
  void* raw_data_right = nullptr;

  uint8_t* video_data_left = nullptr;
  uint8_t* video_data_right = nullptr;

  // get left frame
  rgbFrameLeft_->resize(videoFrameLeft->GetWidth(), videoFrameLeft->GetHeight());

  videoConversion_->ConvertFrame(videoFrameLeft,
                                 static_cast<IDeckLinkVideoFrame*>(rgbFrameLeft_.get()));
  rgbFrameLeft_->GetBytes(&raw_data_left);
  video_data_left = static_cast<uint8_t*>(raw_data_left);

  if (captureFormat_.stereo3D) {
    auto threeDExtension = make_decklink_ptr<IDeckLinkVideoFrame3DExtensions>(videoFrameLeft);

    // get right frame
    IDeckLinkVideoFrame* rightEyeFrameRaw = nullptr;
    threeDExtension->GetFrameForRightEye(&rightEyeFrameRaw);
    SmartDecklinkPtr<IDeckLinkVideoFrame> videoFrameRight{rightEyeFrameRaw};

    if (videoFrameRight == nullptr) {
      // todo: this is another type of exception, should it be thrown?
      throw VideoCaptureDeviceAllocationException("No right frame detected");
    }

    rgbFrameRight_->resize(videoFrameRight->GetWidth(), videoFrameRight->GetHeight());
    videoConversion_->ConvertFrame(videoFrameRight.get(),
                                   static_cast<IDeckLinkVideoFrame*>(rgbFrameRight_.get()));
    rgbFrameRight_->GetBytes(&raw_data_right);
    video_data_right = static_cast<uint8_t*>(raw_data_right);
  }

  VideoPixelFormat pixelFormat = VideoPixelFormat::UNKNOWN;
  switch (rgbFrameLeft_->GetPixelFormat()) {
    case bmdFormat8BitYUV:  // A.k.a. '2vuy';
      pixelFormat = VideoPixelFormat::UYVY;
      break;
    case bmdFormat8BitBGRA:
      pixelFormat = VideoPixelFormat::ARGB;
      break;
    default:
      SendErrorString("Unsupported pixel format");
      break;
  }

  const VideoCaptureFormat capture_format(
      Size(rgbFrameLeft_->GetWidth(),
           rgbFrameLeft_->GetHeight()),  // todo: cast or something (int64_t-> int)
      0.0f,                              // Frame rate is not needed for captured data callback.
      pixelFormat,
      captureFormat_.stereo3D);

  if (frameReceiver_ != nullptr) {
    if (captureFormat_.stereo3D) {
      frameReceiver_->OnIncomingCapturedData(
          {{video_data_left, rgbFrameLeft_->GetRowBytes() * rgbFrameLeft_->GetHeight()},
           {video_data_right, rgbFrameRight_->GetRowBytes() * rgbFrameRight_->GetHeight()}},
          capture_format);
    } else {
      frameReceiver_->OnIncomingCapturedData(
          {{video_data_left, rgbFrameLeft_->GetRowBytes() * rgbFrameLeft_->GetHeight()}},
          capture_format);
    }
  }

  return S_OK;
}

void DecklinkCaptureDelegate::StopAndDeAllocate() {
  if (deckLinkInput_ == nullptr) {
    return;
  }
  if (deckLinkInput_->StopStreams() != S_OK) {
    SendLogString("Problem stopping capture.");
  }
  deckLinkInput_->SetCallback(nullptr);
  deckLinkInput_->DisableVideoInput();
  deckLinkInput_.reset(nullptr);
  deckLink_.reset(nullptr);
  ResetVideoCaptureDeviceReference();
}

// static
bool DecklinkCaptureDelegate::supportedFormat(const VideoCaptureFormat& format) {
  return format.frameSize == Size(1920, 1080) && format.frameRate == 30.0f &&
         format.pixelFormat == VideoPixelFormat::ARGB;
}

void DecklinkCaptureDelegate::SendErrorString(const std::string& reason) {
  if (frameReceiver_ != nullptr) {
    frameReceiver_->SendErrorString(reason);
  }
}

void DecklinkCaptureDelegate::SendLogString(const std::string& message) {
  if (frameReceiver_ != nullptr) {
    frameReceiver_->SendLogString(message);
  }
}

VideoCaptureDeviceDecklink::VideoCaptureDeviceDecklink(
    const VideoCaptureDeviceDescriptor& deviceDescriptor)
    : captureDelegate_{new DecklinkCaptureDelegate{deviceDescriptor, this}} {}

gsl::owner<VideoCaptureDevice*> VideoCaptureDeviceDecklink::clone() const {
  return new VideoCaptureDeviceDecklink(captureDelegate_->getDeviceDescriptor());
}

VideoCaptureDeviceDecklink::~VideoCaptureDeviceDecklink() {
  VideoCaptureDeviceDecklink::StopAndDeAllocate();
}

void VideoCaptureDeviceDecklink::AllocateAndStart(
    const VideoCaptureFormat& format,
    std::unique_ptr<VideoCaptureDevice::Client> client) {
  client_ = std::move(client);
  // todo: should verify that format is supported
  // todo: should get image size from capture delegate
  captureDelegate_->AllocateAndStart(format);
}

void VideoCaptureDeviceDecklink::StopAndDeAllocate() {
  captureDelegate_->StopAndDeAllocate();
}

void VideoCaptureDeviceDecklink::OnIncomingCapturedData(
    const VideoCaptureDevice::Client::Images& images,
    const VideoCaptureFormat& frameFormat) {
  if (client_ != nullptr) {
    client_->OnIncomingCapturedData(images, frameFormat);
  }
}
<commit_msg>Decklink capture device small changes (frameRate on callback = -1.0f)<commit_after>// Copyright 2014 The Chromium Authors. All rights reserved.
// Inspired by Chromium video capture interface
// Simplified and stripped from internal base code

#include "s3d/video/capture/video_capture_device_decklink.h"
#include "s3d/video/capture/decklink.h"

// inspiration: https://forum.blackmagicdesign.com/viewtopic.php?f=12&t=33269
// todo: should verify which pixel format we need (BGRA or RGBA)
// todo: should test int64_t instead of long
class RGB8VideoFrame : public IDeckLinkVideoFrame {
 public:
  static const int kNbBytesPixel = 4;
  static const BMDPixelFormat kPixelFormat = bmdFormat8BitBGRA;

  RGB8VideoFrame(int64_t width, int64_t height, BMDPixelFormat pixelFormat, BMDFrameFlags flags);

  // override these methods for virtual
  int64_t GetWidth() override;
  int64_t GetHeight() override;
  int64_t GetRowBytes() override;
  BMDPixelFormat GetPixelFormat() override;
  BMDFrameFlags GetFlags() override;
  HRESULT GetBytes(/* out */ void** buffer) override;

  void resize(int64_t width, int64_t height);

  // Dummy implementations of remaining virtual methods
  HRESULT GetTimecode(BMDTimecodeFormat /*format*/, IDeckLinkTimecode** /*timecode*/) override {
    return E_NOINTERFACE;
  }

  HRESULT GetAncillaryData(IDeckLinkVideoFrameAncillary** /*ancillary*/) override {
    return E_NOINTERFACE;
  }

  //
  // IUnknown interface (dummy implementation)
  //
  HRESULT QueryInterface(REFIID /*iid*/, LPVOID* /*ppv*/) override { return E_NOINTERFACE; }
  ULONG AddRef() override { return 1; }
  ULONG Release() override { return 1; }

 private:
  int64_t width_;
  int64_t height_;
  BMDPixelFormat pixelFormat_;
  BMDFrameFlags frameFlags_;
  std::vector<uint8_t> bufferPointer_;
};

RGB8VideoFrame::RGB8VideoFrame(int64_t width,
                               int64_t height,
                               BMDPixelFormat pixelFormat,
                               BMDFrameFlags flags)
    : width_{width}, height_{height}, pixelFormat_{pixelFormat}, frameFlags_{flags} {
  assert(pixelFormat == kPixelFormat);
  bufferPointer_.resize(static_cast<size_t>(width_ * kNbBytesPixel * height_));
}

int64_t RGB8VideoFrame::GetWidth() {
  return width_;
}

int64_t RGB8VideoFrame::GetHeight() {
  return height_;
}

int64_t RGB8VideoFrame::GetRowBytes() {
  return width_ * kNbBytesPixel;
}

BMDPixelFormat RGB8VideoFrame::GetPixelFormat() {
  return pixelFormat_;
}

BMDFrameFlags RGB8VideoFrame::GetFlags() {
  return frameFlags_;
}

HRESULT RGB8VideoFrame::GetBytes(/* out */ void** buffer) {
  *buffer = static_cast<void*>(&bufferPointer_[0]);
  return S_OK;
}

void RGB8VideoFrame::resize(int64_t width, int64_t height) {
  width_ = width;
  height_ = height;
  bufferPointer_.resize(static_cast<size_t>(width_ * height_ * kNbBytesPixel));
}

// todo: better consistency between DeckLink and decklink (camel case?)
class DecklinkCaptureDelegate : public IDeckLinkInputCallback {
 public:
  DecklinkCaptureDelegate(const VideoCaptureDeviceDescriptor& device_descriptor,
                          VideoCaptureDeviceDecklink* frameReceiver);

  ~DecklinkCaptureDelegate() override = default;

  void AllocateAndStart(const VideoCaptureFormat& params);
  void StopAndDeAllocate();

  const VideoCaptureDeviceDescriptor& getDeviceDescriptor() { return device_descriptor_; }

  static bool supportedFormat(const VideoCaptureFormat& format);

  void ResetVideoCaptureDeviceReference() { frameReceiver_ = nullptr; }

 private:
  // IDeckLinkInputCallback interface implementation.
  HRESULT VideoInputFormatChanged(BMDVideoInputFormatChangedEvents notification_events,
                                  IDeckLinkDisplayMode* new_display_mode,
                                  BMDDetectedVideoInputFormatFlags detected_signal_flags) override;
  HRESULT VideoInputFrameArrived(IDeckLinkVideoInputFrame* videoFrameLeft,
                                 IDeckLinkAudioInputPacket* audio_packet) override;

  ULONG STDMETHODCALLTYPE AddRef() override { return ++refCount_; }
  ULONG STDMETHODCALLTYPE Release() override { return --refCount_; }  // accepted memory leak
  HRESULT STDMETHODCALLTYPE QueryInterface(REFIID /*iid*/, LPVOID* /*ppv*/) override {
    return E_NOINTERFACE;
  }

  // Forwarder to VideoCaptureDeviceDeckLinkMac::SendErrorString().
  void SendErrorString(const std::string& reason);
  // Forwarder to VideoCaptureDeviceDeckLinkMac::SendLogString().
  void SendLogString(const std::string& message);

  const VideoCaptureDeviceDescriptor device_descriptor_;
  VideoCaptureFormat captureFormat_;

  // Weak reference to the captured frames client, used also for error messages
  // and logging. Initialized on construction and used until cleared by calling
  // ResetVideoCaptureDeviceReference().
  VideoCaptureDeviceDecklink* frameReceiver_;
  // This is used to control the video capturing device input interface.
  SmartDecklinkPtr<IDeckLinkInput> deckLinkInput_;
  // |decklink_| represents a physical device attached to the host.
  SmartDecklinkPtr<IDeckLink> deckLink_;

  SmartDecklinkPtr<IDeckLinkVideoConversion> videoConversion_;
  std::unique_ptr<RGB8VideoFrame> rgbFrameLeft_;
  std::unique_ptr<RGB8VideoFrame> rgbFrameRight_;

  size_t refCount_;

  std::chrono::high_resolution_clock::time_point firstRefTime_;
};

DecklinkCaptureDelegate::DecklinkCaptureDelegate(
    const VideoCaptureDeviceDescriptor& device_descriptor,
    VideoCaptureDeviceDecklink* frameReceiver)
    : device_descriptor_{device_descriptor},
      captureFormat_{{0, 0}, 0.0f, VideoPixelFormat::UNKNOWN},
      frameReceiver_{frameReceiver},
      rgbFrameLeft_{new RGB8VideoFrame(0, 0, RGB8VideoFrame::kPixelFormat, bmdFrameFlagDefault)},
      rgbFrameRight_{new RGB8VideoFrame(0, 0, RGB8VideoFrame::kPixelFormat, bmdFrameFlagDefault)} {}

void DecklinkCaptureDelegate::AllocateAndStart(const VideoCaptureFormat& params) {
  // Only 1920x1080, 30fps, BGRA, 2D or 3D supported
  // todo: is it BGRA or ARGB?
  if (!supportedFormat(params)) {
    // todo: this seems like another type of exception, or a bug?
    throw VideoCaptureDeviceAllocationException("Requested format not supported");
  }

  IDeckLinkIterator* deckLinkIterator = CreateDeckLinkIteratorInstance();
  if (deckLinkIterator == nullptr) {
    throw VideoCaptureDeviceAllocationException("Error creating DeckLink iterator");
  }

  IDeckLink* deckLink;
  if (deckLinkIterator->Next(&deckLink) != S_OK) {
    throw VideoCaptureDeviceAllocationException("No DeckLink device found");
  }

  auto deckLinkInput = make_decklink_ptr<IDeckLinkInput>(deckLink);
  deckLinkInput->SetCallback(this);

  // Check if display mode is supported
  BMDDisplayModeSupport displayModeSupported;

  // todo: set from capture format
  BMDDisplayMode displayMode = bmdModeHD1080p30;
  BMDPixelFormat pixelFormat = bmdFormat8BitYUV;
  BMDVideoInputFlags videoInputFlag =
      params.stereo3D ? bmdVideoInputDualStream3D : bmdVideoInputFlagDefault;

  HRESULT result = deckLinkInput->DoesSupportVideoMode(displayMode, pixelFormat, videoInputFlag,
                                                       &displayModeSupported, nullptr);
  if (result != S_OK) {
    throw VideoCaptureDeviceAllocationException("Display mode not supported");
  }

  // 3D settings for video capture
  if (params.stereo3D) {
    auto decklinkConfiguration = make_decklink_ptr<IDeckLinkConfiguration>(deckLink);
    if (decklinkConfiguration->SetFlag(bmdDeckLinkConfigSDIInput3DPayloadOverride, true) != S_OK) {
      throw VideoCaptureDeviceAllocationException("Cannot set 3D payload override flag");
    }
  }

  // create decklink conversion for YUV -> RGB
  videoConversion_.reset(CreateVideoConversionInstance());

  // Enable Video Input
  if (deckLinkInput->EnableVideoInput(displayMode, pixelFormat, videoInputFlag) != S_OK) {
    throw VideoCaptureDeviceAllocationException("Cannot enable video input");
  }

  // todo: now it's hardcoded to 1080p, 30fps, BGRA
  captureFormat_ = {params.frameSize, params.frameRate, params.pixelFormat, params.stereo3D};
  deckLink_.reset(deckLink);
  deckLinkInput_.swap(deckLinkInput);

  if (deckLinkInput_->StartStreams() != S_OK) {
    throw VideoCaptureDeviceAllocationException("Cannot start capture stream");
  }
}

HRESULT DecklinkCaptureDelegate::VideoInputFormatChanged(
    BMDVideoInputFormatChangedEvents /*notification_events*/,
    IDeckLinkDisplayMode* /*new_display_mode*/,
    BMDDetectedVideoInputFormatFlags /*detected_signal_flags*/) {
  return S_OK;
}

HRESULT DecklinkCaptureDelegate::VideoInputFrameArrived(
    IDeckLinkVideoInputFrame* videoFrameLeft,
    IDeckLinkAudioInputPacket* /*audio_packet*/) {
  if ((videoFrameLeft->GetFlags() & bmdFrameHasNoInputSource) != 0u) {
    SendErrorString("Left frame, no input signal");
    return S_FALSE;
  }

  void* raw_data_left = nullptr;
  void* raw_data_right = nullptr;

  uint8_t* video_data_left = nullptr;
  uint8_t* video_data_right = nullptr;

  // get left frame
  rgbFrameLeft_->resize(videoFrameLeft->GetWidth(), videoFrameLeft->GetHeight());

  videoConversion_->ConvertFrame(videoFrameLeft,
                                 static_cast<IDeckLinkVideoFrame*>(rgbFrameLeft_.get()));
  rgbFrameLeft_->GetBytes(&raw_data_left);
  video_data_left = static_cast<uint8_t*>(raw_data_left);

  if (captureFormat_.stereo3D) {
    auto threeDExtension = make_decklink_ptr<IDeckLinkVideoFrame3DExtensions>(videoFrameLeft);

    // get right frame
    IDeckLinkVideoFrame* rightEyeFrameRaw = nullptr;
    threeDExtension->GetFrameForRightEye(&rightEyeFrameRaw);
    SmartDecklinkPtr<IDeckLinkVideoFrame> videoFrameRight{rightEyeFrameRaw};

    if (videoFrameRight == nullptr) {
      // todo: this is another type of exception, should it be thrown?
      throw VideoCaptureDeviceAllocationException("No right frame detected");
    }

    rgbFrameRight_->resize(videoFrameRight->GetWidth(), videoFrameRight->GetHeight());
    videoConversion_->ConvertFrame(videoFrameRight.get(),
                                   static_cast<IDeckLinkVideoFrame*>(rgbFrameRight_.get()));
    rgbFrameRight_->GetBytes(&raw_data_right);
    video_data_right = static_cast<uint8_t*>(raw_data_right);
  }

  VideoPixelFormat pixelFormat = VideoPixelFormat::UNKNOWN;
  switch (rgbFrameLeft_->GetPixelFormat()) {
    case bmdFormat8BitYUV:  // A.k.a. '2vuy';
      pixelFormat = VideoPixelFormat::UYVY;
      break;
    case bmdFormat8BitBGRA:
      pixelFormat = VideoPixelFormat::ARGB;
      break;
    default:
      SendErrorString("Unsupported pixel format");
      break;
  }

  const VideoCaptureFormat capture_format(
      Size(rgbFrameLeft_->GetWidth(),
           rgbFrameLeft_->GetHeight()),  // todo: cast or something (int64_t-> int)
      -1.0f,                             // Frame rate is not needed for captured data callback.
      pixelFormat,
      captureFormat_.stereo3D);

  if (frameReceiver_ != nullptr) {
    if (captureFormat_.stereo3D) {
      frameReceiver_->OnIncomingCapturedData(
          {{video_data_left, rgbFrameLeft_->GetRowBytes() * rgbFrameLeft_->GetHeight()},
           {video_data_right, rgbFrameRight_->GetRowBytes() * rgbFrameRight_->GetHeight()}},
          capture_format);
    } else {
      frameReceiver_->OnIncomingCapturedData(
          {{video_data_left, rgbFrameLeft_->GetRowBytes() * rgbFrameLeft_->GetHeight()}},
          capture_format);
    }
  }

  return S_OK;
}

void DecklinkCaptureDelegate::StopAndDeAllocate() {
  if (deckLinkInput_ == nullptr) {
    return;
  }
  if (deckLinkInput_->StopStreams() != S_OK) {
    SendLogString("Problem stopping capture.");
  }
  deckLinkInput_->SetCallback(nullptr);
  deckLinkInput_->DisableVideoInput();
  deckLinkInput_.reset(nullptr);
  deckLink_.reset(nullptr);
  ResetVideoCaptureDeviceReference();
}

// static
bool DecklinkCaptureDelegate::supportedFormat(const VideoCaptureFormat& format) {
  return format.frameSize == Size(1920, 1080) && format.frameRate == 30.0f &&
         format.pixelFormat == VideoPixelFormat::ARGB;
}

void DecklinkCaptureDelegate::SendErrorString(const std::string& reason) {
  if (frameReceiver_ != nullptr) {
    frameReceiver_->SendErrorString(reason);
  }
}

void DecklinkCaptureDelegate::SendLogString(const std::string& message) {
  if (frameReceiver_ != nullptr) {
    frameReceiver_->SendLogString(message);
  }
}

VideoCaptureDeviceDecklink::VideoCaptureDeviceDecklink(
    const VideoCaptureDeviceDescriptor& deviceDescriptor)
    : captureDelegate_{new DecklinkCaptureDelegate{deviceDescriptor, this}} {}

gsl::owner<VideoCaptureDevice*> VideoCaptureDeviceDecklink::clone() const {
  return new VideoCaptureDeviceDecklink(captureDelegate_->getDeviceDescriptor());
}

VideoCaptureDeviceDecklink::~VideoCaptureDeviceDecklink() {
  VideoCaptureDeviceDecklink::StopAndDeAllocate();
}

void VideoCaptureDeviceDecklink::AllocateAndStart(
    const VideoCaptureFormat& format,
    std::unique_ptr<VideoCaptureDevice::Client> client) {
  client_ = std::move(client);
  // todo: should verify that format is supported
  // todo: should get image size from capture delegate
  captureDelegate_->AllocateAndStart(format);
}

void VideoCaptureDeviceDecklink::StopAndDeAllocate() {
  captureDelegate_->StopAndDeAllocate();
}

void VideoCaptureDeviceDecklink::OnIncomingCapturedData(
    const VideoCaptureDevice::Client::Images& images,
    const VideoCaptureFormat& frameFormat) {
  if (client_ != nullptr) {
    client_->OnIncomingCapturedData(images, frameFormat);
  }
}
<|endoftext|>