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

#include "modules/perception/obstacle/onboard/radar_process_subnode.h"

#include <string>
#include <unordered_map>
#include <algorithm>
#include "Eigen/Core"
#include "eigen_conversions/eigen_msg.h"
#include "pcl_conversions/pcl_conversions.h"
#include "ros/include/ros/ros.h"

#include "modules/common/adapters/adapter_manager.h"
#include "modules/common/log.h"
#include "modules/common/time/time_util.h"
#include "modules/common/time/timer.h"
#include "modules/perception/common/perception_gflags.h"
#include "modules/perception/lib/config_manager/calibration_config_manager.h"
#include "modules/perception/lib/config_manager/config_manager.h"
#include "modules/perception/obstacle/base/object.h"
#include "modules/perception/obstacle/radar/dummy/dummy_algorithms.h"
#include "modules/perception/onboard/subnode_helper.h"
#include "modules/perception/onboard/transform_input.h"

namespace apollo {
namespace perception {

using apollo::common::adapter::AdapterManager;
using pcl_util::Point;
using pcl_util::PointD;
using Eigen::Matrix4d;
using Eigen::Affine3d;
using std::string;
using std::unordered_map;

bool RadarProcessSubnode::InitInternal() {
  if (inited_) {
    return true;
  }

  RegistAllAlgorithm();

  if (!InitFrameDependence()) {
    AERROR << "failed to Init frame dependence.";
    return false;
  }

  if (!InitAlgorithmPlugin()) {
    AERROR << "failed to Init algorithm plugin.";
    return false;
  }
  // parse reserve fileds
  unordered_map<string, string> reserve_field_map;
  if (!SubnodeHelper::ParseReserveField(reserve_, &reserve_field_map)) {
    AERROR << "Failed to parse reserve filed: " << reserve_;
    return false;
  }

  if (reserve_field_map.find("device_id") == reserve_field_map.end()) {
    AERROR << "Failed to find field device_id, reserve: " << reserve_;
    return false;
  }
  device_id_ = reserve_field_map["device_id"];

  CHECK(AdapterManager::GetContiRadar()) << "Radar is not initialized.";
  AdapterManager::AddContiRadarCallback(&RadarProcessSubnode::OnRadar, this);
  CHECK(AdapterManager::GetLocalization()) << "Localiztion is not initialized.";
  AdapterManager::AddLocalizationCallback(&RadarProcessSubnode::OnLocalization,
                                          this);
  localization_buffer_.set_capacity(FLAGS_localization_buffer_size);
  std::string radar_extrinstic_path = FLAGS_radar_extrinsic_file;
  AINFO << "radar extrinsic path: " << radar_extrinstic_path;
  Eigen::Affine3d radar_extrinsic;
  if (!LoadExtrinsic(radar_extrinstic_path, &radar_extrinsic)) {
    AERROR << "Failed to load extrinsic.";
    return false;
  }
  radar_extrinsic_ = radar_extrinsic.matrix();
  AINFO << "get radar extrinsic succ. pose: \n" << radar_extrinsic_;

  std::string short_camera_extrinsic_path = FLAGS_short_camera_extrinsic_file;
  AINFO << "short camera extrinsic path: " << short_camera_extrinsic_path;
  Eigen::Affine3d short_camera_extrinsic;
  if (!LoadExtrinsic(short_camera_extrinsic_path, &short_camera_extrinsic)) {
    AERROR << "Failed to load extrinsic.";
    return false;
  }
  short_camera_extrinsic_ = short_camera_extrinsic.matrix();
  AINFO << "get short camera  extrinsic succ. pose: \n"
        << short_camera_extrinsic_;
  inited_ = true;

  return true;
}

void RadarProcessSubnode::OnRadar(const ContiRadar &radar_obs) {
  PERF_FUNCTION("RadarProcess");
  ContiRadar radar_obs_proto = radar_obs;
  double timestamp = radar_obs_proto.header().timestamp_sec();
  double unix_timestamp = timestamp;
  const double cur_time = common::time::Clock::NowInSeconds();
  const double start_latency = (cur_time - unix_timestamp) * 1e3;
  AINFO << "FRAME_STATISTICS:Radar:Start:msg_time[" << GLOG_TIMESTAMP(timestamp)
        << "]:cur_time[" << GLOG_TIMESTAMP(cur_time) << "]:cur_latency["
        << start_latency << "]";
  // 0. correct radar timestamp
  timestamp -= 0.07;
  auto *header = radar_obs_proto.mutable_header();
  header->set_timestamp_sec(timestamp);
  header->set_radar_timestamp(timestamp * 1e9);

  conti_id_expansion_.UpdateTimestamp(timestamp);
  conti_id_expansion_.ExpandIds(&radar_obs_proto);

  if (fabs(timestamp - 0.0) < 10e-6) {
    AERROR << "Error timestamp: " << GLOG_TIMESTAMP(timestamp);
    return;
  }
  ADEBUG << "recv radar msg: [timestamp: " << GLOG_TIMESTAMP(timestamp)
         << " num_raw_obstacles: " << radar_obs_proto.contiobs_size() << "]";

  // 1. get radar pose
  std::shared_ptr<Matrix4d> velodyne2world_pose = std::make_shared<Matrix4d>();

  ADEBUG << "use navigation mode " << FLAGS_use_navigation_mode;

  if (!GetVelodyneTrans(timestamp, velodyne2world_pose.get()) &&
      !FLAGS_use_navigation_mode) {
    AERROR << "Failed to get trans at timestamp: " << GLOG_TIMESTAMP(timestamp);
    error_code_ = common::PERCEPTION_ERROR_TF;
    return;
  }
  std::shared_ptr<Matrix4d> radar2world_pose = std::make_shared<Matrix4d>();
  std::shared_ptr<Matrix4d> radar2car_pose = std::make_shared<Matrix4d>();

  if (!FLAGS_use_navigation_mode) {
    *radar2world_pose =
        *velodyne2world_pose * short_camera_extrinsic_ * radar_extrinsic_;
    AINFO << "get radar trans pose succ. pose: \n" << *radar2world_pose;

  } else {
    CalibrationConfigManager *config_manager =
        Singleton<CalibrationConfigManager>::get();
    CameraCalibrationPtr calibrator = config_manager->get_camera_calibration();
    Eigen::Matrix4d camera_to_car = calibrator->get_camera_extrinsics();
    *radar2car_pose = radar_extrinsic_;
    AINFO << "get radar trans pose succ. pose: \n" << *radar2car_pose;
  }

  std::vector<PolygonDType> map_polygons;
  RadarDetectorOptions options;
  // Current Localiztion, radar postion.
  if (!FLAGS_use_navigation_mode) {
    PointD position;
    position.x = (*radar2world_pose)(0, 3);
    position.y = (*radar2world_pose)(1, 3);
    position.z = (*radar2world_pose)(2, 3);
    // 2. Get map polygons.
    HdmapStructPtr hdmap(new HdmapStruct);
    if (FLAGS_enable_hdmap_input && hdmap_input_ &&
        !hdmap_input_->GetROI(position, FLAGS_front_radar_forward_distance,
                              &hdmap)) {
      AWARN << "Failed to get roi. timestamp: " << GLOG_TIMESTAMP(timestamp)
            << " position: [" << position.x << ", " << position.y << ", "
            << position.z << "]";
      // NOTE: if call hdmap failed, using empty map_polygons.
    }

    if (roi_filter_ != nullptr) {
      roi_filter_->MergeHdmapStructToPolygons(hdmap, &map_polygons);
    }
  }

  // 3. get car car_linear_speed
  if (!GetCarLinearSpeed(timestamp, &(options.car_linear_speed))) {
    AERROR << "Failed to call get_car_linear_speed. [timestamp: "
           << GLOG_TIMESTAMP(timestamp);
    return;
  }

  // 4. Call RadarDetector::detect.
  PERF_BLOCK_START();
  if (!FLAGS_use_navigation_mode) {
    options.radar2world_pose = &(*radar2world_pose);
  } else {
    options.radar2world_pose = &(*radar2car_pose);
  }
  std::shared_ptr<SensorObjects> radar_objects(new SensorObjects);
  radar_objects->timestamp = timestamp;
  radar_objects->sensor_type = SensorType::RADAR;
  radar_objects->sensor2world_pose = *radar2world_pose;
  bool result = radar_detector_->Detect(radar_obs_proto, map_polygons, options,
                                        &radar_objects->objects);
  if (!result) {
    radar_objects->error_code = common::PERCEPTION_ERROR_PROCESS;
    PublishDataAndEvent(timestamp, radar_objects);
    AERROR << "Failed to call RadarDetector. [timestamp: "
           << GLOG_TIMESTAMP(timestamp)
           << ", map_polygons_size: " << map_polygons.size()
           << ", num_raw_conti_obstacles: " << radar_obs_proto.contiobs_size()
           << "]";
    return;
  }
  PERF_BLOCK_END("radar_detect");
  PublishDataAndEvent(timestamp, radar_objects);

  const double end_timestamp = common::time::Clock::NowInSeconds();
  const double end_latency = (end_timestamp - unix_timestamp) * 1e3;
  AINFO << "FRAME_STATISTICS:Radar:End:msg_time[" << GLOG_TIMESTAMP(timestamp)
        << "]:cur_time[" << GLOG_TIMESTAMP(end_timestamp) << "]:cur_latency["
        << end_latency << "]";
  ADEBUG << "radar process succ, there are " << (radar_objects->objects).size()
         << " objects.";
  return;
}

void RadarProcessSubnode::OnLocalization(
    const apollo::localization::LocalizationEstimate &localization) {
  double timestamp = localization.header().timestamp_sec();
  AINFO << "localization timestamp:" << GLOG_TIMESTAMP(timestamp);
  LocalizationPair localization_pair;
  localization_pair.first = timestamp;
  localization_pair.second = localization;
  localization_buffer_.push_back(localization_pair);
}

bool RadarProcessSubnode::GetCarLinearSpeed(double timestamp,
                                            Eigen::Vector3f *car_linear_speed) {
  MutexLock lock(&mutex_);
  if (car_linear_speed == nullptr) {
    AERROR << "Param car_linear_speed nullptr error.";
    return false;
  }
  if (localization_buffer_.empty()) {
    AWARN << "Rosmsg buffer is empty.";
    return false;
  }
  if (localization_buffer_.front().first - 0.1 > timestamp) {
    AWARN << "Timestamp (" << GLOG_TIMESTAMP(timestamp)
          << ") is earlier than the oldest "
          << "timestamp (" << localization_buffer_.front().first << ").";
    return false;
  }
  if (localization_buffer_.back().first + 0.1 < timestamp) {
    AWARN << "Timestamp (" << GLOG_TIMESTAMP(timestamp)
          << ") is newer than the latest "
          << "timestamp (" << localization_buffer_.back().first << ").";
    return false;
  }
  // loop to find nearest
  double distance = 1e9;
  int idx = localization_buffer_.size() - 1;
  for (; idx >= 0; --idx) {
    double temp_distance = fabs(timestamp - localization_buffer_[idx].first);
    if (temp_distance >= distance) {
      break;
    }
    distance = temp_distance;
  }

  idx = std::max(0, idx);
  auto velocity =
          localization_buffer_[idx].second.pose().linear_velocity();
  (*car_linear_speed)[0] = velocity.x();
  (*car_linear_speed)[1] = velocity.y();
  (*car_linear_speed)[2] = velocity.z();
  return true;
}

void RadarProcessSubnode::RegistAllAlgorithm() {
  RegisterFactoryDummyRadarDetector();
  RegisterFactoryModestRadarDetector();
}

bool RadarProcessSubnode::InitFrameDependence() {
  /// init share data
  CHECK(shared_data_manager_ != nullptr) << "shared_data_manager_ is nullptr";
  // init preprocess_data
  const string radar_data_name("RadarObjectData");
  radar_data_ = dynamic_cast<RadarObjectData *>(
      shared_data_manager_->GetSharedData(radar_data_name));
  if (radar_data_ == nullptr) {
    AERROR << "Failed to get shared data instance " << radar_data_name;
    return false;
  }
  AINFO << "Init shared data successfully, data: " << radar_data_->name();

  /// init hdmap
  if (FLAGS_enable_hdmap_input) {
    hdmap_input_ = HDMapInput::instance();
    if (!hdmap_input_) {
      AERROR << "Failed to get HDMapInput instance.";
      return false;
    }
    if (!hdmap_input_->Init()) {
      AERROR << "Failed to Init HDMapInput";
      return false;
    }
    AINFO << "Get and Init hdmap_input succ.";
  }

  return true;
}

bool RadarProcessSubnode::InitAlgorithmPlugin() {
  /// init roi filter
  roi_filter_.reset(new HdmapROIFilter());
  if (!roi_filter_->Init()) {
    AERROR << "Failed to Init roi filter: " << roi_filter_->name();
    return false;
  }
  AINFO << "Init algorithm plugin successfully, roi_filter_: "
        << roi_filter_->name();

  /// init radar detector
  radar_detector_.reset(BaseRadarDetectorRegisterer::GetInstanceByName(
      FLAGS_onboard_radar_detector));
  if (!radar_detector_) {
    AERROR << "Failed to get instance: " << FLAGS_onboard_radar_detector;
    return false;
  }
  if (!radar_detector_->Init()) {
    AERROR << "Failed to Init radar detector: " << radar_detector_->name();
    return false;
  }
  AINFO << "Init algorithm plugin successfully, radar detecor: "
        << radar_detector_->name();
  return true;
}

void RadarProcessSubnode::PublishDataAndEvent(
    double timestamp, const SharedDataPtr<SensorObjects> &data) {
  // set shared data
  std::string key;
  if (!SubnodeHelper::ProduceSharedDataKey(timestamp, device_id_, &key)) {
    AERROR << "Failed to produce shared key. time: "
           << GLOG_TIMESTAMP(timestamp) << ", device_id: " << device_id_;
    return;
  }

  radar_data_->Add(key, data);
  // pub events
  for (size_t idx = 0; idx < pub_meta_events_.size(); ++idx) {
    const EventMeta &event_meta = pub_meta_events_[idx];
    Event event;
    event.event_id = event_meta.event_id;
    event.timestamp = timestamp;
    event.reserve = device_id_;
    event_manager_->Publish(event);
  }
}

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

#include "modules/perception/obstacle/onboard/radar_process_subnode.h"

#include <algorithm>
#include <string>
#include <unordered_map>
#include "Eigen/Core"
#include "eigen_conversions/eigen_msg.h"
#include "pcl_conversions/pcl_conversions.h"
#include "ros/include/ros/ros.h"

#include "modules/common/adapters/adapter_manager.h"
#include "modules/common/log.h"
#include "modules/common/time/time_util.h"
#include "modules/common/time/timer.h"
#include "modules/perception/common/perception_gflags.h"
#include "modules/perception/lib/config_manager/calibration_config_manager.h"
#include "modules/perception/lib/config_manager/config_manager.h"
#include "modules/perception/obstacle/base/object.h"
#include "modules/perception/obstacle/radar/dummy/dummy_algorithms.h"
#include "modules/perception/onboard/subnode_helper.h"
#include "modules/perception/onboard/transform_input.h"

namespace apollo {
namespace perception {

using Eigen::Affine3d;
using Eigen::Matrix4d;
using apollo::common::adapter::AdapterManager;
using pcl_util::Point;
using pcl_util::PointD;
using std::string;
using std::unordered_map;

bool RadarProcessSubnode::InitInternal() {
  if (inited_) {
    return true;
  }

  RegistAllAlgorithm();

  if (!InitFrameDependence()) {
    AERROR << "failed to Init frame dependence.";
    return false;
  }

  if (!InitAlgorithmPlugin()) {
    AERROR << "failed to Init algorithm plugin.";
    return false;
  }
  // parse reserve fileds
  unordered_map<string, string> reserve_field_map;
  if (!SubnodeHelper::ParseReserveField(reserve_, &reserve_field_map)) {
    AERROR << "Failed to parse reserve filed: " << reserve_;
    return false;
  }

  if (reserve_field_map.find("device_id") == reserve_field_map.end()) {
    AERROR << "Failed to find field device_id, reserve: " << reserve_;
    return false;
  }
  device_id_ = reserve_field_map["device_id"];

  CHECK(AdapterManager::GetContiRadar()) << "Radar is not initialized.";
  AdapterManager::AddContiRadarCallback(&RadarProcessSubnode::OnRadar, this);
  CHECK(AdapterManager::GetLocalization()) << "Localiztion is not initialized.";
  AdapterManager::AddLocalizationCallback(&RadarProcessSubnode::OnLocalization,
                                          this);
  localization_buffer_.set_capacity(FLAGS_localization_buffer_size);
  std::string radar_extrinstic_path = FLAGS_radar_extrinsic_file;
  AINFO << "radar extrinsic path: " << radar_extrinstic_path;
  Eigen::Affine3d radar_extrinsic;
  if (!LoadExtrinsic(radar_extrinstic_path, &radar_extrinsic)) {
    AERROR << "Failed to load extrinsic.";
    return false;
  }
  radar_extrinsic_ = radar_extrinsic.matrix();
  AINFO << "get radar extrinsic succ. pose: \n" << radar_extrinsic_;

  std::string short_camera_extrinsic_path = FLAGS_short_camera_extrinsic_file;
  AINFO << "short camera extrinsic path: " << short_camera_extrinsic_path;
  Eigen::Affine3d short_camera_extrinsic;
  if (!LoadExtrinsic(short_camera_extrinsic_path, &short_camera_extrinsic)) {
    AERROR << "Failed to load extrinsic.";
    return false;
  }
  short_camera_extrinsic_ = short_camera_extrinsic.matrix();
  AINFO << "get short camera  extrinsic succ. pose: \n"
        << short_camera_extrinsic_;
  inited_ = true;

  return true;
}

void RadarProcessSubnode::OnRadar(const ContiRadar &radar_obs) {
  PERF_FUNCTION("RadarProcess");
  ContiRadar radar_obs_proto = radar_obs;
  double timestamp = radar_obs_proto.header().timestamp_sec();
  double unix_timestamp = timestamp;
  const double cur_time = common::time::Clock::NowInSeconds();
  const double start_latency = (cur_time - unix_timestamp) * 1e3;
  ADEBUG << "FRAME_STATISTICS: Radar:Start:msg_time["
         << GLOG_TIMESTAMP(timestamp) << "]:cur_time["
         << GLOG_TIMESTAMP(cur_time) << "]:cur_latency[" << start_latency
         << "]";
  // 0. correct radar timestamp
  timestamp -= 0.07;
  auto *header = radar_obs_proto.mutable_header();
  header->set_timestamp_sec(timestamp);
  header->set_radar_timestamp(timestamp * 1e9);

  conti_id_expansion_.UpdateTimestamp(timestamp);
  conti_id_expansion_.ExpandIds(&radar_obs_proto);

  if (fabs(timestamp - 0.0) < 10e-6) {
    AERROR << "Error timestamp: " << GLOG_TIMESTAMP(timestamp);
    return;
  }
  ADEBUG << "recv radar msg: [timestamp: " << GLOG_TIMESTAMP(timestamp)
         << " num_raw_obstacles: " << radar_obs_proto.contiobs_size() << "]";

  // 1. get radar pose
  std::shared_ptr<Matrix4d> velodyne2world_pose = std::make_shared<Matrix4d>();

  ADEBUG << "use navigation mode " << FLAGS_use_navigation_mode;

  if (!GetVelodyneTrans(timestamp, velodyne2world_pose.get()) &&
      !FLAGS_use_navigation_mode) {
    AERROR << "Failed to get trans at timestamp: " << GLOG_TIMESTAMP(timestamp);
    error_code_ = common::PERCEPTION_ERROR_TF;
    return;
  }
  std::shared_ptr<Matrix4d> radar2world_pose = std::make_shared<Matrix4d>();
  std::shared_ptr<Matrix4d> radar2car_pose = std::make_shared<Matrix4d>();

  if (!FLAGS_use_navigation_mode) {
    *radar2world_pose =
        *velodyne2world_pose * short_camera_extrinsic_ * radar_extrinsic_;
    ADEBUG << "get radar trans pose succ. pose: \n" << *radar2world_pose;

  } else {
    CalibrationConfigManager *config_manager =
        Singleton<CalibrationConfigManager>::get();
    CameraCalibrationPtr calibrator = config_manager->get_camera_calibration();
    // Eigen::Matrix4d camera_to_car = calibrator->get_camera_extrinsics();
    *radar2car_pose = radar_extrinsic_;
    ADEBUG << "get radar trans pose succ. pose: \n" << *radar2car_pose;
  }

  std::vector<PolygonDType> map_polygons;
  RadarDetectorOptions options;
  // Current Localiztion, radar postion.
  if (!FLAGS_use_navigation_mode) {
    PointD position;
    position.x = (*radar2world_pose)(0, 3);
    position.y = (*radar2world_pose)(1, 3);
    position.z = (*radar2world_pose)(2, 3);
    // 2. Get map polygons.
    HdmapStructPtr hdmap(new HdmapStruct);
    if (FLAGS_enable_hdmap_input && hdmap_input_ &&
        !hdmap_input_->GetROI(position, FLAGS_front_radar_forward_distance,
                              &hdmap)) {
      AWARN << "Failed to get roi. timestamp: " << GLOG_TIMESTAMP(timestamp)
            << " position: [" << position.x << ", " << position.y << ", "
            << position.z << "]";
      // NOTE: if call hdmap failed, using empty map_polygons.
    }

    if (roi_filter_ != nullptr) {
      roi_filter_->MergeHdmapStructToPolygons(hdmap, &map_polygons);
    }
  }

  // 3. get car car_linear_speed
  if (!GetCarLinearSpeed(timestamp, &(options.car_linear_speed))) {
    AERROR << "Failed to call get_car_linear_speed. [timestamp: "
           << GLOG_TIMESTAMP(timestamp);
    return;
  }

  // 4. Call RadarDetector::detect.
  PERF_BLOCK_START();
  if (!FLAGS_use_navigation_mode) {
    options.radar2world_pose = &(*radar2world_pose);
  } else {
    options.radar2world_pose = &(*radar2car_pose);
  }
  std::shared_ptr<SensorObjects> radar_objects(new SensorObjects);
  radar_objects->timestamp = timestamp;
  radar_objects->sensor_type = SensorType::RADAR;
  radar_objects->sensor2world_pose = *radar2world_pose;
  bool result = radar_detector_->Detect(radar_obs_proto, map_polygons, options,
                                        &radar_objects->objects);
  if (!result) {
    radar_objects->error_code = common::PERCEPTION_ERROR_PROCESS;
    PublishDataAndEvent(timestamp, radar_objects);
    AERROR << "Failed to call RadarDetector. [timestamp: "
           << GLOG_TIMESTAMP(timestamp)
           << ", map_polygons_size: " << map_polygons.size()
           << ", num_raw_conti_obstacles: " << radar_obs_proto.contiobs_size()
           << "]";
    return;
  }
  PERF_BLOCK_END("radar_detect");
  PublishDataAndEvent(timestamp, radar_objects);

  const double end_timestamp = common::time::Clock::NowInSeconds();
  const double end_latency = (end_timestamp - unix_timestamp) * 1e3;
  ADEBUG << "FRAME_STATISTICS:Radar: End:msg_time[" << GLOG_TIMESTAMP(timestamp)
         << "]:cur_time[" << GLOG_TIMESTAMP(end_timestamp) << "]:cur_latency["
         << end_latency << "]";
  ADEBUG << "radar process succ, there are " << (radar_objects->objects).size()
         << " objects.";
  return;
}

void RadarProcessSubnode::OnLocalization(
    const apollo::localization::LocalizationEstimate &localization) {
  double timestamp = localization.header().timestamp_sec();
  AINFO << "localization timestamp:" << GLOG_TIMESTAMP(timestamp);
  LocalizationPair localization_pair;
  localization_pair.first = timestamp;
  localization_pair.second = localization;
  localization_buffer_.push_back(localization_pair);
}

bool RadarProcessSubnode::GetCarLinearSpeed(double timestamp,
                                            Eigen::Vector3f *car_linear_speed) {
  MutexLock lock(&mutex_);
  if (car_linear_speed == nullptr) {
    AERROR << "Param car_linear_speed nullptr error.";
    return false;
  }
  if (localization_buffer_.empty()) {
    AWARN << "Rosmsg buffer is empty.";
    return false;
  }
  if (localization_buffer_.front().first - 0.1 > timestamp) {
    AWARN << "Timestamp (" << GLOG_TIMESTAMP(timestamp)
          << ") is earlier than the oldest "
          << "timestamp (" << localization_buffer_.front().first << ").";
    return false;
  }
  if (localization_buffer_.back().first + 0.1 < timestamp) {
    AWARN << "Timestamp (" << GLOG_TIMESTAMP(timestamp)
          << ") is newer than the latest "
          << "timestamp (" << localization_buffer_.back().first << ").";
    return false;
  }
  // loop to find nearest
  double distance = 1e9;
  int idx = localization_buffer_.size() - 1;
  for (; idx >= 0; --idx) {
    double temp_distance = fabs(timestamp - localization_buffer_[idx].first);
    if (temp_distance >= distance) {
      break;
    }
    distance = temp_distance;
  }

  idx = std::max(0, idx);
  auto velocity = localization_buffer_[idx].second.pose().linear_velocity();
  (*car_linear_speed)[0] = velocity.x();
  (*car_linear_speed)[1] = velocity.y();
  (*car_linear_speed)[2] = velocity.z();
  return true;
}

void RadarProcessSubnode::RegistAllAlgorithm() {
  RegisterFactoryDummyRadarDetector();
  RegisterFactoryModestRadarDetector();
}

bool RadarProcessSubnode::InitFrameDependence() {
  /// init share data
  CHECK(shared_data_manager_ != nullptr) << "shared_data_manager_ is nullptr";
  // init preprocess_data
  const string radar_data_name("RadarObjectData");
  radar_data_ = dynamic_cast<RadarObjectData *>(
      shared_data_manager_->GetSharedData(radar_data_name));
  if (radar_data_ == nullptr) {
    AERROR << "Failed to get shared data instance " << radar_data_name;
    return false;
  }
  AINFO << "Init shared data successfully, data: " << radar_data_->name();

  /// init hdmap
  if (FLAGS_enable_hdmap_input) {
    hdmap_input_ = HDMapInput::instance();
    if (!hdmap_input_) {
      AERROR << "Failed to get HDMapInput instance.";
      return false;
    }
    if (!hdmap_input_->Init()) {
      AERROR << "Failed to Init HDMapInput";
      return false;
    }
    AINFO << "Get and Init hdmap_input succ.";
  }

  return true;
}

bool RadarProcessSubnode::InitAlgorithmPlugin() {
  /// init roi filter
  roi_filter_.reset(new HdmapROIFilter());
  if (!roi_filter_->Init()) {
    AERROR << "Failed to Init roi filter: " << roi_filter_->name();
    return false;
  }
  AINFO << "Init algorithm plugin successfully, roi_filter_: "
        << roi_filter_->name();

  /// init radar detector
  radar_detector_.reset(BaseRadarDetectorRegisterer::GetInstanceByName(
      FLAGS_onboard_radar_detector));
  if (!radar_detector_) {
    AERROR << "Failed to get instance: " << FLAGS_onboard_radar_detector;
    return false;
  }
  if (!radar_detector_->Init()) {
    AERROR << "Failed to Init radar detector: " << radar_detector_->name();
    return false;
  }
  AINFO << "Init algorithm plugin successfully, radar detecor: "
        << radar_detector_->name();
  return true;
}

void RadarProcessSubnode::PublishDataAndEvent(
    double timestamp, const SharedDataPtr<SensorObjects> &data) {
  // set shared data
  std::string key;
  if (!SubnodeHelper::ProduceSharedDataKey(timestamp, device_id_, &key)) {
    AERROR << "Failed to produce shared key. time: "
           << GLOG_TIMESTAMP(timestamp) << ", device_id: " << device_id_;
    return;
  }

  radar_data_->Add(key, data);
  // pub events
  for (size_t idx = 0; idx < pub_meta_events_.size(); ++idx) {
    const EventMeta &event_meta = pub_meta_events_[idx];
    Event event;
    event.event_id = event_meta.event_id;
    event.timestamp = timestamp;
    event.reserve = device_id_;
    event_manager_->Publish(event);
  }
}

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


<commit_before>#include "spec_helper.h"
#include "helpers/load_language.h"
#include <unistd.h>
#include <dlfcn.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string>
#include <fstream>
#include "tree_sitter/compiler.h"

using std::string;
using std::ofstream;

static std::string run_cmd(const char *cmd, const char *args[]) {
  int child_pid = fork();
  if (child_pid < 0)
    return "fork failed";

  if (child_pid == 0) {
    close(0);
    dup2(1, 0);
    dup2(2, 1);
    dup2(1, 2);
    execvp(cmd, (char * const * )args);
    return "";
  }

  int status;
  do {
    waitpid(child_pid, &status, 0);
  } while (!WIFEXITED(status));

  if (WEXITSTATUS(status) == 0)
    return "";
  else
    return "command failed";

  return "";
}

const TSLanguage *load_language(const string &name, const TSCompileResult &compile_result) {
  if (compile_result.error_type != TSCompileErrorTypeNone) {
    AssertThat(string(compile_result.error_message), IsEmpty());
    return nullptr;
  }

  return load_language(name, compile_result.code);
}

const TSLanguage *load_language(const string &name, const string &code) {
  string language_function_name = "ts_language_" + name;

  static char source_file_template[256] = {};
  snprintf(source_file_template, 256, "/tmp/tree-sitter-test-%sXXXXXXXXX", name.c_str());

  const char *temp_directory = mkdtemp(source_file_template);
  if (!temp_directory) {
    AssertThat(string("Failed to create temp directory"), IsEmpty());
    return nullptr;
  }

  string source_filename = string(temp_directory) + "/parser.c";
  string obj_filename = string(source_filename) + ".o";
  string lib_filename = string(source_filename) + ".so";
  string header_dir = string(getenv("PWD")) + "/include";

  ofstream source_file;
  source_file.open(source_filename);
  source_file << code;
  source_file.close();

  const char *compiler_name = getenv("CC");
  if (!compiler_name) {
    compiler_name = "gcc";
  }

  const char *compile_argv[] = {
    compiler_name,
    "-x", "c",
    "-fPIC",
    "-I", header_dir.c_str(),
    "-c", source_filename.c_str(),
    "-o", obj_filename.c_str(),
    NULL
  };
  string compile_error = run_cmd("gcc", compile_argv);
  if (!compile_error.empty()) {
    AssertThat(string(compile_error), IsEmpty());
    return nullptr;
  }

  const char *link_argv[] = {
    compiler_name,
    "-shared",
    "-Wl", obj_filename.c_str(),
    "-o", lib_filename.c_str(),
    NULL
  };
  string link_error = run_cmd("gcc", link_argv);
  if (!link_error.empty()) {
    AssertThat(link_error, IsEmpty());
    return nullptr;
  }

  void *parser_lib = dlopen(lib_filename.c_str(), RTLD_NOW);
  if (!parser_lib) {
    std::string message(dlerror());
    AssertThat(message, IsEmpty());
    return nullptr;
  }

  void *symbol_value = dlsym(parser_lib, language_function_name.c_str());
  if (!symbol_value) {
    std::string message(dlerror());
    AssertThat(message, IsEmpty());
    return nullptr;
  }

  typedef TSLanguage * (* LanguageFunction)();
  LanguageFunction language_fn = reinterpret_cast<LanguageFunction>(symbol_value);
  return language_fn();
}
<commit_msg>Compile test grammars w/ debug symbols<commit_after>#include "spec_helper.h"
#include "helpers/load_language.h"
#include <unistd.h>
#include <dlfcn.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string>
#include <fstream>
#include "tree_sitter/compiler.h"

using std::string;
using std::ofstream;

static std::string run_cmd(const char *cmd, const char *args[]) {
  int child_pid = fork();
  if (child_pid < 0)
    return "fork failed";

  if (child_pid == 0) {
    close(0);
    dup2(1, 0);
    dup2(2, 1);
    dup2(1, 2);
    execvp(cmd, (char * const * )args);
    return "";
  }

  int status;
  do {
    waitpid(child_pid, &status, 0);
  } while (!WIFEXITED(status));

  if (WEXITSTATUS(status) == 0)
    return "";
  else
    return "command failed";

  return "";
}

const TSLanguage *load_language(const string &name, const TSCompileResult &compile_result) {
  if (compile_result.error_type != TSCompileErrorTypeNone) {
    AssertThat(string(compile_result.error_message), IsEmpty());
    return nullptr;
  }

  return load_language(name, compile_result.code);
}

const TSLanguage *load_language(const string &name, const string &code) {
  string language_function_name = "ts_language_" + name;

  static char source_file_template[256] = {};
  snprintf(source_file_template, 256, "/tmp/tree-sitter-test-%sXXXXXXXXX", name.c_str());

  const char *temp_directory = mkdtemp(source_file_template);
  if (!temp_directory) {
    AssertThat(string("Failed to create temp directory"), IsEmpty());
    return nullptr;
  }

  string source_filename = string(temp_directory) + "/parser.c";
  string obj_filename = string(source_filename) + ".o";
  string lib_filename = string(source_filename) + ".so";
  string header_dir = string(getenv("PWD")) + "/include";

  ofstream source_file;
  source_file.open(source_filename);
  source_file << code;
  source_file.close();

  const char *compiler_name = getenv("CC");
  if (!compiler_name) {
    compiler_name = "gcc";
  }

  const char *compile_argv[] = {
    compiler_name,
    "-x", "c",
    "-fPIC",
    "-g",
    "-I", header_dir.c_str(),
    "-c", source_filename.c_str(),
    "-o", obj_filename.c_str(),
    NULL
  };
  string compile_error = run_cmd("gcc", compile_argv);
  if (!compile_error.empty()) {
    AssertThat(string(compile_error), IsEmpty());
    return nullptr;
  }

  const char *link_argv[] = {
    compiler_name,
    "-shared",
    "-Wl", obj_filename.c_str(),
    "-o", lib_filename.c_str(),
    NULL
  };
  string link_error = run_cmd("gcc", link_argv);
  if (!link_error.empty()) {
    AssertThat(link_error, IsEmpty());
    return nullptr;
  }

  void *parser_lib = dlopen(lib_filename.c_str(), RTLD_NOW);
  if (!parser_lib) {
    std::string message(dlerror());
    AssertThat(message, IsEmpty());
    return nullptr;
  }

  void *symbol_value = dlsym(parser_lib, language_function_name.c_str());
  if (!symbol_value) {
    std::string message(dlerror());
    AssertThat(message, IsEmpty());
    return nullptr;
  }

  typedef TSLanguage * (* LanguageFunction)();
  LanguageFunction language_fn = reinterpret_cast<LanguageFunction>(symbol_value);
  return language_fn();
}
<|endoftext|>


<commit_before>#include "bloomierHash.h"
BloomierHash::BloomierHash(const size_t pModulo, const size_t pNumberOfElements, const size_t pBitVectorSize, const size_t pHashSeed) {
	mModulo = pModulo;
	mNumberOfElements = pNumberOfElements;
	mHash = new Hash();
	mBitVectorSize = pBitVectorSize;
	mHashSeed = pHashSeed;
};
BloomierHash::~BloomierHash() {
    delete mHash;
};
bitVector* BloomierHash::getMask(const size_t pKey) {
	bitVector* mask = new bitVector(mBitVectorSize);
	size_t randValue = mHash->hash(pKey+1, mHashSeed, mModulo);
	for (size_t i = 0; i < mBitVectorSize; ++i) {
		(*mask)[i] =  static_cast<unsigned char>((randValue >> (8*i)) & 0b00000000000000000000000011111111);
	}
	return mask;
};
void BloomierHash::getKNeighbors(const size_t pElement, const size_t pSeed, vsize_t* pNeighbors) {
    size_t seedValue = pSeed;
    if (seedValue == 0) {
        seedValue = mHashSeed;
    }
    size_t seedChange = 1;
    bitVector* bloomFilterValueSeen = new bitVector(ceil(mModulo/8.0));
	for (size_t i = 0; i < pNeighbors->size(); ++i) {
		size_t neighbor = mHash->hash(pElement+i, seedValue+seedChange, mModulo);
        unsigned char index = floor(neighbor / 8.0);
        unsigned char value = 1 << (neighbor % 8);
        unsigned char valueSeen = (*bloomFilterValueSeen)[index] & value;
        while (value == valueSeen) {
            ++seedChange;
            neighbor = mHash->hash(pElement+1, (seedValue+seedChange), mModulo);
            index = floor(neighbor / 8.0);
            value = 1 << (neighbor % 8);
            valueSeen = (*bloomFilterValueSeen)[index] & value;
        }
        (*bloomFilterValueSeen)[index] = (*bloomFilterValueSeen)[index] | value;

        seedChange = 1;
		(*pNeighbors)[i] = neighbor;
	}
    delete bloomFilterValueSeen;
};

size_t BloomierHash::getHashSeed() const {
	return mHashSeed;
};

void BloomierHash::setHashSeed(size_t pHashSeed) {
	mHashSeed = pHashSeed;
}<commit_msg>Changed return type for function getMask from bitVector* to bitVector<commit_after>#include "bloomierHash.h"
BloomierHash::BloomierHash(const size_t pModulo, const size_t pNumberOfElements, const size_t pBitVectorSize, const size_t pHashSeed) {
	mModulo = pModulo;
	mNumberOfElements = pNumberOfElements;
	mHash = new Hash();
	mBitVectorSize = pBitVectorSize;
	mHashSeed = pHashSeed;
};
BloomierHash::~BloomierHash() {
    delete mHash;
};
bitVector BloomierHash::getMask(const size_t pKey) {
	// bitVector* mask = new bitVector(mBitVectorSize);
    bitVector mask(mBitVectorSize);
	size_t randValue = mHash->hash(pKey+1, mHashSeed, mModulo);
	for (size_t i = 0; i < mBitVectorSize; ++i) {
		mask[i] =  static_cast<unsigned char>((randValue >> (8*i)) & 0b00000000000000000000000011111111);
	}
	return mask;
};
void BloomierHash::getKNeighbors(const size_t pElement, const size_t pSeed, vsize_t* pNeighbors) {
    size_t seedValue = pSeed;
    if (seedValue == 0) {
        seedValue = mHashSeed;
    }
    size_t seedChange = 1;
    bitVector* bloomFilterValueSeen = new bitVector(ceil(mModulo/8.0));
	for (size_t i = 0; i < pNeighbors->size(); ++i) {
		size_t neighbor = mHash->hash(pElement+i, seedValue+seedChange, mModulo);
        unsigned char index = floor(neighbor / 8.0);
        unsigned char value = 1 << (neighbor % 8);
        unsigned char valueSeen = (*bloomFilterValueSeen)[index] & value;
        while (value == valueSeen) {
            ++seedChange;
            neighbor = mHash->hash(pElement+1, (seedValue+seedChange), mModulo);
            index = floor(neighbor / 8.0);
            value = 1 << (neighbor % 8);
            valueSeen = (*bloomFilterValueSeen)[index] & value;
        }
        (*bloomFilterValueSeen)[index] = (*bloomFilterValueSeen)[index] | value;

        seedChange = 1;
		(*pNeighbors)[i] = neighbor;
	}
    delete bloomFilterValueSeen;
};

size_t BloomierHash::getHashSeed() const {
	return mHashSeed;
};

void BloomierHash::setHashSeed(size_t pHashSeed) {
	mHashSeed = pHashSeed;
}<|endoftext|>


<commit_before>// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.

#pragma once

#if !defined(CPPRX_RX_INCLUDES_HPP)
#define CPPRX_RX_INCLUDES_HPP

#pragma push_macro("min")
#pragma push_macro("max")
#undef min
#undef max

#include <exception>
#include <functional>
#include <memory>
#include <vector>
#include <algorithm>
#include <atomic>
#include <map>
#include <mutex>
#include <deque>
#include <thread>
#include <future>
#include <vector>
#include <list>
#include <queue>
#include <chrono>
#include <condition_variable>

// some configuration macros
#if defined(_MSC_VER)

#if _MSC_VER > 1600
#define RXCPP_USE_RVALUEREF 1
#define RXCPP_USE_VARIADIC_TEMPLATES 0
#endif

#if _CPPRTTI
#define RXCPP_USE_RTTI 1
#endif

#elif defined(__clang__)

#if __has_feature(cxx_rvalue_references)
#define RXCPP_USE_RVALUEREF 1
#endif
#if __has_feature(cxx_rtti)
#define RXCPP_USE_RTTI 1
#endif
#if __has_feature(cxx_variadic_templates)
#define RXCPP_USE_VARIADIC_TEMPLATES 1
#endif

#endif

#if !defined(WINAPI_FAMILY) || (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP)
#define RXCPP_USE_WINRT 0
#else
#define RXCPP_USE_WINRT 1
#endif

#if defined(RXCPP_FORCE_USE_VARIADIC_TEMPLATES)
#undef RXCPP_USE_VARIADIC_TEMPLATES
#define RXCPP_USE_VARIADIC_TEMPLATES RXCPP_FORCE_USE_VARIADIC_TEMPLATES
#endif

#if defined(RXCPP_FORCE_USE_RVALUEREF)
#undef RXCPP_USE_RVALUEREF
#define RXCPP_USE_RVALUEREF RXCPP_FORCE_USE_RVALUEREF
#endif

#if defined(RXCPP_FORCE_USE_RTTI)
#undef RXCPP_USE_RTTI
#define RXCPP_USE_RTTI RXCPP_FORCE_USE_RTTI
#endif

#if defined(RXCPP_FORCE_USE_WINRT)
#undef RXCPP_USE_WINRT
#define RXCPP_USE_WINRT RXCPP_FORCE_USE_WINRT
#endif

#include "rx-util.hpp"
#include "rx-base.hpp"
#include "rx-scheduler.hpp"
#include "rx-windows.hpp"
#include "rx-operators.hpp"
#include "rx-winrt.hpp"

#pragma pop_macro("min")
#pragma pop_macro("max")

#endif
<commit_msg>update _MSC_VER checks for VC2013<commit_after>// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.

#pragma once

#if !defined(CPPRX_RX_INCLUDES_HPP)
#define CPPRX_RX_INCLUDES_HPP

#pragma push_macro("min")
#pragma push_macro("max")
#undef min
#undef max

#include <exception>
#include <functional>
#include <memory>
#include <vector>
#include <algorithm>
#include <atomic>
#include <map>
#include <mutex>
#include <deque>
#include <thread>
#include <future>
#include <vector>
#include <list>
#include <queue>
#include <chrono>
#include <condition_variable>

// some configuration macros
#if defined(_MSC_VER)

#if _MSC_VER > 1600
#define RXCPP_USE_RVALUEREF 1
#endif

#if _MSC_VER >= 1800
#define RXCPP_USE_VARIADIC_TEMPLATES 1
#endif

#if _CPPRTTI
#define RXCPP_USE_RTTI 1
#endif

#elif defined(__clang__)

#if __has_feature(cxx_rvalue_references)
#define RXCPP_USE_RVALUEREF 1
#endif
#if __has_feature(cxx_rtti)
#define RXCPP_USE_RTTI 1
#endif
#if __has_feature(cxx_variadic_templates)
#define RXCPP_USE_VARIADIC_TEMPLATES 1
#endif

#endif

#if !defined(WINAPI_FAMILY) || (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP)
#define RXCPP_USE_WINRT 0
#else
#define RXCPP_USE_WINRT 1
#endif

#if defined(RXCPP_FORCE_USE_VARIADIC_TEMPLATES)
#undef RXCPP_USE_VARIADIC_TEMPLATES
#define RXCPP_USE_VARIADIC_TEMPLATES RXCPP_FORCE_USE_VARIADIC_TEMPLATES
#endif

#if defined(RXCPP_FORCE_USE_RVALUEREF)
#undef RXCPP_USE_RVALUEREF
#define RXCPP_USE_RVALUEREF RXCPP_FORCE_USE_RVALUEREF
#endif

#if defined(RXCPP_FORCE_USE_RTTI)
#undef RXCPP_USE_RTTI
#define RXCPP_USE_RTTI RXCPP_FORCE_USE_RTTI
#endif

#if defined(RXCPP_FORCE_USE_WINRT)
#undef RXCPP_USE_WINRT
#define RXCPP_USE_WINRT RXCPP_FORCE_USE_WINRT
#endif

#include "rx-util.hpp"
#include "rx-base.hpp"
#include "rx-scheduler.hpp"
#include "rx-windows.hpp"
#include "rx-operators.hpp"
#include "rx-winrt.hpp"

#pragma pop_macro("min")
#pragma pop_macro("max")

#endif
<|endoftext|>


<commit_before>#include "runtime/debugger.h"
#include "runtime/helpers/spy_debugger.h"
#include "runtime/runtime_spec_helper.h"

extern "C" const TSLanguage * ts_language_json();

START_TEST

describe("Document", [&]() {
  TSDocument *doc;

  before_each([&]() {
    doc = ts_document_make();
  });

  after_each([&]() {
    ts_document_free(doc);
  });

  describe("set_input(TSInput)", [&]() {
    describe("when the language is set", [&]() {
      before_each([&]() {
        ts_document_set_language(doc, ts_language_json());
      });

      it("parses the document", [&]() {
        ts_document_set_input_string(doc, "{ \"key\": [1, 2] }");

        AssertThat(ts_node_string(ts_document_root_node(doc)), Equals(
            "(DOCUMENT (object (string) (array (number) (number))))"));
      });
    });

    describe("when the language is not set", [&]() {
      it("does not try to parse the document", [&]() {
        ts_document_set_input_string(doc, "{ \"key\": [1, 2] }");

        AssertThat(ts_document_root_node(doc), Equals<TSNode *>(nullptr));
      });
    });
  });

  describe("set_language(TSLanguage)", [&]() {
    describe("when the input is not set", [&]() {
      it("does not try to parse the document", [&]() {
        ts_document_set_language(doc, ts_language_json());

        AssertThat(ts_document_root_node(doc), Equals<TSNode *>(nullptr));
      });
    });

    describe("when the input is set", [&]() {
      before_each([&]() {
        ts_document_set_input_string(doc, "{ \"key\": [1, 2] }");
      });

      it("parses the document", [&]() {
        ts_document_set_language(doc, ts_language_json());

        AssertThat(ts_node_string(ts_document_root_node(doc)), Equals(
            "(DOCUMENT (object (string) (array (number) (number))))"));
      });
    });
  });

  describe("set_debugger(TSDebugger)", [&]() {
    SpyDebugger *debugger;

    before_each([&]() {
      debugger = new SpyDebugger();
      ts_document_set_language(doc, ts_language_json());
      ts_document_set_debugger(doc, debugger->debugger());
    });

    it("calls the debugger with a message for each lex action", [&]() {
      ts_document_set_input_string(doc, "[1, 2]");

      AssertThat(debugger->messages, Contains("lookahead char:'1'"));
      AssertThat(debugger->messages, Contains("advance state:1"));
      AssertThat(debugger->messages, Contains("accept_token sym:number"));
    });

    it("calls the debugger with a message for each parse action", [&]() {
      ts_document_set_input_string(doc, "[1, 2]");

      AssertThat(debugger->messages, Contains("shift state:1"));
      AssertThat(debugger->messages, Contains("reduce sym:value count:1"));
      AssertThat(debugger->messages, Contains("accept"));
    });

    it("allows the debugger to be retrieved later", [&]() {
      AssertThat(ts_document_get_debugger(doc).data, Equals(debugger));
    });

    describe("disabling debugging", [&]() {
      before_each([&]() {
        ts_document_set_debugger(doc, {});
      });

      it("does not call the debugger any more", [&]() {
        ts_document_set_input_string(doc, "[1, 2]");
        AssertThat(debugger->messages, IsEmpty());
      });

      it("releases the old debugger", [&]() {
        AssertThat(debugger->release_call_count, Equals<size_t>(1));
      });
    });
  });
});

END_TEST
<commit_msg>Fix build warnings in document spec<commit_after>#include "runtime/debugger.h"
#include "runtime/helpers/spy_debugger.h"
#include "runtime/runtime_spec_helper.h"

extern "C" const TSLanguage * ts_language_json();

START_TEST

describe("Document", [&]() {
  TSDocument *doc;

  before_each([&]() {
    doc = ts_document_make();
  });

  after_each([&]() {
    ts_document_free(doc);
  });

  describe("set_input(TSInput)", [&]() {
    describe("when the language is set", [&]() {
      before_each([&]() {
        ts_document_set_language(doc, ts_language_json());
      });

      it("parses the document", [&]() {
        ts_document_set_input_string(doc, "{ \"key\": [1, 2] }");

        AssertThat(ts_node_string(ts_document_root_node(doc)), Equals(
            "(DOCUMENT (object (string) (array (number) (number))))"));
      });
    });

    describe("when the language is not set", [&]() {
      it("does not try to parse the document", [&]() {
        ts_document_set_input_string(doc, "{ \"key\": [1, 2] }");

        AssertThat(ts_document_root_node(doc), Equals<TSNode *>(nullptr));
      });
    });
  });

  describe("set_language(TSLanguage)", [&]() {
    describe("when the input is not set", [&]() {
      it("does not try to parse the document", [&]() {
        ts_document_set_language(doc, ts_language_json());

        AssertThat(ts_document_root_node(doc), Equals<TSNode *>(nullptr));
      });
    });

    describe("when the input is set", [&]() {
      before_each([&]() {
        ts_document_set_input_string(doc, "{ \"key\": [1, 2] }");
      });

      it("parses the document", [&]() {
        ts_document_set_language(doc, ts_language_json());

        AssertThat(ts_node_string(ts_document_root_node(doc)), Equals(
            "(DOCUMENT (object (string) (array (number) (number))))"));
      });
    });
  });

  describe("set_debugger(TSDebugger)", [&]() {
    SpyDebugger *debugger;

    before_each([&]() {
      debugger = new SpyDebugger();
      ts_document_set_language(doc, ts_language_json());
      ts_document_set_debugger(doc, debugger->debugger());
    });

    it("calls the debugger with a message for each lex action", [&]() {
      ts_document_set_input_string(doc, "[1, 2]");

      AssertThat(debugger->messages, Contains("lookahead char:'1'"));
      AssertThat(debugger->messages, Contains("advance state:1"));
      AssertThat(debugger->messages, Contains("accept_token sym:number"));
    });

    it("calls the debugger with a message for each parse action", [&]() {
      ts_document_set_input_string(doc, "[1, 2]");

      AssertThat(debugger->messages, Contains("shift state:1"));
      AssertThat(debugger->messages, Contains("reduce sym:value count:1"));
      AssertThat(debugger->messages, Contains("accept"));
    });

    it("allows the debugger to be retrieved later", [&]() {
      AssertThat(ts_document_get_debugger(doc).data, Equals(debugger));
    });

    describe("disabling debugging", [&]() {
      before_each([&]() {
        ts_document_set_debugger(doc, ts_debugger_null());
      });

      it("does not call the debugger any more", [&]() {
        ts_document_set_input_string(doc, "[1, 2]");
        AssertThat(debugger->messages, IsEmpty());
      });

      it("releases the old debugger", [&]() {
        AssertThat(debugger->release_call_count, Equals<size_t>(1));
      });
    });
  });
});

END_TEST
<|endoftext|>


<commit_before>#include "TestCommon.hh"

using namespace SDLut::video;

class AssertEngine;

Logger testlog("TestPixelFormat");

Color bgc(128,128,128);
Color red(255,0,0);
Color green(0,255,0);
Color blue(0,0,255);
Color alpha(255,255,255,128);

class MyEngine : public TestEngine
{
    Image * imgred,*imggreen,*imgblue,*imgalpha;

public:

