<commit_before>/*
 * Copyright 2016 The Cartographer Authors
 *
 * 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 <cmath>
#include <string>
#include <vector>

#include "Eigen/Core"
#include "Eigen/Geometry"
#include "cairo/cairo.h"
#include "cartographer/common/mutex.h"
#include "cartographer/common/port.h"
#include "cartographer/io/image.h"
#include "cartographer/mapping/id.h"
#include "cartographer/transform/rigid_transform.h"
#include "cartographer_ros/msg_conversion.h"
#include "cartographer_ros/node_constants.h"
#include "cartographer_ros/ros_log_sink.h"
#include "cartographer_ros/submap.h"
#include "cartographer_ros_msgs/SubmapList.h"
#include "cartographer_ros_msgs/SubmapQuery.h"
#include "gflags/gflags.h"
#include "nav_msgs/OccupancyGrid.h"
#include "ros/ros.h"

DEFINE_double(resolution, 0.05,
              "Resolution of a grid cell in the published occupancy grid.");

namespace cartographer_ros {
namespace {

using ::cartographer::mapping::SubmapId;

constexpr cairo_format_t kCairoFormat = CAIRO_FORMAT_ARGB32;

Eigen::Affine3d ToEigen(const ::cartographer::transform::Rigid3d& rigid3) {
  return Eigen::Translation3d(rigid3.translation()) * rigid3.rotation();
}

struct SubmapState {
  SubmapState()
      : surface(::cartographer::io::MakeUniqueCairoSurfacePtr(nullptr)) {}

  // Texture data.
  int width;
  int height;
  int version;
  double resolution;
  ::cartographer::transform::Rigid3d slice_pose;
  ::cartographer::io::UniqueCairoSurfacePtr surface;
  // Pixel data used by 'surface'. Must outlive 'surface'.
  std::vector<uint32_t> cairo_data;

  // Metadata.
  ::cartographer::transform::Rigid3d pose;
  int metadata_version = -1;
};

void CairoDrawEachSubmap(
    const double scale, std::map<SubmapId, SubmapState>* submaps, cairo_t* cr,
    std::function<void(const SubmapState&)> draw_callback) {
  cairo_scale(cr, scale, scale);

  for (auto& pair : *submaps) {
    auto& submap_state = pair.second;
    if (submap_state.surface == nullptr) {
      return;
    }
    const Eigen::Matrix4d homo =
        ToEigen(submap_state.pose * submap_state.slice_pose).matrix();

    cairo_save(cr);
    cairo_matrix_t matrix;
    cairo_matrix_init(&matrix, homo(1, 0), homo(0, 0), -homo(1, 1), -homo(0, 1),
                      homo(0, 3), -homo(1, 3));
    cairo_transform(cr, &matrix);

    const double submap_resolution = submap_state.resolution;
    cairo_scale(cr, submap_resolution, submap_resolution);
    draw_callback(submap_state);
    cairo_restore(cr);
  }
}

class Node {
 public:
  explicit Node(double resolution);
  ~Node() {}

  Node(const Node&) = delete;
  Node& operator=(const Node&) = delete;

 private:
  void HandleSubmapList(const cartographer_ros_msgs::SubmapList::ConstPtr& msg);
  void DrawAndPublish(const string& frame_id, const ros::Time& time);
  void PublishOccupancyGrid(const string& frame_id, const ros::Time& time,
                            const Eigen::Array2f& origin,
                            const Eigen::Array2i& size,
                            cairo_surface_t* surface);

  ::ros::NodeHandle node_handle_;
  const double resolution_;

  ::cartographer::common::Mutex mutex_;
  ::ros::ServiceClient client_ GUARDED_BY(mutex_);
  ::ros::Subscriber submap_list_subscriber_ GUARDED_BY(mutex_);
  ::ros::Publisher occupancy_grid_publisher_ GUARDED_BY(mutex_);
  std::map<SubmapId, SubmapState> submaps_ GUARDED_BY(mutex_);
};

Node::Node(const double resolution)
    : resolution_(resolution),
      client_(node_handle_.serviceClient<::cartographer_ros_msgs::SubmapQuery>(
          kSubmapQueryServiceName)),
      submap_list_subscriber_(node_handle_.subscribe(
          kSubmapListTopic, kLatestOnlyPublisherQueueSize,
          boost::function<void(
              const cartographer_ros_msgs::SubmapList::ConstPtr&)>(
              [this](const cartographer_ros_msgs::SubmapList::ConstPtr& msg) {
                HandleSubmapList(msg);
              }))),
      occupancy_grid_publisher_(
          node_handle_.advertise<::nav_msgs::OccupancyGrid>(
              kOccupancyGridTopic, kLatestOnlyPublisherQueueSize,
              true /* latched */))

{}

void Node::HandleSubmapList(
    const cartographer_ros_msgs::SubmapList::ConstPtr& msg) {
  ::cartographer::common::MutexLocker locker(&mutex_);

  // We do not do any work if nobody listens.
  if (occupancy_grid_publisher_.getNumSubscribers() == 0) {
    return;
  }
  for (const auto& submap_msg : msg->submap) {
    const SubmapId id{submap_msg.trajectory_id, submap_msg.submap_index};
    SubmapState& submap_state = submaps_[id];
    submap_state.pose = ToRigid3d(submap_msg.pose);
    submap_state.metadata_version = submap_msg.submap_version;
    if (submap_state.surface != nullptr &&
        submap_state.version == submap_msg.submap_version) {
      continue;
    }

    auto fetched_texture = ::cartographer_ros::FetchSubmapTexture(id, &client_);
    if (fetched_texture == nullptr) {
      continue;
    }
    submap_state.width = fetched_texture->width;
    submap_state.height = fetched_texture->height;
    submap_state.version = fetched_texture->version;
    submap_state.slice_pose = fetched_texture->slice_pose;
    submap_state.resolution = fetched_texture->resolution;

    // Properly dealing with a non-common stride would make this code much more
    // complicated. Let's check that it is not needed.
    const int expected_stride = 4 * submap_state.width;
    CHECK_EQ(expected_stride,
             cairo_format_stride_for_width(kCairoFormat, submap_state.width));
    submap_state.cairo_data.clear();
    for (size_t i = 0; i < fetched_texture->intensity.size(); ++i) {
      // We use the red channel to track intensity information. The green
      // channel we use to track if a cell was ever observed.
      const uint8_t intensity = fetched_texture->intensity.at(i);
      const uint8_t alpha = fetched_texture->alpha.at(i);
      const uint8_t observed = (intensity == 0 && alpha == 0) ? 0 : 255;
      submap_state.cairo_data.push_back((alpha << 24) | (intensity << 16) |
                                        (observed << 8) | 0);
    }

    submap_state.surface = ::cartographer::io::MakeUniqueCairoSurfacePtr(
        cairo_image_surface_create_for_data(
            reinterpret_cast<unsigned char*>(submap_state.cairo_data.data()),
            kCairoFormat, submap_state.width, submap_state.height,
            expected_stride));
    CHECK_EQ(cairo_surface_status(submap_state.surface.get()),
             CAIRO_STATUS_SUCCESS)
        << cairo_status_to_string(
               cairo_surface_status(submap_state.surface.get()));
  }
  DrawAndPublish(msg->header.frame_id, msg->header.stamp);
}

void Node::DrawAndPublish(const string& frame_id, const ros::Time& time) {
  if (submaps_.empty()) {
    return;
  }

  Eigen::AlignedBox2f bounding_box;
  {
    auto surface = ::cartographer::io::MakeUniqueCairoSurfacePtr(
        cairo_image_surface_create(kCairoFormat, 1, 1));
    auto cr =
        ::cartographer::io::MakeUniqueCairoPtr(cairo_create(surface.get()));
    const auto update_bounding_box = [&bounding_box, &cr](double x, double y) {
      cairo_user_to_device(cr.get(), &x, &y);
      bounding_box.extend(Eigen::Vector2f(x, y));
    };

    CairoDrawEachSubmap(
        1. / resolution_, &submaps_, cr.get(),
        [&update_bounding_box, &bounding_box](const SubmapState& submap_state) {
          update_bounding_box(0, 0);
          update_bounding_box(submap_state.width, 0);
          update_bounding_box(0, submap_state.height);
          update_bounding_box(submap_state.width, submap_state.height);
        });
  }

  const int kPaddingPixel = 5;
  const Eigen::Array2i size(
      std::ceil(bounding_box.sizes().x()) + 2 * kPaddingPixel,
      std::ceil(bounding_box.sizes().y()) + 2 * kPaddingPixel);
  const Eigen::Array2f origin(-bounding_box.min().x() + kPaddingPixel,
                              -bounding_box.min().y() + kPaddingPixel);

  {
    auto surface = ::cartographer::io::MakeUniqueCairoSurfacePtr(
        cairo_image_surface_create(kCairoFormat, size.x(), size.y()));
    auto cr =
        ::cartographer::io::MakeUniqueCairoPtr(cairo_create(surface.get()));
    cairo_set_source_rgba(cr.get(), 0.5, 0.0, 0.0, 1.);
    cairo_paint(cr.get());
    cairo_translate(cr.get(), origin.x(), origin.y());
    CairoDrawEachSubmap(1. / resolution_, &submaps_, cr.get(),
                        [&cr](const SubmapState& submap_state) {
                          cairo_set_source_surface(
                              cr.get(), submap_state.surface.get(), 0., 0.);
                          cairo_paint(cr.get());
                        });
    cairo_surface_flush(surface.get());
    PublishOccupancyGrid(frame_id, time, origin, size, surface.get());
  }
}

void Node::PublishOccupancyGrid(const string& frame_id, const ros::Time& time,
                                const Eigen::Array2f& origin,
                                const Eigen::Array2i& size,
                                cairo_surface_t* surface) {
  nav_msgs::OccupancyGrid occupancy_grid;
  occupancy_grid.header.stamp = time;
  occupancy_grid.header.frame_id = frame_id;
  occupancy_grid.info.map_load_time = time;
  occupancy_grid.info.resolution = resolution_;
  occupancy_grid.info.width = size.x();
  occupancy_grid.info.height = size.y();
  occupancy_grid.info.origin.position.x = -origin.x() * resolution_;
  occupancy_grid.info.origin.position.y =
      (-size.y() + origin.y()) * resolution_;
  occupancy_grid.info.origin.position.z = 0.;
  occupancy_grid.info.origin.orientation.w = 1.;
  occupancy_grid.info.origin.orientation.x = 0.;
  occupancy_grid.info.origin.orientation.y = 0.;
  occupancy_grid.info.origin.orientation.z = 0.;

  const uint32* pixel_data =
      reinterpret_cast<uint32*>(cairo_image_surface_get_data(surface));
  occupancy_grid.data.reserve(size.x() * size.y());
  for (int y = size.y() - 1; y >= 0; --y) {
    for (int x = 0; x < size.x(); ++x) {
      const uint32 packed = pixel_data[y * size.x() + x];
      const unsigned char color = packed >> 16;
      const unsigned char observed = packed >> 8;
      const int value =
          observed == 0
              ? -1
              : ::cartographer::common::RoundToInt((1. - color / 255.) * 100.);
      CHECK_LE(-1, value);
      CHECK_GE(100, value);
      occupancy_grid.data.push_back(value);
    }
  }
  occupancy_grid_publisher_.publish(occupancy_grid);
}

}  // namespace
}  // namespace cartographer_ros

