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

/**
 * @file piecewise_jerk_path_optimizer.cc
 **/

#include "modules/planning/tasks/optimizers/piecewise_jerk_path/piecewise_jerk_path_optimizer.h"

#include <memory>
#include <utility>
#include <vector>

#include "modules/planning/common/planning_gflags.h"
#include "modules/planning/common/trajectory1d/piecewise_jerk_trajectory1d.h"
#include "modules/planning/math/finite_element_qp/fem_1d_qp_problem.h"

namespace apollo {
namespace planning {

using apollo::common::ErrorCode;
using apollo::common::Status;

PiecewiseJerkPathOptimizer::PiecewiseJerkPathOptimizer(const TaskConfig& config)
    : PathOptimizer(config) {
  SetName("PiecewiseJerkPathOptimizer");
  CHECK(config_.has_piecewise_jerk_path_config());
}

common::Status PiecewiseJerkPathOptimizer::Process(
    const SpeedData& speed_data, const ReferenceLine& reference_line,
    const common::TrajectoryPoint& init_point, PathData* const path_data) {
  const auto frenet_point =
      reference_line.GetFrenetPoint(init_point.path_point());

  const auto& piecewise_jerk_path_config = config_.piecewise_jerk_path_config();

  std::vector<std::pair<double, double>> lateral_boundaries;
  double start_s = 0.0;
  double delta_s = 0.0;
  reference_line_info_->GetPathBoundaries(&lateral_boundaries, &start_s,
                                          &delta_s);

  if (lateral_boundaries.size() < 2) {
    AERROR << "lateral boundary size < 2";
    return Status(ErrorCode::PLANNING_ERROR, "invalid lateral bounds provided");
  }

  // TODO(all): clean this debug messages after the branch is stable
  /**
  AERROR << "Init point:";
  AERROR << "\tl:\t" << frenet_point.l();
  AERROR << "\tdl:\t" << frenet_point.dl();
  AERROR << "\tddl:\t" << frenet_point.ddl();
  **/

  /**
  AERROR << "Weights:";
  AERROR << "\tl:\t" << piecewise_jerk_path_config.l_weight();
  AERROR << "\tdl:\t" << piecewise_jerk_path_config.dl_weight();
  AERROR << "\tddl:\t" << piecewise_jerk_path_config.ddl_weight();
  AERROR << "\tdddl:\t" << piecewise_jerk_path_config.dddl_weight();
  **/

  auto num_of_points = lateral_boundaries.size();

  std::array<double, 5> w = {
      piecewise_jerk_path_config.l_weight(),
      piecewise_jerk_path_config.dl_weight(),
      piecewise_jerk_path_config.ddl_weight(),
      piecewise_jerk_path_config.dddl_weight(),
      0.0
  };

  std::array<double, 3> init_lateral_state{frenet_point.l(), frenet_point.dl(),
                                           frenet_point.ddl()};

  std::unique_ptr<Fem1dQpProblem> fem_1d_qp(
      new Fem1dQpProblem(num_of_points, init_lateral_state, delta_s, w,
          FLAGS_lateral_jerk_bound));

  auto start_time = std::chrono::system_clock::now();

  fem_1d_qp->SetZeroOrderBounds(lateral_boundaries);

  FLAGS_lateral_derivative_bound_default = 1.0;
  double first_order_bounds = AdjustLateralDerivativeBounds(init_point.v(),
      frenet_point.dl(), frenet_point.ddl(),
      FLAGS_lateral_derivative_bound_default);
  AERROR << "adjusted lateral bound from \t"
      << FLAGS_lateral_derivative_bound_default << "\t" << first_order_bounds;
  fem_1d_qp->SetFirstOrderBounds(first_order_bounds);
  fem_1d_qp->SetSecondOrderBounds(FLAGS_lateral_derivative_bound_default);

  bool success = fem_1d_qp->Optimize();

  auto end_time = std::chrono::system_clock::now();
  std::chrono::duration<double> diff = end_time - start_time;
  ADEBUG << "Path Optimizer used time: " << diff.count() * 1000 << " ms.";

  if (!success) {
    AERROR << "piecewise jerk path optimizer failed";
    return Status(ErrorCode::PLANNING_ERROR,
        "piecewise jerk path optimizer failed");
  }

  const auto& x = fem_1d_qp->x();
  const auto& dx = fem_1d_qp->x_derivative();
  const auto& ddx = fem_1d_qp->x_second_order_derivative();

  CHECK(!x.empty() && x.size() == num_of_points);
  CHECK(!dx.empty() && dx.size() == num_of_points);
  CHECK(!ddx.empty() && ddx.size() == num_of_points);

  /*
  // TODO(all): an ad-hoc check for path feasibility since osqp
  //            cannot return the correct status
  const double numerical_buffer = 0.05;
  for (std::size_t i = 0; i < num_of_points; ++i) {
    if (x[i] < lateral_boundaries[i].first - numerical_buffer
        || x[i] > lateral_boundaries[i].second + numerical_buffer) {
      AERROR << "piecewise jerk path optimizer finds a infeasible solution";
      AERROR << "index\t" << i << ":\t" << x[i] <<
          "\t" << lateral_boundaries[i].first <<
          "\t" << lateral_boundaries[i].second;
      return Status(ErrorCode::PLANNING_ERROR,
          "piecewise jerk path optimizer failed");
    }
  }
  */

  PiecewiseJerkTrajectory1d piecewise_jerk_traj(x.front(),
      dx.front(), ddx.front());

  for (std::size_t i = 1; i < x.size(); ++i) {
    const auto dddl = (ddx[i] - ddx[i - 1]) / delta_s;
    piecewise_jerk_traj.AppendSegment(dddl, delta_s);
  }

  std::vector<common::FrenetFramePoint> frenet_frame_path;
  double accumulated_s = 0.0;
  while (accumulated_s < piecewise_jerk_traj.ParamLength()) {
    double l = piecewise_jerk_traj.Evaluate(0, accumulated_s);
    double dl = piecewise_jerk_traj.Evaluate(1, accumulated_s);
    double ddl = piecewise_jerk_traj.Evaluate(2, accumulated_s);

    common::FrenetFramePoint frenet_frame_point;
    frenet_frame_point.set_s(accumulated_s + start_s);
    frenet_frame_point.set_l(l);
    frenet_frame_point.set_dl(dl);
    frenet_frame_point.set_ddl(ddl);
    frenet_frame_path.push_back(std::move(frenet_frame_point));

    accumulated_s += FLAGS_trajectory_space_resolution;
  }

  path_data->SetReferenceLine(&reference_line);
  path_data->SetFrenetPath(FrenetFramePath(frenet_frame_path));

  return Status::OK();
}

double PiecewiseJerkPathOptimizer::AdjustLateralDerivativeBounds(
    const double s_dot, const double dl, const double ddl,
    const double l_dot_bounds) const {
  double s = std::fmax(FLAGS_vehicle_low_speed_threshold, s_dot);
  double l_prime_adjusted = l_dot_bounds / s;
  if (l_prime_adjusted < std::fabs(dl)) {
    l_prime_adjusted = std::fabs(dl) + 0.1;
  }
  return l_prime_adjusted;
}

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

/**
 * @file piecewise_jerk_path_optimizer.cc
 **/

#include "modules/planning/tasks/optimizers/piecewise_jerk_path/piecewise_jerk_path_optimizer.h"

#include <memory>
#include <utility>
#include <vector>

#include "modules/planning/common/planning_gflags.h"
#include "modules/planning/common/trajectory1d/piecewise_jerk_trajectory1d.h"
#include "modules/planning/math/finite_element_qp/fem_1d_qp_problem.h"

namespace apollo {
namespace planning {

using apollo::common::ErrorCode;
using apollo::common::Status;

PiecewiseJerkPathOptimizer::PiecewiseJerkPathOptimizer(const TaskConfig& config)
    : PathOptimizer(config) {
  SetName("PiecewiseJerkPathOptimizer");
  CHECK(config_.has_piecewise_jerk_path_config());
}

common::Status PiecewiseJerkPathOptimizer::Process(
    const SpeedData& speed_data, const ReferenceLine& reference_line,
    const common::TrajectoryPoint& init_point, PathData* const path_data) {
  const auto frenet_point =
      reference_line.GetFrenetPoint(init_point.path_point());

  const auto& piecewise_jerk_path_config = config_.piecewise_jerk_path_config();

  std::vector<std::pair<double, double>> lateral_boundaries;
  double start_s = 0.0;
  double delta_s = 0.0;
  reference_line_info_->GetPathBoundaries(&lateral_boundaries, &start_s,
                                          &delta_s);

  if (lateral_boundaries.size() < 2) {
    AERROR << "lateral boundary size < 2";
    return Status(ErrorCode::PLANNING_ERROR, "invalid lateral bounds provided");
  }

  // TODO(all): clean this debug messages after the branch is stable
  /**
  AERROR << "Init point:";
  AERROR << "\tl:\t" << frenet_point.l();
  AERROR << "\tdl:\t" << frenet_point.dl();
  AERROR << "\tddl:\t" << frenet_point.ddl();
  **/

  /**
  AERROR << "Weights:";
  AERROR << "\tl:\t" << piecewise_jerk_path_config.l_weight();
  AERROR << "\tdl:\t" << piecewise_jerk_path_config.dl_weight();
  AERROR << "\tddl:\t" << piecewise_jerk_path_config.ddl_weight();
  AERROR << "\tdddl:\t" << piecewise_jerk_path_config.dddl_weight();
  **/

  auto num_of_points = lateral_boundaries.size();

  std::array<double, 5> w = {
      piecewise_jerk_path_config.l_weight(),
      piecewise_jerk_path_config.dl_weight(),
      piecewise_jerk_path_config.ddl_weight(),
      piecewise_jerk_path_config.dddl_weight(),
      0.0
  };

  std::array<double, 3> init_lateral_state{frenet_point.l(), frenet_point.dl(),
                                           frenet_point.ddl()};

  std::unique_ptr<Fem1dQpProblem> fem_1d_qp(
      new Fem1dQpProblem(num_of_points, init_lateral_state, delta_s, w,
          FLAGS_lateral_jerk_bound));

  auto start_time = std::chrono::system_clock::now();

  fem_1d_qp->SetZeroOrderBounds(lateral_boundaries);

  // FLAGS_lateral_derivative_bound_default = 1.0;
  double first_order_bounds = AdjustLateralDerivativeBounds(init_point.v(),
      frenet_point.dl(), frenet_point.ddl(),
      FLAGS_lateral_derivative_bound_default);
  AERROR << "adjusted lateral derivative bound from \t"
      << FLAGS_lateral_derivative_bound_default << "\t" << first_order_bounds;
  // TODO(all): temprary disable AdjustLateralDerivativeBounds, enable later
  // fem_1d_qp->SetFirstOrderBounds(first_order_bounds);
  fem_1d_qp->SetFirstOrderBounds(FLAGS_lateral_derivative_bound_default);
  fem_1d_qp->SetSecondOrderBounds(FLAGS_lateral_derivative_bound_default);

  bool success = fem_1d_qp->Optimize();

  auto end_time = std::chrono::system_clock::now();
  std::chrono::duration<double> diff = end_time - start_time;
  ADEBUG << "Path Optimizer used time: " << diff.count() * 1000 << " ms.";

  if (!success) {
    AERROR << "piecewise jerk path optimizer failed";
    return Status(ErrorCode::PLANNING_ERROR,
        "piecewise jerk path optimizer failed");
  }

  const auto& x = fem_1d_qp->x();
  const auto& dx = fem_1d_qp->x_derivative();
  const auto& ddx = fem_1d_qp->x_second_order_derivative();

  CHECK(!x.empty() && x.size() == num_of_points);
  CHECK(!dx.empty() && dx.size() == num_of_points);
  CHECK(!ddx.empty() && ddx.size() == num_of_points);

  /*
  // TODO(all): an ad-hoc check for path feasibility since osqp
  //            cannot return the correct status
  const double numerical_buffer = 0.05;
  for (std::size_t i = 0; i < num_of_points; ++i) {
    if (x[i] < lateral_boundaries[i].first - numerical_buffer
        || x[i] > lateral_boundaries[i].second + numerical_buffer) {
      AERROR << "piecewise jerk path optimizer finds a infeasible solution";
      AERROR << "index\t" << i << ":\t" << x[i] <<
          "\t" << lateral_boundaries[i].first <<
          "\t" << lateral_boundaries[i].second;
      return Status(ErrorCode::PLANNING_ERROR,
          "piecewise jerk path optimizer failed");
    }
  }
  */

  PiecewiseJerkTrajectory1d piecewise_jerk_traj(x.front(),
      dx.front(), ddx.front());

  for (std::size_t i = 1; i < x.size(); ++i) {
    const auto dddl = (ddx[i] - ddx[i - 1]) / delta_s;
    piecewise_jerk_traj.AppendSegment(dddl, delta_s);
  }

  std::vector<common::FrenetFramePoint> frenet_frame_path;
  double accumulated_s = 0.0;
  while (accumulated_s < piecewise_jerk_traj.ParamLength()) {
    double l = piecewise_jerk_traj.Evaluate(0, accumulated_s);
    double dl = piecewise_jerk_traj.Evaluate(1, accumulated_s);
    double ddl = piecewise_jerk_traj.Evaluate(2, accumulated_s);

    common::FrenetFramePoint frenet_frame_point;
    frenet_frame_point.set_s(accumulated_s + start_s);
    frenet_frame_point.set_l(l);
    frenet_frame_point.set_dl(dl);
    frenet_frame_point.set_ddl(ddl);
    frenet_frame_path.push_back(std::move(frenet_frame_point));

    accumulated_s += FLAGS_trajectory_space_resolution;
  }

  path_data->SetReferenceLine(&reference_line);
  path_data->SetFrenetPath(FrenetFramePath(frenet_frame_path));

  return Status::OK();
}

double PiecewiseJerkPathOptimizer::AdjustLateralDerivativeBounds(
    const double s_dot, const double dl, const double ddl,
    const double l_dot_bounds) const {
  double s = std::fmax(FLAGS_vehicle_low_speed_threshold, s_dot);
  double l_prime_adjusted = l_dot_bounds / s;
  if (l_prime_adjusted < std::fabs(dl)) {
    l_prime_adjusted = std::fabs(dl) + 0.1;
  }
  return l_prime_adjusted;
}

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


<commit_before>/*
 *  traywindow.cpp  -  the KDE system tray applet
 *  Program:  kalarm
 *  Copyright © 2002-2006 by David Jarvie <software@astrojar.org.uk>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include "kalarm.h"

#include <stdlib.h>

#include <QToolTip>
#include <QMouseEvent>
#include <QList>

#include <kapplication.h>
#include <klocale.h>
#include <kstdaction.h>
#include <kaboutdata.h>
#include <kmenu.h>
#include <kmessagebox.h>
#include <kstandarddirs.h>
#include <kstdaction.h>
#include <kstdguiitem.h>
#include <kconfig.h>
#include <kdebug.h>

#include "alarmcalendar.h"
#include "alarmlistview.h"
#include "alarmtext.h"
#include "daemon.h"
#include "functions.h"
#include "kalarmapp.h"
#include "mainwindow.h"
#include "messagewin.h"
#include "prefdlg.h"
#include "preferences.h"
#include "templatemenuaction.h"
#include "traywindow.moc"

struct TipItem
{
	QDateTime  dateTime;
	QString    text;
};

/*=============================================================================
= Class: TrayWindow
= The KDE system tray window.
=============================================================================*/

TrayWindow::TrayWindow(MainWindow* parent)
	: KSystemTray((theApp()->wantRunInSystemTray() ? parent : 0)),
	  mAssocMainWindow(parent)
{
	kDebug(5950) << "TrayWindow::TrayWindow()\n";
	// Set up GUI icons
	mPixmapEnabled  = loadIcon("kalarm");
	mPixmapDisabled = loadIcon("kalarm_disabled");
	if (mPixmapEnabled.isNull() || mPixmapDisabled.isNull())
		KMessageBox::sorry(this, i18n("Cannot load system tray icon."));
	setAcceptDrops(true);         // allow drag-and-drop onto this window

	// Set up the context menu
	KActionCollection* actcol = actionCollection();
	KAction* a = Daemon::createAlarmEnableAction(actcol);
	a->plug(contextMenu());
	connect(a, SIGNAL(switched(bool)), SLOT(setEnabledStatus(bool)));
	a = KAlarm::createNewAlarmAction(i18n("&New Alarm..."), actcol, QLatin1String("tNew"));
	a->plug(contextMenu());
	connect(a, SIGNAL(triggered(bool)), SLOT(slotNewAlarm()));
	a = KAlarm::createNewFromTemplateAction(i18n("New Alarm From &Template"), actcol, QLatin1String("tNewFromTempl"));
	a->plug(contextMenu());
	connect(a, SIGNAL(selected(const KAEvent&)), SLOT(slotNewFromTemplate(const KAEvent&)));
	KStdAction::preferences(this, SLOT(slotPreferences()), actcol)->plug(contextMenu());

	// Replace the default handler for the Quit context menu item
	const char* quitName = KStdAction::name(KStdAction::Quit);
	delete actcol->action(quitName);
	KStdAction::quit(this, SLOT(slotQuit()), actcol);

	// Set icon to correspond with the alarms enabled menu status
	Daemon::checkStatus();
	setEnabledStatus(Daemon::monitoringAlarms());
}

TrayWindow::~TrayWindow()
{
	kDebug(5950) << "TrayWindow::~TrayWindow()\n";
	theApp()->removeWindow(this);
	emit deleted();
}

/******************************************************************************
* Called just before the context menu is displayed.
* Update the Alarms Enabled item status.
*/
void TrayWindow::contextMenuAboutToShow(KMenu*)
{
	Daemon::checkStatus();
}

/******************************************************************************
*  Called when the "New Alarm" menu item is selected to edit a new alarm.
*/
void TrayWindow::slotNewAlarm()
{
	MainWindow::executeNew();
}

/******************************************************************************
*  Called when the "New Alarm" menu item is selected to edit a new alarm.
*/
void TrayWindow::slotNewFromTemplate(const KAEvent& event)
{
	MainWindow::executeNew(event);
}

/******************************************************************************
*  Called when the "Configure KAlarm" menu item is selected.
*/
void TrayWindow::slotPreferences()
{
	KAlarmPrefDlg prefDlg;
	prefDlg.exec();
}

/******************************************************************************
* Called when the Quit context menu item is selected.
*/
void TrayWindow::slotQuit()
{
	theApp()->doQuit(this);
}

/******************************************************************************
* Called when the Alarms Enabled action status has changed.
* Updates the alarms enabled menu item check state, and the icon pixmap.
*/
void TrayWindow::setEnabledStatus(bool status)
{
	kDebug(5950) << "TrayWindow::setEnabledStatus(" << (int)status << ")\n";
	setPixmap(status ? mPixmapEnabled : mPixmapDisabled);
}

/******************************************************************************
*  Called when the mouse is clicked over the panel icon.
*  A left click displays the KAlarm main window.
*  A middle button click displays the New Alarm window.
*/
void TrayWindow::mousePressEvent(QMouseEvent* e)
{
	if (e->button() == Qt::LeftButton  &&  !theApp()->wantRunInSystemTray())
	{
		// Left click: display/hide the first main window
		mAssocMainWindow = MainWindow::toggleWindow(mAssocMainWindow);
	}
	else if (e->button() == Qt::MidButton)
		MainWindow::executeNew();    // display a New Alarm dialog
	else
		KSystemTray::mousePressEvent(e);
}

/******************************************************************************
*  Called when the mouse is released over the panel icon.
*  The main window (if not hidden) is raised and made the active window.
*  If this is done in mousePressEvent(), it doesn't work.
*/
void TrayWindow::mouseReleaseEvent(QMouseEvent* e)
{
	if (e->button() == Qt::LeftButton  &&  mAssocMainWindow  &&  mAssocMainWindow->isVisible())
	{
		mAssocMainWindow->raise();
		mAssocMainWindow->activateWindow();
	}
	else
		KSystemTray::mouseReleaseEvent(e);
}

/******************************************************************************
*  Called when the drag cursor enters the panel icon.
*/
void TrayWindow::dragEnterEvent(QDragEnterEvent* e)
{
	MainWindow::executeDragEnterEvent(e);
}

/******************************************************************************
*  Called when an object is dropped on the panel icon.
*  If the object is recognised, the edit alarm dialog is opened appropriately.
*/
void TrayWindow::dropEvent(QDropEvent* e)
{
	MainWindow::executeDropEvent(0, e);
}

/******************************************************************************
*  Called when any event occurs.
*  If it's a tooltip event, display the tooltip text showing alarms due in the
*  next 24 hours. The limit of 24 hours is because only times, not dates, are
*  displayed.
*/
bool TrayWindow::event(QEvent* e)
{
	if (e->type() != QEvent::ToolTip)
		return KSystemTray::event(e);
	QHelpEvent* he = (QHelpEvent*)e;
	QString text;
	if (Daemon::monitoringAlarms())
		text = kapp->aboutData()->programName();
	else
		text = i18n("%1 - disabled", kapp->aboutData()->programName());
	kDebug(5950) << "TrayWindow::event(): " << text << endl;
	if (Preferences::tooltipAlarmCount())
		tooltipAlarmText(text);
	QToolTip::showText(he->pos(), text);
	return true;
}

/******************************************************************************
*  Return the tooltip text showing alarms due in the next 24 hours.
*  The limit of 24 hours is because only times, not dates, are displayed.
*/
void TrayWindow::tooltipAlarmText(QString& text) const
{
	KAEvent event;
	const QString& prefix = Preferences::tooltipTimeToPrefix();
	int maxCount = Preferences::tooltipAlarmCount();
	QDateTime now = QDateTime::currentDateTime();

	// Get today's and tomorrow's alarms, sorted in time order
	QList<TipItem> items;
	KCal::Event::List events = AlarmCalendar::activeCalendar()->eventsWithAlarms(QDateTime(now.date()), now.addDays(1));
	for (KCal::Event::List::ConstIterator it = events.begin();  it != events.end();  ++it)
	{
		KCal::Event* kcalEvent = *it;
		event.set(*kcalEvent);
		if (event.enabled()  &&  !event.expired()  &&  event.action() == KAEvent::MESSAGE)
		{
			TipItem item;
			DateTime dateTime = event.nextDateTime(false);
			if (dateTime.date() > now.date())
			{
				// Ignore alarms after tomorrow at the current clock time
				if (dateTime.date() != now.date().addDays(1)
				||  dateTime.time() >= now.time())
					continue;
			}
			item.dateTime = dateTime.dateTime();

			// The alarm is due today, or early tomorrow
			bool space = false;
			if (Preferences::showTooltipAlarmTime())
			{
				item.text += KGlobal::locale()->formatTime(item.dateTime.time());
				item.text += QLatin1Char(' ');
				space = true;
			}
			if (Preferences::showTooltipTimeToAlarm())
			{
				int mins = (now.secsTo(item.dateTime) + 59) / 60;
				if (mins < 0)
					mins = 0;
				char minutes[3] = "00";
				minutes[0] = (mins%60) / 10 + '0';
				minutes[1] = (mins%60) % 10 + '0';
				if (Preferences::showTooltipAlarmTime())
					item.text += i18nc("prefix + hours:minutes", "(%1%2:%3)", prefix, mins/60, minutes);
				else
					item.text += i18nc("prefix + hours:minutes", "%1%2:%3", prefix, mins/60, minutes);
				item.text += QLatin1Char(' ');
				space = true;
			}
			if (space)
				item.text += QLatin1Char(' ');
			item.text += AlarmText::summary(event);

			// Insert the item into the list in time-sorted order
			int i = 0;
			for (int iend = items.count();  i < iend;  ++i)
			{
				if (item.dateTime <= items[i].dateTime)
					break;
			}
			items.insert(i, item);
		}
        }
	kDebug(5950) << "TrayWindow::tooltipAlarmText():\n";
	int count = 0;
	for (int i = 0, iend = items.count();  i < iend;  ++i)
	{
		kDebug(5950) << "-- " << (count+1) << ") " << items[i].text << endl;
		text += "\n";
		text += items[i].text;
		if (++count == maxCount)
			break;
	}
}

/******************************************************************************
* Called when the associated main window is closed.
*/
void TrayWindow::removeWindow(MainWindow* win)
{
	if (win == mAssocMainWindow)
		mAssocMainWindow = 0;
}

#ifdef HAVE_X11_HEADERS
	#include <X11/X.h>
	#include <X11/Xlib.h>
	#include <X11/Xutil.h>
#include <QX11Info>
#endif

/******************************************************************************
* Check whether the widget is in the system tray.
* Note that it is only sometime AFTER the show event that the system tray
* becomes the widget's parent. So for a definitive status, call this method
* only after waiting a bit...
* Reply = true if the widget is in the system tray, or its status can't be determined.
*       = false if it is not currently in the system tray.
*/
bool TrayWindow::inSystemTray() const
{
#ifdef HAVE_X11_HEADERS
	Window  xParent;    // receives parent window
	Window  root;
	Window* children = 0;
	unsigned int nchildren;
	// Find the X parent window of the widget. This is not the same as the Qt parent widget.
	if (!XQueryTree(QX11Info::display(), winId(), &root, &xParent, &children, &nchildren))
		return true;    // error determining its parent X window
	if (children)
		XFree(children);

	// If it is in the system tray, the system tray window will be its X parent.
	// Otherwise, the root window will be its X parent.
	return xParent != root;
#else
	return true;
#endif // HAVE_X11_HEADERS
}
<commit_msg>compile on Mac OS.<commit_after>/*
 *  traywindow.cpp  -  the KDE system tray applet
 *  Program:  kalarm
 *  Copyright © 2002-2006 by David Jarvie <software@astrojar.org.uk>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include "kalarm.h"

#include <stdlib.h>

#include <QToolTip>
#include <QMouseEvent>
#include <QList>

#include <kapplication.h>
#include <klocale.h>
#include <kstdaction.h>
#include <kaboutdata.h>
#include <kmenu.h>
#include <kmessagebox.h>
#include <kstandarddirs.h>
#include <kstdaction.h>
#include <kstdguiitem.h>
#include <kconfig.h>
#include <kdebug.h>

#include "alarmcalendar.h"
#include "alarmlistview.h"
#include "alarmtext.h"
#include "daemon.h"
#include "functions.h"
#include "kalarmapp.h"
#include "mainwindow.h"
#include "messagewin.h"
#include "prefdlg.h"
#include "preferences.h"
#include "templatemenuaction.h"
#include "traywindow.moc"

struct TipItem
{
	QDateTime  dateTime;
	QString    text;
};

/*=============================================================================
= Class: TrayWindow
= The KDE system tray window.
=============================================================================*/

TrayWindow::TrayWindow(MainWindow* parent)
	: KSystemTray((theApp()->wantRunInSystemTray() ? parent : 0)),
	  mAssocMainWindow(parent)
{
	kDebug(5950) << "TrayWindow::TrayWindow()\n";
	// Set up GUI icons
	mPixmapEnabled  = loadIcon("kalarm");
	mPixmapDisabled = loadIcon("kalarm_disabled");
	if (mPixmapEnabled.isNull() || mPixmapDisabled.isNull())
		KMessageBox::sorry(this, i18n("Cannot load system tray icon."));
	setAcceptDrops(true);         // allow drag-and-drop onto this window

	// Set up the context menu
	KActionCollection* actcol = actionCollection();
	KAction* a = Daemon::createAlarmEnableAction(actcol);
	a->plug(contextMenu());
	connect(a, SIGNAL(switched(bool)), SLOT(setEnabledStatus(bool)));
	a = KAlarm::createNewAlarmAction(i18n("&New Alarm..."), actcol, QLatin1String("tNew"));
	a->plug(contextMenu());
	connect(a, SIGNAL(triggered(bool)), SLOT(slotNewAlarm()));
	a = KAlarm::createNewFromTemplateAction(i18n("New Alarm From &Template"), actcol, QLatin1String("tNewFromTempl"));
	a->plug(contextMenu());
	connect(a, SIGNAL(selected(const KAEvent&)), SLOT(slotNewFromTemplate(const KAEvent&)));
	KStdAction::preferences(this, SLOT(slotPreferences()), actcol)->plug(contextMenu());

	// Replace the default handler for the Quit context menu item
	const char* quitName = KStdAction::name(KStdAction::Quit);
	delete actcol->action(quitName);
	KStdAction::quit(this, SLOT(slotQuit()), actcol);

	// Set icon to correspond with the alarms enabled menu status
	Daemon::checkStatus();
	setEnabledStatus(Daemon::monitoringAlarms());
}

TrayWindow::~TrayWindow()
{
	kDebug(5950) << "TrayWindow::~TrayWindow()\n";
	theApp()->removeWindow(this);
	emit deleted();
}

/******************************************************************************
* Called just before the context menu is displayed.
* Update the Alarms Enabled item status.
*/
void TrayWindow::contextMenuAboutToShow(KMenu*)
{
	Daemon::checkStatus();
}

/******************************************************************************
*  Called when the "New Alarm" menu item is selected to edit a new alarm.
*/
void TrayWindow::slotNewAlarm()
{
	MainWindow::executeNew();
}

/******************************************************************************
*  Called when the "New Alarm" menu item is selected to edit a new alarm.
*/
void TrayWindow::slotNewFromTemplate(const KAEvent& event)
{
	MainWindow::executeNew(event);
}

/******************************************************************************
*  Called when the "Configure KAlarm" menu item is selected.
*/
void TrayWindow::slotPreferences()
{
	KAlarmPrefDlg prefDlg;
	prefDlg.exec();
}

/******************************************************************************
* Called when the Quit context menu item is selected.
*/
void TrayWindow::slotQuit()
{
	theApp()->doQuit(this);
}

/******************************************************************************
* Called when the Alarms Enabled action status has changed.
* Updates the alarms enabled menu item check state, and the icon pixmap.
*/
void TrayWindow::setEnabledStatus(bool status)
{
	kDebug(5950) << "TrayWindow::setEnabledStatus(" << (int)status << ")\n";
	setPixmap(status ? mPixmapEnabled : mPixmapDisabled);
}

/******************************************************************************
*  Called when the mouse is clicked over the panel icon.
*  A left click displays the KAlarm main window.
*  A middle button click displays the New Alarm window.
*/
void TrayWindow::mousePressEvent(QMouseEvent* e)
{
	if (e->button() == Qt::LeftButton  &&  !theApp()->wantRunInSystemTray())
	{
		// Left click: display/hide the first main window
		mAssocMainWindow = MainWindow::toggleWindow(mAssocMainWindow);
	}
	else if (e->button() == Qt::MidButton)
		MainWindow::executeNew();    // display a New Alarm dialog
	else
		KSystemTray::mousePressEvent(e);
}

/******************************************************************************
*  Called when the mouse is released over the panel icon.
*  The main window (if not hidden) is raised and made the active window.
*  If this is done in mousePressEvent(), it doesn't work.
*/
void TrayWindow::mouseReleaseEvent(QMouseEvent* e)
{
	if (e->button() == Qt::LeftButton  &&  mAssocMainWindow  &&  mAssocMainWindow->isVisible())
	{
		mAssocMainWindow->raise();
		mAssocMainWindow->activateWindow();
	}
	else
		KSystemTray::mouseReleaseEvent(e);
}

/******************************************************************************
*  Called when the drag cursor enters the panel icon.
*/
void TrayWindow::dragEnterEvent(QDragEnterEvent* e)
{
	MainWindow::executeDragEnterEvent(e);
}

/******************************************************************************
*  Called when an object is dropped on the panel icon.
*  If the object is recognised, the edit alarm dialog is opened appropriately.
*/
void TrayWindow::dropEvent(QDropEvent* e)
{
	MainWindow::executeDropEvent(0, e);
}

/******************************************************************************
*  Called when any event occurs.
*  If it's a tooltip event, display the tooltip text showing alarms due in the
*  next 24 hours. The limit of 24 hours is because only times, not dates, are
*  displayed.
*/
bool TrayWindow::event(QEvent* e)
{
	if (e->type() != QEvent::ToolTip)
		return KSystemTray::event(e);
	QHelpEvent* he = (QHelpEvent*)e;
	QString text;
	if (Daemon::monitoringAlarms())
		text = kapp->aboutData()->programName();
	else
		text = i18n("%1 - disabled", kapp->aboutData()->programName());
	kDebug(5950) << "TrayWindow::event(): " << text << endl;
	if (Preferences::tooltipAlarmCount())
		tooltipAlarmText(text);
	QToolTip::showText(he->pos(), text);
	return true;
}

/******************************************************************************
*  Return the tooltip text showing alarms due in the next 24 hours.
*  The limit of 24 hours is because only times, not dates, are displayed.
*/
void TrayWindow::tooltipAlarmText(QString& text) const
{
	KAEvent event;
	const QString& prefix = Preferences::tooltipTimeToPrefix();
	int maxCount = Preferences::tooltipAlarmCount();
	QDateTime now = QDateTime::currentDateTime();

	// Get today's and tomorrow's alarms, sorted in time order
	QList<TipItem> items;
	KCal::Event::List events = AlarmCalendar::activeCalendar()->eventsWithAlarms(QDateTime(now.date()), now.addDays(1));
	for (KCal::Event::List::ConstIterator it = events.begin();  it != events.end();  ++it)
	{
		KCal::Event* kcalEvent = *it;
		event.set(*kcalEvent);
		if (event.enabled()  &&  !event.expired()  &&  event.action() == KAEvent::MESSAGE)
		{
			TipItem item;
			DateTime dateTime = event.nextDateTime(false);
			if (dateTime.date() > now.date())
			{
				// Ignore alarms after tomorrow at the current clock time
				if (dateTime.date() != now.date().addDays(1)
				||  dateTime.time() >= now.time())
					continue;
			}
			item.dateTime = dateTime.dateTime();

			// The alarm is due today, or early tomorrow
			bool space = false;
			if (Preferences::showTooltipAlarmTime())
			{
				item.text += KGlobal::locale()->formatTime(item.dateTime.time());
				item.text += QLatin1Char(' ');
				space = true;
			}
			if (Preferences::showTooltipTimeToAlarm())
			{
				int mins = (now.secsTo(item.dateTime) + 59) / 60;
				if (mins < 0)
					mins = 0;
				char minutes[3] = "00";
				minutes[0] = (mins%60) / 10 + '0';
				minutes[1] = (mins%60) % 10 + '0';
				if (Preferences::showTooltipAlarmTime())
					item.text += i18nc("prefix + hours:minutes", "(%1%2:%3)", prefix, mins/60, minutes);
				else
					item.text += i18nc("prefix + hours:minutes", "%1%2:%3", prefix, mins/60, minutes);
				item.text += QLatin1Char(' ');
				space = true;
			}
			if (space)
				item.text += QLatin1Char(' ');
			item.text += AlarmText::summary(event);

			// Insert the item into the list in time-sorted order
			int i = 0;
			for (int iend = items.count();  i < iend;  ++i)
			{
				if (item.dateTime <= items[i].dateTime)
					break;
			}
			items.insert(i, item);
		}
        }
	kDebug(5950) << "TrayWindow::tooltipAlarmText():\n";
	int count = 0;
	for (int i = 0, iend = items.count();  i < iend;  ++i)
	{
		kDebug(5950) << "-- " << (count+1) << ") " << items[i].text << endl;
		text += "\n";
		text += items[i].text;
		if (++count == maxCount)
			break;
	}
}

/******************************************************************************
* Called when the associated main window is closed.
*/
void TrayWindow::removeWindow(MainWindow* win)
{
	if (win == mAssocMainWindow)
		mAssocMainWindow = 0;
}

#if defined(HAVE_X11_HEADERS) && defined(Q_WS_X11)
	#include <X11/X.h>
	#include <X11/Xlib.h>
	#include <X11/Xutil.h>
#include <QX11Info>
#endif

/******************************************************************************
* Check whether the widget is in the system tray.
* Note that it is only sometime AFTER the show event that the system tray
* becomes the widget's parent. So for a definitive status, call this method
* only after waiting a bit...
* Reply = true if the widget is in the system tray, or its status can't be determined.
*       = false if it is not currently in the system tray.
*/
bool TrayWindow::inSystemTray() const
{
#if defined(HAVE_X11_HEADERS) && defined(Q_WS_X11)
	Window  xParent;    // receives parent window
	Window  root;
	Window* children = 0;
	unsigned int nchildren;
	// Find the X parent window of the widget. This is not the same as the Qt parent widget.
	if (!XQueryTree(QX11Info::display(), winId(), &root, &xParent, &children, &nchildren))
		return true;    // error determining its parent X window
	if (children)
		XFree(children);

	// If it is in the system tray, the system tray window will be its X parent.
	// Otherwise, the root window will be its X parent.
	return xParent != root;
#else
	return true;
#endif // HAVE_X11_HEADERS
}
<|endoftext|>


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

// Author: E. Gil Jones, Ken Anderson

#include <ros/ros.h>
#include <distance_field/propagation_distance_field.h>
#include <planning_scene_monitor_tools/kinematic_state_joint_state_publisher.h>
#include <planning_scene_monitor/planning_scene_monitor.h>
#include <collision_distance_field/collision_distance_field_types.h>
#include <collision_distance_field/collision_robot_distance_field.h>
#include <interactive_markers/interactive_marker_server.h>
#include <visualization_msgs/InteractiveMarkerFeedback.h>
#include <moveit_visualization_ros/interactive_marker_helper_functions.h>
#include <planning_models/transforms.h>

using namespace moveit_visualization_ros;

static const std::string VIS_TOPIC_NAME = "distance_field_visualization";

boost::shared_ptr<KinematicStateJointStatePublisher> joint_state_publisher_;
boost::shared_ptr<planning_scene_monitor::PlanningSceneMonitor> planning_scene_monitor_;
//boost::shared_ptr<InteractiveObjectVisualization> iov_;

void publisher_function() {
  ros::WallRate r(10.0);
  while(ros::ok())
  {
    joint_state_publisher_->broadcastRootTransform(planning_scene_monitor_->getPlanningScene()->getCurrentState());
    joint_state_publisher_->publishKinematicState(planning_scene_monitor_->getPlanningScene()->getCurrentState());
    r.sleep();
  }
}

int main(int argc, char** argv)
{
  ros::init(argc, argv, "interactive_object_visualization", ros::init_options::NoSigintHandler);

  ros::AsyncSpinner spinner(1);
  spinner.start();

  // boost::shared_ptr<interactive_markers::InteractiveMarkerServer> interactive_marker_server_;
  // interactive_marker_server_.reset(new interactive_markers::InteractiveMarkerServer("interactive_distance_field_visualization", "", false));
  planning_scene_monitor_.reset(new planning_scene_monitor::PlanningSceneMonitor("robot_description"));
  joint_state_publisher_.reset(new KinematicStateJointStatePublisher());

  boost::thread publisher_thread(boost::bind(&publisher_function));

  ros::NodeHandle nh;

  ros::Publisher vis_marker_array_publisher;
  ros::Publisher vis_marker_publisher;

  vis_marker_publisher = nh.advertise<visualization_msgs::Marker> (VIS_TOPIC_NAME, 128);
  vis_marker_array_publisher = nh.advertise<visualization_msgs::MarkerArray> (VIS_TOPIC_NAME + "_array", 128);

  collision_distance_field::CollisionRobotDistanceField coll(planning_scene_monitor_->getPlanningScene()->getKinematicModel());
  collision_detection::CollisionRequest req;
  collision_detection::CollisionResult res;
  req.group_name = "right_arm";
  collision_detection::AllowedCollisionMatrix acm = planning_scene_monitor_->getPlanningScene()->getAllowedCollisionMatrix();
  acm.setEntry("r_shoulder_pan_link", "r_shoulder_pan_link", true);
  coll.checkSelfCollision(req, res, planning_scene_monitor_->getPlanningScene()->getCurrentState(), acm);

  boost::shared_ptr<const collision_distance_field::CollisionRobotDistanceField::DistanceFieldCacheEntry> dfce = coll.getLastDistanceFieldEntry();
  if(!dfce) {
    ROS_WARN_STREAM("no dfce");
    exit(-1);
  }
  boost::shared_ptr<const collision_distance_field::CollisionRobotDistanceField::GroupStateRepresentation> gsr = coll.getLastGroupStateRepresentation();
  // visualization_msgs::MarkerArray sphere_markers;
  // std_msgs::ColorRGBA col;
  // col.g = 1.0;
  // col.a = .8;
  // collision_distance_field::getCollisionSphereMarkers(col,
  //                                                     planning_scene_monitor_->getPlanningScene()->getPlanningFrame(),
  //                                                     "spheres",
  //                                                     ros::Duration(0.0),
  //                                                     gsr->link_body_decompositions_,
  //                                                     sphere_markers);

  visualization_msgs::MarkerArray arrow_markers;
  std_msgs::ColorRGBA col;
  col.b = 1.0;
  col.a = .8;
  collision_distance_field::getProximityGradientMarkers(col,
                                                       planning_scene_monitor_->getPlanningScene()->getPlanningFrame(),
                                                       "arrows",
                                                       ros::Duration(0.0),
                                                       gsr->link_body_decompositions_,
                                                       gsr->gradients_,
                                                       arrow_markers);

  visualization_msgs::Marker inf_marker;
  dfce->distance_field_->getIsoSurfaceMarkers(0.0,.01,
                                              planning_scene_monitor_->getPlanningScene()->getPlanningFrame(),
                                              ros::Time::now(),
                                              Eigen::Affine3d::Identity(),
                                              inf_marker);
  // bodies::Body* b = bodies::createBodyFromShape(planning_scene_monitor_->getPlanningScene()->getKinematicModel()->getLinkModel("base_link")->getShape().get());
  // b->setPose(planning_scene_monitor_->getPlanningScene()->getCurrentState().getLinkState("base_link")->getGlobalLinkTransform());
  // bodies::ConvexMesh* cm = dynamic_cast<bodies::ConvexMesh*>(b);
  // inf_marker.type = visualization_msgs::Marker::TRIANGLE_LIST;
  // inf_marker.scale.x = inf_marker.scale.y = inf_marker.scale.z = 1.0;
  // inf_marker.color.a = inf_marker.color.b = 1.0;
  // inf_marker.header.frame_id = planning_scene_monitor_->getPlanningScene()->getPlanningFrame();
  // inf_marker.pose.orientation.w = 1.0;
  // for(unsigned int i = 0; i < cm->getTriangles().size(); i+=3) {
  //   // ROS_INFO_STREAM("Triangle " << i << " is " << cm->getTriangles()[i] << " "
  //   //                 << cm->getTriangles()[i+1] << " "
  //   //                 << cm->getTriangles()[i+2]);
  //   geometry_msgs::Point p;
  //   p.x = cm->getVertices()[cm->getTriangles()[i]].x();
  //   p.y = cm->getVertices()[cm->getTriangles()[i]].y();
  //   p.z = cm->getVertices()[cm->getTriangles()[i]].z();
  //   inf_marker.points.push_back(p);
  //   p.x = cm->getVertices()[cm->getTriangles()[i+1]].x();
  //   p.y = cm->getVertices()[cm->getTriangles()[i+1]].y();
  //   p.z = cm->getVertices()[cm->getTriangles()[i+1]].z();
  //   inf_marker.points.push_back(p);
  //   p.x = cm->getVertices()[cm->getTriangles()[i+2]].x();
  //   p.y = cm->getVertices()[cm->getTriangles()[i+2]].y();
  //   p.z = cm->getVertices()[cm->getTriangles()[i+2]].z();
  //   inf_marker.points.push_back(p);
  // }
  ros::WallRate r(1.0);
  while(ros::ok()) {
    vis_marker_publisher.publish(inf_marker);
    //vis_marker_array_publisher.publish(sphere_markers);
    vis_marker_array_publisher.publish(arrow_markers);
    r.sleep();
  }

  // std_msgs::ColorRGBA col;
  // col.r = col.g = col.b = .5;
  // col.a = 1.0;

  // std_msgs::ColorRGBA good_color;
  // good_color.a = 1.0;
  // good_color.g = 1.0;

  // std_msgs::ColorRGBA bad_color;
  // bad_color.a = 1.0;
  // bad_color.r = 1.0;

  // iov_.reset(new InteractiveObjectVisualization(planning_scene_monitor_->getPlanningScene(),
  //                                               interactive_marker_server_,
  //                                               col));

  // kv_->addMenuEntry("Add Cube", boost::bind(&addCubeCallback, _1));

  // iov_->setUpdateCallback(boost::bind(&updateCallback, _1));

  ros::waitForShutdown();
}

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

// Author: E. Gil Jones, Ken Anderson

#include <ros/ros.h>
#include <distance_field/propagation_distance_field.h>
#include <planning_scene_monitor_tools/kinematic_state_joint_state_publisher.h>
#include <planning_scene_monitor/planning_scene_monitor.h>
#include <collision_distance_field/collision_distance_field_types.h>
#include <collision_distance_field/collision_robot_distance_field.h>
#include <collision_distance_field/collision_world_distance_field.h>
#include <interactive_markers/interactive_marker_server.h>
#include <visualization_msgs/InteractiveMarkerFeedback.h>
#include <moveit_visualization_ros/interactive_marker_helper_functions.h>
#include <planning_models/transforms.h>

using namespace moveit_visualization_ros;

static const std::string VIS_TOPIC_NAME = "distance_field_visualization";

boost::shared_ptr<KinematicStateJointStatePublisher> joint_state_publisher_;
boost::shared_ptr<planning_scene_monitor::PlanningSceneMonitor> planning_scene_monitor_;
//boost::shared_ptr<InteractiveObjectVisualization> iov_;

void publisher_function() {
  ros::WallRate r(10.0);
  while(ros::ok())
  {
    joint_state_publisher_->broadcastRootTransform(planning_scene_monitor_->getPlanningScene()->getCurrentState());
    joint_state_publisher_->publishKinematicState(planning_scene_monitor_->getPlanningScene()->getCurrentState());
    r.sleep();
  }
}

int main(int argc, char** argv)
{
  ros::init(argc, argv, "interactive_object_visualization", ros::init_options::NoSigintHandler);

  ros::AsyncSpinner spinner(1);
  spinner.start();

  // boost::shared_ptr<interactive_markers::InteractiveMarkerServer> interactive_marker_server_;
  // interactive_marker_server_.reset(new interactive_markers::InteractiveMarkerServer("interactive_distance_field_visualization", "", false));
  planning_scene_monitor_.reset(new planning_scene_monitor::PlanningSceneMonitor("robot_description"));
  joint_state_publisher_.reset(new KinematicStateJointStatePublisher());

  std::map<std::string, double> joint_vals;
  joint_vals["r_shoulder_pan_joint"] = -.5;
  planning_scene_monitor_->getPlanningScene()->getCurrentState().setStateValues(joint_vals);

  boost::thread publisher_thread(boost::bind(&publisher_function));

  ros::NodeHandle nh;

  ros::Publisher vis_marker_array_publisher;
  ros::Publisher vis_marker_publisher;

  vis_marker_publisher = nh.advertise<visualization_msgs::Marker> (VIS_TOPIC_NAME, 128);
  vis_marker_array_publisher = nh.advertise<visualization_msgs::MarkerArray> (VIS_TOPIC_NAME + "_array", 128);

  collision_distance_field::CollisionRobotDistanceField coll(planning_scene_monitor_->getPlanningScene()->getKinematicModel());
  collision_distance_field::CollisionWorldDistanceField world;
  shapes::Shape* shape = new shapes::Box(.1,.1,.5);
  Eigen::Affine3d pos1 = Eigen::Affine3d::Identity();
  pos1.translation().x() = .4;
  pos1.translation().z() = 1.0;
  world.addToObject("box", shapes::ShapeConstPtr(shape), pos1);

  collision_detection::CollisionRequest req;
  collision_detection::CollisionResult res;
  req.group_name = "right_arm";
  collision_detection::AllowedCollisionMatrix acm = planning_scene_monitor_->getPlanningScene()->getAllowedCollisionMatrix();
  acm.setEntry("r_shoulder_pan_link", "r_shoulder_pan_link", true);
  acm.setEntry("r_shoulder_lift_link", "r_shoulder_lift_link", true);
  acm.setEntry("r_upper_arm_link", "r_upper_arm_link", true);

  boost::shared_ptr<const collision_distance_field::CollisionRobotDistanceField::GroupStateRepresentation> world_gsr =
    world.getCollisionGradients(req,
                                res,
                                coll,
                                planning_scene_monitor_->getPlanningScene()->getCurrentState(),
                                acm);

  // world.checkRobotCollision(req,
  //                           res,
  //                           coll,
  //                           planning_scene_monitor_->getPlanningScene()->getCurrentState(),
  //                           acm);

  visualization_msgs::Marker inf_marker;
  world.getDistanceField()->getIsoSurfaceMarkers(0.0,.01,
                                                  planning_scene_monitor_->getPlanningScene()->getPlanningFrame(),
                                                  ros::Time::now(),
                                                  Eigen::Affine3d::Identity(),
                                                  inf_marker);
  //boost::shared_ptr<const collision_distance_field::CollisionRobotDistanceField::GroupStateRepresentation> world_gsr = world.getLastGroupStateRepresentation();

  visualization_msgs::MarkerArray arrow_markers;
  std_msgs::ColorRGBA col;
  col.b = 1.0;
  col.a = .8;
  collision_distance_field::getProximityGradientMarkers(planning_scene_monitor_->getPlanningScene()->getPlanningFrame(),
                                                        "arrows",
                                                        ros::Duration(0.0),
                                                        world_gsr->link_body_decompositions_,
                                                        world_gsr->gradients_,
                                                        arrow_markers);

  // //req.contacts = true;
  // coll.checkSelfCollision(req, res, planning_scene_monitor_->getPlanningScene()->getCurrentState(), acm);
  // boost::shared_ptr<const collision_distance_field::CollisionRobotDistanceField::DistanceFieldCacheEntry> dfce = coll.getLastDistanceFieldEntry();
  // if(!dfce) {
  //   ROS_WARN_STREAM("no dfce");
  //   exit(-1);
  // }
  // boost::shared_ptr<const collision_distance_field::CollisionRobotDistanceField::GroupStateRepresentation> gsr = coll.getLastGroupStateRepresentation();
  // // visualization_msgs::MarkerArray sphere_markers;
  // // std_msgs::ColorRGBA col;
  // // col.g = 1.0;
  // // col.a = .8;
  // // collision_distance_field::getCollisionSphereMarkers(col,
  // //                                                     planning_scene_monitor_->getPlanningScene()->getPlanningFrame(),
  // //                                                     "spheres",
  // //                                                     ros::Duration(0.0),
  // //                                                     gsr->link_body_decompositions_,
  // //                                                     sphere_markers);

  // visualization_msgs::MarkerArray arrow_markers;
  // // std_msgs::ColorRGBA col;
  // // col.b = 1.0;
  // // col.a = .8;
  // // collision_distance_field::getProximityGradientMarkers(col,
  // //                                                      planning_scene_monitor_->getPlanningScene()->getPlanningFrame(),
  // //                                                      "arrows",
  // //                                                      ros::Duration(0.0),
  // //                                                      gsr->link_body_decompositions_,
  // //                                                      gsr->gradients_,
  // //                                                      arrow_markers);

  // visualization_msgs::Marker inf_marker;
  // dfce->distance_field_->getIsoSurfaceMarkers(0.0,.01,
  //                                             planning_scene_monitor_->getPlanningScene()->getPlanningFrame(),
  //                                             ros::Time::now(),
  //                                             Eigen::Affine3d::Identity(),
  //                                             inf_marker);
  // bodies::Body* b = bodies::createBodyFromShape(planning_scene_monitor_->getPlanningScene()->getKinematicModel()->getLinkModel("base_link")->getShape().get());
  // b->setPose(planning_scene_monitor_->getPlanningScene()->getCurrentState().getLinkState("base_link")->getGlobalLinkTransform());
  // bodies::ConvexMesh* cm = dynamic_cast<bodies::ConvexMesh*>(b);
  // inf_marker.type = visualization_msgs::Marker::TRIANGLE_LIST;
  // inf_marker.scale.x = inf_marker.scale.y = inf_marker.scale.z = 1.0;
  // inf_marker.color.a = inf_marker.color.b = 1.0;
  // inf_marker.header.frame_id = planning_scene_monitor_->getPlanningScene()->getPlanningFrame();
  // inf_marker.pose.orientation.w = 1.0;
  // for(unsigned int i = 0; i < cm->getTriangles().size(); i+=3) {
  //   // ROS_INFO_STREAM("Triangle " << i << " is " << cm->getTriangles()[i] << " "
  //   //                 << cm->getTriangles()[i+1] << " "
  //   //                 << cm->getTriangles()[i+2]);
  //   geometry_msgs::Point p;
  //   p.x = cm->getVertices()[cm->getTriangles()[i]].x();
  //   p.y = cm->getVertices()[cm->getTriangles()[i]].y();
  //   p.z = cm->getVertices()[cm->getTriangles()[i]].z();
  //   inf_marker.points.push_back(p);
  //   p.x = cm->getVertices()[cm->getTriangles()[i+1]].x();
  //   p.y = cm->getVertices()[cm->getTriangles()[i+1]].y();
  //   p.z = cm->getVertices()[cm->getTriangles()[i+1]].z();
  //   inf_marker.points.push_back(p);
  //   p.x = cm->getVertices()[cm->getTriangles()[i+2]].x();
  //   p.y = cm->getVertices()[cm->getTriangles()[i+2]].y();
  //   p.z = cm->getVertices()[cm->getTriangles()[i+2]].z();
  //   inf_marker.points.push_back(p);
  // }
  ros::WallRate r(1.0);
  while(ros::ok()) {
    vis_marker_publisher.publish(inf_marker);
    //vis_marker_array_publisher.publish(sphere_markers);
    vis_marker_array_publisher.publish(arrow_markers);
    r.sleep();
  }

  // std_msgs::ColorRGBA col;
  // col.r = col.g = col.b = .5;
  // col.a = 1.0;

  // std_msgs::ColorRGBA good_color;
  // good_color.a = 1.0;
  // good_color.g = 1.0;

  // std_msgs::ColorRGBA bad_color;
  // bad_color.a = 1.0;
  // bad_color.r = 1.0;

  // iov_.reset(new InteractiveObjectVisualization(planning_scene_monitor_->getPlanningScene(),
  //                                               interactive_marker_server_,
  //                                               col));

  // kv_->addMenuEntry("Add Cube", boost::bind(&addCubeCallback, _1));

  // iov_->setUpdateCallback(boost::bind(&updateCallback, _1));

  ros::waitForShutdown();
}

<|endoftext|>


<commit_before>#include "PipeBase.h"
#include "Simulation.h"
#include "FEProblem.h"
#include "Conversion.h"
#include "R7Conversion.h"
#include "OneDEnergyWallHeating.h"

#include "edge_edge2.h"
#include "fe_type.h"

// physics
#include "Diffusion.h"

template<>
InputParameters validParams<PipeBase>()
{
  InputParameters params = validParams<Component>();
  //Input parameters [NO] default values should be given.
  params.addRequiredParam<std::vector<Real> >("position", "Origin (start) of the pipe");
  params.addRequiredParam<std::vector<Real> >("orientation", "Orientation vector of the pipe");
  params.addRequiredParam<Real>("length", "Length of the pipe");
  params.addRequiredParam<unsigned int>("n_elems", "number of element in this pipe");
  params.addRequiredParam<Real>("A", "Area of the pipe");

  //Input parameters default values could be given.
  params.addParam<Real>("aw", 0.0, "Heating surface density");
  params.addParam<Real>("f", 0.0, "friction");
  params.addParam<Real>("Hw", 0.0, "Convective heat transfer coefficient");
  params.addParam<Real>("Tw", 400, "Wall temperature");

  return params;
}

PipeBase::PipeBase(const std::string & name, InputParameters params) :
    Component(name, params),
    Model(params),
    _position(toPoint(getParam<std::vector<Real> >("position"))),
    _length(getParam<Real>("length")),
    _n_elems(getParam<unsigned int>("n_elems")),
    _A(getParam<Real>("A")),
    _aw(getParam<Real>("aw")),
    _f(getParam<Real>("f")),
    _Hw(getParam<Real>("Hw")),
    _Tw(getParam<Real>("Tw"))
{
  const std::vector<Real> & dir = getParam<std::vector<Real> >("orientation");
  _dir = VectorValue<Real>(dir[0], dir[1], dir[2]);
}

PipeBase::~PipeBase()
{
}

Node *
PipeBase::getBoundaryNode(RELAP7::EEndType id)
{
  std::map<RELAP7::EEndType, Node *>::iterator it = _bnd_nodes.find(id);
  if (it != _bnd_nodes.end())
    return it->second;
  else
    return NULL;
}

unsigned int
PipeBase::getBoundaryId(RELAP7::EEndType id)
{
  std::map<RELAP7::EEndType, unsigned int>::iterator it = _bnd_ids.find(id);
  if (it != _bnd_ids.end())
    return it->second;
  else
    mooseError("PipeBase " << name() << " does not have this type of end defined.");
}

void
PipeBase::buildMesh()
{
  //LZou changed this as PipeBase's protected member variable
  //std::vector<unsigned int> node_ids;
  // points
  Real delta_t = _length / _n_elems;
  Point p(0, 0, 0);                      // origin
  for (unsigned int i = 0; i <= _n_elems; i++)
  {
    const Node * nd = _mesh._mesh.add_point(p);
    node_ids.push_back(nd->id());
    p(0) += delta_t;
  }

  // elems
  _subdomain_id = getNextSubdomainId();
  unsigned int bc_id_in = getNextBCId();
  unsigned int bc_id_out = getNextBCId();
  for (unsigned int i = 0; i < _n_elems; i++)
  {
    Elem * elem = _mesh._mesh.add_elem (new Edge2);
    elem->subdomain_id() = _subdomain_id;
    elem->set_node(0) = _mesh._mesh.node_ptr(node_ids[i]);
    elem->set_node(1) = _mesh._mesh.node_ptr(node_ids[i+1]);

    // BCs
    if (i == 0)
    {
      _bnd_ids[RELAP7::IN] = bc_id_in;
      _mesh._mesh.boundary_info->add_side(elem, 0, bc_id_in);
      _bnd_nodes[RELAP7::IN] = elem->get_node(0);                // first 0 is local bnd_id that Joints will use for connecting
    }
    if (i == (_n_elems - 1))
    {
      _bnd_ids[RELAP7::OUT] = bc_id_out;
      _mesh._mesh.boundary_info->add_side(elem, 1, bc_id_out);
      _bnd_nodes[RELAP7::OUT] = elem->get_node(1);               // first 1 is local bnd_id that Joints will use for connecting
    }
 }
}

void
PipeBase::addVariables()
{
  Model::addVariables(_subdomain_id);
}
<commit_msg>code clean + test cases<commit_after>#include "PipeBase.h"
#include "Simulation.h"
#include "FEProblem.h"
#include "Conversion.h"
#include "R7Conversion.h"
#include "OneDEnergyWallHeating.h"

#include "edge_edge2.h"
#include "fe_type.h"

// physics
#include "Diffusion.h"

template<>
InputParameters validParams<PipeBase>()
{
  InputParameters params = validParams<Component>();
  //Input parameters [NO] default values should be given.
  params.addRequiredParam<std::vector<Real> >("position", "Origin (start) of the pipe");
  params.addRequiredParam<std::vector<Real> >("orientation", "Orientation vector of the pipe");
  params.addRequiredParam<Real>("length", "Length of the pipe");
  params.addRequiredParam<unsigned int>("n_elems", "number of element in this pipe");
  params.addRequiredParam<Real>("A", "Area of the pipe");

  //Input parameters default values could be given.
  params.addParam<Real>("aw", 0.0, "Heating surface density");
  params.addParam<Real>("f", 0.0, "friction");
  params.addParam<Real>("Hw", 0.0, "Convective heat transfer coefficient");
  params.addParam<Real>("Tw", 400, "Wall temperature");

  return params;
}

PipeBase::PipeBase(const std::string & name, InputParameters params) :
    Component(name, params),
    Model(params),
    _position(toPoint(getParam<std::vector<Real> >("position"))),
    _length(getParam<Real>("length")),
    _n_elems(getParam<unsigned int>("n_elems")),
    _A(getParam<Real>("A")),
    _aw(getParam<Real>("aw")),
    _f(getParam<Real>("f")),
    _Hw(getParam<Real>("Hw")),
    _Tw(getParam<Real>("Tw"))
{
  const std::vector<Real> & dir = getParam<std::vector<Real> >("orientation");
  _dir = VectorValue<Real>(dir[0], dir[1], dir[2]);
}

PipeBase::~PipeBase()
{
}

Node *
PipeBase::getBoundaryNode(RELAP7::EEndType id)
{
  std::map<RELAP7::EEndType, Node *>::iterator it = _bnd_nodes.find(id);
  if (it != _bnd_nodes.end())
    return it->second;
  else
    return NULL;
}

unsigned int
PipeBase::getBoundaryId(RELAP7::EEndType id)
{
  std::map<RELAP7::EEndType, unsigned int>::iterator it = _bnd_ids.find(id);
  if (it != _bnd_ids.end())
    return it->second;
  else
    mooseError("PipeBase " << name() << " does not have this type of end defined.");
}

void
PipeBase::buildMesh()
{
  // points
  Real delta_t = _length / _n_elems;
  Point p(0, 0, 0);                      // origin
  for (unsigned int i = 0; i <= _n_elems; i++)
  {
    const Node * nd = _mesh._mesh.add_point(p);
    node_ids.push_back(nd->id());
    p(0) += delta_t;
  }

  // elems
  _subdomain_id = getNextSubdomainId();
  unsigned int bc_id_in = getNextBCId();
  unsigned int bc_id_out = getNextBCId();
  for (unsigned int i = 0; i < _n_elems; i++)
  {
    Elem * elem = _mesh._mesh.add_elem (new Edge2);
    elem->subdomain_id() = _subdomain_id;
    elem->set_node(0) = _mesh._mesh.node_ptr(node_ids[i]);
    elem->set_node(1) = _mesh._mesh.node_ptr(node_ids[i+1]);

    // BCs
    if (i == 0)
    {
      _bnd_ids[RELAP7::IN] = bc_id_in;
      _mesh._mesh.boundary_info->add_side(elem, 0, bc_id_in);
      _bnd_nodes[RELAP7::IN] = elem->get_node(0);                // first 0 is local bnd_id that Joints will use for connecting
    }
    if (i == (_n_elems - 1))
    {
      _bnd_ids[RELAP7::OUT] = bc_id_out;
      _mesh._mesh.boundary_info->add_side(elem, 1, bc_id_out);
      _bnd_nodes[RELAP7::OUT] = elem->get_node(1);               // first 1 is local bnd_id that Joints will use for connecting
    }
 }
}

void
PipeBase::addVariables()
{
  Model::addVariables(_subdomain_id);
}
<|endoftext|>


<commit_before>/**
 * Appcelerator Titanium - licensed under the Apache Public License 2
 * see LICENSE in the root folder for details on the license.
 * Copyright (c) 2009 Appcelerator, Inc. All Rights Reserved.
 */
#include "file_stream.h"
#include <cstring>
#include <sstream>

#include <Poco/LineEndingConverter.h>

namespace ti
{
	FileStream::FileStream(std::string filename_) : stream(NULL)
	{
	#ifdef OS_OSX
		// in OSX, we need to expand ~ in paths to their absolute path value
		// we do that with a nifty helper method in NSString
		this->filename = [[[NSString stringWithCString:filename_.c_str()] stringByExpandingTildeInPath] fileSystemRepresentation];
	#else
		this->filename = filename_;
	#endif

		/**
		 * @tiapi(method=True,name=Filesystem.Filestream.open,since=0.2) Opens the file
		 * @tiresult(for=Filesystem.Filestream.open,type=boolean) returns true if successful
		 */
		this->SetMethod("open",&FileStream::Open);
		/**
		 * @tiapi(method=True,name=Filesystem.Filestream.close,since=0.2) Closes the file
		 * @tiresult(for=Filesystem.Filestream.close,type=boolean) returns true if successful
		 */
		this->SetMethod("close",&FileStream::Close);
		/**
		 * @tiapi(method=True,name=Filesystem.Filestream.read,since=0.2) Reads from the file
		 * @tiresult(for=Filesystem.Filestream.read,type=string) returns data as string
		 */
		this->SetMethod("read",&FileStream::Read);
		/**
		 * @tiapi(method=True,name=Filesystem.Filestream.readLine,since=0.2) Reads one line from the file
		 * @tiresult(for=Filesystem.Filestream.readLine,type=string) returns data as string
		 */
		this->SetMethod("readLine",&FileStream::ReadLine);
		/**
		 * @tiapi(method=True,name=Filesystem.Filestream.write,since=0.2) Writes data into the file
		 * @tiarg(for=Filesystem.Filestream.write,type=string,name=data) data to write
		 * @tiresult(for=Filesystem.Filestream.write,type=boolean) returns true if successful
		 */
		this->SetMethod("write",&FileStream::Write);
		/**
		 * @tiapi(method=True,name=Filesystem.Filestream.writeLine,since=0.4) Writes a line into the file
		 * @tiarg(for=Filesystem.Filestream.writeLine,type=string,name=data) data to write
		 * @tiresult(for=Filesystem.Filestream.writeLine,type=boolean) returns true if successful
		 */
		this->SetMethod("writeLine",&FileStream::WriteLine);
		/**
		 * @tiapi(method=True,name=Filesystem.Filestream.ready,since=0.4) Checks to see if file is ready for IO operations
		 * @tiresult(for=Filesystem.Filestream.ready,type=boolean) returns true if the file open and valid for IO operations
		 */
		this->SetMethod("ready",&FileStream::Ready);
		/**
		 * @tiapi(method=True,name=Filesystem.Filestream.isOpen,since=0.4) Checks to see if file has been opened
		 * @tiresult(for=Filesystem.Filestream.isOpen,type=boolean) returns true if file has been opened
		 */
		this->SetMethod("isOpen",&FileStream::IsOpen);

		/**
		 * @tiapi(property=True,name=Filesystem.Filestream.MODE_READ,since=0.4,type=int) Mode to indicate read
		 */
		this->Set("MODE_READ",Value::NewInt(MODE_READ));
		/**
		 * @tiapi(property=True,name=Filesystem.Filestream.MODE_APPEND,since=0.4,type=int) Mode to indicate appending
		 */
		this->Set("MODE_APPEND",Value::NewInt(MODE_APPEND));
		/**
		 * @tiapi(property=True,name=Filesystem.Filestream.MODE_WRITE,since=0.4,type=int) Mode to indicate writing
		 */
		this->Set("MODE_WRITE",Value::NewInt(MODE_WRITE));
	}