	MyEngine(Logger & log, AssertEngine & ae) : TestEngine(log,ae), imgred(0), imggreen(0),imgblue(0),imgalpha(0)
	{
	    App::getInstance().getDisplay().getScreenBuffer().setBGColor(bgc);
	}

    virtual ~MyEngine()
    {
        delete imgred; delete imggreen; delete imgblue; delete imgalpha;
        }

	virtual bool init(int width, int height)
	{
	    return resize(width,height);
	}

	virtual bool resize(int width, int height)
	{
		delete imgred; delete imggreen; delete imgblue; delete imgalpha;
		imgred = new Image(width/4,height,32);
		imgred->fill(red);
		imggreen = new Image(width/4,height,32);
		imggreen->fill(green);
		imgblue = new Image(width/4,height,32);
		imgblue->fill(blue);
		imgalpha = new Image(width-imgred->getWidth()-imggreen->getWidth()-imgblue->getWidth(),height,32, true);
		imgalpha->fill(alpha);

		testlog << "Red Pixel : " << std::hex << imgred->getpixel(0,0) << std::endl;
		testlog << "Green Pixel : " << std::hex << imggreen->getpixel(0,0)<< std::endl;
		testlog << "Blue Pixel : " << std::hex << imgblue->getpixel(0,0)<< std::endl;
		testlog << "Alpha Pixel : " << std::hex << imgalpha->getpixel(0,0)<< std::endl;

		return true;
	}