int main(int argc, char** argv) {
  google::InitGoogleLogging(argv[0]);
  google::ParseCommandLineFlags(&argc, &argv, true);

  ::ros::init(argc, argv, "cartographer_occupancy_grid_node");
  ::ros::start();

  cartographer_ros::ScopedRosLogSink ros_log_sink;
  ::cartographer_ros::Node node(FLAGS_resolution);

  ::ros::spin();
  ::ros::shutdown();
}
<commit_msg>Configurable occupancy grid publishing speed (#504)<commit_after>/*
 * Copyright 2016 The Cartographer Authors
 *
 * 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 <cmath>
#include <string>
#include <vector>

#include "Eigen/Core"
#include "Eigen/Geometry"
#include "cairo/cairo.h"
#include "cartographer/common/mutex.h"
#include "cartographer/common/port.h"
#include "cartographer/io/image.h"
#include "cartographer/mapping/id.h"
#include "cartographer/transform/rigid_transform.h"
#include "cartographer_ros/msg_conversion.h"
#include "cartographer_ros/node_constants.h"
#include "cartographer_ros/ros_log_sink.h"
#include "cartographer_ros/submap.h"
#include "cartographer_ros_msgs/SubmapList.h"
#include "cartographer_ros_msgs/SubmapQuery.h"
#include "gflags/gflags.h"
#include "nav_msgs/OccupancyGrid.h"
#include "ros/ros.h"

DEFINE_double(resolution, 0.05,
              "Resolution of a grid cell in the published occupancy grid.");
DEFINE_double(publish_period_sec, 1.0, "OccupancyGrid publishing period.");

namespace cartographer_ros {
namespace {

using ::cartographer::mapping::SubmapId;

constexpr cairo_format_t kCairoFormat = CAIRO_FORMAT_ARGB32;

Eigen::Affine3d ToEigen(const ::cartographer::transform::Rigid3d& rigid3) {
  return Eigen::Translation3d(rigid3.translation()) * rigid3.rotation();
}

struct SubmapState {
  SubmapState()
      : surface(::cartographer::io::MakeUniqueCairoSurfacePtr(nullptr)) {}

  // Texture data.
  int width;
  int height;
  int version;
  double resolution;
  ::cartographer::transform::Rigid3d slice_pose;
  ::cartographer::io::UniqueCairoSurfacePtr surface;
  // Pixel data used by 'surface'. Must outlive 'surface'.
  std::vector<uint32_t> cairo_data;

  // Metadata.
  ::cartographer::transform::Rigid3d pose;
  int metadata_version = -1;
};

void CairoDrawEachSubmap(
    const double scale, std::map<SubmapId, SubmapState>* submaps, cairo_t* cr,
    std::function<void(const SubmapState&)> draw_callback) {
  cairo_scale(cr, scale, scale);

  for (auto& pair : *submaps) {
    auto& submap_state = pair.second;
    if (submap_state.surface == nullptr) {
      return;
    }
    const Eigen::Matrix4d homo =
        ToEigen(submap_state.pose * submap_state.slice_pose).matrix();

    cairo_save(cr);
    cairo_matrix_t matrix;
    cairo_matrix_init(&matrix, homo(1, 0), homo(0, 0), -homo(1, 1), -homo(0, 1),
                      homo(0, 3), -homo(1, 3));
    cairo_transform(cr, &matrix);

    const double submap_resolution = submap_state.resolution;
    cairo_scale(cr, submap_resolution, submap_resolution);
    draw_callback(submap_state);
    cairo_restore(cr);
  }
}

class Node {
 public:
  explicit Node(double resolution, double publish_period_sec);
  ~Node() {}

  Node(const Node&) = delete;
  Node& operator=(const Node&) = delete;

 private:
  void HandleSubmapList(const cartographer_ros_msgs::SubmapList::ConstPtr& msg);
  void DrawAndPublish(const ::ros::WallTimerEvent& timer_event);
  void PublishOccupancyGrid(const string& frame_id, const ros::Time& time,
                            const Eigen::Array2f& origin,
                            const Eigen::Array2i& size,
                            cairo_surface_t* surface);

  ::ros::NodeHandle node_handle_;
  const double resolution_;

  ::cartographer::common::Mutex mutex_;
  ::ros::ServiceClient client_ GUARDED_BY(mutex_);
  ::ros::Subscriber submap_list_subscriber_ GUARDED_BY(mutex_);
  ::ros::Publisher occupancy_grid_publisher_ GUARDED_BY(mutex_);
  std::map<SubmapId, SubmapState> submaps_ GUARDED_BY(mutex_);
  ::ros::WallTimer occupancy_grid_publisher_timer_;
  std::string last_frame_id_;
  ros::Time last_timestamp_;
};

Node::Node(const double resolution, const double publish_period_sec)
    : resolution_(resolution),
      client_(node_handle_.serviceClient<::cartographer_ros_msgs::SubmapQuery>(
          kSubmapQueryServiceName)),
      submap_list_subscriber_(node_handle_.subscribe(
          kSubmapListTopic, kLatestOnlyPublisherQueueSize,
          boost::function<void(
              const cartographer_ros_msgs::SubmapList::ConstPtr&)>(
              [this](const cartographer_ros_msgs::SubmapList::ConstPtr& msg) {
                HandleSubmapList(msg);
              }))),
      occupancy_grid_publisher_(
          node_handle_.advertise<::nav_msgs::OccupancyGrid>(
              kOccupancyGridTopic, kLatestOnlyPublisherQueueSize,
              true /* latched */)),
      occupancy_grid_publisher_timer_(
          node_handle_.createWallTimer(::ros::WallDuration(publish_period_sec),
                                       &Node::DrawAndPublish, this)) {}

void Node::HandleSubmapList(
    const cartographer_ros_msgs::SubmapList::ConstPtr& msg) {
  ::cartographer::common::MutexLocker locker(&mutex_);

  // We do not do any work if nobody listens.
  if (occupancy_grid_publisher_.getNumSubscribers() == 0) {
    return;
  }
  for (const auto& submap_msg : msg->submap) {
    const SubmapId id{submap_msg.trajectory_id, submap_msg.submap_index};
    SubmapState& submap_state = submaps_[id];
    submap_state.pose = ToRigid3d(submap_msg.pose);
    submap_state.metadata_version = submap_msg.submap_version;
    if (submap_state.surface != nullptr &&
        submap_state.version == submap_msg.submap_version) {
      continue;
    }

    auto fetched_texture = ::cartographer_ros::FetchSubmapTexture(id, &client_);
    if (fetched_texture == nullptr) {
      continue;
    }
    submap_state.width = fetched_texture->width;
    submap_state.height = fetched_texture->height;
    submap_state.version = fetched_texture->version;
    submap_state.slice_pose = fetched_texture->slice_pose;
    submap_state.resolution = fetched_texture->resolution;

    // Properly dealing with a non-common stride would make this code much more
    // complicated. Let's check that it is not needed.
    const int expected_stride = 4 * submap_state.width;
    CHECK_EQ(expected_stride,
             cairo_format_stride_for_width(kCairoFormat, submap_state.width));
    submap_state.cairo_data.clear();
    for (size_t i = 0; i < fetched_texture->intensity.size(); ++i) {
      // We use the red channel to track intensity information. The green
      // channel we use to track if a cell was ever observed.
      const uint8_t intensity = fetched_texture->intensity.at(i);
      const uint8_t alpha = fetched_texture->alpha.at(i);
      const uint8_t observed = (intensity == 0 && alpha == 0) ? 0 : 255;
      submap_state.cairo_data.push_back((alpha << 24) | (intensity << 16) |
                                        (observed << 8) | 0);
    }

    submap_state.surface = ::cartographer::io::MakeUniqueCairoSurfacePtr(
        cairo_image_surface_create_for_data(
            reinterpret_cast<unsigned char*>(submap_state.cairo_data.data()),
            kCairoFormat, submap_state.width, submap_state.height,
            expected_stride));
    CHECK_EQ(cairo_surface_status(submap_state.surface.get()),
             CAIRO_STATUS_SUCCESS)
        << cairo_status_to_string(
               cairo_surface_status(submap_state.surface.get()));
  }
  last_timestamp_ = msg->header.stamp;
  last_frame_id_ = msg->header.frame_id;
}

void Node::DrawAndPublish(const ::ros::WallTimerEvent& unused_timer_event) {
  if (submaps_.empty() || last_frame_id_.empty()) {
    return;
  }

  ::cartographer::common::MutexLocker locker(&mutex_);
  Eigen::AlignedBox2f bounding_box;
  {
    auto surface = ::cartographer::io::MakeUniqueCairoSurfacePtr(
        cairo_image_surface_create(kCairoFormat, 1, 1));
    auto cr =
        ::cartographer::io::MakeUniqueCairoPtr(cairo_create(surface.get()));
    const auto update_bounding_box = [&bounding_box, &cr](double x, double y) {
      cairo_user_to_device(cr.get(), &x, &y);
      bounding_box.extend(Eigen::Vector2f(x, y));
    };

    CairoDrawEachSubmap(
        1. / resolution_, &submaps_, cr.get(),
        [&update_bounding_box, &bounding_box](const SubmapState& submap_state) {
          update_bounding_box(0, 0);
          update_bounding_box(submap_state.width, 0);
          update_bounding_box(0, submap_state.height);
          update_bounding_box(submap_state.width, submap_state.height);
        });
  }

  const int kPaddingPixel = 5;
  const Eigen::Array2i size(
      std::ceil(bounding_box.sizes().x()) + 2 * kPaddingPixel,
      std::ceil(bounding_box.sizes().y()) + 2 * kPaddingPixel);
  const Eigen::Array2f origin(-bounding_box.min().x() + kPaddingPixel,
                              -bounding_box.min().y() + kPaddingPixel);

  {
    auto surface = ::cartographer::io::MakeUniqueCairoSurfacePtr(
        cairo_image_surface_create(kCairoFormat, size.x(), size.y()));
    auto cr =
        ::cartographer::io::MakeUniqueCairoPtr(cairo_create(surface.get()));
    cairo_set_source_rgba(cr.get(), 0.5, 0.0, 0.0, 1.);
    cairo_paint(cr.get());
    cairo_translate(cr.get(), origin.x(), origin.y());
    CairoDrawEachSubmap(1. / resolution_, &submaps_, cr.get(),
                        [&cr](const SubmapState& submap_state) {
                          cairo_set_source_surface(
                              cr.get(), submap_state.surface.get(), 0., 0.);
                          cairo_paint(cr.get());
                        });
    cairo_surface_flush(surface.get());
    PublishOccupancyGrid(last_frame_id_, last_timestamp_, origin, size,
                         surface.get());
  }
}

void Node::PublishOccupancyGrid(const string& frame_id, const ros::Time& time,
                                const Eigen::Array2f& origin,
                                const Eigen::Array2i& size,
                                cairo_surface_t* surface) {
  nav_msgs::OccupancyGrid occupancy_grid;
  occupancy_grid.header.stamp = time;
  occupancy_grid.header.frame_id = frame_id;
  occupancy_grid.info.map_load_time = time;
  occupancy_grid.info.resolution = resolution_;
  occupancy_grid.info.width = size.x();
  occupancy_grid.info.height = size.y();
  occupancy_grid.info.origin.position.x = -origin.x() * resolution_;
  occupancy_grid.info.origin.position.y =
      (-size.y() + origin.y()) * resolution_;
  occupancy_grid.info.origin.position.z = 0.;
  occupancy_grid.info.origin.orientation.w = 1.;
  occupancy_grid.info.origin.orientation.x = 0.;
  occupancy_grid.info.origin.orientation.y = 0.;
  occupancy_grid.info.origin.orientation.z = 0.;

  const uint32* pixel_data =
      reinterpret_cast<uint32*>(cairo_image_surface_get_data(surface));
  occupancy_grid.data.reserve(size.x() * size.y());
  for (int y = size.y() - 1; y >= 0; --y) {
    for (int x = 0; x < size.x(); ++x) {
      const uint32 packed = pixel_data[y * size.x() + x];
      const unsigned char color = packed >> 16;
      const unsigned char observed = packed >> 8;
      const int value =
          observed == 0
              ? -1
              : ::cartographer::common::RoundToInt((1. - color / 255.) * 100.);
      CHECK_LE(-1, value);
      CHECK_GE(100, value);
      occupancy_grid.data.push_back(value);
    }
  }
  occupancy_grid_publisher_.publish(occupancy_grid);
}

}  // namespace
}  // namespace cartographer_ros

int main(int argc, char** argv) {
  google::InitGoogleLogging(argv[0]);
  google::ParseCommandLineFlags(&argc, &argv, true);

  ::ros::init(argc, argv, "cartographer_occupancy_grid_node");
  ::ros::start();

  cartographer_ros::ScopedRosLogSink ros_log_sink;
  ::cartographer_ros::Node node(FLAGS_resolution, FLAGS_publish_period_sec);

  ::ros::spin();
  ::ros::shutdown();
}
<|endoftext|>


<commit_before>// Copyright (C) 2017 Elviss Strazdins
// This file is part of the Ouzel engine.

#include "RendererOGLAndroid.h"
#include "core/android/ApplicationAndroid.h"
#include "utils/Log.h"

namespace ouzel
{
    namespace graphics
    {
        RendererOGLAndroid::~RendererOGLAndroid()
        {
        }

        bool RendererOGLAndroid::init(Window* newWindow,
                                      const Size2& newSize,
                                      uint32_t newSampleCount,
                                      Texture::Filter newTextureFilter,
                                      PixelFormat newBackBufferFormat,
                                      bool newVerticalSync,
                                      bool newDepth)
        {
            ApplicationAndroid* applicationAndroid = static_cast<ApplicationAndroid*>(sharedApplication);
            JavaVM* javaVM = applicationAndroid->getJavaVM();
            JNIEnv* jniEnv;

            if (javaVM->GetEnv(reinterpret_cast<void**>(&jniEnv), JNI_VERSION_1_6) != JNI_OK)
            {
                Log(Log::Level::ERR) << "Failed to get JNI environment";
            }

            jobject mainActivity = applicationAndroid->getMainActivity();
            jmethodID createSurfaceMethod = applicationAndroid->getCreateSurfaceMethod();
            jniEnv->CallVoidMethod(mainActivity, createSurfaceMethod, 8, 8, 8, 8, newDepth ? 24 : 0, 0, (newSampleCount > 1) ? 1 : 0, newSampleCount);

            apiMajorVersion = 2;
            apiMinorVersion = 0;

            return RendererOGL::init(newWindow, newSize, newSampleCount, newTextureFilter, newBackBufferFormat, newVerticalSync, newDepth);
        }
    } // namespace graphics
} // namespace ouzel
<commit_msg>Return false if failed to get Java VM<commit_after>// Copyright (C) 2017 Elviss Strazdins
// This file is part of the Ouzel engine.

#include "RendererOGLAndroid.h"
#include "core/android/ApplicationAndroid.h"
#include "utils/Log.h"

namespace ouzel
{
    namespace graphics
    {
        RendererOGLAndroid::~RendererOGLAndroid()
        {
        }

        bool RendererOGLAndroid::init(Window* newWindow,
                                      const Size2& newSize,
                                      uint32_t newSampleCount,
                                      Texture::Filter newTextureFilter,
                                      PixelFormat newBackBufferFormat,
                                      bool newVerticalSync,
                                      bool newDepth)
        {
            ApplicationAndroid* applicationAndroid = static_cast<ApplicationAndroid*>(sharedApplication);
            JavaVM* javaVM = applicationAndroid->getJavaVM();
            JNIEnv* jniEnv;

            if (javaVM->GetEnv(reinterpret_cast<void**>(&jniEnv), JNI_VERSION_1_6) != JNI_OK)
            {
                Log(Log::Level::ERR) << "Failed to get JNI environment";
                return false;
            }

            jobject mainActivity = applicationAndroid->getMainActivity();
            jmethodID createSurfaceMethod = applicationAndroid->getCreateSurfaceMethod();
            jniEnv->CallVoidMethod(mainActivity, createSurfaceMethod, 8, 8, 8, 8, newDepth ? 24 : 0, 0, (newSampleCount > 1) ? 1 : 0, newSampleCount);

            apiMajorVersion = 2;
            apiMinorVersion = 0;

            return RendererOGL::init(newWindow, newSize, newSampleCount, newTextureFilter, newBackBufferFormat, newVerticalSync, newDepth);
        }
    } // namespace graphics
} // namespace ouzel
<|endoftext|>


<commit_before>/*
 * TP1.cpp
 *
 *  Created on: 02/02/2015
 *      Author: vagner
 */

#include "TP0.h"
#include "../lib/TrabalhoPratico.h"
#include <iostream>
#include "../lib/PAAException.h"
#include <new>
#include <sstream>
#include <unistd.h>

namespace PAA {

TP0::TP0():TrabalhoPratico()
{
 //Do nothing

}

TP0::~TP0() {
	// TODO Auto-generated destructor stub
}

void TP0::run(void ){
	try {
			this->showUserMessage("Iniciando a execução do TP1");

			this->showUserMessage("Ola Mundo");

			sleep(5);

			this->showUserMessage("Finalizando a execução do TP1");

			this->setFinalTime();

	} catch (const std::exception& e) {

		std::stringstream ss;
		ss << "Erro durante a alocaco de memoria. Tipo de excecao: " << e.what();
		throw PAA::PAAException(ss.str());

	}

}

void TP0::showUserMessage(const std::string& message){

	PAA::TrabalhoPratico::showUserMessage(message);

}

void TP0::showStatistics(void){

	PAA::TrabalhoPratico::showStatistics();
}

void TP0::setFinalTime(void){

	PAA::TrabalhoPratico::setFinalTime();

}

}/* namespace PAA */
<commit_msg>Alteração no arquivo TP0.cpp aumentando o tempo de 'sleep' para 10 segundos<commit_after>/*
 * TP1.cpp
 *
 *  Created on: 02/02/2015
 *      Author: vagner
 */

#include "TP0.h"
#include "../lib/TrabalhoPratico.h"
#include <iostream>
#include "../lib/PAAException.h"
#include <new>
#include <sstream>
#include <unistd.h>

namespace PAA {

TP0::TP0():TrabalhoPratico()
{
 //Do nothing

}

TP0::~TP0() {
	// TODO Auto-generated destructor stub
}

void TP0::run(void ){
	try {
			this->showUserMessage("Iniciando a execução do TP1");

			this->showUserMessage("Ola Mundo");

			sleep(10);

			this->showUserMessage("Finalizando a execução do TP1");

			this->setFinalTime();

	} catch (const std::exception& e) {

		std::stringstream ss;
		ss << "Erro durante a alocaco de memoria. Tipo de excecao: " << e.what();
		throw PAA::PAAException(ss.str());

	}

}

void TP0::showUserMessage(const std::string& message){

	PAA::TrabalhoPratico::showUserMessage(message);

}

void TP0::showStatistics(void){

	PAA::TrabalhoPratico::showStatistics();
}

void TP0::setFinalTime(void){

	PAA::TrabalhoPratico::setFinalTime();

}

}/* namespace PAA */
<|endoftext|>


<commit_before>/**
* Copyright (c) 2014-2016 Dallin Wellington
*
*/

#include <Platform/Platform.h>

#ifdef MONSOON_OS_WINDOWS

#define WIN32_LEAN_AND_MEAN
#include <windows.h>

#include <App/Application.h>
#include <D3D11Renderer.h>

using namespace Monsoon;

class PrimitivesApplication : public Application
{
public:
	PrimitivesApplication()
		: Application((Renderer::Renderer*)(new Renderer::D3D11Renderer(Renderer::RendererSettings(), &mEventManager, &mTransformSystem))) {

	}

	~PrimitivesApplication() {

	}

protected:
	float cameraTheta;

	void OnInitialize() {
		Renderer::VertexBufferHandle pyramidVB = mRenderer->CreatePyramid(1.75f, 1.75f);
		Renderer::VertexBufferHandle cubeVB = mRenderer->CreateCube(1.0f);
		Renderer::VertexBufferHandle planeVB = mRenderer->CreatePlane(10.0f, 7.0f);

		Renderer::MeshComponent triangle_one;
		Scene::TransformComponent triangleOnePosition;
		triangle_one.VertexBuffer = pyramidVB;
		triangleOnePosition.position = Math::Vector3(2.0f, 0.0f, 0.0f);
		mRenderer->AttachMeshComponent(0, triangle_one);
		mTransformSystem.AttachComponent(0, triangleOnePosition);

		Renderer::MeshComponent cube_one;
		Scene::TransformComponent cubeOnePosition;
		cube_one.VertexBuffer = cubeVB;
		cubeOnePosition.position = Math::Vector3(-2.0f, 0.0f, 0.0f);
		mRenderer->AttachMeshComponent(1, cube_one);
		mTransformSystem.AttachComponent(1, cubeOnePosition);

		Renderer::MeshComponent plane;
		Scene::TransformComponent planeOnePosition;
		plane.VertexBuffer = planeVB;
		planeOnePosition.position = Math::Vector3(0.0f, -1.0f, 0.0f);
		planeOnePosition.pitch = 1.57f;
		plane.TextureId = -1;
		mRenderer->AttachMeshComponent(2, plane);
		mTransformSystem.AttachComponent(2, planeOnePosition);

		cameraTheta = 0.0f;
	}

	void OnUpdate() {
		Renderer::Camera& camera = mRenderer->GetCamera();

		mTransformSystem.Rotate(0, Math::Vector3(0.0f, mGameClock.getDeltaTime() * 2.0f, 0.0f));
		mTransformSystem.SetPosition(0, Math::Vector3(mTransformSystem.GetPosition(0).mX, (cos(cameraTheta) + 1.0f), mTransformSystem.GetPosition(0).mZ));

		camera.x = cos(cameraTheta) * 15.0f;
		camera.y = 8.0f;
		camera.z = sin(cameraTheta) * 15.0f;

		cameraTheta += mGameClock.getDeltaTime();
	}

	void OnShutdown() {
		mTransformSystem.DetachComponent(2);
		mRenderer->DetachMeshComponent(2);

		mTransformSystem.DetachComponent(1);
		mRenderer->DetachMeshComponent(1);

		mTransformSystem.DetachComponent(0);
		mRenderer->DetachMeshComponent(0);

		mRenderer->ReleaseTexture(0);
	}

};

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pScmdline, int iCmdshow) {
	PrimitivesApplication application;
	application.Run();
	return 0;
}