	FileStream::~FileStream()
	{
		this->Close();
	}

	void FileStream::Open(const ValueList& args, SharedValue result)
	{
		FileStreamMode mode = MODE_READ;
		bool binary = false;
		bool append = false;
		if (args.size()>=1) mode = (FileStreamMode)args.at(0)->ToInt();
		if (args.size()>=2) binary = args.at(1)->ToBool();
		if (args.size()>=3) append = args.at(2)->ToBool();
		bool opened = this->Open(mode,binary,append);
		result->SetBool(opened);
	}
	bool FileStream::Open(FileStreamMode mode, bool binary, bool append)
	{
		// close the prev stream if needed
		this->Close();

		try
		{
			std::ios::openmode flags = (std::ios::openmode) 0;
			bool output = false;
			if (binary)
			{
				flags|=std::ios::binary;
			}
			if (mode == MODE_APPEND)
			{
				flags|=std::ios::out|std::ios::app;
				output = true;
			}
			else if (mode == MODE_WRITE)
			{
				flags |= std::ios::out|std::ios::trunc;
				output = true;
			}
			else if (mode == MODE_READ)
			{
				flags |= std::ios::in;
			}

#ifdef DEBUG
			Logger* logger = Logger::Get("Filesystem.FileStream");
			logger->Debug("FILE OPEN FLAGS = %d, binary=%d, mode=%d, append=%d",flags,binary,(int)mode,append);
#endif
			if (output)
			{
				this->stream = new Poco::FileOutputStream(this->filename,flags);
#ifndef OS_WIN32
				chmod(this->filename.c_str(),S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
#endif
			}
			else
			{
				this->stream = new Poco::FileInputStream(this->filename,flags);
			}
			return true;
		}
		catch (Poco::Exception& exc)
		{
			Logger* logger = Logger::Get("Filesystem.FileStream");
			logger->Error("Error in open. Exception: %s",exc.displayText().c_str());
			throw ValueException::FromString(exc.displayText());
		}
	}
	void FileStream::Close(const ValueList& args, SharedValue result)
	{
		bool closed = this->Close();
		result->SetBool(closed);
	}
	bool FileStream::Close()
	{
		try
		{
			if (this->stream)
			{
				Poco::FileOutputStream* fos = dynamic_cast<Poco::FileOutputStream*>(this->stream);
				if (fos)
				{
					fos->flush();
				}
				this->stream->close();
				delete this->stream;
				this->stream = NULL;
				return true;
			}
		}
		catch (Poco::Exception& exc)
		{
			Logger* logger = Logger::Get("Filesystem.FileStream");
			logger->Error("Error in close. Exception: %s",exc.displayText().c_str());
			throw ValueException::FromString(exc.displayText());
		}

		return false;
	}
	void FileStream::Write(const ValueList& args, SharedValue result)
	{
		char *text = NULL;
		int size = 0;
		if (args.at(0)->IsObject())
		{
			SharedKObject b = args.at(0)->ToObject();
			SharedPtr<Blob> blob = b.cast<Blob>();
			if (!blob.isNull())
			{
				text = (char*)blob->Get();
				size = (int)blob->Length();
			}
		}
		else if (args.at(0)->IsString())
		{
			text = (char*)args.at(0)->ToString();
		}
		else if (args.at(0)->IsInt())
		{
			std::stringstream ostr;
			ostr << args.at(0)->ToInt();
			text = (char*)ostr.str().c_str();
			size = ostr.str().length();
		}
		else if (args.at(0)->IsDouble())
		{
			std::stringstream ostr;
			ostr << args.at(0)->ToDouble();
			text = (char*)ostr.str().c_str();
			size = ostr.str().length();
		}

		if (size==0)
		{
			size = strlen(text);
		}

		if (text == NULL)
		{
			result->SetBool(false);
			return;
		}
		if (size <= 0)
		{
			result->SetBool(false);
			return;
		}
		Write(text,size);
		result->SetBool(true);
	}
	void FileStream::Write(char *text, int size)
	{
		try
		{
			Poco::FileOutputStream* fos = dynamic_cast<Poco::FileOutputStream*>(this->stream);
			if(!fos)
			{
				throw ValueException::FromString("FileStream must be opened for writing before calling write");
			}

			fos->write(text, size);
		}
		catch (Poco::Exception& exc)
		{
			Logger* logger = Logger::Get("Filesystem.FileStream");
			logger->Error("Error in write. Exception: %s",exc.displayText().c_str());
			throw ValueException::FromString(exc.displayText());
		}
	}
	void FileStream::Read(const ValueList& args, SharedValue result)
	{
		if(!this->stream)
		{
			Logger* logger = Logger::Get("Filesystem.FileStream");
			logger->Error("Error in read. FileStream must be opened before calling read");
			throw ValueException::FromString("FileStream must be opened before calling read");
		}

		try
		{
			std::stringstream ostr;

			Poco::FileInputStream* fis = dynamic_cast<Poco::FileInputStream*>(this->stream);
			if(!fis)
			{
				Logger* logger = Logger::Get("Filesystem.FileStream");
				logger->Error("Error in read. FileInputStream is null");
				throw ValueException::FromString("FileStream must be opened for reading before calling read");
			}

			char buf[4096];
			int count = 0;

			while(!fis->eof())
			{
				fis->read((char*)&buf,4095);
				std::streamsize len = fis->gcount();
				if (len>0)
				{
					buf[len]='\0';
					count+=len;
					ostr << buf;
				}
				else break;
			}

			result->SetObject(new Blob(ostr.str().c_str(),count));
		}
		catch (Poco::Exception& exc)
		{
			Logger* logger = Logger::Get("Filesystem.FileStream");
			logger->Error("Error in read. Exception: %s",exc.displayText().c_str());
			throw ValueException::FromString(exc.displayText());
		}
	}
	void FileStream::ReadLine(const ValueList& args, SharedValue result)
	{
		if(! this->stream)
		{
			Logger* logger = Logger::Get("Filesystem.FileStream");
			logger->Error("Error in readLine. FileStream must be opened before calling read");
			throw ValueException::FromString("FileStream must be opened before calling readLine");
		}

		try
		{
			Poco::FileInputStream* fis = dynamic_cast<Poco::FileInputStream*>(this->stream);
			if(!fis)
			{
				Logger* logger = Logger::Get("Filesystem.FileStream");
				logger->Error("Error in readLine. FileInputStream is null");
				throw ValueException::FromString("FileStream must be opened for reading before calling readLine");
			}

			if(fis->eof())
			{
				// close the file
				result->SetNull();
			}
			else
			{
				std::string line;
				std::getline(*fis, line);
				result->SetObject(new Blob((std::string)line));
			}
		}
		catch (Poco::Exception& exc)
		{
			Logger* logger = Logger::Get("Filesystem.FileStream");
			logger->Error("Error in readLine. Exception: %s",exc.displayText().c_str());
			throw ValueException::FromString(exc.displayText());
		}
	}
	void FileStream::WriteLine(const ValueList& args, SharedValue result)
	{
		if(! this->stream)
		{
			throw ValueException::FromString("FileStream must be opened before calling readLine");
		}
		char *text = NULL;
		int size = 0;
		if (args.at(0)->IsObject())
		{
			SharedKObject b = args.at(0)->ToObject();
			SharedPtr<Blob> blob = b.cast<Blob>();
			if (!blob.isNull())
			{
				text = (char*)blob->Get();
				size = (int)blob->Length();
			}
		}
		else if (args.at(0)->IsString())
		{
			text = (char*)args.at(0)->ToString();
		}
		else if (args.at(0)->IsInt())
		{
			std::stringstream ostr;
			ostr << args.at(0)->ToInt();
			text = (char*)ostr.str().c_str();
			size = ostr.str().length();
		}
		else if (args.at(0)->IsDouble())
		{
			std::stringstream ostr;
			ostr << args.at(0)->ToDouble();
			text = (char*)ostr.str().c_str();
			size = ostr.str().length();
		}

		if (size==0)
		{
			size = strlen(text);
		}

		if (text == NULL)
		{
			result->SetBool(false);
			return;
		}
		if (size <= 0)
		{
			result->SetBool(false);
			return;
		}
		std::string astr = text;
#ifdef OS_WIN32
		astr += "\r\n";
#else
		astr += "\n";
#endif
		Write((char*)astr.c_str(),astr.length());
		result->SetBool(true);
	}

	void FileStream::Ready(const ValueList& args, SharedValue result)
	{
		Poco::FileInputStream* fis = dynamic_cast<Poco::FileInputStream*>(this->stream);
		if(!fis)
		{
			result->SetBool(false);
		}
		else
		{
			result->SetBool(fis->eof()==false);
		}
	}

	void FileStream::IsOpen(const ValueList& args, SharedValue result)
	{
		Poco::FileInputStream* fis = dynamic_cast<Poco::FileInputStream*>(this->stream);
		result->SetBool(fis!=NULL);
	}

}
<commit_msg>fix a really interesting bug where std::getline() leaves carriage returns on files without them ?? (wtf?)<commit_after>/**
 * Appcelerator Titanium - licensed under the Apache Public License 2
 * see LICENSE in the root folder for details on the license.
 * Copyright (c) 2009 Appcelerator, Inc. All Rights Reserved.
 */
#include "file_stream.h"
#include <cstring>
#include <sstream>

#include <Poco/LineEndingConverter.h>

namespace ti
{
	FileStream::FileStream(std::string filename_) : stream(NULL)
	{
	#ifdef OS_OSX
		// in OSX, we need to expand ~ in paths to their absolute path value
		// we do that with a nifty helper method in NSString
		this->filename = [[[NSString stringWithCString:filename_.c_str()] stringByExpandingTildeInPath] fileSystemRepresentation];
	#else
		this->filename = filename_;
	#endif

		/**
		 * @tiapi(method=True,name=Filesystem.Filestream.open,since=0.2) Opens the file
		 * @tiresult(for=Filesystem.Filestream.open,type=boolean) returns true if successful
		 */
		this->SetMethod("open",&FileStream::Open);
		/**
		 * @tiapi(method=True,name=Filesystem.Filestream.close,since=0.2) Closes the file
		 * @tiresult(for=Filesystem.Filestream.close,type=boolean) returns true if successful
		 */
		this->SetMethod("close",&FileStream::Close);
		/**
		 * @tiapi(method=True,name=Filesystem.Filestream.read,since=0.2) Reads from the file
		 * @tiresult(for=Filesystem.Filestream.read,type=string) returns data as string
		 */
		this->SetMethod("read",&FileStream::Read);
		/**
		 * @tiapi(method=True,name=Filesystem.Filestream.readLine,since=0.2) Reads one line from the file
		 * @tiresult(for=Filesystem.Filestream.readLine,type=string) returns data as string
		 */
		this->SetMethod("readLine",&FileStream::ReadLine);
		/**
		 * @tiapi(method=True,name=Filesystem.Filestream.write,since=0.2) Writes data into the file
		 * @tiarg(for=Filesystem.Filestream.write,type=string,name=data) data to write
		 * @tiresult(for=Filesystem.Filestream.write,type=boolean) returns true if successful
		 */
		this->SetMethod("write",&FileStream::Write);
		/**
		 * @tiapi(method=True,name=Filesystem.Filestream.writeLine,since=0.4) Writes a line into the file
		 * @tiarg(for=Filesystem.Filestream.writeLine,type=string,name=data) data to write
		 * @tiresult(for=Filesystem.Filestream.writeLine,type=boolean) returns true if successful
		 */
		this->SetMethod("writeLine",&FileStream::WriteLine);
		/**
		 * @tiapi(method=True,name=Filesystem.Filestream.ready,since=0.4) Checks to see if file is ready for IO operations
		 * @tiresult(for=Filesystem.Filestream.ready,type=boolean) returns true if the file open and valid for IO operations
		 */
		this->SetMethod("ready",&FileStream::Ready);
		/**
		 * @tiapi(method=True,name=Filesystem.Filestream.isOpen,since=0.4) Checks to see if file has been opened
		 * @tiresult(for=Filesystem.Filestream.isOpen,type=boolean) returns true if file has been opened
		 */
		this->SetMethod("isOpen",&FileStream::IsOpen);

		/**
		 * @tiapi(property=True,name=Filesystem.Filestream.MODE_READ,since=0.4,type=int) Mode to indicate read
		 */
		this->Set("MODE_READ",Value::NewInt(MODE_READ));
		/**
		 * @tiapi(property=True,name=Filesystem.Filestream.MODE_APPEND,since=0.4,type=int) Mode to indicate appending
		 */
		this->Set("MODE_APPEND",Value::NewInt(MODE_APPEND));
		/**
		 * @tiapi(property=True,name=Filesystem.Filestream.MODE_WRITE,since=0.4,type=int) Mode to indicate writing
		 */
		this->Set("MODE_WRITE",Value::NewInt(MODE_WRITE));
	}