	virtual bool render(ScreenBuffer & screen) const
    {
        Rect red_dst(0,0,imgred->getWidth(),imgred->getHeight());
		screen.blit(*imgred,red_dst);
		Rect green_dst(0 + imgred->getWidth(),0,imggreen->getWidth(),imggreen->getHeight());
		screen.blit(*imggreen,green_dst);
		Rect blue_dst(0 + imgred->getWidth() + imggreen->getWidth(), 0,imgblue->getWidth(),imgblue->getHeight());
		screen.blit(*imgblue,blue_dst);
		Rect alpha_dst(0 + imgred->getWidth() + imggreen->getWidth() + imgblue->getWidth(), 0, imgalpha->getWidth(),imgalpha->getHeight());
		screen.blit(*imgalpha,alpha_dst);

		return true;
    }

};

class Test : public AssertEngine
{

    Rect posred,posgreen,posblue,posalpha;

public:
    //we only need one render to see which color are there
    Test( Logger & log) : AssertEngine(log,1)
	{
	}

    virtual ~Test()
    {
    }

	virtual bool assertinit(int width, int height)
	{

	    return assertresize(width,height);
	}

	virtual bool assertresize(int width, int height)
	{

		posred = Rect(0,0,width/4,height);
		posgreen = Rect(0 + posred.getw(),0,width/4,height);
        posblue = Rect(0 + posred.getw() + posgreen.getw(), 0,width/4,height);
		posalpha = Rect(0 + posred.getw() + posgreen.getw() + posblue.getw(), 0,width-posred.getw()-posgreen.getw()-posblue.getw(),height);

		return true;
	}