#endif<commit_msg>Primitives sample now quits on ESC key event.<commit_after>/**
* Copyright (c) 2014-2016 Dallin Wellington
*
*/

#include <Platform/Platform.h>

#ifdef MONSOON_OS_WINDOWS

#define WIN32_LEAN_AND_MEAN
#include <windows.h>

#include <App/Application.h>
#include <D3D11Renderer.h>

using namespace Monsoon;

class PrimitivesApplication : public Application
{
public:
	PrimitivesApplication()
		: Application((Renderer::Renderer*)(new Renderer::D3D11Renderer(Renderer::RendererSettings(), &mEventManager, &mTransformSystem))) {

	}

	~PrimitivesApplication() {

	}

protected:
	float cameraTheta;

	void OnInitialize() {
		Renderer::VertexBufferHandle pyramidVB = mRenderer->CreatePyramid(1.75f, 1.75f);
		Renderer::VertexBufferHandle cubeVB = mRenderer->CreateCube(1.0f);
		Renderer::VertexBufferHandle planeVB = mRenderer->CreatePlane(10.0f, 7.0f);

		Renderer::MeshComponent triangle_one;
		Scene::TransformComponent triangleOnePosition;
		triangle_one.VertexBuffer = pyramidVB;
		triangleOnePosition.position = Math::Vector3(2.0f, 0.0f, 0.0f);
		mRenderer->AttachMeshComponent(0, triangle_one);
		mTransformSystem.AttachComponent(0, triangleOnePosition);

		Renderer::MeshComponent cube_one;
		Scene::TransformComponent cubeOnePosition;
		cube_one.VertexBuffer = cubeVB;
		cubeOnePosition.position = Math::Vector3(-2.0f, 0.0f, 0.0f);
		mRenderer->AttachMeshComponent(1, cube_one);
		mTransformSystem.AttachComponent(1, cubeOnePosition);

		Renderer::MeshComponent plane;
		Scene::TransformComponent planeOnePosition;
		plane.VertexBuffer = planeVB;
		planeOnePosition.position = Math::Vector3(0.0f, -1.0f, 0.0f);
		planeOnePosition.pitch = 1.57f;
		plane.TextureId = -1;
		mRenderer->AttachMeshComponent(2, plane);
		mTransformSystem.AttachComponent(2, planeOnePosition);

		cameraTheta = 0.0f;
	}

	void OnUpdate() {
		Renderer::Camera& camera = mRenderer->GetCamera();

		mTransformSystem.Rotate(0, Math::Vector3(0.0f, mGameClock.getDeltaTime() * 2.0f, 0.0f));
		mTransformSystem.SetPosition(0, Math::Vector3(mTransformSystem.GetPosition(0).mX, (cos(cameraTheta) + 1.0f), mTransformSystem.GetPosition(0).mZ));

		camera.x = cos(cameraTheta) * 15.0f;
		camera.y = 8.0f;
		camera.z = sin(cameraTheta) * 15.0f;

		cameraTheta += mGameClock.getDeltaTime();

		if (GetAsyncKeyState(VK_ESCAPE))
			Quit();
	}

	void OnShutdown() {
		mTransformSystem.DetachComponent(2);
		mRenderer->DetachMeshComponent(2);

		mTransformSystem.DetachComponent(1);
		mRenderer->DetachMeshComponent(1);

		mTransformSystem.DetachComponent(0);
		mRenderer->DetachMeshComponent(0);
	}

};

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pScmdline, int iCmdshow) {
	PrimitivesApplication application;
	application.Run();
	return 0;
}

#endif<|endoftext|>


<commit_before>//
// Copyright Antoine Leblanc 2010 - 2015
// Distributed under the MIT license.
//
// http://nauths.fr
// http://github.com/nicuveo
// mailto://antoine.jp.leblanc@gmail.com
//