	FileStream::~FileStream()
	{
		this->Close();
	}

	void FileStream::Open(const ValueList& args, SharedValue result)
	{
		FileStreamMode mode = MODE_READ;
		bool binary = false;
		bool append = false;
		if (args.size()>=1) mode = (FileStreamMode)args.at(0)->ToInt();
		if (args.size()>=2) binary = args.at(1)->ToBool();
		if (args.size()>=3) append = args.at(2)->ToBool();
		bool opened = this->Open(mode,binary,append);
		result->SetBool(opened);
	}
	bool FileStream::Open(FileStreamMode mode, bool binary, bool append)
	{
		// close the prev stream if needed
		this->Close();

		try
		{
			std::ios::openmode flags = (std::ios::openmode) 0;
			bool output = false;
			if (binary)
			{
				flags|=std::ios::binary;
			}
			if (mode == MODE_APPEND)
			{
				flags|=std::ios::out|std::ios::app;
				output = true;
			}
			else if (mode == MODE_WRITE)
			{
				flags |= std::ios::out|std::ios::trunc;
				output = true;
			}
			else if (mode == MODE_READ)
			{
				flags |= std::ios::in;
			}

#ifdef DEBUG
			Logger* logger = Logger::Get("Filesystem.FileStream");
			logger->Debug("FILE OPEN FLAGS = %d, binary=%d, mode=%d, append=%d",flags,binary,(int)mode,append);
#endif
			if (output)
			{
				this->stream = new Poco::FileOutputStream(this->filename,flags);
#ifndef OS_WIN32
				chmod(this->filename.c_str(),S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
#endif
			}
			else
			{
				this->stream = new Poco::FileInputStream(this->filename,flags);
			}
			return true;
		}
		catch (Poco::Exception& exc)
		{
			Logger* logger = Logger::Get("Filesystem.FileStream");
			logger->Error("Error in open. Exception: %s",exc.displayText().c_str());
			throw ValueException::FromString(exc.displayText());
		}
	}
	void FileStream::Close(const ValueList& args, SharedValue result)
	{
		bool closed = this->Close();
		result->SetBool(closed);
	}
	bool FileStream::Close()
	{
		try
		{
			if (this->stream)
			{
				Poco::FileOutputStream* fos = dynamic_cast<Poco::FileOutputStream*>(this->stream);
				if (fos)
				{
					fos->flush();
				}
				this->stream->close();
				delete this->stream;
				this->stream = NULL;
				return true;
			}
		}
		catch (Poco::Exception& exc)
		{
			Logger* logger = Logger::Get("Filesystem.FileStream");
			logger->Error("Error in close. Exception: %s",exc.displayText().c_str());
			throw ValueException::FromString(exc.displayText());
		}

		return false;
	}
	void FileStream::Write(const ValueList& args, SharedValue result)
	{
		char *text = NULL;
		int size = 0;
		if (args.at(0)->IsObject())
		{
			SharedKObject b = args.at(0)->ToObject();
			SharedPtr<Blob> blob = b.cast<Blob>();
			if (!blob.isNull())
			{
				text = (char*)blob->Get();
				size = (int)blob->Length();
			}
		}
		else if (args.at(0)->IsString())
		{
			text = (char*)args.at(0)->ToString();
		}
		else if (args.at(0)->IsInt())
		{
			std::stringstream ostr;
			ostr << args.at(0)->ToInt();
			text = (char*)ostr.str().c_str();
			size = ostr.str().length();
		}
		else if (args.at(0)->IsDouble())
		{
			std::stringstream ostr;
			ostr << args.at(0)->ToDouble();
			text = (char*)ostr.str().c_str();
			size = ostr.str().length();
		}

		if (size==0)
		{
			size = strlen(text);
		}

		if (text == NULL)
		{
			result->SetBool(false);
			return;
		}
		if (size <= 0)
		{
			result->SetBool(false);
			return;
		}
		Write(text,size);
		result->SetBool(true);
	}
	void FileStream::Write(char *text, int size)
	{
		try
		{
			Poco::FileOutputStream* fos = dynamic_cast<Poco::FileOutputStream*>(this->stream);
			if(!fos)
			{
				throw ValueException::FromString("FileStream must be opened for writing before calling write");
			}

			fos->write(text, size);
		}
		catch (Poco::Exception& exc)
		{
			Logger* logger = Logger::Get("Filesystem.FileStream");
			logger->Error("Error in write. Exception: %s",exc.displayText().c_str());
			throw ValueException::FromString(exc.displayText());
		}
	}
	void FileStream::Read(const ValueList& args, SharedValue result)
	{
		if(!this->stream)
		{
			Logger* logger = Logger::Get("Filesystem.FileStream");
			logger->Error("Error in read. FileStream must be opened before calling read");
			throw ValueException::FromString("FileStream must be opened before calling read");
		}

		try
		{
			std::stringstream ostr;

			Poco::FileInputStream* fis = dynamic_cast<Poco::FileInputStream*>(this->stream);
			if(!fis)
			{
				Logger* logger = Logger::Get("Filesystem.FileStream");
				logger->Error("Error in read. FileInputStream is null");
				throw ValueException::FromString("FileStream must be opened for reading before calling read");
			}

			char buf[4096];
			int count = 0;

			while(!fis->eof())
			{
				fis->read((char*)&buf,4095);
				std::streamsize len = fis->gcount();
				if (len>0)
				{
					buf[len]='\0';
					count+=len;
					ostr << buf;
				}
				else break;
			}

			result->SetObject(new Blob(ostr.str().c_str(),count));
		}
		catch (Poco::Exception& exc)
		{
			Logger* logger = Logger::Get("Filesystem.FileStream");
			logger->Error("Error in read. Exception: %s",exc.displayText().c_str());
			throw ValueException::FromString(exc.displayText());
		}
	}
	void FileStream::ReadLine(const ValueList& args, SharedValue result)
	{
		if(! this->stream)
		{
			Logger* logger = Logger::Get("Filesystem.FileStream");
			logger->Error("Error in readLine. FileStream must be opened before calling read");
			throw ValueException::FromString("FileStream must be opened before calling readLine");
		}

		try
		{
			Poco::FileInputStream* fis = dynamic_cast<Poco::FileInputStream*>(this->stream);
			if(!fis)
			{
				Logger* logger = Logger::Get("Filesystem.FileStream");
				logger->Error("Error in readLine. FileInputStream is null");
				throw ValueException::FromString("FileStream must be opened for reading before calling readLine");
			}

			if(fis->eof())
			{
				// close the file
				result->SetNull();
			}
			else
			{
				std::string line;
				std::getline(*fis, line);
#ifdef OS_WIN32
				// In some cases std::getline leaves a CR on the end of the line in win32 -- why God, why?
				char lastChar = line.at(line.size()-1);
				if (lastChar == '\r') {
					line = line.substr(0, line.size()-1);
				}
#endif

				PRINTD("readline='"<<line<<"'");
				result->SetObject(new Blob((std::string)line));
			}
		}
		catch (Poco::Exception& exc)
		{
			Logger* logger = Logger::Get("Filesystem.FileStream");
			logger->Error("Error in readLine. Exception: %s",exc.displayText().c_str());
			throw ValueException::FromString(exc.displayText());
		}
	}
	void FileStream::WriteLine(const ValueList& args, SharedValue result)
	{
		if(! this->stream)
		{
			throw ValueException::FromString("FileStream must be opened before calling readLine");
		}
		char *text = NULL;
		int size = 0;
		if (args.at(0)->IsObject())
		{
			SharedKObject b = args.at(0)->ToObject();
			SharedPtr<Blob> blob = b.cast<Blob>();
			if (!blob.isNull())
			{
				text = (char*)blob->Get();
				size = (int)blob->Length();
			}
		}
		else if (args.at(0)->IsString())
		{
			text = (char*)args.at(0)->ToString();
		}
		else if (args.at(0)->IsInt())
		{
			std::stringstream ostr;
			ostr << args.at(0)->ToInt();
			text = (char*)ostr.str().c_str();
			size = ostr.str().length();
		}
		else if (args.at(0)->IsDouble())
		{
			std::stringstream ostr;
			ostr << args.at(0)->ToDouble();
			text = (char*)ostr.str().c_str();
			size = ostr.str().length();
		}

		if (size==0)
		{
			size = strlen(text);
		}

		if (text == NULL)
		{
			result->SetBool(false);
			return;
		}
		if (size <= 0)
		{
			result->SetBool(false);
			return;
		}
		std::string astr = text;
#ifdef OS_WIN32
		astr += "\r\n";
#else
		astr += "\n";
#endif
		Write((char*)astr.c_str(),astr.length());
		result->SetBool(true);
	}

	void FileStream::Ready(const ValueList& args, SharedValue result)
	{
		Poco::FileInputStream* fis = dynamic_cast<Poco::FileInputStream*>(this->stream);
		if(!fis)
		{
			result->SetBool(false);
		}
		else
		{
			result->SetBool(fis->eof()==false);
		}
	}

	void FileStream::IsOpen(const ValueList& args, SharedValue result)
	{
		Poco::FileInputStream* fis = dynamic_cast<Poco::FileInputStream*>(this->stream);
		result->SetBool(fis!=NULL);
	}

}
<|endoftext|>


<commit_before>#include "NodeUser.h"
#include "NodePlaylistContainer.h"
#include "NodePlaylist.h"

NodeUser::NodeUser(std::unique_ptr<User> _user) : user(std::move(_user)) {}

NodeUser::~NodeUser() {}

NAN_GETTER(NodeUser::getLink) {
  NodeUser* nodeUser = node::ObjectWrap::Unwrap<NodeUser>(info.This());
  NanReturnValue(Nan::New<String>(nodeUser->user->link().c_str()).ToLocalChecked());
}

NAN_GETTER(NodeUser::getCanonicalName) {
  NodeUser* nodeUser = node::ObjectWrap::Unwrap<NodeUser>(info.This());
  NanReturnValue(Nan::New<String>(nodeUser->user->canonicalName().c_str()).ToLocalChecked());
}

NAN_GETTER(NodeUser::getDisplayName) {
  NodeUser* nodeUser = node::ObjectWrap::Unwrap<NodeUser>(info.This());
  NanReturnValue(Nan::New<String>(nodeUser->user->displayName().c_str()).ToLocalChecked());
}

NAN_GETTER(NodeUser::isLoaded) {
  NodeUser* nodeUser = node::ObjectWrap::Unwrap<NodeUser>(info.This());
  NanReturnValue(NanNew<Boolean>(nodeUser->user->isLoaded()));
}

NAN_GETTER(NodeUser::getPublishedPlaylistsContainer) {
  NodeUser* nodeUser = node::ObjectWrap::Unwrap<NodeUser>(info.This());
  auto playlistContainer = nodeUser->user->publishedPlaylists();
  NodePlaylistContainer* nodePlaylistContainer = new NodePlaylistContainer(playlistContainer);
  NanReturnValue(nodePlaylistContainer->createInstance());
}

NAN_GETTER(NodeUser::getStarredPlaylist) {
  NodeUser* nodeUser = node::ObjectWrap::Unwrap<NodeUser>(info.This());
  auto playlist = nodeUser->user->starredPlaylist();
  NodePlaylist* nodePlaylist = new NodePlaylist(playlist);
  NanReturnValue(nodePlaylist->createInstance());
}

void NodeUser::init() {
  NanScope();
  Handle<FunctionTemplate> constructorTemplate = NodeWrapped::init("User");
  constructorTemplate->InstanceTemplate()->SetAccessor(Nan::New<String>("canonicalName").ToLocalChecked(), getCanonicalName);
  constructorTemplate->InstanceTemplate()->SetAccessor(Nan::New<String>("link").ToLocalChecked(), getLink);
  constructorTemplate->InstanceTemplate()->SetAccessor(Nan::New<String>("displayName").ToLocalChecked(), getDisplayName);
  constructorTemplate->InstanceTemplate()->SetAccessor(Nan::New<String>("isLoaded").ToLocalChecked(), isLoaded);
  constructorTemplate->InstanceTemplate()->SetAccessor(Nan::New<String>("playlistContainer").ToLocalChecked(), getPublishedPlaylistsContainer);
  constructorTemplate->InstanceTemplate()->SetAccessor(Nan::New<String>("starredPlaylist").ToLocalChecked(), getStarredPlaylist);
  NanAssignPersistent(NodeUser::constructorTemplate, constructorTemplate);
}
<commit_msg>Fix NodeUser return values and init method.<commit_after>#include "NodeUser.h"
#include "NodePlaylistContainer.h"
#include "NodePlaylist.h"

NodeUser::NodeUser(std::unique_ptr<User> _user) : user(std::move(_user)) {}

NodeUser::~NodeUser() {}

NAN_GETTER(NodeUser::getLink) {
  NodeUser* nodeUser = node::ObjectWrap::Unwrap<NodeUser>(info.This());
  info.GetReturnValue().Set(Nan::New<String>(nodeUser->user->link().c_str()).ToLocalChecked());
}

NAN_GETTER(NodeUser::getCanonicalName) {
  NodeUser* nodeUser = node::ObjectWrap::Unwrap<NodeUser>(info.This());
  info.GetReturnValue().Set(Nan::New<String>(nodeUser->user->canonicalName().c_str()).ToLocalChecked());
}

NAN_GETTER(NodeUser::getDisplayName) {
  NodeUser* nodeUser = node::ObjectWrap::Unwrap<NodeUser>(info.This());
  info.GetReturnValue().Set(Nan::New<String>(nodeUser->user->displayName().c_str()).ToLocalChecked());
}

NAN_GETTER(NodeUser::isLoaded) {
  NodeUser* nodeUser = node::ObjectWrap::Unwrap<NodeUser>(info.This());
  info.GetReturnValue().Set(Nan::New<Boolean>(nodeUser->user->isLoaded()));
}

NAN_GETTER(NodeUser::getPublishedPlaylistsContainer) {
  NodeUser* nodeUser = node::ObjectWrap::Unwrap<NodeUser>(info.This());
  auto playlistContainer = nodeUser->user->publishedPlaylists();
  NodePlaylistContainer* nodePlaylistContainer = new NodePlaylistContainer(playlistContainer);
  info.GetReturnValue().Set(nodePlaylistContainer->createInstance());
}

NAN_GETTER(NodeUser::getStarredPlaylist) {
  NodeUser* nodeUser = node::ObjectWrap::Unwrap<NodeUser>(info.This());
  auto playlist = nodeUser->user->starredPlaylist();
  NodePlaylist* nodePlaylist = new NodePlaylist(playlist);
  info.GetReturnValue().Set(nodePlaylist->createInstance());
}

void NodeUser::init() {
  Handle<FunctionTemplate> constructorTemplate = NodeWrapped::init("User");
  Nan::SetAccessor(constructorTemplate->InstanceTemplate(), Nan::New<String>("canonicalName").ToLocalChecked(), getCanonicalName);
  Nan::SetAccessor(constructorTemplate->InstanceTemplate(), Nan::New<String>("link").ToLocalChecked(), getLink);
  Nan::SetAccessor(constructorTemplate->InstanceTemplate(), Nan::New<String>("displayName").ToLocalChecked(), getDisplayName);
  Nan::SetAccessor(constructorTemplate->InstanceTemplate(), Nan::New<String>("isLoaded").ToLocalChecked(), isLoaded);
  Nan::SetAccessor(constructorTemplate->InstanceTemplate(), Nan::New<String>("playlistContainer").ToLocalChecked(), getPublishedPlaylistsContainer);
  Nan::SetAccessor(constructorTemplate->InstanceTemplate(), Nan::New<String>("starredPlaylist").ToLocalChecked(), getStarredPlaylist);
  NodeUser::constructorTemplate.Reset(constructorTemplate);
}
<|endoftext|>