	virtual bool assertrender(ScreenBuffer & screen) const
    {
        bool res = true;
        res = res &&  blend(red,bgc).isSimilarTo(screen.getpixel(posred.getx(),posred.gety()));
        if (!res)
        {
            m_log << nl << "Red = " << blend(red,bgc);
            m_log << nl << "Pixel = " << screen.getpixel(posred.getx(),posred.gety());
            setError(-1,"Red Pixel is wrong");
        }
		res = res && blend(green,bgc).isSimilarTo(screen.getpixel(posgreen.getx(),posgreen.gety()));
		if (!res)
        {
            m_log << nl << "Green = " << blend(green,bgc);
            m_log << nl << "Pixel = " << screen.getpixel(posgreen.getx(),posgreen.gety());
            setError(-1,"Green Pixel is wrong");
        }
		res = res && blend(blue,bgc).isSimilarTo( screen.getpixel(posblue.getx(),posblue.gety()));
		if (!res)
        {
            m_log << nl << "Blue = " << blend(blue,bgc);
            m_log << nl << "Pixel = " << screen.getpixel(posblue.getx(),posblue.gety());
            setError(-1,"Blue Pixel is wrong");
        }
		res = res && blend(alpha,bgc).isSimilarTo( screen.getpixel(posalpha.getx(),posalpha.gety()));
		if (!res)
        {
            m_log << nl << "Alpha = " << blend(alpha,bgc);
            m_log << nl << "Pixel = " << screen.getpixel(posalpha.getx(),posalpha.gety());
            setError(-1,"Alpha Pixel is wrong");
        }

		return res;
    }

};

int main(int argc, char** argv)
{
    ArgParser args(argc,argv);

    //Starting with usual SDL window
    App::getInstance().initVideo(false,true,false);
	App::getInstance().setName ("SDLut::video test PixelFormat");

    //Setting Display size and BPP
    App::getInstance().getDisplay().setDisplay(300,240); // using autodetected bpp

    App::getInstance().getDisplay().getScreenBuffer().setOpenGL(args.isOGL());

    Test teng(testlog);
	MyEngine engine(testlog,teng);

    int exitstatus = -1;
    if(App::getInstance().getDisplay().show())
    {
       exitstatus = App::getInstance().getDisplay().mainLoop();
    }

    return exitstatus;
}

<commit_msg> quick fix to match new test master classes<commit_after>#include "TestCommon.hh"

using namespace SDLut::video;

class AssertEngine;

Logger testlog("TestPixelFormat");

Color bgc(128,128,128);
Color red(255,0,0);
Color green(0,255,0);
Color blue(0,0,255);
Color alpha(255,255,255,128);

class MyEngine : public TestEngine
{
    Image * imgred,*imggreen,*imgblue,*imgalpha;

public:

	MyEngine(Logger & log, AssertEngine & ae) : TestEngine(log,ae), imgred(0), imggreen(0),imgblue(0),imgalpha(0)
	{
	    App::getInstance().getDisplay().getScreenBuffer().setBGColor(bgc);
	}

    virtual ~MyEngine()
    {
        delete imgred; delete imggreen; delete imgblue; delete imgalpha;
        }

	virtual bool init(int width, int height)
	{
	    return resize(width,height);
	}

	virtual bool resize(int width, int height)
	{
		delete imgred; delete imggreen; delete imgblue; delete imgalpha;
		imgred = new Image(width/4,height,32);
		imgred->fill(red);
		imggreen = new Image(width/4,height,32);
		imggreen->fill(green);
		imgblue = new Image(width/4,height,32);
		imgblue->fill(blue);
		imgalpha = new Image(width-imgred->getWidth()-imggreen->getWidth()-imgblue->getWidth(),height,32, true);
		imgalpha->fill(alpha);

		testlog << "Red Pixel : " << std::hex << imgred->getpixel(0,0) << std::endl;
		testlog << "Green Pixel : " << std::hex << imggreen->getpixel(0,0)<< std::endl;
		testlog << "Blue Pixel : " << std::hex << imgblue->getpixel(0,0)<< std::endl;
		testlog << "Alpha Pixel : " << std::hex << imgalpha->getpixel(0,0)<< std::endl;

		return true;
	}

	virtual bool render(ScreenBuffer & screen) const
    {
        Rect red_dst(0,0,imgred->getWidth(),imgred->getHeight());
		screen.blit(*imgred,red_dst);
		Rect green_dst(0 + imgred->getWidth(),0,imggreen->getWidth(),imggreen->getHeight());
		screen.blit(*imggreen,green_dst);
		Rect blue_dst(0 + imgred->getWidth() + imggreen->getWidth(), 0,imgblue->getWidth(),imgblue->getHeight());
		screen.blit(*imgblue,blue_dst);
		Rect alpha_dst(0 + imgred->getWidth() + imggreen->getWidth() + imgblue->getWidth(), 0, imgalpha->getWidth(),imgalpha->getHeight());
		screen.blit(*imgalpha,alpha_dst);

		return true;
    }

};

class Test : public AssertEngine
{

    Rect posred,posgreen,posblue,posalpha;

public:
    //we only need one render to see which color are there
    Test( Logger & log, const ArgParser & args) : AssertEngine(log,args)
	{
	}

    virtual ~Test()
    {
    }

	virtual bool assertinit(int width, int height)
	{

	    return assertresize(width,height);
	}

	virtual bool assertresize(int width, int height)
	{

		posred = Rect(0,0,width/4,height);
		posgreen = Rect(0 + posred.getw(),0,width/4,height);
        posblue = Rect(0 + posred.getw() + posgreen.getw(), 0,width/4,height);
		posalpha = Rect(0 + posred.getw() + posgreen.getw() + posblue.getw(), 0,width-posred.getw()-posgreen.getw()-posblue.getw(),height);

		return true;
	}