#ifndef NPL_RANGE_HH_
# define NPL_RANGE_HH_

//HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
// Includes

# include "nauths/npl/pair.hh"

//HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
// Declarations

namespace npl
{

  template <typename T>
  class Range : public std::pair<T, T>
  {
    public:
      using std::pair<T, T>::pair;

      T const& begin() const { return this->first;  }
      T const& end()   const { return this->second; }
  };

  template <typename C>
  Range<typename C::const_iterator> range(C const& c)
  {
    return Range(c.begin(), c.end());
  }

  template <typename C>
  Range<typename C::iterator> range(C& c)
  {
    return Range(c.begin(), c.end());
  }

  template <typename C>
  Range<typename C::const_reverse_iterator> rrange(C const& c)
  {
    return Range(c.rbegin(), c.rend());
  }

  template <typename C>
  Range<typename C::reverse_iterator> rrange(C& c)
  {
    return Range(c.rbegin(), c.rend());
  }

}

#endif /* !NPL_RANGE_HH_ */
<commit_msg>Fixed range functions template.<commit_after>//
// Copyright Antoine Leblanc 2010 - 2015
// Distributed under the MIT license.
//
// http://nauths.fr
// http://github.com/nicuveo
// mailto://antoine.jp.leblanc@gmail.com
//

#ifndef NPL_RANGE_HH_
# define NPL_RANGE_HH_

//HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
// Includes

# include "nauths/npl/pair.hh"

//HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
// Declarations

namespace npl
{

  template <typename T>
  class Range : public std::pair<T, T>
  {
    public:
      using std::pair<T, T>::pair;

      T const& begin() const { return this->first;  }
      T const& end()   const { return this->second; }
  };

  template <typename C>
  Range<typename C::const_iterator> range(C const& c)
  {
    return Range<typename C::const_iterator>(c.begin(), c.end());
  }

  template <typename C>
  Range<typename C::iterator> range(C& c)
  {
    return Range<typename C::iterator>(c.begin(), c.end());
  }

  template <typename C>
  Range<typename C::const_reverse_iterator> rrange(C const& c)
  {
    return Range<typename C::const_reverse_iterator>(c.rbegin(), c.rend());
  }

  template <typename C>
  Range<typename C::reverse_iterator> rrange(C& c)
  {
    return Range<typename C::reverse_iterator>(c.rbegin(), c.rend());
  }

}

#endif /* !NPL_RANGE_HH_ */
<|endoftext|>


<commit_before>#ifndef LIBTEN_TASK_CONTEXT_HH
#define LIBTEN_TASK_CONTEXT_HH

//! \file
//! context handles switching stacks
//
//! there are two implementations, ucontext
//! and fcontext. ucontext is slower because it
//! also saves and restores the signal handler state
//! this requires system calls. fcontext only saves
//! the bare minimum register states.

#if USE_BOOST_FCONTEXT
#include <string.h>
#include <boost/context/fcontext.hpp>

namespace ten {

struct context : boost::ctx::fcontext_t {
    typedef void (*proc)(void *);
    typedef void (*proc_ctx)(intptr_t);
    intptr_t arg;

    void init(proc f=nullptr, void *arg_=nullptr, char *stack=nullptr, size_t stack_size=0) {
        memset(this, 0, sizeof(context));
        arg = (intptr_t)arg_;
        if (f && stack && stack_size) {
            fc_stack.base = stack;
            // stack grows down
            fc_stack.limit = stack-stack_size;
            boost::ctx::make_fcontext(this, (proc_ctx)f);
        }
    }

    void swap(context *other) {
        boost::ctx::jump_fcontext(this, other, other->arg);
    }
};

} // end namespace ten

#else
#error "no context implementation chosen"
#endif

#endif // LIBTEN_TASK_CONTEXT_HH
<commit_msg>support boost 1.52<commit_after>#ifndef LIBTEN_TASK_CONTEXT_HH
#define LIBTEN_TASK_CONTEXT_HH

//! \file
//! context handles switching stacks
//
//! there are two implementations, ucontext
//! and fcontext. ucontext is slower because it
//! also saves and restores the signal handler state
//! this requires system calls. fcontext only saves
//! the bare minimum register states.

#if USE_BOOST_FCONTEXT
#include <string.h>
#include <boost/version.hpp>
#include <boost/context/fcontext.hpp>

namespace ten {

#if BOOST_VERSION == 105100
struct context : boost::ctx::fcontext_t {
    typedef void (*proc)(void *);
    typedef void (*proc_ctx)(intptr_t);
    intptr_t arg;

    void init(proc f=nullptr, void *arg_=nullptr, char *stack=nullptr, size_t stack_size=0) {
        memset(this, 0, sizeof(context));
        arg = (intptr_t)arg_;
        if (f && stack && stack_size) {
            fc_stack.base = stack;
            // stack grows down
            fc_stack.limit = stack-stack_size;
            boost::ctx::make_fcontext(this, (proc_ctx)f);
        }
    }

    void swap(context *other) {
        boost::ctx::jump_fcontext(this, other, other->arg);
    }
};
#elif BOOST_VERSION >= 105200
struct context : boost::context::fcontext_t {
    typedef void (*proc)(void *);
    typedef void (*proc_ctx)(intptr_t);
    intptr_t arg;
    boost::context::fcontext_t *ctx;

    void init(proc f=nullptr, void *arg_=nullptr, char *stack=nullptr, size_t stack_size=0) {
        memset(this, 0, sizeof(context));
        arg = (intptr_t)arg_;
        if (f && stack && stack_size) {
            ctx = boost::context::make_fcontext(stack, stack_size, (proc_ctx)f);
        } else {
            ctx = this;
        }
    }

    void swap(context *other) {
        boost::context::jump_fcontext(ctx, other->ctx, other->arg);
    }
};
#endif

} // end namespace ten

#else
#error "no context implementation chosen"
#endif

#endif // LIBTEN_TASK_CONTEXT_HH
<|endoftext|>


<commit_before>/**
 * @file llthread.cpp
 *
 * $LicenseInfo:firstyear=2004&license=viewerlgpl$
 * Second Life Viewer Source Code
 * Copyright (C) 2010-2013, Linden Research, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation;
 * version 2.1 of the License only.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 * $/LicenseInfo$
 */

#include "linden_common.h"
#include "llapr.h"

#include "apr_portable.h"

#include "llthread.h"
#include "llmutex.h"

#include "lltimer.h"
#include "lltrace.h"
#include "lltracethreadrecorder.h"

#if LL_LINUX || LL_SOLARIS
#include <sched.h>
#endif

#ifdef LL_WINDOWS
const DWORD MS_VC_EXCEPTION=0x406D1388;

#pragma pack(push,8)
typedef struct tagTHREADNAME_INFO
{
	DWORD dwType; // Must be 0x1000.
	LPCSTR szName; // Pointer to name (in user addr space).
	DWORD dwThreadID; // Thread ID (-1=caller thread).
	DWORD dwFlags; // Reserved for future use, must be zero.
} THREADNAME_INFO;
#pragma pack(pop)

void set_thread_name( DWORD dwThreadID, const char* threadName)
{
	THREADNAME_INFO info;
	info.dwType = 0x1000;
	info.szName = threadName;
	info.dwThreadID = dwThreadID;
	info.dwFlags = 0;

	__try
	{
		// <FS:ND> Proper arguments for RaiseException
		// ::RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(DWORD), (DWORD*)&info );
		::RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(DWORD), (ULONG_PTR*)&info );
		// </FS:ND>
	}
	__except(EXCEPTION_CONTINUE_EXECUTION)
	{
	}
}
#endif

//----------------------------------------------------------------------------
// Usage:
// void run_func(LLThread* thread)
// {
// }
// LLThread* thread = new LLThread();
// thread->run(run_func);
// ...
// thread->setQuitting();
// while(!timeout)
// {
//   if (thread->isStopped())
//   {
//     delete thread;
//     break;
//   }
// }
//
//----------------------------------------------------------------------------

#if LL_DARWIN
// statically allocated thread local storage not supported in Darwin executable formats
#elif LL_WINDOWS
U32 __declspec(thread) sThreadID = 0;
#elif LL_LINUX
U32 __thread sThreadID = 0;
#endif

U32 LLThread::sIDIter = 0;

LL_COMMON_API void assert_main_thread()
{
	static uintptr_t s_thread_id = LLThread::currentID();
	if (LLThread::currentID() != s_thread_id)
	{
		LL_WARNS() << "Illegal execution from thread id " << (intrptr_t) LLThread::currentID()
			<< " outside main thread " << (intrptr_t) s_thread_id << LL_ENDL;
	}
}

void LLThread::registerThreadID()
{
#if !LL_DARWIN
	sThreadID = ++sIDIter;
#endif
}

//
// Handed to the APR thread creation function
//
void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap)
{
	LLThread *threadp = (LLThread *)datap;

#ifdef LL_WINDOWS
	set_thread_name(-1, threadp->mName.c_str());
#endif

	// for now, hard code all LLThreads to report to single master thread recorder, which is known to be running on main thread
	threadp->mRecorder = new LLTrace::ThreadRecorder(*LLTrace::get_master_thread_recorder());

#if !LL_DARWIN
	sThreadID = threadp->mID;
#endif

	// Run the user supplied function
	threadp->run();

	//LL_INFOS() << "LLThread::staticRun() Exiting: " << threadp->mName << LL_ENDL;

	delete threadp->mRecorder;
	threadp->mRecorder = NULL;

	// We're done with the run function, this thread is done executing now.
	//NB: we are using this flag to sync across threads...we really need memory barriers here
	threadp->mStatus = STOPPED;

	return NULL;
}

LLThread::LLThread(const std::string& name, apr_pool_t *poolp) :
	mPaused(FALSE),
	mName(name),
	mAPRThreadp(NULL),
	mStatus(STOPPED),
	mRecorder(NULL)
{

	mID = ++sIDIter;

	// Thread creation probably CAN be paranoid about APR being initialized, if necessary
	if (poolp)
	{
		mIsLocalPool = FALSE;
		mAPRPoolp = poolp;
	}
	else
	{
		mIsLocalPool = TRUE;
		apr_pool_create(&mAPRPoolp, NULL); // Create a subpool for this thread
	}
	mRunCondition = new LLCondition(mAPRPoolp);
	mDataLock = new LLMutex(mAPRPoolp);
	mLocalAPRFilePoolp = NULL ;
}

LLThread::~LLThread()
{
	shutdown();

	if(mLocalAPRFilePoolp)
	{
		delete mLocalAPRFilePoolp ;
		mLocalAPRFilePoolp = NULL ;
	}
}

void LLThread::shutdown()
{
	// Warning!  If you somehow call the thread destructor from itself,
	// the thread will die in an unclean fashion!
	if (mAPRThreadp)
	{
		if (!isStopped())
		{
			// The thread isn't already stopped
			// First, set the flag that indicates that we're ready to die
			setQuitting();

			//LL_INFOS() << "LLThread::~LLThread() Killing thread " << mName << " Status: " << mStatus << LL_ENDL;
			// Now wait a bit for the thread to exit
			// It's unclear whether I should even bother doing this - this destructor
			// should never get called unless we're already stopped, really...
			S32 counter = 0;
			const S32 MAX_WAIT = 600;
			while (counter < MAX_WAIT)
			{
				if (isStopped())
				{
					break;
				}
				// Sleep for a tenth of a second
				ms_sleep(100);
				yield();
				counter++;
			}
		}

		if (!isStopped())
		{
			// This thread just wouldn't stop, even though we gave it time
			//LL_WARNS() << "LLThread::~LLThread() exiting thread before clean exit!" << LL_ENDL;
			// Put a stake in its heart.
			delete mRecorder;

			apr_thread_exit(mAPRThreadp, -1);
			return;
		}
		mAPRThreadp = NULL;
	}

	delete mRunCondition;
	mRunCondition = NULL;

	delete mDataLock;
	mDataLock = NULL;

	if (mIsLocalPool && mAPRPoolp)
	{
		apr_pool_destroy(mAPRPoolp);
		mAPRPoolp = 0;
	}

	if (mRecorder)
	{
		// missed chance to properly shut down recorder (needs to be done in thread context)
		// probably due to abnormal thread termination
		// so just leak it and remove it from parent
		LLTrace::get_master_thread_recorder()->removeChildRecorder(mRecorder);
	}
}