	virtual bool assertrender(ScreenBuffer & screen) const
    {
        bool res = true;
        res = res &&  blend(red,bgc).isSimilarTo(screen.getpixel(posred.getx(),posred.gety()));
        if (!res)
        {
            m_log << nl << "Red = " << blend(red,bgc);
            m_log << nl << "Pixel = " << screen.getpixel(posred.getx(),posred.gety());
            setError(-1,"Red Pixel is wrong");
        }
		res = res && blend(green,bgc).isSimilarTo(screen.getpixel(posgreen.getx(),posgreen.gety()));
		if (!res)
        {
            m_log << nl << "Green = " << blend(green,bgc);
            m_log << nl << "Pixel = " << screen.getpixel(posgreen.getx(),posgreen.gety());
            setError(-1,"Green Pixel is wrong");
        }
		res = res && blend(blue,bgc).isSimilarTo( screen.getpixel(posblue.getx(),posblue.gety()));
		if (!res)
        {
            m_log << nl << "Blue = " << blend(blue,bgc);
            m_log << nl << "Pixel = " << screen.getpixel(posblue.getx(),posblue.gety());
            setError(-1,"Blue Pixel is wrong");
        }
		res = res && blend(alpha,bgc).isSimilarTo( screen.getpixel(posalpha.getx(),posalpha.gety()));
		if (!res)
        {
            m_log << nl << "Alpha = " << blend(alpha,bgc);
            m_log << nl << "Pixel = " << screen.getpixel(posalpha.getx(),posalpha.gety());
            setError(-1,"Alpha Pixel is wrong");
        }

		return res;
    }

};

int main(int argc, char** argv)
{
    ArgParser args(argc,argv);

    //Starting with usual SDL window
    App::getInstance().initVideo(false,true,false);
	App::getInstance().setName ("SDLut::video test PixelFormat");

    //Setting Display size and BPP
    App::getInstance().getDisplay().setDisplay(300,240); // using autodetected bpp

    App::getInstance().getDisplay().getScreenBuffer().setOpenGL(args.isOGL());

    Test teng(testlog,args);
	MyEngine engine(testlog,teng);

    int exitstatus = -1;
    if(App::getInstance().getDisplay().show())
    {
       exitstatus = App::getInstance().getDisplay().mainLoop();
    }

    return exitstatus;
}

<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
// Name:      dirctrl.cpp
// Purpose:   Implementation of class wxExGenericDirCtrl
// Author:    Anton van Wezenbeek
// Copyright: (c) 2013 Anton van Wezenbeek
////////////////////////////////////////////////////////////////////////////////

#include <wx/stockitem.h> // for wxGetStockLabel
#include <wx/textfile.h>
#include <wx/extension/filename.h>
#include <wx/extension/menu.h>
#include <wx/extension/util.h>
#include <wx/extension/vcs.h>
#include <wx/extension/report/dirctrl.h>
#include <wx/extension/report/defs.h>
#include <wx/extension/report/frame.h>

#if wxUSE_DIRDLG

BEGIN_EVENT_TABLE(wxExGenericDirCtrl, wxGenericDirCtrl)
  EVT_MENU_RANGE(
    ID_EDIT_VCS_LOWEST,
    ID_EDIT_VCS_HIGHEST,
    wxExGenericDirCtrl::OnCommand)
  EVT_MENU_RANGE(ID_TREE_OPEN, ID_TREE_RUN_MAKE, wxExGenericDirCtrl::OnCommand)
  EVT_MENU_RANGE(ID_TOOL_LOWEST, ID_TOOL_HIGHEST, wxExGenericDirCtrl::OnCommand)
  EVT_TREE_ITEM_ACTIVATED(wxID_TREECTRL, wxExGenericDirCtrl::OnTree)
  EVT_TREE_ITEM_MENU(wxID_TREECTRL, wxExGenericDirCtrl::OnTree)
  EVT_TREE_SEL_CHANGED(wxID_TREECTRL, wxExGenericDirCtrl::OnTree)
END_EVENT_TABLE()

wxExGenericDirCtrl::wxExGenericDirCtrl(
  wxWindow *parent,
  wxExFrameWithHistory* frame,
  const wxWindowID id,
  const wxPoint &pos,
  const wxSize &size,
  long style,
  const wxString &filter,
  int defaultFilter,
  const wxString &name)
  : wxGenericDirCtrl(
      parent,
      id,
      wxDirDialogDefaultFolderStr,
      pos,
      size,
      style,
      filter,
      defaultFilter,
      name)
  , m_Frame(frame)
{
}

void wxExGenericDirCtrl::ExpandAndSelectPath(const wxString& path)
{
  ExpandPath(path);
  SelectPath(path);
}

void wxExGenericDirCtrl::OnCommand(wxCommandEvent& event)
{
  if (event.GetId() > ID_EDIT_VCS_LOWEST &&
      event.GetId() < ID_EDIT_VCS_HIGHEST)
  {
    wxExVCSExecute(m_Frame,
      event.GetId() - ID_EDIT_VCS_LOWEST - 1, wxExToVectorString(*this).Get());
  }
  else if (event.GetId() > ID_TOOL_LOWEST && event.GetId() < ID_TOOL_HIGHEST)
  {
    m_Frame->FindInFiles(wxExToVectorString(*this).Get(), event.GetId());
  }
  else switch (event.GetId())
  {
  case ID_TREE_COPY:
    {
    const std::vector<wxString> files(wxExToVectorString(*this).Get());
    wxBusyCursor wait;
    wxString clipboard;
    for (const auto& it : files)
    {
      clipboard += it + wxTextFile::GetEOL();
    }
    wxExClipboardAdd(clipboard);
    }
  break;

  case ID_TREE_OPEN:
    wxExOpenFiles(m_Frame,
      wxExToVectorString(*this).Get(), 0, wxDIR_FILES); // only files in this dir
  break;

  case ID_TREE_RUN_MAKE:
    {
    const std::vector<wxString> files(wxExToVectorString(*this).Get());
    wxExMake(files[0]);
    }
    break;

  default: wxFAIL;
  }
}

void wxExGenericDirCtrl::OnTree(wxTreeEvent& event)
{
  const std::vector< wxString > files(wxExToVectorString(*this).Get());

  if (files.empty())
  {
    event.Skip();
    return;
  }

  if (event.GetEventType() == wxEVT_COMMAND_TREE_ITEM_MENU)
  {
    const wxExFileName filename(files[0]);

    wxExMenu menu; // uses AppendVCS

    if (filename.FileExists())
    {
      menu.Append(ID_TREE_OPEN, _("&Open"));
      menu.AppendSeparator();
    }

    menu.Append(ID_TREE_COPY,
      wxGetStockLabel(wxID_COPY), wxEmptyString, wxART_COPY);

    if (wxExVCS::DirExists(filename))
    {
      menu.AppendSeparator();
      menu.AppendVCS(filename);
    }

    if (filename.GetLexer().GetScintillaLexer() == "makefile")
    {
      menu.AppendSeparator();
      menu.Append(ID_TREE_RUN_MAKE, "&Make");
    }

    menu.AppendSeparator();
    menu.Append(ID_TOOL_REPORT_FIND,
      wxExEllipsed(m_Frame->GetFindInCaption(ID_TOOL_REPORT_FIND)));

    menu.Append(ID_TOOL_REPORT_REPLACE,
      wxExEllipsed(m_Frame->GetFindInCaption(ID_TOOL_REPORT_REPLACE)));

    PopupMenu(&menu);
  }
  else if (event.GetEventType() == wxEVT_COMMAND_TREE_ITEM_ACTIVATED)
  {
    const wxFileName fn(files[0]);

    if (!fn.FileExists() && fn.DirExists())
    {
      if (!GetTreeCtrl()->IsExpanded(event.GetItem()))
      {
        ExpandAndSelectPath(files[0]);
      }
      else
      {
        CollapsePath(files[0]);
      }
    }
    else
    {
      wxExOpenFiles(m_Frame, files, 0, wxDIR_FILES); // only files in this dir
    }
  }
  else if (event.GetEventType() ==  wxEVT_COMMAND_TREE_SEL_CHANGED)
  {
    wxExLogStatus(wxFileName(files[0]), STAT_FULLPATH);
  }
  else
  {
    wxFAIL;
  }
}
#endif
<commit_msg>corrected filter<commit_after>////////////////////////////////////////////////////////////////////////////////
// Name:      dirctrl.cpp
// Purpose:   Implementation of class wxExGenericDirCtrl
// Author:    Anton van Wezenbeek
// Copyright: (c) 2014 Anton van Wezenbeek
////////////////////////////////////////////////////////////////////////////////

#include <wx/stockitem.h> // for wxGetStockLabel
#include <wx/textfile.h>
#include <wx/extension/filename.h>
#include <wx/extension/menu.h>
#include <wx/extension/util.h>
#include <wx/extension/vcs.h>
#include <wx/extension/report/dirctrl.h>
#include <wx/extension/report/defs.h>
#include <wx/extension/report/frame.h>

#if wxUSE_DIRDLG

BEGIN_EVENT_TABLE(wxExGenericDirCtrl, wxGenericDirCtrl)
  EVT_MENU_RANGE(
    ID_EDIT_VCS_LOWEST,
    ID_EDIT_VCS_HIGHEST,
    wxExGenericDirCtrl::OnCommand)
  EVT_MENU_RANGE(ID_TREE_OPEN, ID_TREE_RUN_MAKE, wxExGenericDirCtrl::OnCommand)
  EVT_MENU_RANGE(ID_TOOL_LOWEST, ID_TOOL_HIGHEST, wxExGenericDirCtrl::OnCommand)
  EVT_TREE_ITEM_ACTIVATED(wxID_TREECTRL, wxExGenericDirCtrl::OnTree)
  EVT_TREE_ITEM_MENU(wxID_TREECTRL, wxExGenericDirCtrl::OnTree)
  EVT_TREE_SEL_CHANGED(wxID_TREECTRL, wxExGenericDirCtrl::OnTree)
END_EVENT_TABLE()

wxExGenericDirCtrl::wxExGenericDirCtrl(
  wxWindow *parent,
  wxExFrameWithHistory* frame,
  const wxWindowID id,
  const wxPoint &pos,
  const wxSize &size,
  long style,
  const wxString &filter,
  int defaultFilter,
  const wxString &name)
  : wxGenericDirCtrl(
      parent,
      id,
      wxDirDialogDefaultFolderStr,
      pos,
      size,
      style,
      (filter.empty() ? "*": filter),
      defaultFilter,
      name)
  , m_Frame(frame)
{
}

void wxExGenericDirCtrl::ExpandAndSelectPath(const wxString& path)
{
  ExpandPath(path);
  SelectPath(path);
}

void wxExGenericDirCtrl::OnCommand(wxCommandEvent& event)
{
  if (event.GetId() > ID_EDIT_VCS_LOWEST &&
      event.GetId() < ID_EDIT_VCS_HIGHEST)
  {
    wxExVCSExecute(m_Frame,
      event.GetId() - ID_EDIT_VCS_LOWEST - 1, wxExToVectorString(*this).Get());
  }
  else if (event.GetId() > ID_TOOL_LOWEST && event.GetId() < ID_TOOL_HIGHEST)
  {
    m_Frame->FindInFiles(wxExToVectorString(*this).Get(), event.GetId());
  }
  else switch (event.GetId())
  {
  case ID_TREE_COPY:
    {
    const std::vector<wxString> files(wxExToVectorString(*this).Get());
    wxBusyCursor wait;
    wxString clipboard;
    for (const auto& it : files)
    {
      clipboard += it + wxTextFile::GetEOL();
    }
    wxExClipboardAdd(clipboard);
    }
  break;

  case ID_TREE_OPEN:
    wxExOpenFiles(m_Frame,
      wxExToVectorString(*this).Get(), 0, wxDIR_FILES); // only files in this dir
  break;

  case ID_TREE_RUN_MAKE:
    {
    const std::vector<wxString> files(wxExToVectorString(*this).Get());
    wxExMake(files[0]);
    }
    break;

  default: wxFAIL;
  }
}

void wxExGenericDirCtrl::OnTree(wxTreeEvent& event)
{
  const std::vector< wxString > files(wxExToVectorString(*this).Get());

  if (files.empty())
  {
    event.Skip();
    return;
  }

  if (event.GetEventType() == wxEVT_COMMAND_TREE_ITEM_MENU)
  {
    const wxExFileName filename(files[0]);

    wxExMenu menu; // uses AppendVCS

    if (filename.FileExists())
    {
      menu.Append(ID_TREE_OPEN, _("&Open"));
      menu.AppendSeparator();
    }

    menu.Append(ID_TREE_COPY,
      wxGetStockLabel(wxID_COPY), wxEmptyString, wxART_COPY);

    if (wxExVCS::DirExists(filename))
    {
      menu.AppendSeparator();
      menu.AppendVCS(filename);
    }

    if (filename.GetLexer().GetScintillaLexer() == "makefile")
    {
      menu.AppendSeparator();
      menu.Append(ID_TREE_RUN_MAKE, "&Make");
    }

    menu.AppendSeparator();
    menu.Append(ID_TOOL_REPORT_FIND,
      wxExEllipsed(m_Frame->GetFindInCaption(ID_TOOL_REPORT_FIND)));

    menu.Append(ID_TOOL_REPORT_REPLACE,
      wxExEllipsed(m_Frame->GetFindInCaption(ID_TOOL_REPORT_REPLACE)));

    PopupMenu(&menu);
  }
  else if (event.GetEventType() == wxEVT_COMMAND_TREE_ITEM_ACTIVATED)
  {
    const wxFileName fn(files[0]);

    if (!fn.FileExists() && fn.DirExists())
    {
      if (!GetTreeCtrl()->IsExpanded(event.GetItem()))
      {
        ExpandAndSelectPath(files[0]);
      }
      else
      {
        CollapsePath(files[0]);
      }
    }
    else
    {
      wxExOpenFiles(m_Frame, files, 0, wxDIR_FILES); // only files in this dir
    }
  }
  else if (event.GetEventType() ==  wxEVT_COMMAND_TREE_SEL_CHANGED)
  {
    wxExLogStatus(wxFileName(files[0]), STAT_FULLPATH);
  }
  else
  {
    wxFAIL;
  }
}
#endif
<|endoftext|>


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

#include "device_split_kernel.h"

#include "kernel_types.h"
#include "kernel_split_data.h"

#include "util_time.h"

CCL_NAMESPACE_BEGIN

static const double alpha = 0.1; /* alpha for rolling average */

DeviceSplitKernel::DeviceSplitKernel(Device *device) : device(device)
{
	current_max_closure = -1;
	first_tile = true;

	avg_time_per_sample = 0.0;
}

DeviceSplitKernel::~DeviceSplitKernel()
{
	device->mem_free(split_data);
	device->mem_free(ray_state);
	device->mem_free(use_queues_flag);
	device->mem_free(queue_index);
	device->mem_free(work_pool_wgs);

	delete kernel_path_init;
	delete kernel_scene_intersect;
	delete kernel_lamp_emission;
	delete kernel_queue_enqueue;
	delete kernel_background_buffer_update;
	delete kernel_shader_eval;
	delete kernel_holdout_emission_blurring_pathtermination_ao;
	delete kernel_direct_lighting;
	delete kernel_shadow_blocked;
	delete kernel_next_iteration_setup;
}

bool DeviceSplitKernel::load_kernels(const DeviceRequestedFeatures& requested_features)
{
#define LOAD_KERNEL(name) \
		kernel_##name = get_split_kernel_function(#name, requested_features); \
		if(!kernel_##name) { \
			return false; \
		}

	LOAD_KERNEL(path_init);
	LOAD_KERNEL(scene_intersect);
	LOAD_KERNEL(lamp_emission);
	LOAD_KERNEL(queue_enqueue);
	LOAD_KERNEL(background_buffer_update);
	LOAD_KERNEL(shader_eval);
	LOAD_KERNEL(holdout_emission_blurring_pathtermination_ao);
	LOAD_KERNEL(direct_lighting);
	LOAD_KERNEL(shadow_blocked);
	LOAD_KERNEL(next_iteration_setup);

#undef LOAD_KERNEL

	current_max_closure = requested_features.max_closure;

	return true;
}

size_t DeviceSplitKernel::max_elements_for_max_buffer_size(size_t max_buffer_size, size_t passes_size)
{
	size_t size_per_element = split_data_buffer_size(1024, current_max_closure, passes_size) / 1024;
	return max_buffer_size / size_per_element;
}

bool DeviceSplitKernel::path_trace(DeviceTask *task,
                                   RenderTile& tile,
                                   device_memory& kgbuffer,
                                   device_memory& kernel_data)
{
	if(device->have_error()) {
		return false;
	}

	/* Get local size */
	size_t local_size[2];
	{
		int2 lsize = split_kernel_local_size();
		local_size[0] = lsize[0];
		local_size[1] = lsize[1];
	}

	/* Calculate per_thread_output_buffer_size. */
	size_t per_thread_output_buffer_size = task->passes_size;

	/* Set gloabl size */
	size_t global_size[2];
	{
		int2 gsize = split_kernel_global_size(task);

		/* Make sure that set work size is a multiple of local
		 * work size dimensions.
		 */
		global_size[0] = round_up(gsize[0], local_size[0]);
		global_size[1] = round_up(gsize[1], local_size[1]);
	}

	/* Number of elements in the global state buffer */
	int num_global_elements = global_size[0] * global_size[1];

	/* Allocate all required global memory once. */
	if(first_tile) {
		first_tile = false;

		/* Calculate max groups */

		/* Denotes the maximum work groups possible w.r.t. current requested tile size. */
		unsigned int max_work_groups = num_global_elements / WORK_POOL_SIZE + 1;

		/* Allocate work_pool_wgs memory. */
		work_pool_wgs.resize(max_work_groups * sizeof(unsigned int));
		device->mem_alloc("work_pool_wgs", work_pool_wgs, MEM_READ_WRITE);

		queue_index.resize(NUM_QUEUES * sizeof(int));
		device->mem_alloc("queue_index", queue_index, MEM_READ_WRITE);

		use_queues_flag.resize(sizeof(char));
		device->mem_alloc("use_queues_flag", use_queues_flag, MEM_READ_WRITE);

		ray_state.resize(num_global_elements);
		device->mem_alloc("ray_state", ray_state, MEM_READ_WRITE);

		split_data.resize(split_data_buffer_size(num_global_elements,
		                                         current_max_closure,
		                                         per_thread_output_buffer_size));
		device->mem_alloc("split_data", split_data, MEM_READ_WRITE);
	}

#define ENQUEUE_SPLIT_KERNEL(name, global_size, local_size) \
		if(device->have_error()) { \
			return false; \
		} \
		if(!kernel_##name->enqueue(KernelDimensions(global_size, local_size), kgbuffer, kernel_data)) { \
			return false; \
		}

	tile.sample = tile.start_sample;

	/* for exponential increase between tile updates */
	int time_multiplier = 1;

	while(tile.sample < tile.start_sample + tile.num_samples) {
		/* to keep track of how long it takes to run a number of samples */
		double start_time = time_dt();

		/* initial guess to start rolling average */
		const int initial_num_samples = 1;
		/* approx number of samples per second */
		int samples_per_second = (avg_time_per_sample > 0.0) ?
		                         int(double(time_multiplier) / avg_time_per_sample) + 1 : initial_num_samples;

		RenderTile subtile = tile;
		subtile.start_sample = tile.sample;
		subtile.num_samples = min(samples_per_second, tile.start_sample + tile.num_samples - tile.sample);

		if(device->have_error()) {
			return false;
		}

		/* reset state memory here as global size for data_init
		 * kernel might not be large enough to do in kernel
		 */
		device->mem_zero(work_pool_wgs);
		device->mem_zero(split_data);

		if(!enqueue_split_kernel_data_init(KernelDimensions(global_size, local_size),
		                                           subtile,
		                                           num_global_elements,
		                                           kgbuffer,
		                                           kernel_data,
		                                           split_data,
		                                           ray_state,
		                                           queue_index,
		                                           use_queues_flag,
		                                           work_pool_wgs
		                                           ))
		{
			return false;
		}

		ENQUEUE_SPLIT_KERNEL(path_init, global_size, local_size);

		bool activeRaysAvailable = true;

		while(activeRaysAvailable) {
			/* Twice the global work size of other kernels for
			 * ckPathTraceKernel_shadow_blocked_direct_lighting. */
			size_t global_size_shadow_blocked[2];
			global_size_shadow_blocked[0] = global_size[0] * 2;
			global_size_shadow_blocked[1] = global_size[1];

			/* Do path-iteration in host [Enqueue Path-iteration kernels. */
			for(int PathIter = 0; PathIter < 16; PathIter++) {
				ENQUEUE_SPLIT_KERNEL(scene_intersect, global_size, local_size);
				ENQUEUE_SPLIT_KERNEL(lamp_emission, global_size, local_size);
				ENQUEUE_SPLIT_KERNEL(queue_enqueue, global_size, local_size);
				ENQUEUE_SPLIT_KERNEL(background_buffer_update, global_size, local_size);
				ENQUEUE_SPLIT_KERNEL(shader_eval, global_size, local_size);
				ENQUEUE_SPLIT_KERNEL(holdout_emission_blurring_pathtermination_ao, global_size, local_size);
				ENQUEUE_SPLIT_KERNEL(direct_lighting, global_size, local_size);
				ENQUEUE_SPLIT_KERNEL(shadow_blocked, global_size_shadow_blocked, local_size);
				ENQUEUE_SPLIT_KERNEL(next_iteration_setup, global_size, local_size);

				if(task->get_cancel()) {
					return true;
				}
			}

			/* Decide if we should exit path-iteration in host. */
			device->mem_copy_from(ray_state, 0, global_size[0] * global_size[1] * sizeof(char), 1, 1);

			activeRaysAvailable = false;

			for(int rayStateIter = 0; rayStateIter < global_size[0] * global_size[1]; ++rayStateIter) {
				if(int8_t(ray_state.get_data()[rayStateIter]) != RAY_INACTIVE) {
					/* Not all rays are RAY_INACTIVE. */
					activeRaysAvailable = true;
					break;
				}
			}

			if(task->get_cancel()) {
				return true;
			}
		}

		double time_per_sample = ((time_dt()-start_time) / subtile.num_samples);

		if(avg_time_per_sample == 0.0) {
			/* start rolling average */
			avg_time_per_sample = time_per_sample;
		}
		else {
			avg_time_per_sample = alpha*time_per_sample + (1.0-alpha)*avg_time_per_sample;
		}

#undef ENQUEUE_SPLIT_KERNEL

		tile.sample += subtile.num_samples;
		task->update_progress(&tile, tile.w*tile.h*subtile.num_samples);

		time_multiplier = min(time_multiplier << 1, 10);

		if(task->get_cancel()) {
			return true;
		}
	}

	return true;
}

CCL_NAMESPACE_END

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

#include "device_split_kernel.h"

#include "kernel_types.h"
#include "kernel_split_data.h"

#include "util_time.h"

CCL_NAMESPACE_BEGIN

static const double alpha = 0.1; /* alpha for rolling average */

DeviceSplitKernel::DeviceSplitKernel(Device *device) : device(device)
{
	current_max_closure = -1;
	first_tile = true;

	avg_time_per_sample = 0.0;

	kernel_path_init = NULL;
	kernel_scene_intersect = NULL;
	kernel_lamp_emission = NULL;
	kernel_queue_enqueue = NULL;
	kernel_background_buffer_update = NULL;
	kernel_shader_eval = NULL;
	kernel_holdout_emission_blurring_pathtermination_ao = NULL;
	kernel_direct_lighting = NULL;
	kernel_shadow_blocked = NULL;
	kernel_next_iteration_setup = NULL;
}

DeviceSplitKernel::~DeviceSplitKernel()
{
	device->mem_free(split_data);
	device->mem_free(ray_state);
	device->mem_free(use_queues_flag);
	device->mem_free(queue_index);
	device->mem_free(work_pool_wgs);

	delete kernel_path_init;
	delete kernel_scene_intersect;
	delete kernel_lamp_emission;
	delete kernel_queue_enqueue;
	delete kernel_background_buffer_update;
	delete kernel_shader_eval;
	delete kernel_holdout_emission_blurring_pathtermination_ao;
	delete kernel_direct_lighting;
	delete kernel_shadow_blocked;
	delete kernel_next_iteration_setup;
}

bool DeviceSplitKernel::load_kernels(const DeviceRequestedFeatures& requested_features)
{
#define LOAD_KERNEL(name) \
		kernel_##name = get_split_kernel_function(#name, requested_features); \
		if(!kernel_##name) { \
			return false; \
		}

	LOAD_KERNEL(path_init);
	LOAD_KERNEL(scene_intersect);
	LOAD_KERNEL(lamp_emission);
	LOAD_KERNEL(queue_enqueue);
	LOAD_KERNEL(background_buffer_update);
	LOAD_KERNEL(shader_eval);
	LOAD_KERNEL(holdout_emission_blurring_pathtermination_ao);
	LOAD_KERNEL(direct_lighting);
	LOAD_KERNEL(shadow_blocked);
	LOAD_KERNEL(next_iteration_setup);

#undef LOAD_KERNEL

	current_max_closure = requested_features.max_closure;

	return true;
}

size_t DeviceSplitKernel::max_elements_for_max_buffer_size(size_t max_buffer_size, size_t passes_size)
{
	size_t size_per_element = split_data_buffer_size(1024, current_max_closure, passes_size) / 1024;
	return max_buffer_size / size_per_element;
}

bool DeviceSplitKernel::path_trace(DeviceTask *task,
                                   RenderTile& tile,
                                   device_memory& kgbuffer,
                                   device_memory& kernel_data)
{
	if(device->have_error()) {
		return false;
	}

	/* Get local size */
	size_t local_size[2];
	{
		int2 lsize = split_kernel_local_size();
		local_size[0] = lsize[0];
		local_size[1] = lsize[1];
	}

	/* Calculate per_thread_output_buffer_size. */
	size_t per_thread_output_buffer_size = task->passes_size;

	/* Set gloabl size */
	size_t global_size[2];
	{
		int2 gsize = split_kernel_global_size(task);

		/* Make sure that set work size is a multiple of local
		 * work size dimensions.
		 */
		global_size[0] = round_up(gsize[0], local_size[0]);
		global_size[1] = round_up(gsize[1], local_size[1]);
	}

	/* Number of elements in the global state buffer */
	int num_global_elements = global_size[0] * global_size[1];

	/* Allocate all required global memory once. */
	if(first_tile) {
		first_tile = false;

		/* Calculate max groups */

		/* Denotes the maximum work groups possible w.r.t. current requested tile size. */
		unsigned int max_work_groups = num_global_elements / WORK_POOL_SIZE + 1;

		/* Allocate work_pool_wgs memory. */
		work_pool_wgs.resize(max_work_groups * sizeof(unsigned int));
		device->mem_alloc("work_pool_wgs", work_pool_wgs, MEM_READ_WRITE);

		queue_index.resize(NUM_QUEUES * sizeof(int));
		device->mem_alloc("queue_index", queue_index, MEM_READ_WRITE);

		use_queues_flag.resize(sizeof(char));
		device->mem_alloc("use_queues_flag", use_queues_flag, MEM_READ_WRITE);

		ray_state.resize(num_global_elements);
		device->mem_alloc("ray_state", ray_state, MEM_READ_WRITE);

		split_data.resize(split_data_buffer_size(num_global_elements,
		                                         current_max_closure,
		                                         per_thread_output_buffer_size));
		device->mem_alloc("split_data", split_data, MEM_READ_WRITE);
	}

#define ENQUEUE_SPLIT_KERNEL(name, global_size, local_size) \
		if(device->have_error()) { \
			return false; \
		} \
		if(!kernel_##name->enqueue(KernelDimensions(global_size, local_size), kgbuffer, kernel_data)) { \
			return false; \
		}

	tile.sample = tile.start_sample;

	/* for exponential increase between tile updates */
	int time_multiplier = 1;

	while(tile.sample < tile.start_sample + tile.num_samples) {
		/* to keep track of how long it takes to run a number of samples */
		double start_time = time_dt();

		/* initial guess to start rolling average */
		const int initial_num_samples = 1;
		/* approx number of samples per second */
		int samples_per_second = (avg_time_per_sample > 0.0) ?
		                         int(double(time_multiplier) / avg_time_per_sample) + 1 : initial_num_samples;

		RenderTile subtile = tile;
		subtile.start_sample = tile.sample;
		subtile.num_samples = min(samples_per_second, tile.start_sample + tile.num_samples - tile.sample);

		if(device->have_error()) {
			return false;
		}

		/* reset state memory here as global size for data_init
		 * kernel might not be large enough to do in kernel
		 */
		device->mem_zero(work_pool_wgs);
		device->mem_zero(split_data);

		if(!enqueue_split_kernel_data_init(KernelDimensions(global_size, local_size),
		                                           subtile,
		                                           num_global_elements,
		                                           kgbuffer,
		                                           kernel_data,
		                                           split_data,
		                                           ray_state,
		                                           queue_index,
		                                           use_queues_flag,
		                                           work_pool_wgs
		                                           ))
		{
			return false;
		}

		ENQUEUE_SPLIT_KERNEL(path_init, global_size, local_size);

		bool activeRaysAvailable = true;

		while(activeRaysAvailable) {
			/* Twice the global work size of other kernels for
			 * ckPathTraceKernel_shadow_blocked_direct_lighting. */
			size_t global_size_shadow_blocked[2];
			global_size_shadow_blocked[0] = global_size[0] * 2;
			global_size_shadow_blocked[1] = global_size[1];

			/* Do path-iteration in host [Enqueue Path-iteration kernels. */
			for(int PathIter = 0; PathIter < 16; PathIter++) {
				ENQUEUE_SPLIT_KERNEL(scene_intersect, global_size, local_size);
				ENQUEUE_SPLIT_KERNEL(lamp_emission, global_size, local_size);
				ENQUEUE_SPLIT_KERNEL(queue_enqueue, global_size, local_size);
				ENQUEUE_SPLIT_KERNEL(background_buffer_update, global_size, local_size);
				ENQUEUE_SPLIT_KERNEL(shader_eval, global_size, local_size);
				ENQUEUE_SPLIT_KERNEL(holdout_emission_blurring_pathtermination_ao, global_size, local_size);
				ENQUEUE_SPLIT_KERNEL(direct_lighting, global_size, local_size);
				ENQUEUE_SPLIT_KERNEL(shadow_blocked, global_size_shadow_blocked, local_size);
				ENQUEUE_SPLIT_KERNEL(next_iteration_setup, global_size, local_size);

				if(task->get_cancel()) {
					return true;
				}
			}

			/* Decide if we should exit path-iteration in host. */
			device->mem_copy_from(ray_state, 0, global_size[0] * global_size[1] * sizeof(char), 1, 1);

			activeRaysAvailable = false;

			for(int rayStateIter = 0; rayStateIter < global_size[0] * global_size[1]; ++rayStateIter) {
				if(int8_t(ray_state.get_data()[rayStateIter]) != RAY_INACTIVE) {
					/* Not all rays are RAY_INACTIVE. */
					activeRaysAvailable = true;
					break;
				}
			}

			if(task->get_cancel()) {
				return true;
			}
		}

		double time_per_sample = ((time_dt()-start_time) / subtile.num_samples);

		if(avg_time_per_sample == 0.0) {
			/* start rolling average */
			avg_time_per_sample = time_per_sample;
		}
		else {
			avg_time_per_sample = alpha*time_per_sample + (1.0-alpha)*avg_time_per_sample;
		}

#undef ENQUEUE_SPLIT_KERNEL

		tile.sample += subtile.num_samples;
		task->update_progress(&tile, tile.w*tile.h*subtile.num_samples);

		time_multiplier = min(time_multiplier << 1, 10);

		if(task->get_cancel()) {
			return true;
		}
	}

	return true;
}

CCL_NAMESPACE_END

<|endoftext|>


<commit_before>/**
	A portable OpenAL audio subsystem implementation

	Based on https://github.com/corporateshark/Android-NDK-Game-Development-Cookbook/tree/master/Chapter5
**/

#include <atomic>
#include <thread>

#include "AudioSubsystem_OpenAL.h"
#include "OpenAL/LAL.h"

class clAudioSource_OpenAL: public iAudioSource
{
public:
};

class clAudioSubsystem_OpenAL: public iAudioSubsystem
{
public:
	clAudioSubsystem_OpenAL();
	virtual ~clAudioSubsystem_OpenAL();