void LLThread::start()
{
	llassert(isStopped());

	// Set thread state to running
	mStatus = RUNNING;

	apr_status_t status =
		apr_thread_create(&mAPRThreadp, NULL, staticRun, (void *)this, mAPRPoolp);

	if(status == APR_SUCCESS)
	{
		// We won't bother joining
		apr_thread_detach(mAPRThreadp);
	}
	else
	{
		mStatus = STOPPED;
		LL_WARNS() << "failed to start thread " << mName << LL_ENDL;
		ll_apr_warn_status(status);
	}

}

//============================================================================
// Called from MAIN THREAD.

// Request that the thread pause/resume.
// The thread will pause when (and if) it calls checkPause()
void LLThread::pause()
{
	if (!mPaused)
	{
		// this will cause the thread to stop execution as soon as checkPause() is called
		mPaused = 1;		// Does not need to be atomic since this is only set/unset from the main thread
	}
}

void LLThread::unpause()
{
	if (mPaused)
	{
		mPaused = 0;
	}

	wake(); // wake up the thread if necessary
}

// virtual predicate function -- returns true if the thread should wake up, false if it should sleep.
bool LLThread::runCondition(void)
{
	// by default, always run.  Handling of pause/unpause is done regardless of this function's result.
	return true;
}

//============================================================================
// Called from run() (CHILD THREAD).
// Stop thread execution if requested until unpaused.
void LLThread::checkPause()
{
	mDataLock->lock();

	// This is in a while loop because the pthread API allows for spurious wakeups.
	while(shouldSleep())
	{
		mDataLock->unlock();
		mRunCondition->wait(); // unlocks mRunCondition
		mDataLock->lock();
		// mRunCondition is locked when the thread wakes up
	}

 	mDataLock->unlock();
}

//============================================================================

void LLThread::setQuitting()
{
	mDataLock->lock();
	if (mStatus == RUNNING)
	{
		mStatus = QUITTING;
	}
	mDataLock->unlock();
	wake();
}

// static
uintptr_t LLThread::currentID()
{
#if LL_DARWIN
	// statically allocated thread local storage not supported in Darwin executable formats
	return (uintptr_t)apr_os_thread_current();
#else
	return sThreadID;
#endif

}

// static
void LLThread::yield()
{
#if LL_LINUX || LL_SOLARIS
	sched_yield(); // annoyingly, apr_thread_yield  is a noop on linux...
#else
	apr_thread_yield();
#endif
}

void LLThread::wake()
{
	mDataLock->lock();
	if(!shouldSleep())
	{
		mRunCondition->signal();
	}
	mDataLock->unlock();
}

void LLThread::wakeLocked()
{
	if(!shouldSleep())
	{
		mRunCondition->signal();
	}
}

//============================================================================

//----------------------------------------------------------------------------

//static
LLMutex* LLThreadSafeRefCount::sMutex = 0;

//static
void LLThreadSafeRefCount::initThreadSafeRefCount()
{
	if (!sMutex)
	{
		sMutex = new LLMutex(0);
	}
}

//static
void LLThreadSafeRefCount::cleanupThreadSafeRefCount()
{
	delete sMutex;
	sMutex = NULL;
}

//----------------------------------------------------------------------------

LLThreadSafeRefCount::LLThreadSafeRefCount() :
	mRef(0)
{
}

LLThreadSafeRefCount::LLThreadSafeRefCount(const LLThreadSafeRefCount& src)
{
	mRef = 0;
}

LLThreadSafeRefCount::~LLThreadSafeRefCount()
{
	if (mRef != 0)
	{
		LL_ERRS() << "deleting non-zero reference" << LL_ENDL;
	}
}

//============================================================================

LLResponder::~LLResponder()
{
}

//============================================================================
<commit_msg>Fix for typo during merge.<commit_after>/**
 * @file llthread.cpp
 *
 * $LicenseInfo:firstyear=2004&license=viewerlgpl$
 * Second Life Viewer Source Code
 * Copyright (C) 2010-2013, Linden Research, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation;
 * version 2.1 of the License only.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 * $/LicenseInfo$
 */

#include "linden_common.h"
#include "llapr.h"

#include "apr_portable.h"

#include "llthread.h"
#include "llmutex.h"

#include "lltimer.h"
#include "lltrace.h"
#include "lltracethreadrecorder.h"

#if LL_LINUX || LL_SOLARIS
#include <sched.h>
#endif

#ifdef LL_WINDOWS
const DWORD MS_VC_EXCEPTION=0x406D1388;

#pragma pack(push,8)
typedef struct tagTHREADNAME_INFO
{
	DWORD dwType; // Must be 0x1000.
	LPCSTR szName; // Pointer to name (in user addr space).
	DWORD dwThreadID; // Thread ID (-1=caller thread).
	DWORD dwFlags; // Reserved for future use, must be zero.
} THREADNAME_INFO;
#pragma pack(pop)

void set_thread_name( DWORD dwThreadID, const char* threadName)
{
	THREADNAME_INFO info;
	info.dwType = 0x1000;
	info.szName = threadName;
	info.dwThreadID = dwThreadID;
	info.dwFlags = 0;

	__try
	{
		// <FS:ND> Proper arguments for RaiseException
		// ::RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(DWORD), (DWORD*)&info );
		::RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(DWORD), (ULONG_PTR*)&info );
		// </FS:ND>
	}
	__except(EXCEPTION_CONTINUE_EXECUTION)
	{
	}
}
#endif

//----------------------------------------------------------------------------
// Usage:
// void run_func(LLThread* thread)
// {
// }
// LLThread* thread = new LLThread();
// thread->run(run_func);
// ...
// thread->setQuitting();
// while(!timeout)
// {
//   if (thread->isStopped())
//   {
//     delete thread;
//     break;
//   }
// }
//
//----------------------------------------------------------------------------

#if LL_DARWIN
// statically allocated thread local storage not supported in Darwin executable formats
#elif LL_WINDOWS
U32 __declspec(thread) sThreadID = 0;
#elif LL_LINUX
U32 __thread sThreadID = 0;
#endif

U32 LLThread::sIDIter = 0;

LL_COMMON_API void assert_main_thread()
{
	static uintptr_t s_thread_id = LLThread::currentID();
	if (LLThread::currentID() != s_thread_id)
	{
		LL_WARNS() << "Illegal execution from thread id " << (intptr_t) LLThread::currentID()
			<< " outside main thread " << (intptr_t) s_thread_id << LL_ENDL;
	}
}

void LLThread::registerThreadID()
{
#if !LL_DARWIN
	sThreadID = ++sIDIter;
#endif
}

//
// Handed to the APR thread creation function
//
void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap)
{
	LLThread *threadp = (LLThread *)datap;

#ifdef LL_WINDOWS
	set_thread_name(-1, threadp->mName.c_str());
#endif

	// for now, hard code all LLThreads to report to single master thread recorder, which is known to be running on main thread
	threadp->mRecorder = new LLTrace::ThreadRecorder(*LLTrace::get_master_thread_recorder());

#if !LL_DARWIN
	sThreadID = threadp->mID;
#endif

	// Run the user supplied function
	threadp->run();

	//LL_INFOS() << "LLThread::staticRun() Exiting: " << threadp->mName << LL_ENDL;

	delete threadp->mRecorder;
	threadp->mRecorder = NULL;

	// We're done with the run function, this thread is done executing now.
	//NB: we are using this flag to sync across threads...we really need memory barriers here
	threadp->mStatus = STOPPED;

	return NULL;
}

LLThread::LLThread(const std::string& name, apr_pool_t *poolp) :
	mPaused(FALSE),
	mName(name),
	mAPRThreadp(NULL),
	mStatus(STOPPED),
	mRecorder(NULL)
{

	mID = ++sIDIter;

	// Thread creation probably CAN be paranoid about APR being initialized, if necessary
	if (poolp)
	{
		mIsLocalPool = FALSE;
		mAPRPoolp = poolp;
	}
	else
	{
		mIsLocalPool = TRUE;
		apr_pool_create(&mAPRPoolp, NULL); // Create a subpool for this thread
	}
	mRunCondition = new LLCondition(mAPRPoolp);
	mDataLock = new LLMutex(mAPRPoolp);
	mLocalAPRFilePoolp = NULL ;
}

LLThread::~LLThread()
{
	shutdown();

	if(mLocalAPRFilePoolp)
	{
		delete mLocalAPRFilePoolp ;
		mLocalAPRFilePoolp = NULL ;
	}
}

void LLThread::shutdown()
{
	// Warning!  If you somehow call the thread destructor from itself,
	// the thread will die in an unclean fashion!
	if (mAPRThreadp)
	{
		if (!isStopped())
		{
			// The thread isn't already stopped
			// First, set the flag that indicates that we're ready to die
			setQuitting();

			//LL_INFOS() << "LLThread::~LLThread() Killing thread " << mName << " Status: " << mStatus << LL_ENDL;
			// Now wait a bit for the thread to exit
			// It's unclear whether I should even bother doing this - this destructor
			// should never get called unless we're already stopped, really...
			S32 counter = 0;
			const S32 MAX_WAIT = 600;
			while (counter < MAX_WAIT)
			{
				if (isStopped())
				{
					break;
				}
				// Sleep for a tenth of a second
				ms_sleep(100);
				yield();
				counter++;
			}
		}

		if (!isStopped())
		{
			// This thread just wouldn't stop, even though we gave it time
			//LL_WARNS() << "LLThread::~LLThread() exiting thread before clean exit!" << LL_ENDL;
			// Put a stake in its heart.
			delete mRecorder;

			apr_thread_exit(mAPRThreadp, -1);
			return;
		}
		mAPRThreadp = NULL;
	}

	delete mRunCondition;
	mRunCondition = NULL;

	delete mDataLock;
	mDataLock = NULL;

	if (mIsLocalPool && mAPRPoolp)
	{
		apr_pool_destroy(mAPRPoolp);
		mAPRPoolp = 0;
	}

	if (mRecorder)
	{
		// missed chance to properly shut down recorder (needs to be done in thread context)
		// probably due to abnormal thread termination
		// so just leak it and remove it from parent
		LLTrace::get_master_thread_recorder()->removeChildRecorder(mRecorder);
	}
}

void LLThread::start()
{
	llassert(isStopped());

	// Set thread state to running
	mStatus = RUNNING;

	apr_status_t status =
		apr_thread_create(&mAPRThreadp, NULL, staticRun, (void *)this, mAPRPoolp);

	if(status == APR_SUCCESS)
	{
		// We won't bother joining
		apr_thread_detach(mAPRThreadp);
	}
	else
	{
		mStatus = STOPPED;
		LL_WARNS() << "failed to start thread " << mName << LL_ENDL;
		ll_apr_warn_status(status);
	}

}

//============================================================================
// Called from MAIN THREAD.

// Request that the thread pause/resume.
// The thread will pause when (and if) it calls checkPause()
void LLThread::pause()
{
	if (!mPaused)
	{
		// this will cause the thread to stop execution as soon as checkPause() is called
		mPaused = 1;		// Does not need to be atomic since this is only set/unset from the main thread
	}
}

void LLThread::unpause()
{
	if (mPaused)
	{
		mPaused = 0;
	}

	wake(); // wake up the thread if necessary
}

// virtual predicate function -- returns true if the thread should wake up, false if it should sleep.
bool LLThread::runCondition(void)
{
	// by default, always run.  Handling of pause/unpause is done regardless of this function's result.
	return true;
}

//============================================================================
// Called from run() (CHILD THREAD).
// Stop thread execution if requested until unpaused.
void LLThread::checkPause()
{
	mDataLock->lock();

	// This is in a while loop because the pthread API allows for spurious wakeups.
	while(shouldSleep())
	{
		mDataLock->unlock();
		mRunCondition->wait(); // unlocks mRunCondition
		mDataLock->lock();
		// mRunCondition is locked when the thread wakes up
	}

 	mDataLock->unlock();
}

//============================================================================

void LLThread::setQuitting()
{
	mDataLock->lock();
	if (mStatus == RUNNING)
	{
		mStatus = QUITTING;
	}
	mDataLock->unlock();
	wake();
}

// static
uintptr_t LLThread::currentID()
{
#if LL_DARWIN
	// statically allocated thread local storage not supported in Darwin executable formats
	return (uintptr_t)apr_os_thread_current();
#else
	return sThreadID;
#endif

}

// static
void LLThread::yield()
{
#if LL_LINUX || LL_SOLARIS
	sched_yield(); // annoyingly, apr_thread_yield  is a noop on linux...
#else
	apr_thread_yield();
#endif
}

void LLThread::wake()
{
	mDataLock->lock();
	if(!shouldSleep())
	{
		mRunCondition->signal();
	}
	mDataLock->unlock();
}

void LLThread::wakeLocked()
{
	if(!shouldSleep())
	{
		mRunCondition->signal();
	}
}

//============================================================================

//----------------------------------------------------------------------------

//static
LLMutex* LLThreadSafeRefCount::sMutex = 0;

//static
void LLThreadSafeRefCount::initThreadSafeRefCount()
{
	if (!sMutex)
	{
		sMutex = new LLMutex(0);
	}
}

//static
void LLThreadSafeRefCount::cleanupThreadSafeRefCount()
{
	delete sMutex;
	sMutex = NULL;
}

//----------------------------------------------------------------------------

LLThreadSafeRefCount::LLThreadSafeRefCount() :
	mRef(0)
{
}

LLThreadSafeRefCount::LLThreadSafeRefCount(const LLThreadSafeRefCount& src)
{
	mRef = 0;
}

LLThreadSafeRefCount::~LLThreadSafeRefCount()
{
	if (mRef != 0)
	{
		LL_ERRS() << "deleting non-zero reference" << LL_ENDL;
	}
}

//============================================================================

LLResponder::~LLResponder()
{
}

//============================================================================
<|endoftext|>


<commit_before>#include "schandler.h"

SCHandler::SCHandler(QObject *parent)
{
    raw_results = QJsonArray();
}

SCHandler::~SCHandler()
{

}

//category: artist, title, user,
int SCHandler::query(QString key, QString value){

    if(value == NULL)
        return -1;
    if(key == NULL)
        return -1;
    //check to prevent same query twice? nah don't be dumb

    // create custom temporary event loop on stack
    QEventLoop eventLoop;
    QUrl url(SC_TRACKS_URL);
    QUrlQuery query;
    query.addQueryItem("downloadable", "true");
    query.addQueryItem(key, value);

    query.addQueryItem("client_id", SC_CLIENT_ID);

    url.setQuery(query.query());
    qDebug() << url;

    // "quit()" the event-loop, when the network request "finished()"
    QNetworkAccessManager mgr;
    QObject::connect(&mgr, SIGNAL(finished(QNetworkReply*)), &eventLoop, SLOT(quit()));

    // the HTTP request
    QNetworkRequest req(url);
    QNetworkReply *reply = mgr.get(req);
    eventLoop.exec(); // blocks stack until "finished()" has been called

    if (reply->error() == QNetworkReply::NoError) {
        QJsonParseError err;
        QJsonDocument jsondoc = QJsonDocument(QJsonDocument::fromJson(QString(reply->readAll()).toUtf8(), &err)); //raw string to qtstring to bytecode to jsondoc fucking shit
        raw_results = jsondoc.array(); //take the pile of responses and make them an array so you can fucking do something with the
//        qDebug() << raw_results;

    return raw_results.size();

    }
    else {
        //failure
        qDebug() << "Failed query: " <<reply->errorString();
        delete reply;
        return -1;
    }
}

QJsonValue SCHandler::format(QJsonValue initial){
    QJsonObject jobj = initial.toObject();
    QString length;
    if (jobj["duration"].toInt() > 0){
        QString minutes;
        QString seconds;
        int duration = jobj["duration"].toInt()/1000; //ain't nobody got time for accuracy
        minutes = QString::number(duration/60);
        seconds = QString::number(duration%60);
        if(duration/60 < 10)
            minutes = QString("0"+minutes);
        if(duration%60 < 10)
            seconds = QString("0"+seconds);

        length = QString(minutes+":"+seconds);
    }

    QJsonObject media{
        {"hash", jobj["download_url"].toString()},
        {"order",""},
    };

    QJsonObject meta{
        {"title", jobj["title"].toString()},
        {"album",""}, //nope because soundcloud
        {"artist", jobj["user"].toObject()["username"].toString()},
        {"track_number", 0},
        {"length", length}, //get from fucking duration
        {"genre", jobj["genre"].toString()}
    };
    //add meta to media
    media["metadata"] = meta;

    return QJsonValue(media);
}

QJsonArray SCHandler::search(QString value, QString key){
    QJsonArray results = QJsonArray();
    QJsonObject jobj;
    QString result;
    int num_queried = query(key, value);
    for(int i=0; i<num_queried; i++){
        jobj = raw_results[i].toObject();
        result = jobj["download_url"].toString();
//        qDebug() << result.compare(QString(""));
        if(result.compare(QString("")) != 0)
            results.append(format(raw_results[i]));
    }

    emit onSearchComplete(&results);
    return results;
}

QJsonArray SCHandler::search(int count, QString value, QString key){
    QJsonArray results = QJsonArray();
    int num_queried = query(key, value);
    for(int i=0; i<num_queried; i++){
        jobj = raw_results[i].toObject();
        result = jobj["download_url"].toString();
        qDebug() << result.compare(QString(""));
        if(result.compare(QString("")) != 0)
            results.append(format(raw_results[i]));
    }
    if(count > results.size())
        count = results.size();
    for(int i=0; i<count; i++){
        results.append(format(raw_results[i]));
    }
    emit onSearchComplete(&results);
    return results;
}

QByteArray SCHandler::request_song(QString download_url){
    // create custom temporary event loop on stack
    QNetworkRequest request;
    request.setRawHeader("User-Agent", USER_AGENT);
    QEventLoop eventLoop;
    QString req_url = download_url;
    QUrl url(req_url);
    QUrlQuery query;

    query.addQueryItem("client_id", SC_CLIENT_ID);

    url.setQuery(query.query());

    // "quit()" the event-loop, when the network request "finished()"
    QNetworkAccessManager mgr;
    QObject::connect(&mgr, SIGNAL(finished(QNetworkReply*)), &eventLoop, SLOT(quit()));

    // the HTTP request
    QNetworkRequest req(url);

    //req.setRawHeader();
    QNetworkReply *reply = mgr.get(req);
    eventLoop.exec(); // blocks stack until "finished()" has been called

    if (reply->error() == QNetworkReply::NoError) {
        //get temp download url as json
        QJsonDocument jsondoc = QJsonDocument(QJsonDocument::fromJson(QString(reply->readAll()).toUtf8()));
        QJsonObject jobj = jsondoc.object();
        QString download_url = jobj["location"].toString();

        //download
        if (reply->error() == QNetworkReply::NoError) {
            req_url = download_url;
            QUrl url(req_url);
            QNetworkRequest req(url);
            req.setRawHeader("User-Agent",USER_AGENT);
            QNetworkReply *reply = mgr.get(req);
            eventLoop.exec();

            return reply->readAll();

        }
        else{
            qDebug() << "Failure on download request" <<reply->errorString();
            delete reply;
            return NULL;
        }

    }
    else {
        //failure
        qDebug() << "Failure on initial request" <<reply->errorString();
        delete reply;
        return NULL;
    }
}

<commit_msg>Fixed minor bug in schandler<commit_after>#include "schandler.h"

SCHandler::SCHandler(QObject *parent)
{
    raw_results = QJsonArray();
}

SCHandler::~SCHandler()
{

}

//category: artist, title, user,
int SCHandler::query(QString key, QString value){

    if(value == NULL)
        return -1;
    if(key == NULL)
        return -1;
    //check to prevent same query twice? nah don't be dumb

    // create custom temporary event loop on stack
    QEventLoop eventLoop;
    QUrl url(SC_TRACKS_URL);
    QUrlQuery query;
    query.addQueryItem("downloadable", "true");
    query.addQueryItem(key, value);

    query.addQueryItem("client_id", SC_CLIENT_ID);

    url.setQuery(query.query());
    qDebug() << url;

    // "quit()" the event-loop, when the network request "finished()"
    QNetworkAccessManager mgr;
    QObject::connect(&mgr, SIGNAL(finished(QNetworkReply*)), &eventLoop, SLOT(quit()));

    // the HTTP request
    QNetworkRequest req(url);
    QNetworkReply *reply = mgr.get(req);
    eventLoop.exec(); // blocks stack until "finished()" has been called

    if (reply->error() == QNetworkReply::NoError) {
        QJsonParseError err;
        QJsonDocument jsondoc = QJsonDocument(QJsonDocument::fromJson(QString(reply->readAll()).toUtf8(), &err)); //raw string to qtstring to bytecode to jsondoc fucking shit
        raw_results = jsondoc.array(); //take the pile of responses and make them an array so you can fucking do something with the
//        qDebug() << raw_results;

    return raw_results.size();

    }
    else {
        //failure
        qDebug() << "Failed query: " <<reply->errorString();
        delete reply;
        return -1;
    }
}

QJsonValue SCHandler::format(QJsonValue initial){
    QJsonObject jobj = initial.toObject();
    QString length;
    if (jobj["duration"].toInt() > 0){
        QString minutes;
        QString seconds;
        int duration = jobj["duration"].toInt()/1000; //ain't nobody got time for accuracy
        minutes = QString::number(duration/60);
        seconds = QString::number(duration%60);
        if(duration/60 < 10)
            minutes = QString("0"+minutes);
        if(duration%60 < 10)
            seconds = QString("0"+seconds);

        length = QString(minutes+":"+seconds);
    }

    QJsonObject media{
        {"hash", jobj["download_url"].toString()},
        {"order",""},
    };

    QJsonObject meta{
        {"title", jobj["title"].toString()},
        {"album",""}, //nope because soundcloud
        {"artist", jobj["user"].toObject()["username"].toString()},
        {"track_number", 0},
        {"length", length}, //get from fucking duration
        {"genre", jobj["genre"].toString()}
    };
    //add meta to media
    media["metadata"] = meta;

    return QJsonValue(media);
}

QJsonArray SCHandler::search(QString value, QString key){
    QJsonArray results = QJsonArray();
    QJsonObject jobj;
    QString result;
    int num_queried = query(key, value);
    for(int i=0; i<num_queried; i++){
        jobj = raw_results[i].toObject();
        result = jobj["download_url"].toString();
//        qDebug() << result.compare(QString(""));
        if(result.compare(QString("")) != 0)
            results.append(format(raw_results[i]));
    }

    emit onSearchComplete(&results);
    return results;
}

QJsonArray SCHandler::search(int count, QString value, QString key){
    QJsonArray results = QJsonArray();
    int num_queried = query(key, value);
    for(int i=0; i<num_queried; i++){
        QJsonObject jobj = raw_results[i].toObject();
        QString result = jobj["download_url"].toString();
        qDebug() << result.compare(QString(""));
        if(result.compare(QString("")) != 0)
            results.append(format(raw_results[i]));
    }
    if(count > results.size())
        count = results.size();
    for(int i=0; i<count; i++){
        results.append(format(raw_results[i]));
    }
    emit onSearchComplete(&results);
    return results;
}

QByteArray SCHandler::request_song(QString download_url){
    // create custom temporary event loop on stack
    QNetworkRequest request;
    request.setRawHeader("User-Agent", USER_AGENT);
    QEventLoop eventLoop;
    QString req_url = download_url;
    QUrl url(req_url);
    QUrlQuery query;

    query.addQueryItem("client_id", SC_CLIENT_ID);

    url.setQuery(query.query());

    // "quit()" the event-loop, when the network request "finished()"
    QNetworkAccessManager mgr;
    QObject::connect(&mgr, SIGNAL(finished(QNetworkReply*)), &eventLoop, SLOT(quit()));

    // the HTTP request
    QNetworkRequest req(url);

    //req.setRawHeader();
    QNetworkReply *reply = mgr.get(req);
    eventLoop.exec(); // blocks stack until "finished()" has been called

    if (reply->error() == QNetworkReply::NoError) {
        //get temp download url as json
        QJsonDocument jsondoc = QJsonDocument(QJsonDocument::fromJson(QString(reply->readAll()).toUtf8()));
        QJsonObject jobj = jsondoc.object();
        QString download_url = jobj["location"].toString();

        //download
        if (reply->error() == QNetworkReply::NoError) {
            req_url = download_url;
            QUrl url(req_url);
            QNetworkRequest req(url);
            req.setRawHeader("User-Agent",USER_AGENT);
            QNetworkReply *reply = mgr.get(req);
            eventLoop.exec();

            return reply->readAll();

        }
        else{
            qDebug() << "Failure on download request" <<reply->errorString();
            delete reply;
            return NULL;
        }

    }
    else {
        //failure
        qDebug() << "Failure on initial request" <<reply->errorString();
        delete reply;
        return NULL;
    }
}

<|endoftext|>


<commit_before>#include "schandler.h"

SCHandler::SCHandler(QObject *parent)
{
    raw_results = QJsonArray();
}

SCHandler::~SCHandler()
{

}