	virtual void Start() override;
	virtual void Stop() override;

	virtual std::shared_ptr<iAudioSource> CreateAudioSource() override;

	virtual void SetListenerGain( float Gain ) override;

private:
	void DebugPrintVersion();

private:
	ALCdevice*  m_Device;
	ALCcontext* m_Context;

	std::shared_ptr<std::thread> m_AudioThread;
	std::atomic<bool> m_IsPendingExit;
	std::atomic<bool> m_IsInitialized;
};

std::shared_ptr<iAudioSubsystem> CreateAudioSubsystem_OpenAL()
{
	return std::make_shared<clAudioSubsystem_OpenAL>();
}

clAudioSubsystem_OpenAL::clAudioSubsystem_OpenAL()
: m_Device( nullptr )
, m_Context( nullptr )
, m_AudioThread()
, m_IsPendingExit( false )
, m_IsInitialized( false )
{
	LoadAL();
}

clAudioSubsystem_OpenAL::~clAudioSubsystem_OpenAL()
{
	UnloadAL();
}

void clAudioSubsystem_OpenAL::DebugPrintVersion()
{
	printf( "OpenAL version : %s\n", alGetString( AL_VERSION  ) );
	printf( "OpenAL vendor  : %s\n", alGetString( AL_VENDOR   ) );
	printf( "OpenAL renderer: %s\n", alGetString( AL_RENDERER ) );
	printf( "OpenAL extensions:\n%s\n", alGetString( AL_EXTENSIONS ) );
}

void clAudioSubsystem_OpenAL::Start()
{
	m_AudioThread = std::make_shared<std::thread>(
		[this]()
		{
			m_Device = alcOpenDevice( nullptr );
			m_Context = alcCreateContext( m_Device, nullptr );
			alcMakeContextCurrent( m_Context );

			DebugPrintVersion();

			m_IsInitialized = true;

			while ( !m_IsPendingExit )
			{
			}

			alcDestroyContext( m_Context );
			alcCloseDevice( m_Device );

			m_IsInitialized = false;

		}
	);
}

void clAudioSubsystem_OpenAL::Stop()
{
	m_IsPendingExit = true;

	m_AudioThread->join();
}

std::shared_ptr<iAudioSource> clAudioSubsystem_OpenAL::CreateAudioSource()
{
	return std::make_shared<clAudioSource_OpenAL>();
}

void clAudioSubsystem_OpenAL::SetListenerGain( float Gain )
{
}
<commit_msg>Implemented clAudioSubsystem_OpenAL::SetListenerGain()<commit_after>/**
	A portable OpenAL audio subsystem implementation

	Based on https://github.com/corporateshark/Android-NDK-Game-Development-Cookbook/tree/master/Chapter5
**/

#include <atomic>
#include <thread>

#include "AudioSubsystem_OpenAL.h"
#include "OpenAL/LAL.h"

class clAudioSource_OpenAL: public iAudioSource
{
public:
};

class clAudioSubsystem_OpenAL: public iAudioSubsystem
{
public:
	clAudioSubsystem_OpenAL();
	virtual ~clAudioSubsystem_OpenAL();