//category: artist, title, user,
int SCHandler::query(QString key, QString value){

    if(value == NULL)
        return -1;
    if(key == NULL)
        return -1;
    //check to prevent same query twice? nah don't be dumb

    // create custom temporary event loop on stack
    QEventLoop eventLoop;
    QUrl url(SC_TRACKS_URL);
    QUrlQuery query;
    query.addQueryItem("downloadable", "true");
    query.addQueryItem(key, value);

    query.addQueryItem("client_id", SC_CLIENT_ID);

    url.setQuery(query.query());
    qDebug() << url;

    // "quit()" the event-loop, when the network request "finished()"
    QNetworkAccessManager mgr;
    QObject::connect(&mgr, SIGNAL(finished(QNetworkReply*)), &eventLoop, SLOT(quit()));

    // the HTTP request
    QNetworkRequest req(url);
    QNetworkReply *reply = mgr.get(req);
    eventLoop.exec(); // blocks stack until "finished()" has been called

    if (reply->error() == QNetworkReply::NoError) {
        QJsonParseError err;
        QJsonDocument jsondoc = QJsonDocument(QJsonDocument::fromJson(QString(reply->readAll()).toUtf8(), &err)); //raw string to qtstring to bytecode to jsondoc fucking shit
        raw_results = jsondoc.array(); //take the pile of responses and make them an array so you can fucking do something with the
//        qDebug() << raw_results;

    return raw_results.size();

    }
    else {
        //failure
        qDebug() << "Failed query: " <<reply->errorString();
        delete reply;
        return -1;
    }
}

QJsonValue SCHandler::format(QJsonValue initial){
    QJsonObject jobj = initial.toObject();
    QString length;
    if (jobj["duration"].toInt() > 0){
        QString minutes;
        QString seconds;
        int duration = jobj["duration"].toInt()/1000; //ain't nobody got time for accuracy
        minutes = QString::number(duration/60);
        seconds = QString::number(duration%60);
        if(duration/60 < 10)
            minutes = QString("0"+minutes);
        if(duration%60 < 10)
            seconds = QString("0"+seconds);

        length = QString(minutes+":"+seconds);
    }

    QJsonObject media{
        {"hash", jobj["download_url"].toString()},
        {"order",""},
    };

    QJsonObject meta{
        {"title", jobj["title"].toString()},
        {"album",""}, //nope because soundcloud
        {"artist", jobj["user"].toObject()["username"].toString()},
        {"track_number", 0},
        {"length", length}, //get from fucking duration
        {"genre", jobj["genre"].toString()}
    };
    //add meta to media
    media["metadata"] = meta;

    return QJsonValue(media);
}

QJsonArray SCHandler::search(QString value, QString key){
    QJsonArray results = QJsonArray();
    QJsonObject jobj;
    QString result;
    int num_queried = query(key, value);
    for(int i=0; i<num_queried; i++){
        jobj = raw_results[i].toObject();
        result = jobj["download_url"].toString();
//        qDebug() << result.compare(QString(""));
        if(result.compare(QString("")) != 0)
            results.append(format(raw_results[i]));
    }

    emit onSearchComplete(&results);
    return results;
}

QJsonArray SCHandler::search(int count, QString value, QString key){
    QJsonArray results = QJsonArray();
    int num_queried = query(key, value);
    for(int i=0; i<num_queried; i++){
        jobj = raw_results[i].toObject();
        result = jobj["download_url"].toString();
        qDebug() << result.compare(QString(""));
        if(result.compare(QString("")) != 0)
            results.append(format(raw_results[i]));
    }
    if(count > num_queried)
        count = num_queried;
    for(int i=0; i<40; i++){
        results.append(format(raw_results[i]));
    }
    emit onSearchComplete(&results);
    return results;
}

QByteArray SCHandler::request_song(QString download_url){
    // create custom temporary event loop on stack
    QNetworkRequest request;
    request.setRawHeader("User-Agent", USER_AGENT);
    QEventLoop eventLoop;
    QString req_url = download_url;
    QUrl url(req_url);
    QUrlQuery query;

    query.addQueryItem("client_id", SC_CLIENT_ID);

    url.setQuery(query.query());

    // "quit()" the event-loop, when the network request "finished()"
    QNetworkAccessManager mgr;
    QObject::connect(&mgr, SIGNAL(finished(QNetworkReply*)), &eventLoop, SLOT(quit()));

    // the HTTP request
    QNetworkRequest req(url);

    //req.setRawHeader();
    QNetworkReply *reply = mgr.get(req);
    eventLoop.exec(); // blocks stack until "finished()" has been called

    if (reply->error() == QNetworkReply::NoError) {
        //get temp download url as json
        QJsonDocument jsondoc = QJsonDocument(QJsonDocument::fromJson(QString(reply->readAll()).toUtf8()));
        QJsonObject jobj = jsondoc.object();
        QString download_url = jobj["location"].toString();

        //download
        if (reply->error() == QNetworkReply::NoError) {
            req_url = download_url;
            QUrl url(req_url);
            QNetworkRequest req(url);
            req.setRawHeader("User-Agent",USER_AGENT);
            QNetworkReply *reply = mgr.get(req);
            eventLoop.exec();

            return reply->readAll();

        }
        else{
            qDebug() << "Failure on download request" <<reply->errorString();
            delete reply;
            return NULL;
        }

    }
    else {
        //failure
        qDebug() << "Failure on initial request" <<reply->errorString();
        delete reply;
        return NULL;
    }
}

<commit_msg>fixed search(int count...) function. Updated comments to reflect. Still janky. Still works.<commit_after>#include "schandler.h"

SCHandler::SCHandler(QObject *parent)
{
    raw_results = QJsonArray();
}

SCHandler::~SCHandler()
{

}

//category: artist, title, user,
int SCHandler::query(QString key, QString value){

    if(value == NULL)
        return -1;
    if(key == NULL)
        return -1;
    //check to prevent same query twice? nah don't be dumb

    // create custom temporary event loop on stack
    QEventLoop eventLoop;
    QUrl url(SC_TRACKS_URL);
    QUrlQuery query;
    query.addQueryItem("downloadable", "true");
    query.addQueryItem(key, value);

    query.addQueryItem("client_id", SC_CLIENT_ID);

    url.setQuery(query.query());
    qDebug() << url;

    // "quit()" the event-loop, when the network request "finished()"
    QNetworkAccessManager mgr;
    QObject::connect(&mgr, SIGNAL(finished(QNetworkReply*)), &eventLoop, SLOT(quit()));

    // the HTTP request
    QNetworkRequest req(url);
    QNetworkReply *reply = mgr.get(req);
    eventLoop.exec(); // blocks stack until "finished()" has been called

    if (reply->error() == QNetworkReply::NoError) {
        QJsonParseError err;
        QJsonDocument jsondoc = QJsonDocument(QJsonDocument::fromJson(QString(reply->readAll()).toUtf8(), &err)); //raw string to qtstring to bytecode to jsondoc fucking shit
        raw_results = jsondoc.array(); //take the pile of responses and make them an array so you can fucking do something with the
//        qDebug() << raw_results;

    return raw_results.size();

    }
    else {
        //failure
        qDebug() << "Failed query: " <<reply->errorString();
        delete reply;
        return -1;
    }
}

QJsonValue SCHandler::format(QJsonValue initial){
    QJsonObject jobj = initial.toObject();
    QString length;
    if (jobj["duration"].toInt() > 0){
        QString minutes;
        QString seconds;
        int duration = jobj["duration"].toInt()/1000; //ain't nobody got time for accuracy
        minutes = QString::number(duration/60);
        seconds = QString::number(duration%60);
        if(duration/60 < 10)
            minutes = QString("0"+minutes);
        if(duration%60 < 10)
            seconds = QString("0"+seconds);

        length = QString(minutes+":"+seconds);
    }

    QJsonObject media{
        {"hash", jobj["download_url"].toString()},
        {"order",""},
    };

    QJsonObject meta{
        {"title", jobj["title"].toString()},
        {"album",""}, //nope because soundcloud
        {"artist", jobj["user"].toObject()["username"].toString()},
        {"track_number", 0},
        {"length", length}, //get from fucking duration
        {"genre", jobj["genre"].toString()}
    };
    //add meta to media
    media["metadata"] = meta;

    return QJsonValue(media);
}

QJsonArray SCHandler::search(QString value, QString key){
    QJsonArray results = QJsonArray();
    QJsonObject jobj;
    QString result;
    int num_queried = query(key, value);
    for(int i=0; i<num_queried; i++){
        jobj = raw_results[i].toObject();
        result = jobj["download_url"].toString();
//        qDebug() << result.compare(QString(""));
        if(result.compare(QString("")) != 0)
            results.append(format(raw_results[i]));
    }

    emit onSearchComplete(&results);
    return results;
}

QJsonArray SCHandler::search(int count, QString value, QString key){
    QJsonArray results = QJsonArray();
    int num_queried = query(key, value);
    for(int i=0; i<num_queried; i++){
        jobj = raw_results[i].toObject();
        result = jobj["download_url"].toString();
        qDebug() << result.compare(QString(""));
        if(result.compare(QString("")) != 0)
            results.append(format(raw_results[i]));
    }
    if(count > results.size())
        count = results.size();
    for(int i=0; i<count; i++){
        results.append(format(raw_results[i]));
    }
    emit onSearchComplete(&results);
    return results;
}

QByteArray SCHandler::request_song(QString download_url){
    // create custom temporary event loop on stack
    QNetworkRequest request;
    request.setRawHeader("User-Agent", USER_AGENT);
    QEventLoop eventLoop;
    QString req_url = download_url;
    QUrl url(req_url);
    QUrlQuery query;

    query.addQueryItem("client_id", SC_CLIENT_ID);

    url.setQuery(query.query());

    // "quit()" the event-loop, when the network request "finished()"
    QNetworkAccessManager mgr;
    QObject::connect(&mgr, SIGNAL(finished(QNetworkReply*)), &eventLoop, SLOT(quit()));

    // the HTTP request
    QNetworkRequest req(url);

    //req.setRawHeader();
    QNetworkReply *reply = mgr.get(req);
    eventLoop.exec(); // blocks stack until "finished()" has been called

    if (reply->error() == QNetworkReply::NoError) {
        //get temp download url as json
        QJsonDocument jsondoc = QJsonDocument(QJsonDocument::fromJson(QString(reply->readAll()).toUtf8()));
        QJsonObject jobj = jsondoc.object();
        QString download_url = jobj["location"].toString();

        //download
        if (reply->error() == QNetworkReply::NoError) {
            req_url = download_url;
            QUrl url(req_url);
            QNetworkRequest req(url);
            req.setRawHeader("User-Agent",USER_AGENT);
            QNetworkReply *reply = mgr.get(req);
            eventLoop.exec();

            return reply->readAll();

        }
        else{
            qDebug() << "Failure on download request" <<reply->errorString();
            delete reply;
            return NULL;
        }

    }
    else {
        //failure
        qDebug() << "Failure on initial request" <<reply->errorString();
        delete reply;
        return NULL;
    }
}

<|endoftext|>


<commit_before>/**
 * @file llagentui.cpp
 * @brief Utility methods to process agent's data as slurl's etc. before displaying
 *
 * $LicenseInfo:firstyear=2009&license=viewergpl$
 *
 * Copyright (c) 2009, Linden Research, Inc.
 *
 * Second Life Viewer Source Code
 * The source code in this file ("Source Code") is provided by Linden Lab
 * to you under the terms of the GNU General Public License, version 2.0
 * ("GPL"), unless you have obtained a separate licensing agreement
 * ("Other License"), formally executed by you and Linden Lab.  Terms of
 * the GPL can be found in doc/GPL-license.txt in this distribution, or
 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
 *
 * There are special exceptions to the terms and conditions of the GPL as
 * it is applied to this Source Code. View the full text of the exception
 * in the file doc/FLOSS-exception.txt in this software distribution, or
 * online at
 * http://secondlifegrid.net/programs/open_source/licensing/flossexception
 *
 * By copying, modifying or distributing this software, you acknowledge
 * that you have read and understood your obligations described above,
 * and agree to abide by those obligations.
 *
 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
 * COMPLETENESS OR PERFORMANCE.
 * $/LicenseInfo$
 */

#include "llviewerprecompiledheaders.h"

#include "llagentui.h"

// Library includes
#include "llparcel.h"

// Viewer includes
#include "llagent.h"
#include "llviewercontrol.h"
#include "llviewerregion.h"
#include "llviewerparcelmgr.h"
#include "llvoavatarself.h"
#include "llslurl.h"

//static
void LLAgentUI::buildName(std::string& name)
{
	name.clear();

	LLVOAvatarSelf* avatar_object = gAgent.getAvatarObject();
	if (avatar_object)
	{
		LLNameValue *first_nv = avatar_object->getNVPair("FirstName");
		LLNameValue *last_nv = avatar_object->getNVPair("LastName");
		if (first_nv && last_nv)
		{
			name = first_nv->printData() + " " + last_nv->printData();
		}
		else
		{
			llwarns << "Agent is missing FirstName and/or LastName nv pair." << llendl;
		}
	}
	else
	{
		name = gSavedSettings.getString("FirstName") + " " + gSavedSettings.getString("LastName");
	}
}

//static
void LLAgentUI::buildFullname(std::string& name)
{
	if (gAgent.getAvatarObject()) name = gAgent.getAvatarObject()->getFullname();
}

//static
std::string LLAgentUI::buildSLURL(const bool escaped /*= true*/)
{
	std::string slurl;
	LLViewerRegion *regionp = gAgent.getRegion();
	if (regionp)
	{
		LLVector3d agentPos = gAgent.getPositionGlobal();
		slurl = LLSLURL::buildSLURLfromPosGlobal(regionp->getName(), agentPos, escaped);
	}
	return slurl;
}

//static
BOOL LLAgentUI::checkAgentDistance(const LLVector3& pole, F32 radius)
{
	F32 delta_x = gAgent.getPositionAgent().mV[VX] - pole.mV[VX];
	F32 delta_y = gAgent.getPositionAgent().mV[VY] - pole.mV[VY];

	return  sqrt( delta_x* delta_x + delta_y* delta_y ) < radius;
}
BOOL LLAgentUI::buildLocationString(std::string& str, ELocationFormat fmt,const LLVector3& agent_pos_region)
{
	LLViewerRegion* region = gAgent.getRegion();
	LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();

	if (!region || !parcel) return FALSE;

	S32 pos_x = S32(agent_pos_region.mV[VX]);
	S32 pos_y = S32(agent_pos_region.mV[VY]);
	S32 pos_z = S32(agent_pos_region.mV[VZ]);

	// Round the numbers based on the velocity
	F32 velocity_mag_sq = gAgent.getVelocity().magVecSquared();

	const F32 FLY_CUTOFF = 6.f;		// meters/sec
	const F32 FLY_CUTOFF_SQ = FLY_CUTOFF * FLY_CUTOFF;
	const F32 WALK_CUTOFF = 1.5f;	// meters/sec
	const F32 WALK_CUTOFF_SQ = WALK_CUTOFF * WALK_CUTOFF;

	if (velocity_mag_sq > FLY_CUTOFF_SQ)
	{
		pos_x -= pos_x % 4;
		pos_y -= pos_y % 4;
	}
	else if (velocity_mag_sq > WALK_CUTOFF_SQ)
	{
		pos_x -= pos_x % 2;
		pos_y -= pos_y % 2;
	}

	// create a default name and description for the landmark
	std::string parcel_name = LLViewerParcelMgr::getInstance()->getAgentParcelName();
	std::string region_name = region->getName();
	std::string sim_access_string = region->getSimAccessString();
	std::string buffer;
	if( parcel_name.empty() )
	{
		// the parcel doesn't have a name
		switch (fmt)
		{
		case LOCATION_FORMAT_LANDMARK:
			buffer = llformat("%.100s", region_name.c_str());
			break;
		case LOCATION_FORMAT_NORMAL:
			buffer = llformat("%s", region_name.c_str());
			break;
		case LOCATION_FORMAT_NO_COORDS:
			buffer = llformat("%s%s%s",
				region_name.c_str(),
				sim_access_string.empty() ? "" : " - ",
				sim_access_string.c_str());
			break;
		case LOCATION_FORMAT_NO_MATURITY:
		case LOCATION_FORMAT_FULL:
			buffer = llformat("%s (%d, %d, %d)",
				region_name.c_str(),
				pos_x, pos_y, pos_z);
			break;
		}
	}
	else
	{
		// the parcel has a name, so include it in the landmark name
		switch (fmt)
		{
		case LOCATION_FORMAT_LANDMARK:
			buffer = llformat("%.100s", parcel_name.c_str());
			break;
		case LOCATION_FORMAT_NORMAL:
			buffer = llformat("%s, %s", parcel_name.c_str(), region_name.c_str());
			break;
		case LOCATION_FORMAT_NO_MATURITY:
			buffer = llformat("%s, %s (%d, %d, %d)",
				parcel_name.c_str(),
				region_name.c_str(),
				pos_x, pos_y, pos_z);
			break;
		case LOCATION_FORMAT_NO_COORDS:
			buffer = llformat("%s, %s%s%s",
							  parcel_name.c_str(),
							  region_name.c_str(),
							  sim_access_string.empty() ? "" : " - ",
							  sim_access_string.c_str());
				break;
		case LOCATION_FORMAT_FULL:
			buffer = llformat("%s, %s (%d, %d, %d)%s%s",
				parcel_name.c_str(),
				region_name.c_str(),
				pos_x, pos_y, pos_z,
				sim_access_string.empty() ? "" : " - ",
				sim_access_string.c_str());
			break;
		}
	}
	str = buffer;
	return TRUE;
}
BOOL LLAgentUI::buildLocationString(std::string& str, ELocationFormat fmt)
{
	return buildLocationString(str,fmt, gAgent.getPositionAgent());
}
<commit_msg>Fixed normal bug EXT-5207 - Region Maturity level not displayed on nav bar when coordinates are enabled and parcel got no name. Added maturity rating to full location string in case parcel name is empty.<commit_after>/**
 * @file llagentui.cpp
 * @brief Utility methods to process agent's data as slurl's etc. before displaying
 *
 * $LicenseInfo:firstyear=2009&license=viewergpl$
 *
 * Copyright (c) 2009, Linden Research, Inc.
 *
 * Second Life Viewer Source Code
 * The source code in this file ("Source Code") is provided by Linden Lab
 * to you under the terms of the GNU General Public License, version 2.0
 * ("GPL"), unless you have obtained a separate licensing agreement
 * ("Other License"), formally executed by you and Linden Lab.  Terms of
 * the GPL can be found in doc/GPL-license.txt in this distribution, or
 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
 *
 * There are special exceptions to the terms and conditions of the GPL as
 * it is applied to this Source Code. View the full text of the exception
 * in the file doc/FLOSS-exception.txt in this software distribution, or
 * online at
 * http://secondlifegrid.net/programs/open_source/licensing/flossexception
 *
 * By copying, modifying or distributing this software, you acknowledge
 * that you have read and understood your obligations described above,
 * and agree to abide by those obligations.
 *
 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
 * COMPLETENESS OR PERFORMANCE.
 * $/LicenseInfo$
 */

#include "llviewerprecompiledheaders.h"

#include "llagentui.h"

// Library includes
#include "llparcel.h"

// Viewer includes
#include "llagent.h"
#include "llviewercontrol.h"
#include "llviewerregion.h"
#include "llviewerparcelmgr.h"
#include "llvoavatarself.h"
#include "llslurl.h"

//static
void LLAgentUI::buildName(std::string& name)
{
	name.clear();

	LLVOAvatarSelf* avatar_object = gAgent.getAvatarObject();
	if (avatar_object)
	{
		LLNameValue *first_nv = avatar_object->getNVPair("FirstName");
		LLNameValue *last_nv = avatar_object->getNVPair("LastName");
		if (first_nv && last_nv)
		{
			name = first_nv->printData() + " " + last_nv->printData();
		}
		else
		{
			llwarns << "Agent is missing FirstName and/or LastName nv pair." << llendl;
		}
	}
	else
	{
		name = gSavedSettings.getString("FirstName") + " " + gSavedSettings.getString("LastName");
	}
}

//static
void LLAgentUI::buildFullname(std::string& name)
{
	if (gAgent.getAvatarObject()) name = gAgent.getAvatarObject()->getFullname();
}

//static
std::string LLAgentUI::buildSLURL(const bool escaped /*= true*/)
{
	std::string slurl;
	LLViewerRegion *regionp = gAgent.getRegion();
	if (regionp)
	{
		LLVector3d agentPos = gAgent.getPositionGlobal();
		slurl = LLSLURL::buildSLURLfromPosGlobal(regionp->getName(), agentPos, escaped);
	}
	return slurl;
}

//static
BOOL LLAgentUI::checkAgentDistance(const LLVector3& pole, F32 radius)
{
	F32 delta_x = gAgent.getPositionAgent().mV[VX] - pole.mV[VX];
	F32 delta_y = gAgent.getPositionAgent().mV[VY] - pole.mV[VY];

	return  sqrt( delta_x* delta_x + delta_y* delta_y ) < radius;
}
BOOL LLAgentUI::buildLocationString(std::string& str, ELocationFormat fmt,const LLVector3& agent_pos_region)
{
	LLViewerRegion* region = gAgent.getRegion();
	LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();

	if (!region || !parcel) return FALSE;

	S32 pos_x = S32(agent_pos_region.mV[VX]);
	S32 pos_y = S32(agent_pos_region.mV[VY]);
	S32 pos_z = S32(agent_pos_region.mV[VZ]);

	// Round the numbers based on the velocity
	F32 velocity_mag_sq = gAgent.getVelocity().magVecSquared();

	const F32 FLY_CUTOFF = 6.f;		// meters/sec
	const F32 FLY_CUTOFF_SQ = FLY_CUTOFF * FLY_CUTOFF;
	const F32 WALK_CUTOFF = 1.5f;	// meters/sec
	const F32 WALK_CUTOFF_SQ = WALK_CUTOFF * WALK_CUTOFF;

	if (velocity_mag_sq > FLY_CUTOFF_SQ)
	{
		pos_x -= pos_x % 4;
		pos_y -= pos_y % 4;
	}
	else if (velocity_mag_sq > WALK_CUTOFF_SQ)
	{
		pos_x -= pos_x % 2;
		pos_y -= pos_y % 2;
	}

	// create a default name and description for the landmark
	std::string parcel_name = LLViewerParcelMgr::getInstance()->getAgentParcelName();
	std::string region_name = region->getName();
	std::string sim_access_string = region->getSimAccessString();
	std::string buffer;
	if( parcel_name.empty() )
	{
		// the parcel doesn't have a name
		switch (fmt)
		{
		case LOCATION_FORMAT_LANDMARK:
			buffer = llformat("%.100s", region_name.c_str());
			break;
		case LOCATION_FORMAT_NORMAL:
			buffer = llformat("%s", region_name.c_str());
			break;
		case LOCATION_FORMAT_NO_COORDS:
			buffer = llformat("%s%s%s",
				region_name.c_str(),
				sim_access_string.empty() ? "" : " - ",
				sim_access_string.c_str());
			break;
		case LOCATION_FORMAT_NO_MATURITY:
			buffer = llformat("%s (%d, %d, %d)",
				region_name.c_str(),
				pos_x, pos_y, pos_z);
			break;
		case LOCATION_FORMAT_FULL:
			buffer = llformat("%s (%d, %d, %d)%s%s",
				region_name.c_str(),
				pos_x, pos_y, pos_z,
				sim_access_string.empty() ? "" : " - ",
				sim_access_string.c_str());
			break;
		}
	}
	else
	{
		// the parcel has a name, so include it in the landmark name
		switch (fmt)
		{
		case LOCATION_FORMAT_LANDMARK:
			buffer = llformat("%.100s", parcel_name.c_str());
			break;
		case LOCATION_FORMAT_NORMAL:
			buffer = llformat("%s, %s", parcel_name.c_str(), region_name.c_str());
			break;
		case LOCATION_FORMAT_NO_MATURITY:
			buffer = llformat("%s, %s (%d, %d, %d)",
				parcel_name.c_str(),
				region_name.c_str(),
				pos_x, pos_y, pos_z);
			break;
		case LOCATION_FORMAT_NO_COORDS:
			buffer = llformat("%s, %s%s%s",
							  parcel_name.c_str(),
							  region_name.c_str(),
							  sim_access_string.empty() ? "" : " - ",
							  sim_access_string.c_str());
				break;
		case LOCATION_FORMAT_FULL:
			buffer = llformat("%s, %s (%d, %d, %d)%s%s",
				parcel_name.c_str(),
				region_name.c_str(),
				pos_x, pos_y, pos_z,
				sim_access_string.empty() ? "" : " - ",
				sim_access_string.c_str());
			break;
		}
	}
	str = buffer;
	return TRUE;
}
BOOL LLAgentUI::buildLocationString(std::string& str, ELocationFormat fmt)
{
	return buildLocationString(str,fmt, gAgent.getPositionAgent());
}
<|endoftext|>