	virtual void Start() override;
	virtual void Stop() override;

	virtual std::shared_ptr<iAudioSource> CreateAudioSource() override;

	virtual void SetListenerGain( float Gain ) override;

private:
	void DebugPrintVersion();

private:
	ALCdevice*  m_Device;
	ALCcontext* m_Context;

	std::shared_ptr<std::thread> m_AudioThread;
	std::atomic<bool> m_IsPendingExit;
	std::atomic<bool> m_IsInitialized;
};

std::shared_ptr<iAudioSubsystem> CreateAudioSubsystem_OpenAL()
{
	return std::make_shared<clAudioSubsystem_OpenAL>();
}

clAudioSubsystem_OpenAL::clAudioSubsystem_OpenAL()
: m_Device( nullptr )
, m_Context( nullptr )
, m_AudioThread()
, m_IsPendingExit( false )
, m_IsInitialized( false )
{
	LoadAL();
}

clAudioSubsystem_OpenAL::~clAudioSubsystem_OpenAL()
{
	UnloadAL();
}

void clAudioSubsystem_OpenAL::DebugPrintVersion()
{
	printf( "OpenAL version : %s\n", alGetString( AL_VERSION  ) );
	printf( "OpenAL vendor  : %s\n", alGetString( AL_VENDOR   ) );
	printf( "OpenAL renderer: %s\n", alGetString( AL_RENDERER ) );
	printf( "OpenAL extensions:\n%s\n", alGetString( AL_EXTENSIONS ) );
}

void clAudioSubsystem_OpenAL::Start()
{
	m_AudioThread = std::make_shared<std::thread>(
		[this]()
		{
			m_Device = alcOpenDevice( nullptr );
			m_Context = alcCreateContext( m_Device, nullptr );
			alcMakeContextCurrent( m_Context );

			DebugPrintVersion();

			m_IsInitialized = true;

			while ( !m_IsPendingExit )
			{
			}

			alcDestroyContext( m_Context );
			alcCloseDevice( m_Device );

			m_IsInitialized = false;

		}
	);
}

void clAudioSubsystem_OpenAL::Stop()
{
	m_IsPendingExit = true;

	m_AudioThread->join();
}

std::shared_ptr<iAudioSource> clAudioSubsystem_OpenAL::CreateAudioSource()
{
	return std::make_shared<clAudioSource_OpenAL>();
}

void clAudioSubsystem_OpenAL::SetListenerGain( float Gain )
{
	alListenerf( AL_GAIN, Gain );
}
<|endoftext|>