addon.cpp
Go to the documentation of this file.
1 // Copyright (c) 2017 Intel Corporation. All rights reserved.
2 // Use of this source code is governed by an Apache 2.0 license
3 // that can be found in the LICENSE file.
4 
5 #include <librealsense2/rs.h>
9 #include <nan.h>
10 
11 #include <iostream>
12 #include <list>
13 #include <memory>
14 #include <sstream>
15 #include <string>
16 #include <utility>
17 #include <vector>
18 
19 class DictBase {
20  public:
21  explicit DictBase(v8::Local<v8::Object> source) : v8obj_(source) {}
22 
24  v8obj_ = v8::Object::New(v8::Isolate::GetCurrent());
25  }
26 
27  ~DictBase() {}
28 
29  v8::Local<v8::Value> GetMember(const char* name) const {
30  return v8obj_->Get(Nan::GetCurrentContext(), Nan::New(name).ToLocalChecked()).ToLocalChecked();
31  }
32 
33  v8::Local<v8::Value> GetMember(const std::string& name) const {
34  return GetMember(name.c_str());
35  }
36 
37  void SetMemberUndefined(const char* name) {
38  v8obj_->Set(Nan::GetCurrentContext(), Nan::New(name).ToLocalChecked(), Nan::Undefined());
39  }
40 
41  void DeleteMember(const char* name) {
42  v8obj_->Delete(Nan::GetCurrentContext(), Nan::New(name).ToLocalChecked());
43  }
44 
45  void SetMember(const char* name, const char* value) {
46  v8obj_->Set(Nan::GetCurrentContext(), Nan::New(name).ToLocalChecked(),
47  Nan::New(value).ToLocalChecked());
48  }
49 
50  void SetMember(const char* name, v8::Local<v8::Value> value) {
51  v8obj_->Set(Nan::GetCurrentContext(), Nan::New(name).ToLocalChecked(), value);
52  }
53 
54  void SetMember(const char* name, const std::string& value) {
55  v8obj_->Set(Nan::GetCurrentContext(), Nan::New(name).ToLocalChecked(),
56  Nan::New(value.c_str()).ToLocalChecked());
57  }
58 
59  template <typename T, typename V, uint32_t len>
60  void SetMemberArray(const char* name, V value[len]) {
61  v8::Local<v8::Array> array = Nan::New<v8::Array>(len);
62  for (uint32_t i = 0; i < len; i++) {
63  array->Set(Nan::GetCurrentContext(), i, Nan::New<T>(value[i]));
64  }
65  SetMember(name, array);
66  }
67 
68  template <typename T>
69  void SetMemberT(const char* name, const T& value) {
70  v8obj_->Set(Nan::GetCurrentContext(), Nan::New(name).ToLocalChecked(),
71  Nan::New(value));
72  }
73 
74  bool IsMemberPresent(const char* name) const {
75  v8::Local<v8::Value> v = v8obj_->Get(Nan::GetCurrentContext(), Nan::New(name).ToLocalChecked()).ToLocalChecked();
76  return !(v->IsUndefined() || v->IsNull());
77  }
78 
79  bool IsMemberPresent(const std::string& name) const {
80  return IsMemberPresent(name.c_str());
81  }
82 
83  v8::Local<v8::Object> GetObject() const {
84  return v8obj_;
85  }
86 
87  protected:
88  mutable v8::Local<v8::Object> v8obj_;
89 };
90 
91 class ErrorUtil {
92  public:
93  class ErrorInfo {
94  public:
95  ErrorInfo() : is_error_(false), recoverable_(false) {}
96 
98 
99  void Update(bool is_error, bool recoverable, std::string description,
100  std::string function) {
101  is_error_ = is_error;
102  recoverable_ = recoverable;
103  description_ = description;
104  native_function_ = function;
105  }
106 
107  void Reset() { Update(false, false, "", ""); }
108 
109  // set value to js attributes only when this method is called
110  v8::Local<v8::Object> GetJSObject() {
111  DictBase obj;
112  obj.SetMemberT("recoverable", recoverable_);
113  obj.SetMember("description", description_);
114  obj.SetMember("nativeFunction", native_function_);
115  return obj.GetObject();
116  }
117 
118  private:
119  bool is_error_;
123 
124  friend class ErrorUtil;
125  };
126 
128 
129  static void Init() {
130  if (!singleton_) singleton_ = new ErrorUtil();
131  }
132 
134  const Nan::FunctionCallbackInfo<v8::Value>& info) {
135  v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
136  singleton_->js_error_container_.Reset(info[0]->ToObject(context).ToLocalChecked());
137  Nan::Utf8String value(info[1]->ToString(context).ToLocalChecked());
139  }
140 
141  static void AnalyzeError(rs2_error* err) {
142  if (!err) return;
143 
144  auto function = std::string(rs2_get_failed_function(err));
146  auto msg = std::string(rs2_get_error_message(err));
147  bool recoverable = false;
148 
152  recoverable = true;
153  }
154 
155  singleton_->MarkError(recoverable, msg, function);
156  }
157 
158  static void ResetError() {
160  }
161 
162  static v8::Local<v8::Value> GetJSErrorObject() {
165 
166  return Nan::Undefined();
167  }
168 
169  private:
170  // Save detailed error info to the js object
171  void MarkError(bool recoverable, std::string description,
172  std::string native_function) {
173  error_info_.Update(true, recoverable, description, native_function);
174  v8::Local<v8::Value> args[1] = { GetJSErrorObject() };
175  auto container = Nan::New<v8::Object>(js_error_container_);
176  Nan::AsyncResource resource("js_error_callback_name_");
177  resource.runInAsyncScope(container, js_error_callback_name_.c_str(), 1, args);
178  // Nan::MakeCallback(container, ,
179  // 1, args);
180  }
181 
184  Nan::Persistent<v8::Object> js_error_container_;
186 };
187 
189 
190 template<typename R, typename F, typename... arguments>
192  // reset the error pointer for each call.
193  *error = nullptr;
195  R val = func(params...);
196  ErrorUtil::AnalyzeError(*error);
197  return val;
198 }
199 
200 template<typename F, typename... arguments>
201 void CallNativeFunc(F func, rs2_error** error, arguments... params) {
202  // reset the error pointer for each call.
203  *error = nullptr;
205  func(params...);
206  ErrorUtil::AnalyzeError(*error);
207 }
208 
210  public:
211  MainThreadCallbackInfo() : consumed_(false) {
212  pending_infos_.push_back(this);
213  }
215  pending_infos_.erase(
216  std::find(pending_infos_.begin(), pending_infos_.end(), this));
217  }
218  virtual void Run() {}
219  virtual void Release() {}
220  void SetConsumed() { consumed_ = true; }
222  auto result = std::find(pending_infos_.begin(), pending_infos_.end(), info);
223  return (result != pending_infos_.end());
224  }
225  static void ReleasePendingInfos() {
226  while (pending_infos_.size()) { delete *(pending_infos_.begin()); }
227  }
228 
229  protected:
230  static std::list<MainThreadCallbackInfo*> pending_infos_;
231  bool consumed_;
232 };
233 
234 std::list<MainThreadCallbackInfo*> MainThreadCallbackInfo::pending_infos_;
235 
237  public:
238  class LockGuard {
239  public:
242  }
245  }
246  };
247  static void Init() {
248  if (!singleton_)
249  singleton_ = new MainThreadCallback();
250  }
251  static void Destroy() {
252  if (singleton_) {
253  delete singleton_;
254  singleton_ = nullptr;
256  }
257  }
259  uv_close(reinterpret_cast<uv_handle_t*>(async_),
260  [](uv_handle_t* ptr) -> void {
261  free(ptr);
262  });
263  uv_mutex_destroy(&mutex_);
264  }
266  if (singleton_) {
267  LockGuard guard;
268  if (singleton_->async_->data) {
269  MainThreadCallbackInfo* info =
270  reinterpret_cast<MainThreadCallbackInfo*>(singleton_->async_->data);
271  info->Release();
272  delete info;
273  }
274  singleton_->async_->data = static_cast<void*>(info);
275  uv_async_send(singleton_->async_);
276  }
277  }
278 
279  private:
281  async_ = static_cast<uv_async_t*>(malloc(sizeof(uv_async_t)));
282  async_->data = nullptr;
283  uv_async_init(uv_default_loop(), async_, AsyncProc);
284  uv_mutex_init(&mutex_);
285  }
286  static void Lock() {
287  if (singleton_) uv_mutex_lock(&(singleton_->mutex_));
288  }
289  static void Unlock() {
290  if (singleton_) uv_mutex_unlock(&(singleton_->mutex_));
291  }
292  static void AsyncProc(uv_async_t* async) {
293  MainThreadCallbackInfo* info = nullptr;
294  {
295  LockGuard guard;
296  if (!(async->data))
297  return;
298 
299  info = reinterpret_cast<MainThreadCallbackInfo*>(async->data);
300  async->data = nullptr;
301  }
302  info->Run();
303  // As the above info->Run() enters js world and during that, any code
304  // such as cleanup() could be called to release everything. So this info
305  // may has been released, we need to check before releasing it.
306  if (MainThreadCallbackInfo::InfoExist(info)) delete info;
307  }
309  uv_async_t* async_;
310  uv_mutex_t mutex_;
311 };
312 
316 
317 class RSExtrinsics : public DictBase {
318  public:
320  SetMemberArray<v8::Number, float, 9>("rotation", extrinsics.rotation);
321  SetMemberArray<v8::Number, float, 3>("translation", extrinsics.translation);
322  }
323 };
324 
325 
328 
329 class RSIntrinsics : public DictBase {
330  public:
332  SetMemberT("width", intrinsics.width);
333  SetMemberT("height", intrinsics.height);
334  SetMemberT("ppx", intrinsics.ppx);
335  SetMemberT("ppy", intrinsics.ppy);
336  SetMemberT("fx", intrinsics.fx);
337  SetMemberT("fy", intrinsics.fy);
338  SetMemberT("model", intrinsics.model);
339  SetMemberArray<v8::Number, float, 5>("coeffs", intrinsics.coeffs);
340  }
341 };
342 
343 class RSMotionIntrinsics : public DictBase {
344  public:
346  v8::Local<v8::Array> data_array = Nan::New<v8::Array>(3);
347  int32_t index = 0;
348  for (int32_t i = 0; i < 3; i++) {
349  for (int32_t j = 0; j < 4; j++) {
350  data_array->Set(Nan::GetCurrentContext(),
351  index++, Nan::New(intri->data[i][j]));
352  }
353  }
354  SetMember("data", data_array);
355  SetMemberArray<v8::Number, float, 3>("noiseVariances",
356  intri->noise_variances);
357  SetMemberArray<v8::Number, float, 3>("biasVariances",
358  intri->bias_variances);
359  }
360 };
361 
362 class RSOptionRange : public DictBase {
363  public:
364  RSOptionRange(float min, float max, float step, float def) {
365  SetMemberT("minValue", min);
366  SetMemberT("maxValue", max);
367  SetMemberT("step", step);
368  SetMemberT("defaultValue", def);
369  }
370 };
371 
372 class RSNotification : public DictBase {
373  public:
376  const std::string& serialized_data) {
377  SetMember("descr", des);
378  SetMemberT("timestamp", time);
379  SetMemberT("severity", (int32_t)severity);
380  SetMemberT("category", (int32_t)category);
381  SetMember("serializedData", serialized_data);
382  }
383 };
384 
385 class RSRegionOfInterest : public DictBase {
386  public:
388  SetMemberT("minX", minx);
389  SetMemberT("minY", miny);
390  SetMemberT("maxX", maxx);
391  SetMemberT("maxY", maxy);
392  }
393 };
394 
395 class RSStreamProfile : public Nan::ObjectWrap {
396  public:
397  static void Init(v8::Local<v8::Object> exports) {
398  v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
399  tpl->SetClassName(Nan::New("RSStreamProfile").ToLocalChecked());
400  tpl->InstanceTemplate()->SetInternalFieldCount(1);
401 
402  Nan::SetPrototypeMethod(tpl, "destroy", Destroy);
403  Nan::SetPrototypeMethod(tpl, "stream", Stream);
404  Nan::SetPrototypeMethod(tpl, "format", Format);
405  Nan::SetPrototypeMethod(tpl, "fps", Fps);
406  Nan::SetPrototypeMethod(tpl, "index", Index);
407  Nan::SetPrototypeMethod(tpl, "uniqueID", UniqueID);
408  Nan::SetPrototypeMethod(tpl, "isDefault", IsDefault);
409  Nan::SetPrototypeMethod(tpl, "isVideoProfile", IsVideoProfile);
410  Nan::SetPrototypeMethod(tpl, "isMotionProfile", IsMotionProfile);
411  Nan::SetPrototypeMethod(tpl, "width", Width);
412  Nan::SetPrototypeMethod(tpl, "height", Height);
413  Nan::SetPrototypeMethod(tpl, "getExtrinsicsTo", GetExtrinsicsTo);
414  Nan::SetPrototypeMethod(tpl, "getVideoStreamIntrinsics",
415  GetVideoStreamIntrinsics);
416  Nan::SetPrototypeMethod(tpl, "getMotionIntrinsics", GetMotionIntrinsics);
417 
418  v8::Local<v8::Context> context = exports->CreationContext();
419 
420  constructor_.Reset(tpl->GetFunction(context).ToLocalChecked());
421  exports->Set(context, Nan::New("RSStreamProfile").ToLocalChecked(),
422  tpl->GetFunction(context).ToLocalChecked());
423  }
424 
425  static v8::Local<v8::Object> NewInstance(
426  rs2_stream_profile* p, bool own = false) {
427  Nan::EscapableHandleScope scope;
428 
429  v8::Local<v8::Function> cons = Nan::New<v8::Function>(constructor_);
430  v8::Local<v8::Context> context = Nan::GetCurrentContext();
431 
432  v8::Local<v8::Object> instance =
433  cons->NewInstance(context, 0, nullptr).ToLocalChecked();
434  auto me = Nan::ObjectWrap::Unwrap<RSStreamProfile>(instance);
435  me->profile_ = p;
436  me->own_profile_ = own;
437  CallNativeFunc(rs2_get_stream_profile_data, &me->error_, p, &me->stream_,
438  &me->format_, &me->index_, &me->unique_id_, &me->fps_, &me->error_);
439  me->is_default_ = rs2_is_stream_profile_default(p, &me->error_);
440  if (GetNativeResult<bool>(rs2_stream_profile_is, &me->error_, p,
441  RS2_EXTENSION_VIDEO_PROFILE, &me->error_)) {
442  me->is_video_ = true;
444  &me->width_, &me->height_, &me->error_);
445  } else if (GetNativeResult<bool>(rs2_stream_profile_is, &me->error_, p,
446  RS2_EXTENSION_MOTION_PROFILE, &me->error_)) {
447  me->is_motion_ = true;
448  }
449 
450  return scope.Escape(instance);
451  }
452 
453  private:
454  RSStreamProfile() : error_(nullptr), profile_(nullptr), index_(0),
455  unique_id_(0), fps_(0), format_(static_cast<rs2_format>(0)),
456  stream_(static_cast<rs2_stream>(0)), is_video_(false), width_(0),
457  height_(0), is_default_(false), own_profile_(false), is_motion_(false) {}
458 
460  DestroyMe();
461  }
462 
463  void DestroyMe() {
464  if (error_) rs2_free_error(error_);
465  error_ = nullptr;
466  if (profile_ && own_profile_) rs2_delete_stream_profile(profile_);
467  profile_ = nullptr;
468  }
469 
470  static NAN_METHOD(Destroy) {
471  auto me = Nan::ObjectWrap::Unwrap<RSStreamProfile>(info.Holder());
472  if (me) {
473  me->DestroyMe();
474  }
475  info.GetReturnValue().Set(Nan::Undefined());
476  }
477 
478  static void New(const Nan::FunctionCallbackInfo<v8::Value>& info) {
479  if (info.IsConstructCall()) {
481  obj->Wrap(info.This());
482  info.GetReturnValue().Set(info.This());
483  }
484  }
485 
486  static NAN_METHOD(Stream) {
487  auto me = Nan::ObjectWrap::Unwrap<RSStreamProfile>(info.Holder());
488  if (me) {
489  info.GetReturnValue().Set(Nan::New(me->stream_));
490  return;
491  }
492  info.GetReturnValue().Set(Nan::Undefined());
493  }
494  static NAN_METHOD(Format) {
495  auto me = Nan::ObjectWrap::Unwrap<RSStreamProfile>(info.Holder());
496  if (me) {
497  info.GetReturnValue().Set(Nan::New(me->format_));
498  return;
499  }
500  info.GetReturnValue().Set(Nan::Undefined());
501  }
502  static NAN_METHOD(Fps) {
503  auto me = Nan::ObjectWrap::Unwrap<RSStreamProfile>(info.Holder());
504  if (me) {
505  info.GetReturnValue().Set(Nan::New(me->fps_));
506  return;
507  }
508  info.GetReturnValue().Set(Nan::Undefined());
509  }
510  static NAN_METHOD(Index) {
511  auto me = Nan::ObjectWrap::Unwrap<RSStreamProfile>(info.Holder());
512  if (me) {
513  info.GetReturnValue().Set(Nan::New(me->index_));
514  return;
515  }
516  info.GetReturnValue().Set(Nan::Undefined());
517  }
518  static NAN_METHOD(UniqueID) {
519  auto me = Nan::ObjectWrap::Unwrap<RSStreamProfile>(info.Holder());
520  if (me) {
521  info.GetReturnValue().Set(Nan::New(me->unique_id_));
522  return;
523  }
524  info.GetReturnValue().Set(Nan::Undefined());
525  }
526  static NAN_METHOD(IsDefault) {
527  auto me = Nan::ObjectWrap::Unwrap<RSStreamProfile>(info.Holder());
528  if (me) {
529  info.GetReturnValue().Set(Nan::New(me->is_default_));
530  return;
531  }
532  info.GetReturnValue().Set(Nan::Undefined());
533  }
534  static NAN_METHOD(IsVideoProfile) {
535  auto me = Nan::ObjectWrap::Unwrap<RSStreamProfile>(info.Holder());
536  if (me) {
537  info.GetReturnValue().Set(Nan::New(me->is_video_));
538  return;
539  }
540  info.GetReturnValue().Set(Nan::Undefined());
541  }
542 
543  static NAN_METHOD(IsMotionProfile) {
544  auto me = Nan::ObjectWrap::Unwrap<RSStreamProfile>(info.Holder());
545  info.GetReturnValue().Set(Nan::Undefined());
546  if (!me) return;
547 
548  info.GetReturnValue().Set(Nan::New(me->is_motion_));
549  }
550 
551  static NAN_METHOD(Width) {
552  auto me = Nan::ObjectWrap::Unwrap<RSStreamProfile>(info.Holder());
553  if (me) {
554  info.GetReturnValue().Set(Nan::New(me->width_));
555  return;
556  }
557  info.GetReturnValue().Set(Nan::Undefined());
558  }
559 
560  static NAN_METHOD(Height) {
561  auto me = Nan::ObjectWrap::Unwrap<RSStreamProfile>(info.Holder());
562  if (me) {
563  info.GetReturnValue().Set(Nan::New(me->height_));
564  return;
565  }
566  info.GetReturnValue().Set(Nan::Undefined());
567  }
568 
569  static NAN_METHOD(GetExtrinsicsTo) {
570  info.GetReturnValue().Set(Nan::Undefined());
571  v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
572  auto me = Nan::ObjectWrap::Unwrap<RSStreamProfile>(info.Holder());
573  auto to = Nan::ObjectWrap::Unwrap<RSStreamProfile>(info[0]->ToObject(context).ToLocalChecked());
574  if (!me || !to) return;
575 
577  CallNativeFunc(rs2_get_extrinsics, &me->error_, me->profile_, to->profile_,
578  &res, &me->error_);
579  if (me->error_) return;
580 
581  RSExtrinsics rsres(res);
582  info.GetReturnValue().Set(rsres.GetObject());
583  }
584 
585  static NAN_METHOD(GetVideoStreamIntrinsics) {
586  info.GetReturnValue().Set(Nan::Undefined());
587  auto me = Nan::ObjectWrap::Unwrap<RSStreamProfile>(info.Holder());
588  if (!me) return;
589 
591  CallNativeFunc(rs2_get_video_stream_intrinsics, &me->error_, me->profile_,
592  &intr, &me->error_);
593  if (me->error_) return;
594 
595  RSIntrinsics res(intr);
596  info.GetReturnValue().Set(res.GetObject());
597  }
598 
599  static NAN_METHOD(GetMotionIntrinsics) {
600  info.GetReturnValue().Set(Nan::Undefined());
601  auto me = Nan::ObjectWrap::Unwrap<RSStreamProfile>(info.Holder());
602  if (!me) return;
603 
605  CallNativeFunc(rs2_get_motion_intrinsics, &me->error_, me->profile_,
606  &output, &me->error_);
607  if (me->error_) return;
608 
610  info.GetReturnValue().Set(intrinsics.GetObject());
611  }
612 
613  private:
614  static Nan::Persistent<v8::Function> constructor_;
615 
623  bool is_video_;
629 
630  friend class RSSensor;
631 };
632 
633 Nan::Persistent<v8::Function> RSStreamProfile::constructor_;
634 
638 // //
639 // 8888888b. .d8888b. 8888888888 //
640 // 888 Y88b d88P Y88b 888 //
641 // 888 888 Y88b. 888 //
642 // 888 d88P "Y888b. 8888888 888d888 8888b. 88888b.d88b. .d88b. //
643 // 8888888P" "Y88b. 888 888P" "88b 888 "888 "88b d8P Y8b //
644 // 888 T88b "888 888 888 .d888888 888 888 888 88888888 //
645 // 888 T88b Y88b d88P 888 888 888 888 888 888 888 Y8b. //
646 // 888 T88b "Y8888P" 888 888 "Y888888 888 888 888 "Y8888 //
647 // //
651 
652 class RSFrame : public Nan::ObjectWrap {
653  public:
654  static void Init(v8::Local<v8::Object> exports) {
655  v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
656  tpl->SetClassName(Nan::New("RSFrame").ToLocalChecked());
657  tpl->InstanceTemplate()->SetInternalFieldCount(1);
658 
659  Nan::SetPrototypeMethod(tpl, "destroy", Destroy);
660  Nan::SetPrototypeMethod(tpl, "getStreamProfile", GetStreamProfile);
661  Nan::SetPrototypeMethod(tpl, "getData", GetData);
662  Nan::SetPrototypeMethod(tpl, "writeData", WriteData);
663  Nan::SetPrototypeMethod(tpl, "getWidth", GetWidth);
664  Nan::SetPrototypeMethod(tpl, "getHeight", GetHeight);
665  Nan::SetPrototypeMethod(tpl, "getStrideInBytes", GetStrideInBytes);
666  Nan::SetPrototypeMethod(tpl, "getBitsPerPixel", GetBitsPerPixel);
667  Nan::SetPrototypeMethod(tpl, "getTimestamp", GetTimestamp);
668  Nan::SetPrototypeMethod(tpl, "getTimestampDomain", GetTimestampDomain);
669  Nan::SetPrototypeMethod(tpl, "getFrameNumber", GetFrameNumber);
670  Nan::SetPrototypeMethod(tpl, "getFrameMetadata", GetFrameMetadata);
671  Nan::SetPrototypeMethod(tpl, "supportsFrameMetadata",
672  SupportsFrameMetadata);
673  Nan::SetPrototypeMethod(tpl, "isVideoFrame", IsVideoFrame);
674  Nan::SetPrototypeMethod(tpl, "isDepthFrame", IsDepthFrame);
675  Nan::SetPrototypeMethod(tpl, "isDisparityFrame", IsDisparityFrame);
676  Nan::SetPrototypeMethod(tpl, "isMotionFrame", IsMotionFrame);
677  Nan::SetPrototypeMethod(tpl, "isPoseFrame", IsPoseFrame);
678 
679  // Points related APIs
680  Nan::SetPrototypeMethod(tpl, "canGetPoints", CanGetPoints);
681  Nan::SetPrototypeMethod(tpl, "getVertices", GetVertices);
682  Nan::SetPrototypeMethod(tpl, "getVerticesBufferLen", GetVerticesBufferLen);
683  Nan::SetPrototypeMethod(tpl, "getTexCoordBufferLen", GetTexCoordBufferLen);
684  Nan::SetPrototypeMethod(tpl, "writeVertices", WriteVertices);
685  Nan::SetPrototypeMethod(tpl, "getTextureCoordinates",
686  GetTextureCoordinates);
687  Nan::SetPrototypeMethod(tpl, "writeTextureCoordinates",
688  WriteTextureCoordinates);
689  Nan::SetPrototypeMethod(tpl, "getPointsCount", GetPointsCount);
690  Nan::SetPrototypeMethod(tpl, "exportToPly", ExportToPly);
691  Nan::SetPrototypeMethod(tpl, "isValid", IsValid);
692  Nan::SetPrototypeMethod(tpl, "getDistance", GetDistance);
693  Nan::SetPrototypeMethod(tpl, "getBaseLine", GetBaseLine);
694  Nan::SetPrototypeMethod(tpl, "keep", Keep);
695  Nan::SetPrototypeMethod(tpl, "getMotionData", GetMotionData);
696  Nan::SetPrototypeMethod(tpl, "getPoseData", GetPoseData);
697 
698  v8::Local<v8::Context> context = exports->CreationContext();
699 
700  constructor_.Reset(tpl->GetFunction(context).ToLocalChecked());
701  exports->Set(context, Nan::New("RSFrame").ToLocalChecked(),
702  tpl->GetFunction(context).ToLocalChecked());
703  }
704 
705  static v8::Local<v8::Object> NewInstance(rs2_frame* frame) {
706  Nan::EscapableHandleScope scope;
707 
708  v8::Local<v8::Function> cons = Nan::New<v8::Function>(constructor_);
709  v8::Local<v8::Context> context = Nan::GetCurrentContext();
710 
711  v8::Local<v8::Object> instance =
712  cons->NewInstance(context, 0, nullptr).ToLocalChecked();
713 
714  auto me = Nan::ObjectWrap::Unwrap<RSFrame>(instance);
715  me->frame_ = frame;
716 
717  return scope.Escape(instance);
718  }
719 
721  DestroyMe();
722  frame_ = value;
723  // As the underlying frame changed, we must clean the js side's buffer
724  Nan::AsyncResource resource("_internalResetBuffer");
725  resource.runInAsyncScope(handle(), "_internalResetBuffer", 0, nullptr);
726  // Nan::MakeCallback(handle(), "_internalResetBuffer", 0, nullptr);
727  }
728 
729  private:
730  RSFrame() : frame_(nullptr), error_(nullptr) {}
731 
733  DestroyMe();
734  }
735 
736  void DestroyMe() {
737  if (error_) rs2_free_error(error_);
738  if (frame_) rs2_release_frame(frame_);
739  error_ = nullptr;
740  frame_ = nullptr;
741  }
742 
743  static void SetAFloatInVectorObject(v8::Local<v8::Object> obj, uint32_t index,
744  float value) {
745  const char* names[4] = {"x", "y", "z", "w"};
746  v8::Local<v8::String> name = Nan::New(names[index]).ToLocalChecked();
747  Nan::Set(obj, name, Nan::New(value));
748  }
749 
750  static void FillAFloatVector(v8::Local<v8::Object> obj,
751  const rs2_vector& vec) {
752  SetAFloatInVectorObject(obj, 0, vec.x);
753  SetAFloatInVectorObject(obj, 1, vec.y);
754  SetAFloatInVectorObject(obj, 2, vec.z);
755  }
756 
757  static void FillAFloatQuaternion(v8::Local<v8::Object> obj,
758  const rs2_quaternion& quaternion) {
759  SetAFloatInVectorObject(obj, 0, quaternion.x);
760  SetAFloatInVectorObject(obj, 1, quaternion.y);
761  SetAFloatInVectorObject(obj, 2, quaternion.z);
762  SetAFloatInVectorObject(obj, 3, quaternion.w);
763  }
764 
765  static void AssemblePoseData(v8::Local<v8::Object> obj,
766  const rs2_pose& pose) {
767  auto translation_name = Nan::New("translation").ToLocalChecked();
768  auto velocity_name = Nan::New("velocity").ToLocalChecked();
769  auto acceleration_name = Nan::New("acceleration").ToLocalChecked();
770  auto rotation_name = Nan::New("rotation").ToLocalChecked();
771  auto angular_velocity_name = Nan::New("angularVelocity").ToLocalChecked();
772  auto angular_acceleration_name =
773  Nan::New("angularAcceleration").ToLocalChecked();
774  auto tracker_confidence_name =
775  Nan::New("trackerConfidence").ToLocalChecked();
776  auto mapper_confidence_name = Nan::New("mapperConfidence").ToLocalChecked();
777 
778  auto translation_obj = Nan::GetRealNamedProperty(
779  obj, translation_name).ToLocalChecked()->ToObject(Nan::GetCurrentContext());
780  auto velocity_obj = Nan::GetRealNamedProperty(
781  obj, velocity_name).ToLocalChecked()->ToObject(Nan::GetCurrentContext());
782  auto acceleration_obj = Nan::GetRealNamedProperty(
783  obj, acceleration_name).ToLocalChecked()->ToObject(Nan::GetCurrentContext());
784  auto rotation_obj = Nan::GetRealNamedProperty(
785  obj, rotation_name).ToLocalChecked()->ToObject(Nan::GetCurrentContext());
786  auto angular_velocity_obj = Nan::GetRealNamedProperty(
787  obj, angular_velocity_name).ToLocalChecked()->ToObject(Nan::GetCurrentContext());
788  auto angular_acceleration_obj = Nan::GetRealNamedProperty(
789  obj, angular_acceleration_name).ToLocalChecked()->ToObject(Nan::GetCurrentContext());
790 
791  FillAFloatVector(translation_obj.ToLocalChecked(), pose.translation);
792  FillAFloatVector(velocity_obj.ToLocalChecked(), pose.velocity);
793  FillAFloatVector(acceleration_obj.ToLocalChecked(), pose.acceleration);
794  FillAFloatQuaternion(rotation_obj.ToLocalChecked(), pose.rotation);
795  FillAFloatVector(angular_velocity_obj.ToLocalChecked(), pose.angular_velocity);
796  FillAFloatVector(angular_acceleration_obj.ToLocalChecked(), pose.angular_acceleration);
797 
798  Nan::Set(obj, tracker_confidence_name, Nan::New(pose.tracker_confidence));
799  Nan::Set(obj, mapper_confidence_name, Nan::New(pose.mapper_confidence));
800  }
801 
802  static void New(const Nan::FunctionCallbackInfo<v8::Value>& info) {
803  if (info.IsConstructCall()) {
804  RSFrame* obj = new RSFrame();
805  obj->Wrap(info.This());
806  info.GetReturnValue().Set(info.This());
807  }
808  }
809 
810  static NAN_METHOD(GetStreamProfile) {
811  info.GetReturnValue().Set(Nan::Undefined());
812  auto me = Nan::ObjectWrap::Unwrap<RSFrame>(info.Holder());
813  if (!me || !me->frame_) return;
814 
817  int32_t index = 0;
818  int32_t unique_id = 0;
819  int32_t fps = 0;
820  const rs2_stream_profile* profile_org =
821  GetNativeResult<const rs2_stream_profile*>(rs2_get_frame_stream_profile,
822  &me->error_, me->frame_, &me->error_);
823  CallNativeFunc(rs2_get_stream_profile_data, &me->error_, profile_org,
824  &stream, &format, &index, &unique_id, &fps, &me->error_);
825  if (me->error_) return;
826 
827  rs2_stream_profile* profile = GetNativeResult<rs2_stream_profile*>(
828  rs2_clone_stream_profile, &me->error_, profile_org, stream, index,
829  format, &me->error_);
830  if (!profile) return;
831 
832  info.GetReturnValue().Set(RSStreamProfile::NewInstance(profile, true));
833  }
834 
835  static NAN_METHOD(GetData) {
836  info.GetReturnValue().Set(Nan::Undefined());
837  auto me = Nan::ObjectWrap::Unwrap<RSFrame>(info.Holder());
838  if (!me) return;
839 
840  auto buffer = GetNativeResult<const void*>(rs2_get_frame_data, &me->error_,
841  me->frame_, &me->error_);
842  if (!buffer) return;
843 
844  const auto stride = GetNativeResult<int>(rs2_get_frame_stride_in_bytes,
845  &me->error_, me->frame_, &me->error_);
846  const auto height = GetNativeResult<int>(rs2_get_frame_height, &me->error_,
847  me->frame_, &me->error_);
848  const auto length = stride * height;
849  auto array_buffer = v8::ArrayBuffer::New(
850  v8::Isolate::GetCurrent(),
851  static_cast<uint8_t*>(const_cast<void*>(buffer)), length,
852  v8::ArrayBufferCreationMode::kExternalized);
853  info.GetReturnValue().Set(array_buffer);
854  }
855 
856  static NAN_METHOD(WriteData) {
857  info.GetReturnValue().Set(Nan::Undefined());
858  auto array_buffer = v8::Local<v8::ArrayBuffer>::Cast(info[0]);
859  auto me = Nan::ObjectWrap::Unwrap<RSFrame>(info.Holder());
860  if (!me) return;
861 
862  const auto buffer = GetNativeResult<const void*>(rs2_get_frame_data,
863  &me->error_, me->frame_, &me->error_);
864  const auto stride = GetNativeResult<int>(rs2_get_frame_stride_in_bytes,
865  &me->error_, me->frame_, &me->error_);
866  const auto height = GetNativeResult<int>(rs2_get_frame_height, &me->error_,
867  me->frame_, &me->error_);
868  const size_t length = stride * height;
869  if (buffer && array_buffer->ByteLength() >= length) {
870  auto contents = array_buffer->GetContents();
871  memcpy(contents.Data(), buffer, length);
872  }
873  }
874 
875  static NAN_METHOD(GetWidth) {
876  info.GetReturnValue().Set(Nan::Undefined());
877  auto me = Nan::ObjectWrap::Unwrap<RSFrame>(info.Holder());
878  if (!me) return;
879 
880  auto value = GetNativeResult<int>(rs2_get_frame_width, &me->error_,
881  me->frame_, &me->error_);
882  info.GetReturnValue().Set(Nan::New(value));
883  }
884 
885  static NAN_METHOD(GetHeight) {
886  info.GetReturnValue().Set(Nan::Undefined());
887  auto me = Nan::ObjectWrap::Unwrap<RSFrame>(info.Holder());
888  if (!me) return;
889 
890  auto value = GetNativeResult<int>(rs2_get_frame_height, &me->error_,
891  me->frame_, &me->error_);
892  info.GetReturnValue().Set(Nan::New(value));
893  }
894 
895  static NAN_METHOD(GetStrideInBytes) {
896  info.GetReturnValue().Set(Nan::Undefined());
897  auto me = Nan::ObjectWrap::Unwrap<RSFrame>(info.Holder());
898  if (!me) return;
899 
900  auto value = GetNativeResult<int>(rs2_get_frame_stride_in_bytes,
901  &me->error_, me->frame_, &me->error_);
902  info.GetReturnValue().Set(Nan::New(value));
903  }
904 
905  static NAN_METHOD(GetBitsPerPixel) {
906  info.GetReturnValue().Set(Nan::Undefined());
907  auto me = Nan::ObjectWrap::Unwrap<RSFrame>(info.Holder());
908  if (!me) return;
909 
910  auto value = GetNativeResult<int>(rs2_get_frame_bits_per_pixel, &me->error_,
911  me->frame_, &me->error_);
912  info.GetReturnValue().Set(Nan::New(value));
913  }
914 
915  static NAN_METHOD(GetTimestamp) {
916  info.GetReturnValue().Set(Nan::Undefined());
917  auto me = Nan::ObjectWrap::Unwrap<RSFrame>(info.Holder());
918  if (!me) return;
919 
920  auto value = GetNativeResult<double>(rs2_get_frame_timestamp, &me->error_,
921  me->frame_, &me->error_);
922  info.GetReturnValue().Set(Nan::New(value));
923  }
924 
925  static NAN_METHOD(GetTimestampDomain) {
926  info.GetReturnValue().Set(Nan::Undefined());
927  auto me = Nan::ObjectWrap::Unwrap<RSFrame>(info.Holder());
928  if (!me) return;
929 
930  auto value = GetNativeResult<rs2_timestamp_domain>(
931  rs2_get_frame_timestamp_domain, &me->error_, me->frame_, &me->error_);
932  info.GetReturnValue().Set(Nan::New(value));
933  }
934 
935  static NAN_METHOD(GetFrameNumber) {
936  info.GetReturnValue().Set(Nan::Undefined());
937  auto me = Nan::ObjectWrap::Unwrap<RSFrame>(info.Holder());
938  if (!me) return;
939 
940  uint32_t value = GetNativeResult<uint32_t>(rs2_get_frame_number,
941  &me->error_, me->frame_, &me->error_);
942  info.GetReturnValue().Set(Nan::New(value));
943  }
944 
945  static NAN_METHOD(IsVideoFrame) {
946  info.GetReturnValue().Set(Nan::Undefined());
947  auto me = Nan::ObjectWrap::Unwrap<RSFrame>(info.Holder());
948  if (!me) return;
949 
950  bool isVideo = false;
951  if (GetNativeResult<bool>(rs2_is_frame_extendable_to, &me->error_,
952  me->frame_, RS2_EXTENSION_VIDEO_FRAME, &me->error_))
953  isVideo = true;
954  info.GetReturnValue().Set(Nan::New(isVideo));
955  }
956 
957  static NAN_METHOD(IsDepthFrame) {
958  info.GetReturnValue().Set(Nan::Undefined());
959  auto me = Nan::ObjectWrap::Unwrap<RSFrame>(info.Holder());
960  if (!me) return;
961 
962  bool isDepth = false;
963  if (GetNativeResult<bool>(rs2_is_frame_extendable_to, &me->error_,
964  me->frame_, RS2_EXTENSION_DEPTH_FRAME, &me->error_))
965  isDepth = true;
966  info.GetReturnValue().Set(Nan::New(isDepth));
967  }
968 
969  static NAN_METHOD(IsDisparityFrame) {
970  auto me = Nan::ObjectWrap::Unwrap<RSFrame>(info.Holder());
971  info.GetReturnValue().Set(Nan::Undefined());
972  if (!me) return;
973 
974  auto is_disparity = GetNativeResult<int>(rs2_is_frame_extendable_to,
975  &me->error_, me->frame_, RS2_EXTENSION_DISPARITY_FRAME, &me->error_);
976  info.GetReturnValue().Set(Nan::New(is_disparity ? true : false));
977  }
978 
979  static NAN_METHOD(IsMotionFrame) {
980  auto me = Nan::ObjectWrap::Unwrap<RSFrame>(info.Holder());
981  info.GetReturnValue().Set(Nan::Undefined());
982  if (!me) return;
983 
984  auto val = GetNativeResult<int>(rs2_is_frame_extendable_to, &me->error_,
985  me->frame_, RS2_EXTENSION_MOTION_FRAME, &me->error_);
986  info.GetReturnValue().Set(Nan::New(val ? true : false));
987  }
988 
989  static NAN_METHOD(IsPoseFrame) {
990  auto me = Nan::ObjectWrap::Unwrap<RSFrame>(info.Holder());
991  info.GetReturnValue().Set(Nan::Undefined());
992  if (!me) return;
993 
994  auto val = GetNativeResult<int>(rs2_is_frame_extendable_to, &me->error_,
995  me->frame_, RS2_EXTENSION_POSE_FRAME, &me->error_);
996  info.GetReturnValue().Set(Nan::New(val ? true : false));
997  }
998 
999  static NAN_METHOD(GetFrameMetadata) {
1000  info.GetReturnValue().Set(Nan::New(false));
1001  auto me = Nan::ObjectWrap::Unwrap<RSFrame>(info.Holder());
1003  (rs2_frame_metadata_value)(Nan::To<int64_t>(info[0]).FromJust());
1004  Nan::TypedArrayContents<unsigned char> content(info[1]);
1005  unsigned char* internal_data = *content;
1006  if (!me || !internal_data) return;
1007 
1008  rs2_metadata_type output = GetNativeResult<rs2_metadata_type>(
1009  rs2_get_frame_metadata, &me->error_, me->frame_, metadata, &me->error_);
1010  unsigned char* out_ptr = reinterpret_cast<unsigned char*>(&output);
1011  uint32_t val = 1;
1012  unsigned char* val_ptr = reinterpret_cast<unsigned char*>(&val);
1013 
1014  if (*val_ptr == 0) {
1015  // big endian
1016  memcpy(internal_data, out_ptr, 8);
1017  } else {
1018  // little endian
1019  for (int32_t i=0; i < 8; i++) {
1020  internal_data[i] = out_ptr[7-i];
1021  }
1022  }
1023  info.GetReturnValue().Set(Nan::New(true));
1024  }
1025 
1026  static NAN_METHOD(SupportsFrameMetadata) {
1027  info.GetReturnValue().Set(Nan::Undefined());
1028  auto me = Nan::ObjectWrap::Unwrap<RSFrame>(info.Holder());
1030  (rs2_frame_metadata_value)(Nan::To<int64_t>(info[0]).FromJust());
1031  if (!me) return;
1032 
1033  int result = GetNativeResult<int>(rs2_supports_frame_metadata, &me->error_,
1034  me->frame_, metadata, &me->error_);
1035  info.GetReturnValue().Set(Nan::New(result ? true : false));
1036  }
1037 
1038  static NAN_METHOD(Destroy) {
1039  auto me = Nan::ObjectWrap::Unwrap<RSFrame>(info.Holder());
1040  if (me) {
1041  me->DestroyMe();
1042  }
1043  info.GetReturnValue().Set(Nan::Undefined());
1044  }
1045 
1046  static NAN_METHOD(CanGetPoints) {
1047  info.GetReturnValue().Set(Nan::Undefined());
1048  auto me = Nan::ObjectWrap::Unwrap<RSFrame>(info.Holder());
1049  if (!me) return;
1050 
1051  bool result = false;
1052  if (GetNativeResult<int>(rs2_is_frame_extendable_to, &me->error_,
1053  me->frame_, RS2_EXTENSION_POINTS, &me->error_))
1054  result = true;
1055  info.GetReturnValue().Set(Nan::New(result));
1056  }
1057 
1058  static NAN_METHOD(GetVertices) {
1059  info.GetReturnValue().Set(Nan::Undefined());
1060  auto me = Nan::ObjectWrap::Unwrap<RSFrame>(info.Holder());
1061  if (!me) return;
1062 
1063  rs2_vertex* vertices = GetNativeResult<rs2_vertex*>(rs2_get_frame_vertices,
1064  &me->error_, me->frame_, &me->error_);
1065  size_t count = GetNativeResult<size_t>(rs2_get_frame_points_count,
1066  &me->error_, me->frame_, &me->error_);
1067  if (!vertices || !count) return;
1068 
1069  uint32_t step = 3 * sizeof(float);
1070  uint32_t len = count * step;
1071  auto vertex_buf = static_cast<uint8_t*>(malloc(len));
1072 
1073  for (size_t i = 0; i < count; i++) {
1074  memcpy(vertex_buf+i*step, vertices[i].xyz, step);
1075  }
1076  auto array_buffer = v8::ArrayBuffer::New(
1077  v8::Isolate::GetCurrent(), vertex_buf, len,
1078  v8::ArrayBufferCreationMode::kInternalized);
1079 
1080  info.GetReturnValue().Set(v8::Float32Array::New(array_buffer, 0, 3*count));
1081  }
1082 
1083  static NAN_METHOD(GetVerticesBufferLen) {
1084  info.GetReturnValue().Set(Nan::Undefined());
1085  auto me = Nan::ObjectWrap::Unwrap<RSFrame>(info.Holder());
1086  if (!me) return;
1087 
1088  const size_t count = GetNativeResult<size_t>(rs2_get_frame_points_count,
1089  &me->error_, me->frame_, &me->error_);
1090  const uint32_t step = 3 * sizeof(float);
1091  const uint32_t length = count * step;
1092  info.GetReturnValue().Set(Nan::New(length));
1093  }
1094 
1095  static NAN_METHOD(GetTexCoordBufferLen) {
1096  info.GetReturnValue().Set(Nan::Undefined());
1097  auto me = Nan::ObjectWrap::Unwrap<RSFrame>(info.Holder());
1098  if (!me) return;
1099 
1100  const size_t count = GetNativeResult<size_t>(rs2_get_frame_points_count,
1101  &me->error_, me->frame_, &me->error_);
1102  const uint32_t step = 2 * sizeof(int);
1103  const uint32_t length = count * step;
1104  info.GetReturnValue().Set(Nan::New(length));
1105  }
1106 
1107  static NAN_METHOD(WriteVertices) {
1108  info.GetReturnValue().Set(Nan::False());
1109  auto me = Nan::ObjectWrap::Unwrap<RSFrame>(info.Holder());
1110  auto array_buffer = v8::Local<v8::ArrayBuffer>::Cast(info[0]);
1111  if (!me) return;
1112 
1113  const rs2_vertex* vertBuf = GetNativeResult<rs2_vertex*>(
1114  rs2_get_frame_vertices, &me->error_, me->frame_, &me->error_);
1115  const size_t count = GetNativeResult<size_t>(rs2_get_frame_points_count,
1116  &me->error_, me->frame_, &me->error_);
1117  if (!vertBuf || !count) return;
1118 
1119  const uint32_t step = 3 * sizeof(float);
1120  const uint32_t length = count * step;
1121  if (array_buffer->ByteLength() < length) return;
1122 
1123  auto contents = array_buffer->GetContents();
1124  uint8_t* vertex_buf = static_cast<uint8_t*>(contents.Data());
1125  for (size_t i = 0; i < count; i++) {
1126  memcpy(vertex_buf+i*step, vertBuf[i].xyz, step);
1127  }
1128  info.GetReturnValue().Set(Nan::True());
1129  }
1130 
1131  static NAN_METHOD(GetTextureCoordinates) {
1132  info.GetReturnValue().Set(Nan::Undefined());
1133  auto me = Nan::ObjectWrap::Unwrap<RSFrame>(info.Holder());
1134  if (!me) return;
1135 
1136  rs2_pixel* coords = GetNativeResult<rs2_pixel*>(
1137  rs2_get_frame_texture_coordinates, &me->error_, me->frame_,
1138  &me->error_);
1139  size_t count = GetNativeResult<size_t>(rs2_get_frame_points_count,
1140  &me->error_, me->frame_, &me->error_);
1141  if (!coords || !count) return;
1142 
1143  uint32_t step = 2 * sizeof(int);
1144  uint32_t len = count * step;
1145  auto texcoord_buf = static_cast<uint8_t*>(malloc(len));
1146 
1147  for (size_t i = 0; i < count; ++i) {
1148  memcpy(texcoord_buf + i * step, coords[i].ij, step);
1149  }
1150  auto array_buffer = v8::ArrayBuffer::New(
1151  v8::Isolate::GetCurrent(), texcoord_buf, len,
1152  v8::ArrayBufferCreationMode::kInternalized);
1153 
1154  info.GetReturnValue().Set(v8::Int32Array::New(array_buffer, 0, 2*count));
1155  }
1156 
1157  static NAN_METHOD(WriteTextureCoordinates) {
1158  info.GetReturnValue().Set(Nan::False());
1159  auto me = Nan::ObjectWrap::Unwrap<RSFrame>(info.Holder());
1160  auto array_buffer = v8::Local<v8::ArrayBuffer>::Cast(info[0]);
1161  if (!me) return;
1162 
1163  const rs2_pixel* coords =
1164  rs2_get_frame_texture_coordinates(me->frame_, &me->error_);
1165  const size_t count = GetNativeResult<size_t>(rs2_get_frame_points_count,
1166  &me->error_, me->frame_, &me->error_);
1167  if (!coords || !count) return;
1168 
1169  const uint32_t step = 2 * sizeof(int);
1170  const uint32_t length = count * step;
1171  if (array_buffer->ByteLength() < length) return;
1172 
1173  auto contents = array_buffer->GetContents();
1174  uint8_t* texcoord_buf = static_cast<uint8_t*>(contents.Data());
1175  for (size_t i = 0; i < count; ++i) {
1176  memcpy(texcoord_buf + i * step, coords[i].ij, step);
1177  }
1178  info.GetReturnValue().Set(Nan::True());
1179  }
1180 
1181  static NAN_METHOD(GetPointsCount) {
1182  info.GetReturnValue().Set(Nan::Undefined());
1183  auto me = Nan::ObjectWrap::Unwrap<RSFrame>(info.Holder());
1184  if (!me) return;
1185 
1186  int32_t count = GetNativeResult<int>(rs2_get_frame_points_count,
1187  &me->error_, me->frame_, &me->error_);
1188  info.GetReturnValue().Set(Nan::New(count));
1189  }
1190 
1191  static NAN_METHOD(ExportToPly) {
1192  auto me = Nan::ObjectWrap::Unwrap<RSFrame>(info.Holder());
1193  // v8::String::Utf8Value str(info[0]);
1194  Nan::Utf8String str(info[0]);
1195  std::string file = std::string(*str);
1196  v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
1197  auto texture = Nan::ObjectWrap::Unwrap<RSFrame>(
1198  info[1]->ToObject(context).ToLocalChecked());
1199  info.GetReturnValue().Set(Nan::Undefined());
1200  if (!me || !texture) return;
1201 
1202  rs2_frame* ptr = nullptr;
1203  std::swap(texture->frame_, ptr);
1204  CallNativeFunc(rs2_export_to_ply, &me->error_, me->frame_, file.c_str(),
1205  ptr, &me->error_);
1206  }
1207 
1208  static NAN_METHOD(IsValid) {
1209  auto me = Nan::ObjectWrap::Unwrap<RSFrame>(info.Holder());
1210  if (me) {
1211  if (me->frame_) {
1212  info.GetReturnValue().Set(Nan::True());
1213  return;
1214  }
1215  }
1216  info.GetReturnValue().Set(Nan::False());
1217  }
1218 
1219  static NAN_METHOD(GetDistance) {
1220  info.GetReturnValue().Set(Nan::Undefined());
1221  auto me = Nan::ObjectWrap::Unwrap<RSFrame>(info.Holder());
1222  auto x = Nan::To<int64_t>(info[0]).FromJust();
1223  auto y = Nan::To<int64_t>(info[1]).FromJust();
1224  if (!me) return;
1225 
1226  auto val = GetNativeResult<float>(rs2_depth_frame_get_distance, &me->error_,
1227  me->frame_, x, y, &me->error_);
1228  info.GetReturnValue().Set(Nan::New(val));
1229  }
1230 
1231  static NAN_METHOD(GetBaseLine) {
1232  auto me = Nan::ObjectWrap::Unwrap<RSFrame>(info.Holder());
1233  info.GetReturnValue().Set(Nan::Undefined());
1234  if (!me) return;
1235 
1236  auto val = GetNativeResult<float>(rs2_depth_stereo_frame_get_baseline,
1237  &me->error_, me->frame_, &me->error_);
1238  info.GetReturnValue().Set(Nan::New(val));
1239  }
1240 
1241  static NAN_METHOD(Keep) {
1242  auto me = Nan::ObjectWrap::Unwrap<RSFrame>(info.Holder());
1243  info.GetReturnValue().Set(Nan::Undefined());
1244  if (!me || !me->frame_) return;
1245 
1246  rs2_keep_frame(me->frame_);
1247  }
1248 
1249  static NAN_METHOD(GetMotionData) {
1250  auto me = Nan::ObjectWrap::Unwrap<RSFrame>(info.Holder());
1251  info.GetReturnValue().Set(Nan::Undefined());
1252  if (!me) return;
1253  v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
1254  auto obj = info[0]->ToObject(context).ToLocalChecked();
1255  auto frame_data = static_cast<const float*>(GetNativeResult<const void*>(
1256  rs2_get_frame_data, &me->error_, me->frame_, &me->error_));
1257  for (uint32_t i = 0; i < 3; i++) {
1258  SetAFloatInVectorObject(obj, i, frame_data[i]);
1259  }
1260  }
1261 
1262  static NAN_METHOD(GetPoseData) {
1263  auto me = Nan::ObjectWrap::Unwrap<RSFrame>(info.Holder());
1264  info.GetReturnValue().Set(Nan::False());
1265  if (!me) return;
1266 
1267  rs2_pose pose_data;
1268  CallNativeFunc(rs2_pose_frame_get_pose_data, &me->error_, me->frame_,
1269  &pose_data, &me->error_);
1270  if (me->error_) return;
1271  v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
1272  AssemblePoseData(info[0]->ToObject(context).ToLocalChecked(), pose_data);
1273  info.GetReturnValue().Set(Nan::True());
1274  }
1275 
1276  private:
1277  static Nan::Persistent<v8::Function> constructor_;
1280  friend class RSColorizer;
1281  friend class RSFilter;
1282  friend class RSFrameQueue;
1283  friend class RSPointCloud;
1284  friend class RSSyncer;
1285 };
1286 
1287 Nan::Persistent<v8::Function> RSFrame::constructor_;
1288 
1289 
1293 //
1294 // 8888888888 .d88888b. //
1295 // 888 d88P" "Y88b //
1296 // 888 888 888 //
1297 // 8888888 888d888 8888b. 88888b.d88b. .d88b. 888 888 //
1298 // 888 888P" "88b 888 "888 "88b d8P Y8b 888 888 //
1299 // 888 888 .d888888 888 888 888 88888888 888 Y8b 888 //
1300 // 888 888 888 888 888 888 888 Y8b. Y88b.Y8b88P //
1301 // 888 888 "Y888888 888 888 888 "Y8888 "Y888888" //
1302 // //
1303 //
1307 // TODO(shaoting) remove this class if not used in future.
1308 class RSFrameQueue : public Nan::ObjectWrap {
1309  public:
1310  static void Init(v8::Local<v8::Object> exports) {
1311  v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
1312  tpl->SetClassName(Nan::New("RSFrameQueue").ToLocalChecked());
1313  tpl->InstanceTemplate()->SetInternalFieldCount(1);
1314 
1315  Nan::SetPrototypeMethod(tpl, "create", Create);
1316  Nan::SetPrototypeMethod(tpl, "destroy", Destroy);
1317  Nan::SetPrototypeMethod(tpl, "waitForFrame", WaitForFrame);
1318  Nan::SetPrototypeMethod(tpl, "pollForFrame", PollForFrame);
1319  Nan::SetPrototypeMethod(tpl, "enqueueFrame", EnqueueFrame);
1320  v8::Local<v8::Context> context = exports->CreationContext();
1321  constructor_.Reset(tpl->GetFunction(context).ToLocalChecked());
1322  exports->Set(context, Nan::New("RSFrameQueue").ToLocalChecked(),
1323  tpl->GetFunction(context).ToLocalChecked());
1324  }
1325 
1326  static v8::Local<v8::Object> NewInstance() {
1327  Nan::EscapableHandleScope scope;
1328 
1329  v8::Local<v8::Function> cons = Nan::New<v8::Function>(constructor_);
1330  v8::Local<v8::Context> context = Nan::GetCurrentContext();
1331 
1332  v8::Local<v8::Object> instance =
1333  cons->NewInstance(context, 0, nullptr).ToLocalChecked();
1334 
1335  return scope.Escape(instance);
1336  }
1337 
1338  private:
1339  RSFrameQueue() : frame_queue_(nullptr), error_(nullptr) {}
1340 
1342  DestroyMe();
1343  }
1344 
1345  void DestroyMe() {
1346  if (error_) rs2_free_error(error_);
1347  error_ = nullptr;
1348  if (frame_queue_) rs2_delete_frame_queue(frame_queue_);
1349  frame_queue_ = nullptr;
1350  }
1351 
1352  static void New(const Nan::FunctionCallbackInfo<v8::Value>& info) {
1353  if (info.IsConstructCall()) {
1354  RSFrameQueue* obj = new RSFrameQueue();
1355  obj->Wrap(info.This());
1356  info.GetReturnValue().Set(info.This());
1357  }
1358  }
1359 
1360  static NAN_METHOD(WaitForFrame) {
1361  info.GetReturnValue().Set(Nan::Undefined());
1362  int32_t timeout = Nan::To<int32_t>(info[0]).FromJust(); // in ms
1363  auto me = Nan::ObjectWrap::Unwrap<RSFrameQueue>(info.Holder());
1364  if (!me) return;
1365 
1366  auto frame = GetNativeResult<rs2_frame*>(rs2_wait_for_frame, &me->error_,
1367  me->frame_queue_, timeout, &me->error_);
1368  if (!frame) return;
1369 
1370  info.GetReturnValue().Set(RSFrame::NewInstance(frame));
1371  }
1372 
1373  static NAN_METHOD(Create) {
1374  info.GetReturnValue().Set(Nan::Undefined());
1375  int32_t capacity = Nan::To<int32_t>(info[0]).FromJust();
1376  auto me = Nan::ObjectWrap::Unwrap<RSFrameQueue>(info.Holder());
1377  if (!me) return;
1378 
1379  me->frame_queue_ = GetNativeResult<rs2_frame_queue*>(rs2_create_frame_queue,
1380  &me->error_, capacity, &me->error_);
1381  }
1382 
1383  static NAN_METHOD(Destroy) {
1384  auto me = Nan::ObjectWrap::Unwrap<RSFrameQueue>(info.Holder());
1385  if (me) {
1386  me->DestroyMe();
1387  }
1388  info.GetReturnValue().Set(Nan::Undefined());
1389  }
1390 
1391  static NAN_METHOD(PollForFrame) {
1392  info.GetReturnValue().Set(Nan::Undefined());
1393  auto me = Nan::ObjectWrap::Unwrap<RSFrameQueue>(info.Holder());
1394  if (!me) return;
1395 
1396  rs2_frame* frame = nullptr;
1397  auto res = GetNativeResult<int>(rs2_poll_for_frame, &me->error_,
1398  me->frame_queue_, &frame, &me->error_);
1399  if (!res) return;
1400 
1401  info.GetReturnValue().Set(RSFrame::NewInstance(frame));
1402  }
1403 
1404  static NAN_METHOD(EnqueueFrame) {
1405  v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
1406  auto me = Nan::ObjectWrap::Unwrap<RSFrameQueue>(info.Holder());
1407  auto frame = Nan::ObjectWrap::Unwrap<RSFrame>(info[0]->ToObject(context).ToLocalChecked());
1408 
1409  if (me && frame) {
1410  rs2_enqueue_frame(frame->frame_, me->frame_queue_);
1411  frame->frame_ = nullptr;
1412  }
1413  info.GetReturnValue().Set(Nan::Undefined());
1414  }
1415 
1416  private:
1417  static Nan::Persistent<v8::Function> constructor_;
1420  friend class RSDevice;
1421 };
1422 
1423 Nan::Persistent<v8::Function> RSFrameQueue::constructor_;
1424 
1425 class RSDevice;
1426 class RSSensor;
1428  public:
1430  frame_(frame), sensor_(static_cast<RSSensor*>(data)) {}
1431  virtual ~FrameCallbackInfo() { if (!consumed_) Release(); }
1432  virtual void Run();
1433  virtual void Release() {
1434  if (frame_) {
1435  rs2_release_frame(frame_);
1436  frame_ = nullptr;
1437  }
1438  }
1439 
1440  private:
1443 };
1444 
1446  public:
1447  NotificationCallbackInfo(const char* desc,
1448  rs2_time_t time,
1450  rs2_notification_category category,
1451  std::string serialized_data,
1452  RSSensor* s) :
1453  desc_(desc), time_(time), severity_(severity),
1454  category_(category), serialized_data_(serialized_data),
1455  sensor_(s) {}
1457  virtual void Run();
1458 
1459  private:
1467 };
1468 
1470  public:
1471  explicit NotificationCallback(RSSensor* s) : error_(nullptr), sensor_(s) {}
1472  void on_notification(rs2_notification* notification) override {
1473  if (notification) {
1474  const char* desc = GetNativeResult<const char*>(
1475  rs2_get_notification_description, &error_, notification, &error_);
1476  rs2_time_t time = GetNativeResult<rs2_time_t>(
1477  rs2_get_notification_timestamp, &error_, notification, &error_);
1478  rs2_log_severity severity = GetNativeResult<rs2_log_severity>(
1479  rs2_get_notification_severity, &error_, notification, &error_);
1480  rs2_notification_category category =
1481  GetNativeResult<rs2_notification_category>(
1482  rs2_get_notification_category, &error_, notification, &error_);
1483  std::string serialized_data = GetNativeResult<std::string>(
1484  rs2_get_notification_serialized_data, &error_, notification, &error_);
1486  time, severity, category, serialized_data, sensor_));
1487  }
1488  }
1489  void release() override { delete this; }
1492 };
1493 
1495  public:
1497  : frame_queue_(queue) {}
1498  void on_frame(rs2_frame* frame) override {
1499  if (frame && frame_queue_)
1500  rs2_enqueue_frame(frame, frame_queue_);
1501  }
1502  void release() override { delete this; }
1504 };
1505 
1507  public:
1508  explicit FrameCallbackForProc(void* data) : callback_data_(data) {}
1509  void on_frame(rs2_frame* frame) override {
1511  new FrameCallbackInfo(frame, callback_data_));
1512  }
1513  void release() override { delete this; }
1515 };
1516 
1518  public:
1520  block_(block_ptr), error_(nullptr) {}
1522  if (error_) rs2_free_error(error_);
1523  }
1524  void on_frame(rs2_frame* frame) override {
1525  rs2_process_frame(block_, frame, &error_);
1526  }
1527  void release() override { delete this; }
1530 };
1531 
1533  public:
1535  status_(status), dev_(dev), error_(nullptr) {}
1537  virtual void Run();
1538 
1539  private:
1543 };
1544 
1546  public:
1547  explicit PlaybackStatusCallback(RSDevice* dev) : error_(nullptr), dev_(dev) {}
1550  dev_));
1551  }
1552  void release() override { delete this; }
1553 
1554  private:
1557 };
1558 
1560  public:
1562  rs2_get_stream_profile_data(profile, &stream_, &format_, &index_,
1563  &unique_id_, &fps_, &error_);
1564  }
1572 };
1573 
1574 class RSFrameSet : public Nan::ObjectWrap {
1575  public:
1576  static void Init(v8::Local<v8::Object> exports) {
1577  v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
1578  tpl->SetClassName(Nan::New("RSFrameSet").ToLocalChecked());
1579  tpl->InstanceTemplate()->SetInternalFieldCount(1);
1580 
1581  Nan::SetPrototypeMethod(tpl, "destroy", Destroy);
1582  Nan::SetPrototypeMethod(tpl, "getSize", GetSize);
1583  Nan::SetPrototypeMethod(tpl, "getFrame", GetFrame);
1584  Nan::SetPrototypeMethod(tpl, "replaceFrame", ReplaceFrame);
1585  Nan::SetPrototypeMethod(tpl, "indexToStream", IndexToStream);
1586  Nan::SetPrototypeMethod(tpl, "indexToStreamIndex", IndexToStreamIndex);
1587  v8::Local<v8::Context> context = exports->CreationContext();
1588  constructor_.Reset(tpl->GetFunction(context).ToLocalChecked());
1589  exports->Set(context, Nan::New("RSFrameSet").ToLocalChecked(),
1590  tpl->GetFunction(context).ToLocalChecked());
1591  }
1592 
1593  static v8::Local<v8::Object> NewInstance(rs2_frame* frame) {
1594  Nan::EscapableHandleScope scope;
1595 
1596  v8::Local<v8::Function> cons = Nan::New<v8::Function>(constructor_);
1597  v8::Local<v8::Context> context = Nan::GetCurrentContext();
1598 
1599  v8::Local<v8::Object> instance =
1600  cons->NewInstance(context, 0, nullptr).ToLocalChecked();
1601  auto me = Nan::ObjectWrap::Unwrap<RSFrameSet>(instance);
1602  me->SetFrame(frame);
1603 
1604  return scope.Escape(instance);
1605  }
1606 
1608  return frames_;
1609  }
1610 
1611  void Replace(rs2_frame* frame) {
1612  DestroyMe();
1613  SetFrame(frame);
1614  }
1615 
1616  private:
1618  error_ = nullptr;
1619  frames_ = nullptr;
1620  }
1621 
1623  DestroyMe();
1624  }
1625 
1626  void SetFrame(rs2_frame* frame) {
1627  if (!frame || (!GetNativeResult<int>(rs2_is_frame_extendable_to, &error_,
1628  frame, RS2_EXTENSION_COMPOSITE_FRAME, &error_))) return;
1629 
1630  frames_ = frame;
1631  frame_count_ = GetNativeResult<int>(rs2_embedded_frames_count, &error_,
1632  frame, &error_);
1633  }
1634 
1635  void DestroyMe() {
1636  if (error_) rs2_free_error(error_);
1637  error_ = nullptr;
1638  if (frames_) rs2_release_frame(frames_);
1639  frames_ = nullptr;
1640  }
1641 
1642  static NAN_METHOD(Destroy) {
1643  auto me = Nan::ObjectWrap::Unwrap<RSFrameSet>(info.Holder());
1644  if (me) {
1645  me->DestroyMe();
1646  }
1647  info.GetReturnValue().Set(Nan::Undefined());
1648  }
1649 
1650  static void New(const Nan::FunctionCallbackInfo<v8::Value>& info) {
1651  if (info.IsConstructCall()) {
1652  RSFrameSet* obj = new RSFrameSet();
1653  obj->Wrap(info.This());
1654  info.GetReturnValue().Set(info.This());
1655  }
1656  }
1657 
1658  static NAN_METHOD(GetSize) {
1659  auto me = Nan::ObjectWrap::Unwrap<RSFrameSet>(info.Holder());
1660  if (me && me->frames_) {
1661  info.GetReturnValue().Set(Nan::New(me->frame_count_));
1662  return;
1663  }
1664  info.GetReturnValue().Set(Nan::New(0));
1665  }
1666 
1667  static NAN_METHOD(GetFrame) {
1668  info.GetReturnValue().Set(Nan::Undefined());
1669  auto me = Nan::ObjectWrap::Unwrap<RSFrameSet>(info.Holder());
1670  if (!me || !me->frames_) return;
1671 
1672  rs2_stream stream = static_cast<rs2_stream>(Nan::To<int64_t>(info[0]).FromJust());
1673  auto stream_index = Nan::To<int64_t>(info[1]).FromJust();
1674  // if RS2_STREAM_ANY is used, we return the first frame.
1675  if (stream == RS2_STREAM_ANY && me->frame_count_) {
1676  rs2_frame* frame = GetNativeResult<rs2_frame*>(rs2_extract_frame,
1677  &me->error_, me->frames_, 0, &me->error_);
1678  if (!frame) return;
1679 
1680  info.GetReturnValue().Set(RSFrame::NewInstance(frame));
1681  return;
1682  }
1683 
1684  for (uint32_t i=0; i < me->frame_count_; i++) {
1685  rs2_frame* frame = GetNativeResult<rs2_frame*>(rs2_extract_frame,
1686  &me->error_, me->frames_, i, &me->error_);
1687  if (!frame) continue;
1688 
1689  const rs2_stream_profile* profile =
1690  GetNativeResult<const rs2_stream_profile*>(
1691  rs2_get_frame_stream_profile, &me->error_, frame, &me->error_);
1692  if (profile) {
1693  StreamProfileExtrator extrator(profile);
1694  if (extrator.stream_ == stream && (!stream_index ||
1695  (stream_index && stream_index == extrator.index_))) {
1696  info.GetReturnValue().Set(RSFrame::NewInstance(frame));
1697  return;
1698  }
1699  }
1700  rs2_release_frame(frame);
1701  }
1702  }
1703 
1704  static NAN_METHOD(ReplaceFrame) {
1705  info.GetReturnValue().Set(Nan::False());
1706  auto me = Nan::ObjectWrap::Unwrap<RSFrameSet>(info.Holder());
1707  rs2_stream stream = static_cast<rs2_stream>(Nan::To<int64_t>(info[0]).FromJust());
1708  auto stream_index = Nan::To<int64_t>(info[1]).FromJust();
1709  auto target_frame = Nan::ObjectWrap::Unwrap<RSFrame>(Nan::To<v8::Object>(info[2]).ToLocalChecked());
1710 
1711  if (!me || !me->frames_) return;
1712 
1713  for (uint32_t i = 0; i < me->frame_count_; i++) {
1714  rs2_frame* frame = GetNativeResult<rs2_frame*>(rs2_extract_frame,
1715  &me->error_, me->frames_, i, &me->error_);
1716  if (!frame) continue;
1717 
1718  const rs2_stream_profile* profile =
1719  GetNativeResult<const rs2_stream_profile*>(
1720  rs2_get_frame_stream_profile, &me->error_, frame, &me->error_);
1721  if (profile) {
1722  StreamProfileExtrator extrator(profile);
1723  if (extrator.stream_ == stream && (!stream_index ||
1724  (stream_index && stream_index == extrator.index_))) {
1725  target_frame->Replace(frame);
1726  info.GetReturnValue().Set(Nan::True());
1727  return;
1728  }
1729  }
1730  rs2_release_frame(frame);
1731  }
1732  }
1733 
1734  static NAN_METHOD(IndexToStream) {
1735  info.GetReturnValue().Set(Nan::Undefined());
1736  auto me = Nan::ObjectWrap::Unwrap<RSFrameSet>(info.Holder());
1737  if (!me || !me->frames_) return;
1738 
1739  int32_t index = Nan::To<int32_t>(info[0]).FromJust();
1740  rs2_frame* frame = GetNativeResult<rs2_frame*>(rs2_extract_frame,
1741  &me->error_, me->frames_, index, &me->error_);
1742  if (!frame) return;
1743 
1744  const rs2_stream_profile* profile =
1745  GetNativeResult<const rs2_stream_profile*>(rs2_get_frame_stream_profile,
1746  &me->error_, frame, &me->error_);
1747  if (!profile) {
1748  rs2_release_frame(frame);
1749  return;
1750  }
1751 
1754  int32_t fps = 0;
1755  int32_t idx = 0;
1756  int32_t unique_id = 0;
1757  CallNativeFunc(rs2_get_stream_profile_data, &me->error_, profile, &stream,
1758  &format, &idx, &unique_id, &fps, &me->error_);
1759  rs2_release_frame(frame);
1760  if (me->error_) return;
1761 
1762  info.GetReturnValue().Set(Nan::New(stream));
1763  }
1764 
1765  static NAN_METHOD(IndexToStreamIndex) {
1766  auto me = Nan::ObjectWrap::Unwrap<RSFrameSet>(info.Holder());
1767  info.GetReturnValue().Set(Nan::Undefined());
1768  if (!me || !me->frames_) return;
1769 
1770  int32_t index = Nan::To<int32_t>(info[0]).FromJust();
1771  rs2_frame* frame = GetNativeResult<rs2_frame*>(rs2_extract_frame,
1772  &me->error_, me->frames_, index, &me->error_);
1773  if (!frame) return;
1774 
1775  const rs2_stream_profile* profile =
1776  GetNativeResult<const rs2_stream_profile*>(rs2_get_frame_stream_profile,
1777  &me->error_, frame, &me->error_);
1778  if (!profile) {
1779  rs2_release_frame(frame);
1780  return;
1781  }
1784  int32_t fps = 0;
1785  int32_t idx = 0;
1786  int32_t unique_id = 0;
1787  CallNativeFunc(rs2_get_stream_profile_data, &me->error_, profile, &stream,
1788  &format, &idx, &unique_id, &fps, &me->error_);
1789  rs2_release_frame(frame);
1790  if (me->error_) return;
1791 
1792  info.GetReturnValue().Set(Nan::New(idx));
1793  }
1794 
1795  private:
1796  static Nan::Persistent<v8::Function> constructor_;
1800 };
1801 
1802 Nan::Persistent<v8::Function> RSFrameSet::constructor_;
1803 
1807 //
1808 // .d8888b. //
1809 // d88P Y88b //
1810 // Y88b. //
1811 // "Y888b. 888 888 88888b. .d8888b .d88b. 888d888 //
1812 // "Y88b. 888 888 888 "88b d88P" d8P Y8b 888P" //
1813 // "888 888 888 888 888 888 88888888 888 //
1814 // Y88b d88P Y88b 888 888 888 Y88b. Y8b. 888 //
1815 // "Y8888P" "Y88888 888 888 "Y8888P "Y8888 888 //
1816 // 888 //
1817 // Y8b d88P //
1818 // "Y88P" //
1819 //
1823 
1824 class RSSyncer : public Nan::ObjectWrap {
1825  public:
1826  static void Init(v8::Local<v8::Object> exports) {
1827  v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
1828  tpl->SetClassName(Nan::New("RSSyncer").ToLocalChecked());
1829  tpl->InstanceTemplate()->SetInternalFieldCount(1);
1830 
1831  Nan::SetPrototypeMethod(tpl, "destroy", Destroy);
1832  Nan::SetPrototypeMethod(tpl, "waitForFrames", WaitForFrames);
1833  Nan::SetPrototypeMethod(tpl, "pollForFrames", PollForFrames);
1834 
1835  v8::Local<v8::Context> context = exports->CreationContext();
1836  constructor_.Reset(tpl->GetFunction(context).ToLocalChecked());
1837  exports->Set(context, Nan::New("RSSyncer").ToLocalChecked(),
1838  tpl->GetFunction(context).ToLocalChecked());
1839  }
1840 
1841  static v8::Local<v8::Object> NewInstance() {
1842  Nan::EscapableHandleScope scope;
1843 
1844  v8::Local<v8::Function> cons = Nan::New<v8::Function>(constructor_);
1845  v8::Local<v8::Context> context = Nan::GetCurrentContext();
1846 
1847  v8::Local<v8::Object> instance =
1848  cons->NewInstance(context, 0, nullptr).ToLocalChecked();
1849 
1850  return scope.Escape(instance);
1851  }
1852 
1853  private:
1854  RSSyncer() : syncer_(nullptr), frame_queue_(nullptr), error_(nullptr) {}
1855 
1857  DestroyMe();
1858  }
1859 
1860  void DestroyMe() {
1861  if (error_) rs2_free_error(error_);
1862  error_ = nullptr;
1863  if (syncer_) rs2_delete_processing_block(syncer_);
1864  syncer_ = nullptr;
1865  if (frame_queue_) rs2_delete_frame_queue(frame_queue_);
1866  frame_queue_ = nullptr;
1867  }
1868 
1869  static void New(const Nan::FunctionCallbackInfo<v8::Value>& info) {
1870  if (info.IsConstructCall()) {
1871  RSSyncer* obj = new RSSyncer();
1872  obj->syncer_ = GetNativeResult<rs2_processing_block*>(
1874  obj->frame_queue_ = GetNativeResult<rs2_frame_queue*>(
1875  rs2_create_frame_queue, &obj->error_, 1, &obj->error_);
1877  CallNativeFunc(rs2_start_processing, &obj->error_, obj->syncer_, callback,
1878  &obj->error_);
1879  obj->Wrap(info.This());
1880  info.GetReturnValue().Set(info.This());
1881  }
1882  }
1883 
1884  static NAN_METHOD(WaitForFrames) {
1885  info.GetReturnValue().Set(Nan::False());
1886  auto me = Nan::ObjectWrap::Unwrap<RSSyncer>(info.Holder());
1887  auto frameset = Nan::ObjectWrap::Unwrap<RSFrameSet>(Nan::To<v8::Object>(info[0]).ToLocalChecked());
1888  auto timeout = Nan::To<int64_t>(info[1]).FromJust();
1889  if (!me || !frameset) return;
1890 
1891  rs2_frame* frames = GetNativeResult<rs2_frame*>(rs2_wait_for_frame,
1892  &me->error_, me->frame_queue_, timeout, &me->error_);
1893  if (!frames) return;
1894 
1895  frameset->Replace(frames);
1896  info.GetReturnValue().Set(Nan::True());
1897  }
1898 
1899  static NAN_METHOD(Destroy) {
1900  auto me = Nan::ObjectWrap::Unwrap<RSSyncer>(info.Holder());
1901  if (me) {
1902  me->DestroyMe();
1903  }
1904  info.GetReturnValue().Set(Nan::Undefined());
1905  }
1906 
1907  static NAN_METHOD(PollForFrames) {
1908  info.GetReturnValue().Set(Nan::False());
1909  auto me = Nan::ObjectWrap::Unwrap<RSSyncer>(info.Holder());
1910  auto frameset = Nan::ObjectWrap::Unwrap<RSFrameSet>(Nan::To<v8::Object>(info[0]).ToLocalChecked());
1911  if (!me || !frameset) return;
1912 
1913  rs2_frame* frame_ref = nullptr;
1914  auto res = GetNativeResult<int>(rs2_poll_for_frame, &me->error_,
1915  me->frame_queue_, &frame_ref, &me->error_);
1916  if (!res) return;
1917 
1918  frameset->Replace(frame_ref);
1919  info.GetReturnValue().Set(Nan::True());
1920  }
1921 
1922  private:
1923  static Nan::Persistent<v8::Function> constructor_;
1927  friend class RSSensor;
1928 };
1929 
1930 Nan::Persistent<v8::Function> RSSyncer::constructor_;
1931 
1932 class Options {
1933  public:
1934  Options() : error_(nullptr) {}
1935 
1936  virtual ~Options() {
1937  if (error_) rs2_free_error(error_);
1938  }
1939 
1940  virtual rs2_options* GetOptionsPointer() = 0;
1941 
1943  const Nan::FunctionCallbackInfo<v8::Value>& info) {
1944  int32_t option = Nan::To<int32_t>(info[0]).FromJust();
1945  auto on = GetNativeResult<int>(rs2_supports_option, &error_,
1946  GetOptionsPointer(), static_cast<rs2_option>(option), &error_);
1947  info.GetReturnValue().Set(Nan::New(on ? true : false));
1948  return;
1949  }
1950 
1951  void GetOptionInternal(const Nan::FunctionCallbackInfo<v8::Value>& info) {
1952  int32_t option = Nan::To<int32_t>(info[0]).FromJust();
1953  auto value = GetNativeResult<float>(rs2_get_option, &error_,
1954  GetOptionsPointer(), static_cast<rs2_option>(option), &error_);
1955  info.GetReturnValue().Set(Nan::New(value));
1956  }
1957 
1959  const Nan::FunctionCallbackInfo<v8::Value>& info) {
1960  int32_t option = Nan::To<int32_t>(info[0]).FromJust();
1961  auto desc = GetNativeResult<const char*>(rs2_get_option_description,
1962  &error_, GetOptionsPointer(), static_cast<rs2_option>(option), &error_);
1963  if (desc)
1964  info.GetReturnValue().Set(Nan::New(desc).ToLocalChecked());
1965  else
1966  info.GetReturnValue().Set(Nan::Undefined());
1967  }
1968 
1970  const Nan::FunctionCallbackInfo<v8::Value>& info) {
1971  int32_t option = Nan::To<int32_t>(info[0]).FromJust();
1972  auto val = Nan::To<double>(info[1]).FromJust();
1973  auto desc = GetNativeResult<const char*>(rs2_get_option_value_description,
1974  &error_, GetOptionsPointer(), static_cast<rs2_option>(option),
1975  val, &error_);
1976  if (desc)
1977  info.GetReturnValue().Set(Nan::New(desc).ToLocalChecked());
1978  else
1979  info.GetReturnValue().Set(Nan::Undefined());
1980  }
1981 
1982  void SetOptionInternal(const Nan::FunctionCallbackInfo<v8::Value>& info) {
1983  int32_t option = Nan::To<int32_t>(info[0]).FromJust();
1984  auto val = Nan::To<double>(info[1]).FromJust();
1985  CallNativeFunc(rs2_set_option, &error_, GetOptionsPointer(),
1986  static_cast<rs2_option>(option), val, &error_);
1987  info.GetReturnValue().Set(Nan::Undefined());
1988  }
1989 
1991  const Nan::FunctionCallbackInfo<v8::Value>& info) {
1992  int32_t option = Nan::To<int32_t>(info[0]).FromJust();
1993  float min = 0;
1994  float max = 0;
1995  float step = 0;
1996  float def = 0;
1997  CallNativeFunc(rs2_get_option_range, &error_, GetOptionsPointer(),
1998  static_cast<rs2_option>(option), &min, &max, &step, &def, &error_);
1999  info.GetReturnValue().Set(RSOptionRange(min, max, step, def).GetObject());
2000  }
2001 
2003  const Nan::FunctionCallbackInfo<v8::Value>& info) {
2004  int32_t option = Nan::To<int32_t>(info[0]).FromJust();
2005  auto val = GetNativeResult<int>(rs2_is_option_read_only, &error_,
2006  GetOptionsPointer(), static_cast<rs2_option>(option), &error_);
2007  info.GetReturnValue().Set(Nan::New((val) ? true : false));
2008  }
2009 
2010  private:
2012 };
2013 
2014 class RSSensor : public Nan::ObjectWrap, Options {
2015  public:
2016  static void Init(v8::Local<v8::Object> exports) {
2017  v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
2018  tpl->SetClassName(Nan::New("RSSensor").ToLocalChecked());
2019  tpl->InstanceTemplate()->SetInternalFieldCount(1);
2020 
2021  Nan::SetPrototypeMethod(tpl, "destroy", Destroy);
2022  Nan::SetPrototypeMethod(tpl, "openStream", OpenStream);
2023  Nan::SetPrototypeMethod(tpl, "openMultipleStream", OpenMultipleStream);
2024  Nan::SetPrototypeMethod(tpl, "getCameraInfo", GetCameraInfo);
2025  Nan::SetPrototypeMethod(tpl, "startWithSyncer", StartWithSyncer);
2026  Nan::SetPrototypeMethod(tpl, "startWithCallback", StartWithCallback);
2027  Nan::SetPrototypeMethod(tpl, "supportsOption", SupportsOption);
2028  Nan::SetPrototypeMethod(tpl, "getOption", GetOption);
2029  Nan::SetPrototypeMethod(tpl, "setOption", SetOption);
2030  Nan::SetPrototypeMethod(tpl, "getOptionRange", GetOptionRange);
2031  Nan::SetPrototypeMethod(tpl, "isOptionReadonly", IsOptionReadonly);
2032  Nan::SetPrototypeMethod(tpl, "getOptionDescription", GetOptionDescription);
2033  Nan::SetPrototypeMethod(tpl, "getOptionValueDescription",
2034  GetOptionValueDescription);
2035  Nan::SetPrototypeMethod(tpl, "stop", Stop);
2036  Nan::SetPrototypeMethod(tpl, "supportsCameraInfo", SupportsCameraInfo);
2037  Nan::SetPrototypeMethod(tpl, "getStreamProfiles", GetStreamProfiles);
2038  Nan::SetPrototypeMethod(tpl, "close", Close);
2039  Nan::SetPrototypeMethod(tpl, "setNotificationCallback",
2040  SetNotificationCallback);
2041  Nan::SetPrototypeMethod(tpl, "setRegionOfInterest", SetRegionOfInterest);
2042  Nan::SetPrototypeMethod(tpl, "getRegionOfInterest", GetRegionOfInterest);
2043  Nan::SetPrototypeMethod(tpl, "getDepthScale", GetDepthScale);
2044  Nan::SetPrototypeMethod(tpl, "isROISensor", IsROISensor);
2045  Nan::SetPrototypeMethod(tpl, "is", Is);
2046 
2047  v8::Local<v8::Context> context = exports->CreationContext();
2048  constructor_.Reset(tpl->GetFunction(context).ToLocalChecked());
2049  exports->Set(context, Nan::New("RSSensor").ToLocalChecked(),
2050  tpl->GetFunction(context).ToLocalChecked());
2051  }
2052 
2053  static v8::Local<v8::Object> NewInstance(rs2_sensor* sensor) {
2054  Nan::EscapableHandleScope scope;
2055 
2056  v8::Local<v8::Function> cons = Nan::New<v8::Function>(constructor_);
2057  v8::Local<v8::Context> context = Nan::GetCurrentContext();
2058 
2059  v8::Local<v8::Object> instance =
2060  cons->NewInstance(context, 0, nullptr).ToLocalChecked();
2061 
2062  auto me = Nan::ObjectWrap::Unwrap<RSSensor>(instance);
2063  me->sensor_ = sensor;
2064  return scope.Escape(instance);
2065  }
2066 
2068  // TODO(shaoting) find better way to avoid the reinterpret_cast which was
2069  // caused the inheritance relation was hidden
2070  return reinterpret_cast<rs2_options*>(sensor_);
2071  }
2072 
2073  void ReplaceFrame(rs2_frame* raw_frame) {
2074  // clear old frame first.
2075  frame_->Replace(nullptr);
2076  video_frame_->Replace(nullptr);
2077  depth_frame_->Replace(nullptr);
2078  disparity_frame_->Replace(nullptr);
2079  motion_frame_->Replace(nullptr);
2080  pose_frame_->Replace(nullptr);
2081 
2082  if (GetNativeResult<int>(rs2_is_frame_extendable_to, &error_,
2083  raw_frame, RS2_EXTENSION_DISPARITY_FRAME, &error_)) {
2084  disparity_frame_->Replace(raw_frame);
2085  } else if (GetNativeResult<int>(rs2_is_frame_extendable_to, &error_,
2086  raw_frame, RS2_EXTENSION_DEPTH_FRAME, &error_)) {
2087  depth_frame_->Replace(raw_frame);
2088  } else if (GetNativeResult<int>(rs2_is_frame_extendable_to, &error_,
2089  raw_frame, RS2_EXTENSION_VIDEO_FRAME, &error_)) {
2090  video_frame_->Replace(raw_frame);
2091  } else if (GetNativeResult<int>(rs2_is_frame_extendable_to, &error_,
2092  raw_frame, RS2_EXTENSION_MOTION_FRAME, &error_)) {
2093  motion_frame_->Replace(raw_frame);
2094  } else if (GetNativeResult<int>(rs2_is_frame_extendable_to, &error_,
2095  raw_frame, RS2_EXTENSION_POSE_FRAME, &error_)) {
2096  pose_frame_->Replace(raw_frame);
2097  } else {
2098  frame_->Replace(raw_frame);
2099  }
2100  }
2101 
2102  private:
2103  RSSensor() : sensor_(nullptr), error_(nullptr), profile_list_(nullptr),
2104  frame_(nullptr), video_frame_(nullptr), depth_frame_(nullptr),
2105  disparity_frame_(nullptr), motion_frame_(nullptr), pose_frame_(nullptr) {}
2106 
2108  DestroyMe();
2109  }
2110 
2111  void RegisterNotificationCallbackMethod();
2112 
2113  void DestroyMe() {
2114  if (error_) rs2_free_error(error_);
2115  error_ = nullptr;
2116  if (sensor_) rs2_delete_sensor(sensor_);
2117  sensor_ = nullptr;
2118  if (profile_list_) rs2_delete_stream_profiles_list(profile_list_);
2119  profile_list_ = nullptr;
2120  }
2121 
2122  static void New(const Nan::FunctionCallbackInfo<v8::Value>& info) {
2123  if (info.IsConstructCall()) {
2124  RSSensor* obj = new RSSensor();
2125  obj->Wrap(info.This());
2126  info.GetReturnValue().Set(info.This());
2127  }
2128  }
2129 
2130  static NAN_METHOD(SupportsOption) {
2131  auto me = Nan::ObjectWrap::Unwrap<RSSensor>(info.Holder());
2132  if (me) return me->SupportsOptionInternal(info);
2133 
2134  info.GetReturnValue().Set(Nan::False());
2135  }
2136 
2137  static NAN_METHOD(GetOption) {
2138  auto me = Nan::ObjectWrap::Unwrap<RSSensor>(info.Holder());
2139  if (me) return me->GetOptionInternal(info);
2140 
2141  info.GetReturnValue().Set(Nan::Undefined());
2142  }
2143 
2144  static NAN_METHOD(GetOptionDescription) {
2145  auto me = Nan::ObjectWrap::Unwrap<RSSensor>(info.Holder());
2146  if (me) return me->GetOptionDescriptionInternal(info);
2147 
2148  info.GetReturnValue().Set(Nan::Undefined());
2149  }
2150 
2151  static NAN_METHOD(GetOptionValueDescription) {
2152  auto me = Nan::ObjectWrap::Unwrap<RSSensor>(info.Holder());
2153  if (me) return me->GetOptionValueDescriptionInternal(info);
2154 
2155  info.GetReturnValue().Set(Nan::Undefined());
2156  }
2157 
2158  static NAN_METHOD(SetOption) {
2159  auto me = Nan::ObjectWrap::Unwrap<RSSensor>(info.Holder());
2160  if (me) return me->SetOptionInternal(info);
2161 
2162  info.GetReturnValue().Set(Nan::Undefined());
2163  }
2164 
2165  static NAN_METHOD(GetOptionRange) {
2166  auto me = Nan::ObjectWrap::Unwrap<RSSensor>(info.Holder());
2167  if (me) return me->GetOptionRangeInternal(info);
2168 
2169  info.GetReturnValue().Set(Nan::Undefined());
2170  }
2171 
2172  static NAN_METHOD(IsOptionReadonly) {
2173  auto me = Nan::ObjectWrap::Unwrap<RSSensor>(info.Holder());
2174  if (me) return me->IsOptionReadonlyInternal(info);
2175 
2176  info.GetReturnValue().Set(Nan::False());
2177  }
2178 
2179  static NAN_METHOD(GetCameraInfo) {
2180  info.GetReturnValue().Set(Nan::Undefined());
2181  int32_t camera_info = Nan::To<int32_t>(info[0]).FromJust();
2182  auto me = Nan::ObjectWrap::Unwrap<RSSensor>(info.Holder());
2183  if (!me) return;
2184 
2185  auto value = GetNativeResult<const char*>(rs2_get_sensor_info,
2186  &me->error_, me->sensor_, static_cast<rs2_camera_info>(camera_info),
2187  &me->error_);
2188  if (me->error_) return;
2189 
2190  info.GetReturnValue().Set(Nan::New(value).ToLocalChecked());
2191  }
2192 
2193  static NAN_METHOD(StartWithSyncer) {
2194  info.GetReturnValue().Set(Nan::Undefined());
2195  auto syncer = Nan::ObjectWrap::Unwrap<RSSyncer>(Nan::To<v8::Object>(info[0]).ToLocalChecked());
2196  auto me = Nan::ObjectWrap::Unwrap<RSSensor>(info.Holder());
2197  if (!me || !syncer) return;
2198 
2199  CallNativeFunc(rs2_start_cpp, &me->error_, me->sensor_,
2200  new FrameCallbackForProcessingBlock(syncer->syncer_), &me->error_);
2201  }
2202 
2203  static NAN_METHOD(StartWithCallback) {
2204  auto frame = Nan::ObjectWrap::Unwrap<RSFrame>(Nan::To<v8::Object>(info[1]).ToLocalChecked());
2205  auto depth_frame = Nan::ObjectWrap::Unwrap<RSFrame>(Nan::To<v8::Object>(info[2]).ToLocalChecked());
2206  auto video_frame = Nan::ObjectWrap::Unwrap<RSFrame>(Nan::To<v8::Object>(info[3]).ToLocalChecked());
2207  auto disparity_frame = Nan::ObjectWrap::Unwrap<RSFrame>(Nan::To<v8::Object>(info[4]).ToLocalChecked());
2208  auto motion_frame = Nan::ObjectWrap::Unwrap<RSFrame>(Nan::To<v8::Object>(info[5]).ToLocalChecked());
2209  auto pose_frame = Nan::ObjectWrap::Unwrap<RSFrame>(Nan::To<v8::Object>(info[6]).ToLocalChecked());
2210  auto me = Nan::ObjectWrap::Unwrap<RSSensor>(info.Holder());
2211  if (me && frame && depth_frame && video_frame && disparity_frame &&
2212  motion_frame && pose_frame) {
2213  me->frame_ = frame;
2214  me->depth_frame_ = depth_frame;
2215  me->video_frame_ = video_frame;
2216  me->disparity_frame_ = disparity_frame;
2217  me->motion_frame_ = motion_frame;
2218  me->pose_frame_ = pose_frame;
2219  Nan::Utf8String str(info[0]);
2220  me->frame_callback_name_ = std::string(*str);
2221  CallNativeFunc(rs2_start_cpp, &me->error_, me->sensor_,
2222  new FrameCallbackForProc(me), &me->error_);
2223  }
2224  info.GetReturnValue().Set(Nan::Undefined());
2225  }
2226 
2227  static NAN_METHOD(Destroy) {
2228  auto me = Nan::ObjectWrap::Unwrap<RSSensor>(info.Holder());
2229  if (me) {
2230  me->DestroyMe();
2231  }
2232  info.GetReturnValue().Set(Nan::Undefined());
2233  }
2234 
2235  static NAN_METHOD(OpenStream) {
2236  info.GetReturnValue().Set(Nan::Undefined());
2237  auto me = Nan::ObjectWrap::Unwrap<RSSensor>(info.Holder());
2238  auto profile =
2239  Nan::ObjectWrap::Unwrap<RSStreamProfile>(Nan::To<v8::Object>(info[0]).ToLocalChecked());
2240  if (!me || !profile) return;
2241 
2242  CallNativeFunc(rs2_open, &me->error_, me->sensor_, profile->profile_,
2243  &me->error_);
2244  }
2245 
2246  static NAN_METHOD(OpenMultipleStream) {
2247  info.GetReturnValue().Set(Nan::Undefined());
2248  auto me = Nan::ObjectWrap::Unwrap<RSSensor>(info.Holder());
2249  if (!me) return;
2250 
2251  auto array = v8::Local<v8::Array>::Cast(info[0]);
2252  uint32_t len = array->Length();
2253  std::vector<const rs2_stream_profile*> profs;
2254  v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
2255  for (uint32_t i=0; i < len; i++) {
2256  auto profile =
2257  Nan::ObjectWrap::Unwrap<RSStreamProfile>(Nan::To<v8::Object>(array->Get(context, i).ToLocalChecked()).ToLocalChecked());
2258  profs.push_back(profile->profile_);
2259  }
2260  CallNativeFunc(rs2_open_multiple, &me->error_, me->sensor_, profs.data(),
2261  len, &me->error_);
2262  }
2263 
2264  static NAN_METHOD(Stop) {
2265  auto me = Nan::ObjectWrap::Unwrap<RSSensor>(info.Holder());
2266  if (!me) return;
2267 
2268  CallNativeFunc(rs2_stop, &me->error_, me->sensor_, &me->error_);
2269  }
2270 
2271  static NAN_METHOD(GetStreamProfiles) {
2272  info.GetReturnValue().Set(Nan::Undefined());
2273  auto me = Nan::ObjectWrap::Unwrap<RSSensor>(info.Holder());
2274  if (!me) return;
2275 
2276  rs2_stream_profile_list* list = me->profile_list_;
2277  if (!list) {
2278  list = GetNativeResult<rs2_stream_profile_list*>(rs2_get_stream_profiles,
2279  &me->error_, me->sensor_, &me->error_);
2280  me->profile_list_ = list;
2281  }
2282  if (!list) return;
2283 
2284  int32_t size = GetNativeResult<int>(rs2_get_stream_profiles_count,
2285  &me->error_, list, &me->error_);
2286 
2287  v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
2288  v8::Local<v8::Array> array = Nan::New<v8::Array>(size);
2289  for (int32_t i = 0; i < size; i++) {
2291  rs2_get_stream_profile(list, i, &me->error_));
2292  array->Set(context, i, RSStreamProfile::NewInstance(profile));
2293  }
2294  info.GetReturnValue().Set(array);
2295  }
2296 
2297  static NAN_METHOD(SupportsCameraInfo) {
2298  info.GetReturnValue().Set(Nan::False());
2299  int32_t camera_info = Nan::To<int32_t>(info[0]).FromJust();
2300  auto me = Nan::ObjectWrap::Unwrap<RSSensor>(info.Holder());
2301  if (!me) return;
2302 
2303  int32_t on = GetNativeResult<int>(rs2_supports_sensor_info, &me->error_,
2304  me->sensor_, (rs2_camera_info)camera_info, &me->error_);
2305  info.GetReturnValue().Set(Nan::New(on ? true : false));
2306  }
2307 
2308  static NAN_METHOD(Close) {
2309  auto me = Nan::ObjectWrap::Unwrap<RSSensor>(info.Holder());
2310  if (!me) return;
2311 
2312  CallNativeFunc(rs2_close, &me->error_, me->sensor_, &me->error_);
2313  }
2314 
2315  static NAN_METHOD(SetNotificationCallback) {
2316  auto me = Nan::ObjectWrap::Unwrap<RSSensor>(info.Holder());
2317  if (!me) return;
2318 
2319  Nan::Utf8String value(Nan::To<v8::String>(info[0]).ToLocalChecked());
2320  me->notification_callback_name_ = std::string(*value);
2321  me->RegisterNotificationCallbackMethod();
2322  }
2323 
2324  static NAN_METHOD(SetRegionOfInterest) {
2325  info.GetReturnValue().Set(Nan::Undefined());
2326  int32_t minx = Nan::To<int32_t>(info[0]).FromJust();
2327  int32_t miny = Nan::To<int32_t>(info[1]).FromJust();
2328  int32_t maxx = Nan::To<int32_t>(info[2]).FromJust();
2329  int32_t maxy = Nan::To<int32_t>(info[3]).FromJust();
2330  auto me = Nan::ObjectWrap::Unwrap<RSSensor>(info.Holder());
2331  if (!me) return;
2332 
2333  CallNativeFunc(rs2_set_region_of_interest, &me->error_, me->sensor_, minx,
2334  miny, maxx, maxy, &me->error_);
2335  }
2336 
2337  static NAN_METHOD(GetRegionOfInterest) {
2338  info.GetReturnValue().Set(Nan::Undefined());
2339  int32_t minx = 0;
2340  int32_t miny = 0;
2341  int32_t maxx = 0;
2342  int32_t maxy = 0;
2343  auto me = Nan::ObjectWrap::Unwrap<RSSensor>(info.Holder());
2344  if (!me) return;
2345 
2346  CallNativeFunc(rs2_get_region_of_interest, &me->error_, me->sensor_, &minx,
2347  &miny, &maxx, &maxy, &me->error_);
2348  if (me->error_) return;
2349  info.GetReturnValue().Set(
2350  RSRegionOfInterest(minx, miny, maxx, maxy).GetObject());
2351  }
2352 
2354  info.GetReturnValue().Set(Nan::Undefined());
2355  auto me = Nan::ObjectWrap::Unwrap<RSSensor>(info.Holder());
2356  if (!me) return;
2357 
2358  auto scale = GetNativeResult<float>(rs2_get_depth_scale, &me->error_,
2359  me->sensor_, &me->error_);
2360  if (me->error_) return;
2361 
2362  info.GetReturnValue().Set(Nan::New(scale));
2363  }
2364 
2365  static NAN_METHOD(Is) {
2366  info.GetReturnValue().Set(Nan::Undefined());
2367  int32_t stype = Nan::To<int32_t>(info[0]).FromJust();
2368 
2369  auto me = Nan::ObjectWrap::Unwrap<RSSensor>(info.Holder());
2370  if (!me) return;
2371 
2372  bool is_ok = GetNativeResult<int>(rs2_is_sensor_extendable_to,
2373  &me->error_, me->sensor_, static_cast<rs2_extension>(stype), &me->error_);
2374  if (me->error_) return;
2375 
2376  info.GetReturnValue().Set(Nan::New(is_ok));
2377  }
2378 
2379  static NAN_METHOD(IsROISensor) {
2380  info.GetReturnValue().Set(Nan::Undefined());
2381  auto me = Nan::ObjectWrap::Unwrap<RSSensor>(info.Holder());
2382  if (!me) return;
2383 
2384  bool is_roi = GetNativeResult<int>(rs2_is_sensor_extendable_to, &me->error_,
2385  me->sensor_, RS2_EXTENSION_ROI, &me->error_);
2386  if (me->error_) return;
2387 
2388  info.GetReturnValue().Set(Nan::New(is_roi));
2389  }
2390 
2391  private:
2392  static Nan::Persistent<v8::Function> constructor_;
2404  friend class RSContext;
2406  friend class FrameCallbackInfo;
2408 };
2409 
2410 Nan::Persistent<v8::Function> RSSensor::constructor_;
2411 
2414  new NotificationCallback(this), &error_);
2415 }
2416 
2420 //
2421 // 8888888b. .d8888b. 8888888b. d8b //
2422 // 888 Y88b d88P Y88b 888 "Y88b Y8P //
2423 // 888 888 Y88b. 888 888 //
2424 // 888 d88P "Y888b. 888 888 .d88b. 888 888 888 .d8888b .d88b. //
2425 // 8888888P" "Y88b. 888 888 d8P Y8b 888 888 888 d88P" d8P Y8b //
2426 // 888 T88b "888 888 888 88888888 Y88 88P 888 888 88888888 //
2427 // 888 T88b Y88b d88P 888 .d88P Y8b. Y8bd8P 888 Y88b. Y8b. //
2428 // 888 T88b "Y8888P" 8888888P" "Y8888 Y88P 888 "Y8888P "Y8888 //
2429 //
2433 
2434 class RSDevice : public Nan::ObjectWrap {
2435  public:
2436  enum DeviceType {
2437  kNormalDevice = 0,
2440  };
2441  static void Init(v8::Local<v8::Object> exports) {
2442  v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
2443  tpl->SetClassName(Nan::New("RSDevice").ToLocalChecked());
2444  tpl->InstanceTemplate()->SetInternalFieldCount(1);
2445 
2446  Nan::SetPrototypeMethod(tpl, "destroy", Destroy);
2447  Nan::SetPrototypeMethod(tpl, "getCameraInfo", GetCameraInfo);
2448  Nan::SetPrototypeMethod(tpl, "supportsCameraInfo", SupportsCameraInfo);
2449  Nan::SetPrototypeMethod(tpl, "reset", Reset);
2450  Nan::SetPrototypeMethod(tpl, "querySensors", QuerySensors);
2451  Nan::SetPrototypeMethod(tpl, "triggerErrorForTest", TriggerErrorForTest);
2452  Nan::SetPrototypeMethod(tpl, "spawnRecorderDevice", SpawnRecorderDevice);
2453 
2454  // Methods for record or playback
2455  Nan::SetPrototypeMethod(tpl, "pauseRecord", PauseRecord);
2456  Nan::SetPrototypeMethod(tpl, "resumeRecord", ResumeRecord);
2457  Nan::SetPrototypeMethod(tpl, "getFileName", GetFileName);
2458  Nan::SetPrototypeMethod(tpl, "pausePlayback", PausePlayback);
2459  Nan::SetPrototypeMethod(tpl, "resumePlayback", ResumePlayback);
2460  Nan::SetPrototypeMethod(tpl, "stopPlayback", StopPlayback);
2461  Nan::SetPrototypeMethod(tpl, "getPosition", GetPosition);
2462  Nan::SetPrototypeMethod(tpl, "getDuration", GetDuration);
2463  Nan::SetPrototypeMethod(tpl, "seek", Seek);
2464  Nan::SetPrototypeMethod(tpl, "isRealTime", IsRealTime);
2465  Nan::SetPrototypeMethod(tpl, "setIsRealTime", SetIsRealTime);
2466  Nan::SetPrototypeMethod(tpl, "setPlaybackSpeed", SetPlaybackSpeed);
2467  Nan::SetPrototypeMethod(tpl, "getCurrentStatus", GetCurrentStatus);
2468  Nan::SetPrototypeMethod(tpl, "setStatusChangedCallbackMethodName",
2469  SetStatusChangedCallbackMethodName);
2470  Nan::SetPrototypeMethod(tpl, "isTm2", IsTm2);
2471  Nan::SetPrototypeMethod(tpl, "isPlayback", IsPlayback);
2472  Nan::SetPrototypeMethod(tpl, "isRecorder", IsRecorder);
2473 
2474  // methods of tm2 device
2475  Nan::SetPrototypeMethod(tpl, "enableLoopback", EnableLoopback);
2476  Nan::SetPrototypeMethod(tpl, "disableLoopback", DisableLoopback);
2477  Nan::SetPrototypeMethod(tpl, "isLoopbackEnabled", IsLoopbackEnabled);
2478 
2479  v8::Local<v8::Context> context = exports->CreationContext();
2480  constructor_.Reset(tpl->GetFunction(context).ToLocalChecked());
2481  exports->Set(context, Nan::New("RSDevice").ToLocalChecked(),
2482  tpl->GetFunction(context).ToLocalChecked());
2483  }
2484 
2485  static v8::Local<v8::Object> NewInstance(rs2_device* dev,
2486  DeviceType type = kNormalDevice) {
2487  Nan::EscapableHandleScope scope;
2488 
2489  v8::Local<v8::Function> cons = Nan::New<v8::Function>(constructor_);
2490  v8::Local<v8::Context> context = Nan::GetCurrentContext();
2491 
2492  v8::Local<v8::Object> instance =
2493  cons->NewInstance(context, 0, nullptr).ToLocalChecked();
2494 
2495  auto me = Nan::ObjectWrap::Unwrap<RSDevice>(instance);
2496  me->dev_ = dev;
2497  me->type_ = type;
2498 
2499  return scope.Escape(instance);
2500  }
2501 
2502  private:
2503  explicit RSDevice(DeviceType type = kNormalDevice) : dev_(nullptr),
2504  error_(nullptr), type_(type) {}
2505 
2507  DestroyMe();
2508  }
2509 
2510  void DestroyMe() {
2511  if (error_) rs2_free_error(error_);
2512  error_ = nullptr;
2513  if (dev_) rs2_delete_device(dev_);
2514  dev_ = nullptr;
2515  }
2516 
2517  static void New(const Nan::FunctionCallbackInfo<v8::Value>& info) {
2518  if (info.IsConstructCall()) {
2519  RSDevice* obj = new RSDevice();
2520  obj->Wrap(info.This());
2521  info.GetReturnValue().Set(info.This());
2522  }
2523  }
2524 
2525  static NAN_METHOD(GetCameraInfo) {
2526  info.GetReturnValue().Set(Nan::Undefined());
2527  int32_t camera_info = Nan::To<int32_t>(info[0]).FromJust();
2528  auto me = Nan::ObjectWrap::Unwrap<RSDevice>(info.Holder());
2529  if (!me) return;
2530 
2531  auto value = GetNativeResult<const char*>(rs2_get_device_info,
2532  &me->error_, me->dev_, static_cast<rs2_camera_info>(camera_info),
2533  &me->error_);
2534  if (me->error_) return;
2535 
2536  info.GetReturnValue().Set(Nan::New(value).ToLocalChecked());
2537  }
2538 
2539  static NAN_METHOD(Destroy) {
2540  auto me = Nan::ObjectWrap::Unwrap<RSDevice>(info.Holder());
2541  if (me) {
2542  me->DestroyMe();
2543  }
2544  info.GetReturnValue().Set(Nan::Undefined());
2545  }
2546 
2547 
2548  static NAN_METHOD(SupportsCameraInfo) {
2549  info.GetReturnValue().Set(Nan::False());
2550  int32_t camera_info = Nan::To<int32_t>(info[0]).FromJust();
2551  auto me = Nan::ObjectWrap::Unwrap<RSDevice>(info.Holder());
2552  if (!me) return;
2553 
2554  int32_t on = GetNativeResult<int>(rs2_supports_device_info, &me->error_,
2555  me->dev_, (rs2_camera_info)camera_info, &me->error_);
2556  if (me->error_) return;
2557  info.GetReturnValue().Set(Nan::New(on ? true : false));
2558  }
2559 
2560  static NAN_METHOD(Reset) {
2561  auto me = Nan::ObjectWrap::Unwrap<RSDevice>(info.Holder());
2562  if (!me) return;
2563 
2564  CallNativeFunc(rs2_hardware_reset, &me->error_, me->dev_, &me->error_);
2565  }
2566 
2567  static NAN_METHOD(QuerySensors) {
2568  info.GetReturnValue().Set(Nan::Undefined());
2569  auto me = Nan::ObjectWrap::Unwrap<RSDevice>(info.Holder());
2570  if (!me) return;
2571 
2572  std::shared_ptr<rs2_sensor_list> list(
2573  GetNativeResult<rs2_sensor_list*>(rs2_query_sensors, &me->error_,
2574  me->dev_, &me->error_), rs2_delete_sensor_list);
2575  if (!list) return;
2576 
2577  auto size = GetNativeResult<int>(rs2_get_sensors_count, &me->error_,
2578  list.get(), &me->error_);
2579  if (!size) return;
2580 
2581  v8::Local<v8::Array> array = Nan::New<v8::Array>();
2582  v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
2583  for (int32_t i = 0; i < size; i++) {
2584  rs2_sensor* sensor = GetNativeResult<rs2_sensor*>(rs2_create_sensor,
2585  &me->error_, list.get(), i, &me->error_);
2586  array->Set(context, i, RSSensor::NewInstance(sensor));
2587  }
2588  info.GetReturnValue().Set(array);
2589  }
2590 
2591  static NAN_METHOD(TriggerErrorForTest) {
2592  info.GetReturnValue().Set(Nan::Undefined());
2593  auto me = Nan::ObjectWrap::Unwrap<RSDevice>(info.Holder());
2594  if (!me) return;
2595 
2596  uint8_t raw_data[24] = {0};
2597  raw_data[0] = 0x14;
2598  raw_data[2] = 0xab;
2599  raw_data[3] = 0xcd;
2600  raw_data[4] = 0x4d;
2601  raw_data[8] = 4;
2602  CallNativeFunc(rs2_send_and_receive_raw_data, &me->error_, me->dev_,
2603  static_cast<void*>(raw_data), 24, &me->error_);
2604  }
2605 
2606  static NAN_METHOD(SpawnRecorderDevice) {
2607  auto me = Nan::ObjectWrap::Unwrap<RSDevice>(info.Holder());
2608  info.GetReturnValue().Set(Nan::Undefined());
2609  if (!me) return;
2610 
2611  Nan::Utf8String file(Nan::To<v8::String>(info[0]).ToLocalChecked());
2612  auto dev = GetNativeResult<rs2_device*>(rs2_create_record_device,
2613  &me->error_, me->dev_, *file, &me->error_);
2614  if (me->error_) return;
2615 
2616  auto obj = RSDevice::NewInstance(dev, kRecorderDevice);
2617  info.GetReturnValue().Set(obj);
2618  }
2619 
2620  static NAN_METHOD(PauseRecord) {
2621  info.GetReturnValue().Set(Nan::Undefined());
2622  auto me = Nan::ObjectWrap::Unwrap<RSDevice>(info.Holder());
2623  if (!me) return;
2624 
2625  CallNativeFunc(rs2_record_device_pause, &me->error_, me->dev_,
2626  &me->error_);
2627  }
2628 
2629  static NAN_METHOD(ResumeRecord) {
2630  info.GetReturnValue().Set(Nan::Undefined());
2631  auto me = Nan::ObjectWrap::Unwrap<RSDevice>(info.Holder());
2632  if (!me) return;
2633 
2634  CallNativeFunc(rs2_record_device_resume, &me->error_, me->dev_,
2635  &me->error_);
2636  }
2637 
2638  static NAN_METHOD(GetFileName) {
2639  auto me = Nan::ObjectWrap::Unwrap<RSDevice>(info.Holder());
2640  info.GetReturnValue().Set(Nan::Undefined());
2641  if (!me) return;
2642 
2643  const char* file = nullptr;
2644  if (me->IsPlaybackInternal()) {
2645  file = GetNativeResult<const char*>(rs2_playback_device_get_file_path,
2646  &me->error_, me->dev_, &me->error_);
2647  } else if (me->IsRecorderInternal()) {
2648  file = GetNativeResult<const char*>(rs2_record_device_filename,
2649  &me->error_, me->dev_, &me->error_);
2650  } else {
2651  return;
2652  }
2653  if (me->error_) return;
2654 
2655  info.GetReturnValue().Set(Nan::New(file).ToLocalChecked());
2656  }
2657 
2658  static NAN_METHOD(PausePlayback) {
2659  info.GetReturnValue().Set(Nan::Undefined());
2660  auto me = Nan::ObjectWrap::Unwrap<RSDevice>(info.Holder());
2661  if (!me) return;
2662 
2663  CallNativeFunc(rs2_playback_device_pause, &me->error_, me->dev_,
2664  &me->error_);
2665  }
2666 
2667  static NAN_METHOD(ResumePlayback) {
2668  info.GetReturnValue().Set(Nan::Undefined());
2669  auto me = Nan::ObjectWrap::Unwrap<RSDevice>(info.Holder());
2670  if (!me) return;
2671 
2672  CallNativeFunc(rs2_playback_device_resume, &me->error_, me->dev_,
2673  &me->error_);
2674  }
2675 
2676  static NAN_METHOD(StopPlayback) {
2677  info.GetReturnValue().Set(Nan::Undefined());
2678  auto me = Nan::ObjectWrap::Unwrap<RSDevice>(info.Holder());
2679  if (!me) return;
2680 
2681  CallNativeFunc(rs2_playback_device_stop, &me->error_, me->dev_,
2682  &me->error_);
2683  }
2684 
2685  static NAN_METHOD(GetPosition) {
2686  auto me = Nan::ObjectWrap::Unwrap<RSDevice>(info.Holder());
2687  info.GetReturnValue().Set(Nan::Undefined());
2688  if (!me) return;
2689 
2690  auto pos = static_cast<uint32_t>(GetNativeResult<uint32_t>(
2691  rs2_playback_get_position, &me->error_, me->dev_, &me->error_)/1000000);
2692  info.GetReturnValue().Set(Nan::New(pos));
2693  }
2694 
2695  static NAN_METHOD(GetDuration) {
2696  auto me = Nan::ObjectWrap::Unwrap<RSDevice>(info.Holder());
2697  info.GetReturnValue().Set(Nan::Undefined());
2698  if (!me) return;
2699 
2700  auto duration = static_cast<uint32_t>(
2701  GetNativeResult<uint32_t>(rs2_playback_get_duration, &me->error_,
2702  me->dev_, &me->error_)/1000000);
2703  info.GetReturnValue().Set(Nan::New(duration));
2704  }
2705 
2706  static NAN_METHOD(Seek) {
2707  auto me = Nan::ObjectWrap::Unwrap<RSDevice>(info.Holder());
2708  info.GetReturnValue().Set(Nan::Undefined());
2709  if (!me) return;
2710 
2711  uint64_t time = Nan::To<int64_t>(info[0]).FromJust();
2712  CallNativeFunc(rs2_playback_seek, &me->error_, me->dev_, time*1000000,
2713  &me->error_);
2714  }
2715 
2716  static NAN_METHOD(IsRealTime) {
2717  auto me = Nan::ObjectWrap::Unwrap<RSDevice>(info.Holder());
2718  info.GetReturnValue().Set(Nan::Undefined());
2719  if (!me) return;
2720 
2721  auto val = GetNativeResult<int>(rs2_playback_device_is_real_time,
2722  &me->error_, me->dev_, &me->error_);
2723  if (me->error_) return;
2724 
2725  info.GetReturnValue().Set(val ? Nan::True() : Nan::False());
2726  }
2727 
2728  static NAN_METHOD(SetIsRealTime) {
2729  auto me = Nan::ObjectWrap::Unwrap<RSDevice>(info.Holder());
2730  info.GetReturnValue().Set(Nan::Undefined());
2731  if (!me) return;
2732 
2733  auto val = Nan::To<bool>(info[0]).FromJust();
2735  me->dev_, val, &me->error_);
2736  }
2737 
2738  static NAN_METHOD(SetPlaybackSpeed) {
2739  auto me = Nan::ObjectWrap::Unwrap<RSDevice>(info.Holder());
2740  info.GetReturnValue().Set(Nan::Undefined());
2741  if (!me) return;
2742 
2743  auto speed = Nan::To<double>(info[0]).FromJust();
2745  me->dev_, speed, &me->error_);
2746  }
2747 
2748  static NAN_METHOD(IsPlayback) {
2749  auto me = Nan::ObjectWrap::Unwrap<RSDevice>(info.Holder());
2750  info.GetReturnValue().Set(Nan::Undefined());
2751  if (!me) return;
2752 
2753  auto val = me->IsPlaybackInternal();
2754  info.GetReturnValue().Set(val ? Nan::True() : Nan::False());
2755  }
2756 
2757  static NAN_METHOD(IsRecorder) {
2758  auto me = Nan::ObjectWrap::Unwrap<RSDevice>(info.Holder());
2759  info.GetReturnValue().Set(Nan::Undefined());
2760  if (!me) return;
2761 
2762  auto val = me->IsRecorderInternal();
2763  info.GetReturnValue().Set(val ? Nan::True() : Nan::False());
2764  }
2765 
2766  static NAN_METHOD(GetCurrentStatus) {
2767  auto me = Nan::ObjectWrap::Unwrap<RSDevice>(info.Holder());
2768  info.GetReturnValue().Set(Nan::Undefined());
2769  if (!me) return;
2770 
2771  auto status = GetNativeResult<rs2_playback_status>(
2773  me->dev_, &me->error_);
2774  if (me->error_) return;
2775 
2776  info.GetReturnValue().Set(Nan::New(status));
2777  }
2778 
2779  static NAN_METHOD(SetStatusChangedCallbackMethodName) {
2780  auto me = Nan::ObjectWrap::Unwrap<RSDevice>(info.Holder());
2781  info.GetReturnValue().Set(Nan::Undefined());
2782  if (!me) return;
2783 
2784  Nan::Utf8String method(Nan::To<v8::String>(info[0]).ToLocalChecked());
2785  me->status_changed_callback_method_name_ = std::string(*method);
2787  me->dev_, new PlaybackStatusCallback(me), &me->error_);
2788  }
2789 
2790  static NAN_METHOD(IsTm2) {
2791  auto me = Nan::ObjectWrap::Unwrap<RSDevice>(info.Holder());
2792  info.GetReturnValue().Set(Nan::Undefined());
2793  if (!me) return;
2794 
2795  auto val = GetNativeResult<int>(rs2_is_device_extendable_to, &me->error_,
2796  me->dev_, RS2_EXTENSION_TM2, &me->error_);
2797  info.GetReturnValue().Set(val ? Nan::True() : Nan::False());
2798  }
2799 
2800  static NAN_METHOD(EnableLoopback) {
2801  auto me = Nan::ObjectWrap::Unwrap<RSDevice>(info.Holder());
2802  info.GetReturnValue().Set(Nan::Undefined());
2803  if (!me) return;
2804 
2805  Nan::Utf8String file(Nan::To<v8::String>(info[0]).ToLocalChecked());
2806  CallNativeFunc(rs2_loopback_enable, &me->error_, me->dev_, *file,
2807  &me->error_);
2808  }
2809 
2810  static NAN_METHOD(DisableLoopback) {
2811  auto me = Nan::ObjectWrap::Unwrap<RSDevice>(info.Holder());
2812  info.GetReturnValue().Set(Nan::Undefined());
2813  if (!me) return;
2814 
2815  CallNativeFunc(rs2_loopback_disable, &me->error_, me->dev_,
2816  &me->error_);
2817  }
2818 
2819  static NAN_METHOD(IsLoopbackEnabled) {
2820  auto me = Nan::ObjectWrap::Unwrap<RSDevice>(info.Holder());
2821  info.GetReturnValue().Set(Nan::Undefined());
2822  if (!me) return;
2823 
2824  auto val = GetNativeResult<int>(rs2_loopback_is_enabled, &me->error_,
2825  me->dev_, &me->error_);
2826  info.GetReturnValue().Set(val ? Nan::True() : Nan::False());
2827  }
2828 
2829  private:
2831  auto val = GetNativeResult<int>(rs2_is_device_extendable_to, &error_, dev_,
2832  RS2_EXTENSION_PLAYBACK, &error_);
2833 
2834  return (error_ || !val) ? false : true;
2835  }
2836 
2838  auto val = GetNativeResult<int>(rs2_is_device_extendable_to, &error_, dev_,
2839  RS2_EXTENSION_RECORD, &error_);
2840 
2841  return (error_ || !val) ? false : true;
2842  }
2843  static Nan::Persistent<v8::Function> constructor_;
2848  friend class RSContext;
2850  friend class FrameCallbackInfo;
2851  friend class RSPipeline;
2852  friend class RSDeviceList;
2853  friend class RSDeviceHub;
2855 };
2856 
2857 Nan::Persistent<v8::Function> RSDevice::constructor_;
2858 
2860  SetConsumed();
2861  Nan::HandleScope scope;
2862  // save the rs2_frame to the sensor
2863  sensor_->ReplaceFrame(frame_);
2864 
2865  Nan::AsyncResource resource("frame_callback_name_");
2866  resource.runInAsyncScope(sensor_->handle(), sensor_->frame_callback_name_.c_str(), 0, nullptr);
2867  // Nan::MakeCallback(sensor_->handle(), sensor_->frame_callback_name_.c_str(), 0,
2868  // nullptr);
2869 }
2870 
2872  SetConsumed();
2873  Nan::HandleScope scope;
2874  v8::Local<v8::Value> args[1] = {
2876  desc_, time_, severity_, category_, serialized_data_).GetObject()
2877  };
2878 
2879  Nan::AsyncResource resource("notification_callback_name_");
2880  resource.runInAsyncScope(sensor_->handle(), sensor_->notification_callback_name_.c_str(), 1, args);
2881  // Nan::MakeCallback(sensor_->handle(),
2882  // sensor_->notification_callback_name_.c_str(), 1, args);
2883 }
2884 
2886  SetConsumed();
2887  Nan::HandleScope scope;
2888  v8::Local<v8::Value> args[1] = { Nan::New(status_) };
2889  Nan::AsyncResource resource("status_changed_callback_method_name_");
2890  resource.runInAsyncScope(dev_->handle(), dev_->status_changed_callback_method_name_.c_str(), 1, args);
2891  // Nan::MakeCallback(dev_->handle(),
2892  // dev_->status_changed_callback_method_name_.c_str(), 1, args);
2893 }
2894 
2895 class RSPointCloud : public Nan::ObjectWrap, Options {
2896  public:
2897  static void Init(v8::Local<v8::Object> exports) {
2898  v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
2899  tpl->SetClassName(Nan::New("RSPointCloud").ToLocalChecked());
2900  tpl->InstanceTemplate()->SetInternalFieldCount(1);
2901 
2902  Nan::SetPrototypeMethod(tpl, "destroy", Destroy);
2903  Nan::SetPrototypeMethod(tpl, "calculate", Calculate);
2904  Nan::SetPrototypeMethod(tpl, "mapTo", MapTo);
2905 
2906  // options API
2907  Nan::SetPrototypeMethod(tpl, "supportsOption", SupportsOption);
2908  Nan::SetPrototypeMethod(tpl, "getOption", GetOption);
2909  Nan::SetPrototypeMethod(tpl, "setOption", SetOption);
2910  Nan::SetPrototypeMethod(tpl, "getOptionRange", GetOptionRange);
2911  Nan::SetPrototypeMethod(tpl, "isOptionReadonly", IsOptionReadonly);
2912  Nan::SetPrototypeMethod(tpl, "getOptionDescription", GetOptionDescription);
2913  Nan::SetPrototypeMethod(tpl, "getOptionValueDescription",
2914  GetOptionValueDescription);
2915 
2916  v8::Local<v8::Context> context = exports->CreationContext();
2917  constructor_.Reset(tpl->GetFunction(context).ToLocalChecked());
2918  exports->Set(context, Nan::New("RSPointCloud").ToLocalChecked(),
2919  tpl->GetFunction(context).ToLocalChecked());
2920  }
2921 
2923  // we have to reinterpret_cast as they are unrelated types to compiler
2924  return reinterpret_cast<rs2_options*>(processing_block_);
2925  }
2926 
2927  private:
2928  RSPointCloud() : processing_block_(nullptr), error_(nullptr) {
2929  frame_queue_ = rs2_create_frame_queue(1, &error_);
2930  }
2931 
2933  DestroyMe();
2934  }
2935 
2936  void DestroyMe() {
2937  if (error_) rs2_free_error(error_);
2938  error_ = nullptr;
2939  if (processing_block_) rs2_delete_processing_block(processing_block_);
2940  processing_block_ = nullptr;
2941  if (frame_queue_) rs2_delete_frame_queue(frame_queue_);
2942  frame_queue_ = nullptr;
2943  }
2944 
2945  static NAN_METHOD(Destroy) {
2946  auto me = Nan::ObjectWrap::Unwrap<RSPointCloud>(info.Holder());
2947  if (me) {
2948  me->DestroyMe();
2949  }
2950  info.GetReturnValue().Set(Nan::Undefined());
2951  }
2952 
2953  static void New(const Nan::FunctionCallbackInfo<v8::Value>& info) {
2954  if (info.IsConstructCall()) {
2955  RSPointCloud* obj = new RSPointCloud();
2956  obj->processing_block_ = GetNativeResult<rs2_processing_block*>(
2957  rs2_create_pointcloud, &obj->error_, &obj->error_);
2960  callback, &obj->error_);
2961 
2962  obj->Wrap(info.This());
2963  info.GetReturnValue().Set(info.This());
2964  }
2965  }
2966 
2967  static NAN_METHOD(Calculate) {
2968  info.GetReturnValue().Set(Nan::False());
2969  auto me = Nan::ObjectWrap::Unwrap<RSPointCloud>(info.Holder());
2970  auto frame = Nan::ObjectWrap::Unwrap<RSFrame>(Nan::To<v8::Object>(info[0]).ToLocalChecked());
2971  auto target_frame = Nan::ObjectWrap::Unwrap<RSFrame>(Nan::To<v8::Object>(info[1]).ToLocalChecked());
2972  if (!me || !frame || !frame->frame_ || !target_frame) return;
2973 
2974  // rs2_process_frame will release the input frame, so we need to addref
2975  CallNativeFunc(rs2_frame_add_ref, &me->error_, frame->frame_, &me->error_);
2976  if (me->error_) return;
2977 
2978  CallNativeFunc(rs2_process_frame, &me->error_, me->processing_block_,
2979  frame->frame_, &me->error_);
2980  if (me->error_) return;
2981 
2982  auto new_frame = GetNativeResult<rs2_frame*>(rs2_wait_for_frame,
2983  &me->error_, me->frame_queue_, 5000, &me->error_);
2984  if (!new_frame) return;
2985 
2986  target_frame->Replace(new_frame);
2987  info.GetReturnValue().Set(Nan::True());
2988  }
2989 
2990  static NAN_METHOD(MapTo) {
2991  auto me = Nan::ObjectWrap::Unwrap<RSPointCloud>(info.Holder());
2992  auto frame = Nan::ObjectWrap::Unwrap<RSFrame>(Nan::To<v8::Object>(info[0]).ToLocalChecked());
2993  info.GetReturnValue().Set(Nan::Undefined());
2994  if (!me || !frame) return;
2995 
2996  const rs2_stream_profile* profile =
2997  GetNativeResult<const rs2_stream_profile*>(rs2_get_frame_stream_profile,
2998  &me->error_, frame->frame_, &me->error_);
2999  if (!profile) return;
3000 
3001  StreamProfileExtrator extrator(profile);
3002  CallNativeFunc(rs2_set_option, &me->error_,
3003  reinterpret_cast<rs2_options*>(me->processing_block_),
3005  static_cast<float>(extrator.stream_),
3006  &me->error_);
3007 
3008  CallNativeFunc(rs2_set_option, &me->error_,
3009  reinterpret_cast<rs2_options*>(me->processing_block_),
3011  static_cast<float>(extrator.format_),
3012  &me->error_);
3013 
3014  CallNativeFunc(rs2_set_option, &me->error_,
3015  reinterpret_cast<rs2_options*>(me->processing_block_),
3017  static_cast<float>(extrator.index_),
3018  &me->error_);
3019 
3020  if (extrator.stream_ == RS2_STREAM_DEPTH) return;
3021 
3022  // rs2_process_frame will release the input frame, so we need to addref
3023  CallNativeFunc(rs2_frame_add_ref, &me->error_, frame->frame_, &me->error_);
3024  if (me->error_) return;
3025 
3026  CallNativeFunc(rs2_process_frame, &me->error_, me->processing_block_,
3027  frame->frame_, &me->error_);
3028  }
3029 
3030  static NAN_METHOD(SupportsOption) {
3031  auto me = Nan::ObjectWrap::Unwrap<RSPointCloud>(info.Holder());
3032  if (me) return me->SupportsOptionInternal(info);
3033 
3034  info.GetReturnValue().Set(Nan::False());
3035  }
3036 
3037  static NAN_METHOD(GetOption) {
3038  auto me = Nan::ObjectWrap::Unwrap<RSPointCloud>(info.Holder());
3039  if (me) return me->GetOptionInternal(info);
3040 
3041  info.GetReturnValue().Set(Nan::Undefined());
3042  }
3043 
3044  static NAN_METHOD(GetOptionDescription) {
3045  auto me = Nan::ObjectWrap::Unwrap<RSPointCloud>(info.Holder());
3046  if (me) return me->GetOptionDescriptionInternal(info);
3047 
3048  info.GetReturnValue().Set(Nan::Undefined());
3049  }
3050 
3051  static NAN_METHOD(GetOptionValueDescription) {
3052  auto me = Nan::ObjectWrap::Unwrap<RSPointCloud>(info.Holder());
3053  if (me) return me->GetOptionValueDescriptionInternal(info);
3054 
3055  info.GetReturnValue().Set(Nan::Undefined());
3056  }
3057 
3058  static NAN_METHOD(SetOption) {
3059  auto me = Nan::ObjectWrap::Unwrap<RSPointCloud>(info.Holder());
3060  if (me) return me->SetOptionInternal(info);
3061 
3062  info.GetReturnValue().Set(Nan::Undefined());
3063  }
3064 
3065  static NAN_METHOD(GetOptionRange) {
3066  auto me = Nan::ObjectWrap::Unwrap<RSPointCloud>(info.Holder());
3067  if (me) return me->GetOptionRangeInternal(info);
3068 
3069  info.GetReturnValue().Set(Nan::Undefined());
3070  }
3071 
3072  static NAN_METHOD(IsOptionReadonly) {
3073  auto me = Nan::ObjectWrap::Unwrap<RSPointCloud>(info.Holder());
3074  if (me) return me->IsOptionReadonlyInternal(info);
3075 
3076  info.GetReturnValue().Set(Nan::False());
3077  }
3078 
3079  private:
3080  static Nan::Persistent<v8::Function> constructor_;
3081 
3085 };
3086 
3087 Nan::Persistent<v8::Function> RSPointCloud::constructor_;
3088 
3089 class RSDeviceList : public Nan::ObjectWrap {
3090  public:
3091  static void Init(v8::Local<v8::Object> exports) {
3092  v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
3093  tpl->SetClassName(Nan::New("RSDeviceList").ToLocalChecked());
3094  tpl->InstanceTemplate()->SetInternalFieldCount(1);
3095 
3096  Nan::SetPrototypeMethod(tpl, "destroy", Destroy);
3097  Nan::SetPrototypeMethod(tpl, "contains", Contains);
3098  Nan::SetPrototypeMethod(tpl, "size", Size);
3099  Nan::SetPrototypeMethod(tpl, "getDevice", GetDevice);
3100 
3101  v8::Local<v8::Context> context = exports->CreationContext();
3102  constructor_.Reset(tpl->GetFunction(context).ToLocalChecked());
3103  exports->Set(context, Nan::New("RSDeviceList").ToLocalChecked(),
3104  tpl->GetFunction(context).ToLocalChecked());
3105  }
3106 
3107  static v8::Local<v8::Object> NewInstance(rs2_device_list* list) {
3108  Nan::EscapableHandleScope scope;
3109  v8::Local<v8::Function> cons = Nan::New<v8::Function>(constructor_);
3110  v8::Local<v8::Context> context = Nan::GetCurrentContext();
3111  v8::Local<v8::Object> instance =
3112  cons->NewInstance(context, 0, nullptr).ToLocalChecked();
3113  auto me = Nan::ObjectWrap::Unwrap<RSDeviceList>(instance);
3114  me->list_ = list;
3115  return scope.Escape(instance);
3116  }
3117 
3118  private:
3119  RSDeviceList() : error_(nullptr), list_(nullptr) {}
3120 
3122  DestroyMe();
3123  }
3124 
3125  void DestroyMe() {
3126  if (error_) rs2_free_error(error_);
3127  error_ = nullptr;
3128  if (list_) rs2_delete_device_list(list_);
3129  list_ = nullptr;
3130  }
3131 
3132  static void New(const Nan::FunctionCallbackInfo<v8::Value>& info) {
3133  if (info.IsConstructCall()) {
3134  RSDeviceList* obj = new RSDeviceList();
3135  obj->Wrap(info.This());
3136  info.GetReturnValue().Set(info.This());
3137  }
3138  }
3139 
3140  static NAN_METHOD(Destroy) {
3141  auto me = Nan::ObjectWrap::Unwrap<RSDeviceList>(info.Holder());
3142  if (me) me->DestroyMe();
3143 
3144  info.GetReturnValue().Set(Nan::Undefined());
3145  }
3146 
3148  info.GetReturnValue().Set(Nan::Undefined());
3149  auto me = Nan::ObjectWrap::Unwrap<RSDeviceList>(info.Holder());
3150  auto dev = Nan::ObjectWrap::Unwrap<RSDevice>(Nan::To<v8::Object>(info[0]).ToLocalChecked());
3151  if (!me && dev) return;
3152 
3153  bool contains = GetNativeResult<int>(rs2_device_list_contains, &me->error_,
3154  me->list_, dev->dev_, &me->error_);
3155  if (me->error_) return;
3156 
3157  info.GetReturnValue().Set(Nan::New(contains));
3158  }
3159 
3160  static NAN_METHOD(Size) {
3161  info.GetReturnValue().Set(Nan::Undefined());
3162  auto me = Nan::ObjectWrap::Unwrap<RSDeviceList>(info.Holder());
3163  if (!me) return;
3164 
3165  auto cnt = GetNativeResult<int>(rs2_get_device_count, &me->error_,
3166  me->list_, &me->error_);
3167  if (me->error_) return;
3168 
3169  info.GetReturnValue().Set(Nan::New(cnt));
3170  }
3171 
3172  static NAN_METHOD(GetDevice) {
3173  info.GetReturnValue().Set(Nan::Undefined());
3174  auto me = Nan::ObjectWrap::Unwrap<RSDeviceList>(info.Holder());
3175  auto index = Nan::To<int64_t>(info[0]).FromJust();
3176  if (!me) return;
3177 
3178  auto dev = GetNativeResult<rs2_device*>(rs2_create_device, &me->error_,
3179  me->list_, index, &me->error_);
3180  if (!dev) return;
3181 
3182  info.GetReturnValue().Set(RSDevice::NewInstance(dev));
3183  }
3184 
3185  private:
3186  static Nan::Persistent<v8::Function> constructor_;
3189 };
3190 
3191 Nan::Persistent<v8::Function> RSDeviceList::constructor_;
3192 
3196 //
3197 // .d8888b. 888 888 //
3198 // d88P Y88b 888 888 //
3199 // 888 888 888 888 //
3200 // 888 .d88b. 88888b. 888888 .d88b. 888 888 888888 //
3201 // 888 d88""88b 888 "88b 888 d8P Y8b `Y8bd8P' 888 //
3202 // 888 888 888 888 888 888 888 88888888 X88K 888 //
3203 // Y88b d88P Y88..88P 888 888 Y88b. Y8b. .d8""8b. Y88b. //
3204 // "Y8888P" "Y88P" 888 888 "Y888 "Y8888 888 888 "Y888 //
3205 //
3209 
3210 class RSContext : public Nan::ObjectWrap {
3211  public:
3213  kNormal = 0,
3216  };
3217  static void Init(v8::Local<v8::Object> exports) {
3218  v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
3219  tpl->SetClassName(Nan::New("RSContext").ToLocalChecked());
3220  tpl->InstanceTemplate()->SetInternalFieldCount(1);
3221 
3222  Nan::SetPrototypeMethod(tpl, "destroy", Destroy);
3223  Nan::SetPrototypeMethod(tpl, "create", Create);
3224  Nan::SetPrototypeMethod(tpl, "queryDevices", QueryDevices);
3225  Nan::SetPrototypeMethod(tpl, "setDevicesChangedCallback",
3226  SetDevicesChangedCallback);
3227  Nan::SetPrototypeMethod(tpl, "loadDeviceFile", LoadDeviceFile);
3228  Nan::SetPrototypeMethod(tpl, "unloadDeviceFile", UnloadDeviceFile);
3229  Nan::SetPrototypeMethod(tpl, "createDeviceFromSensor",
3230  CreateDeviceFromSensor);
3231 
3232  v8::Local<v8::Context> context = exports->CreationContext();
3233  constructor_.Reset(tpl->GetFunction(context).ToLocalChecked());
3234  exports->Set(context, Nan::New("RSContext").ToLocalChecked(),
3235  tpl->GetFunction(context).ToLocalChecked());
3236  }
3237 
3238  static v8::Local<v8::Object> NewInstance(rs2_context* ctx_ptr = nullptr) {
3239  Nan::EscapableHandleScope scope;
3240 
3241  v8::Local<v8::Function> cons = Nan::New<v8::Function>(constructor_);
3242  v8::Local<v8::Context> context = Nan::GetCurrentContext();
3243 
3244  v8::Local<v8::Object> instance =
3245  cons->NewInstance(context, 0, nullptr).ToLocalChecked();
3246 
3247  // If ctx_ptr is provided, no need to call create.
3248  if (ctx_ptr) {
3249  auto me = Nan::ObjectWrap::Unwrap<RSContext>(instance);
3250  me->ctx_ = ctx_ptr;
3251  }
3252  return scope.Escape(instance);
3253  }
3254 
3255  private:
3256  explicit RSContext(ContextType type = kNormal) : ctx_(nullptr),
3257  error_(nullptr), type_(type), mode_(RS2_RECORDING_MODE_BLANK_FRAMES) {}
3258 
3260  DestroyMe();
3261  }
3262 
3263  void RegisterDevicesChangedCallbackMethod();
3264 
3265  void DestroyMe() {
3266  if (error_) rs2_free_error(error_);
3267  error_ = nullptr;
3268  if (ctx_) rs2_delete_context(ctx_);
3269  ctx_ = nullptr;
3270  }
3271 
3272  static void New(const Nan::FunctionCallbackInfo<v8::Value>& info) {
3273  if (!info.IsConstructCall()) return;
3274 
3275  ContextType type = kNormal;
3276  if (info.Length()) {
3277  Nan::Utf8String type_str(Nan::To<v8::String>(info[0]).ToLocalChecked());
3278  std::string std_type_str(*type_str);
3279  if (!std_type_str.compare("recording"))
3280  type = kRecording;
3281  else if (!std_type_str.compare("playback"))
3282  type = kPlayback;
3283  }
3284  RSContext* obj = new RSContext(type);
3285  if (type == kRecording || type == kPlayback) {
3286  Nan::Utf8String file(Nan::To<v8::String>(info[1]).ToLocalChecked());
3287  Nan::Utf8String section(Nan::To<v8::String>(info[2]).ToLocalChecked());
3288  obj->file_name_ = std::string(*file);
3289  obj->section_ = std::string(*section);
3290  }
3291  if (type == kRecording)
3292  obj->mode_ = static_cast<rs2_recording_mode>(Nan::To<int64_t>(info[3]).FromJust());
3293  obj->Wrap(info.This());
3294  info.GetReturnValue().Set(info.This());
3295  }
3296 
3297  static NAN_METHOD(Create) {
3299  info.GetReturnValue().Set(Nan::Undefined());
3300  auto me = Nan::ObjectWrap::Unwrap<RSContext>(info.Holder());
3301  if (!me) return;
3302 
3303  switch (me->type_) {
3304  case kRecording:
3305  me->ctx_ = GetNativeResult<rs2_context*>(rs2_create_recording_context,
3306  &me->error_, RS2_API_VERSION, me->file_name_.c_str(),
3307  me->section_.c_str(), me->mode_, &me->error_);
3308  break;
3309  case kPlayback:
3310  me->ctx_ = GetNativeResult<rs2_context*>(rs2_create_mock_context,
3311  &me->error_, RS2_API_VERSION, me->file_name_.c_str(),
3312  me->section_.c_str(), &me->error_);
3313  break;
3314  default:
3315  me->ctx_ = GetNativeResult<rs2_context*>(rs2_create_context,
3316  &me->error_, RS2_API_VERSION, &me->error_);
3317  break;
3318  }
3319  }
3320 
3321  static NAN_METHOD(Destroy) {
3322  auto me = Nan::ObjectWrap::Unwrap<RSContext>(info.Holder());
3323  if (me) {
3324  me->DestroyMe();
3325  }
3326  info.GetReturnValue().Set(Nan::Undefined());
3327  }
3328 
3329  static NAN_METHOD(SetDevicesChangedCallback) {
3330  auto me = Nan::ObjectWrap::Unwrap<RSContext>(info.Holder());
3331  if (me) {
3332  Nan::Utf8String value(Nan::To<v8::String>(info[0]).ToLocalChecked());
3333  me->device_changed_callback_name_ = std::string(*value);
3334  me->RegisterDevicesChangedCallbackMethod();
3335  }
3336  info.GetReturnValue().Set(Nan::Undefined());
3337  }
3338 
3339  static NAN_METHOD(LoadDeviceFile) {
3340  info.GetReturnValue().Set(Nan::Undefined());
3341  auto me = Nan::ObjectWrap::Unwrap<RSContext>(info.Holder());
3342  if (!me) return;
3343 
3344  Nan::Utf8String value(Nan::To<v8::String>(info[0]).ToLocalChecked());
3345  auto dev = GetNativeResult<rs2_device*>(rs2_context_add_device, &me->error_,
3346  me->ctx_, *value, &me->error_);
3347  if (!dev) return;
3348 
3350  info.GetReturnValue().Set(jsobj);
3351  }
3352 
3353  static NAN_METHOD(UnloadDeviceFile) {
3354  auto me = Nan::ObjectWrap::Unwrap<RSContext>(info.Holder());
3355  info.GetReturnValue().Set(Nan::Undefined());
3356  if (!me) return;
3357 
3358  Nan::Utf8String value(Nan::To<v8::String>(info[0]).ToLocalChecked());
3359  CallNativeFunc(rs2_context_remove_device, &me->error_, me->ctx_, *value,
3360  &me->error_);
3361  }
3362 
3363  static NAN_METHOD(CreateDeviceFromSensor) {
3364  info.GetReturnValue().Set(Nan::Undefined());
3365  auto sensor = Nan::ObjectWrap::Unwrap<RSSensor>(Nan::To<v8::Object>(info[0]).ToLocalChecked());
3366  if (!sensor) return;
3367 
3368  rs2_error* error = nullptr;
3369  auto dev = GetNativeResult<rs2_device*>(rs2_create_device_from_sensor,
3370  &error, sensor->sensor_, &error);
3371  if (!dev) return;
3372 
3373  auto jsobj = RSDevice::NewInstance(dev);
3374  info.GetReturnValue().Set(jsobj);
3375  }
3376 
3377  static NAN_METHOD(QueryDevices) {
3378  info.GetReturnValue().Set(Nan::Undefined());
3379  auto me = Nan::ObjectWrap::Unwrap<RSContext>(info.Holder());
3380  if (!me) return;
3381 
3382  auto dev_list = GetNativeResult<rs2_device_list*>(rs2_query_devices,
3383  &me->error_, me->ctx_, &me->error_);
3384  if (!dev_list) return;
3385 
3386  auto jsobj = RSDeviceList::NewInstance(dev_list);
3387  info.GetReturnValue().Set(jsobj);
3388  }
3389 
3390  private:
3391  static Nan::Persistent<v8::Function> constructor_;
3392 
3401  friend class RSPipeline;
3402  friend class RSDeviceHub;
3403 };
3404 
3405 Nan::Persistent<v8::Function> RSContext::constructor_;
3406 
3408  public:
3411  removed_(r), added_(a), ctx_(ctx) {}
3412  virtual ~DevicesChangedCallbackInfo() { if (!consumed_) Release(); }
3413  virtual void Run() {
3414  SetConsumed();
3415  Nan::HandleScope scope;
3416  v8::Local<v8::Value> rmlist;
3417  v8::Local<v8::Value> addlist;
3418  if (removed_)
3419  rmlist = RSDeviceList::NewInstance(removed_);
3420  else
3421  rmlist = Nan::Undefined();
3422 
3423  if (added_)
3424  addlist = RSDeviceList::NewInstance(added_);
3425  else
3426  addlist = Nan::Undefined();
3427 
3428  v8::Local<v8::Value> args[2] = {rmlist, addlist};
3429 
3430  Nan::AsyncResource resource("device_changed_callback_name_");
3431  resource.runInAsyncScope(ctx_->handle(), ctx_->device_changed_callback_name_.c_str(), 2, args);
3432  // Nan::MakeCallback(ctx_->handle(),
3433  // ctx_->device_changed_callback_name_.c_str(), 2, args);
3434  }
3435  virtual void Release() {
3436  if (removed_) {
3437  rs2_delete_device_list(removed_);
3438  removed_ = nullptr;
3439  }
3440 
3441  if (added_) {
3442  rs2_delete_device_list(added_);
3443  added_ = nullptr;
3444  }
3445  }
3446 
3447  private:
3451 };
3452 
3454  public:
3455  explicit DevicesChangedCallback(RSContext* context) : ctx_(context) {}
3456  virtual void on_devices_changed(
3457  rs2_device_list* removed, rs2_device_list* added) {
3459  new DevicesChangedCallbackInfo(removed, added, ctx_));
3460  }
3461 
3462  virtual void release() {
3463  delete this;
3464  }
3465 
3468 };
3469 
3472  new DevicesChangedCallback(this), &error_);
3473 }
3474 
3475 class RSDeviceHub : public Nan::ObjectWrap {
3476  public:
3477  static void Init(v8::Local<v8::Object> exports) {
3478  v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
3479  tpl->SetClassName(Nan::New("RSDeviceHub").ToLocalChecked());
3480  tpl->InstanceTemplate()->SetInternalFieldCount(1);
3481 
3482  Nan::SetPrototypeMethod(tpl, "waitForDevice", WaitForDevice);
3483  Nan::SetPrototypeMethod(tpl, "isConnected", IsConnected);
3484  Nan::SetPrototypeMethod(tpl, "destroy", Destroy);
3485 
3486  v8::Local<v8::Context> context = exports->CreationContext();
3487  constructor_.Reset(tpl->GetFunction(context).ToLocalChecked());
3488  exports->Set(context, Nan::New("RSDeviceHub").ToLocalChecked(),
3489  tpl->GetFunction(context).ToLocalChecked());
3490  }
3491 
3492  static v8::Local<v8::Object> NewInstance() {
3493  Nan::EscapableHandleScope scope;
3494 
3495  v8::Local<v8::Function> cons = Nan::New<v8::Function>(constructor_);
3496  v8::Local<v8::Context> context = Nan::GetCurrentContext();
3497 
3498  v8::Local<v8::Object> instance =
3499  cons->NewInstance(context, 0, nullptr).ToLocalChecked();
3500 
3501  return scope.Escape(instance);
3502  }
3503 
3504  private:
3505  RSDeviceHub() : hub_(nullptr), ctx_(nullptr), error_(nullptr) {}
3506 
3508  DestroyMe();
3509  }
3510 
3511  void DestroyMe() {
3512  if (error_) rs2_free_error(error_);
3513  error_ = nullptr;
3514 
3515  if (hub_) rs2_delete_device_hub(hub_);
3516  hub_ = nullptr;
3517  ctx_ = nullptr;
3518  }
3519 
3520  static NAN_METHOD(Destroy) {
3521  auto me = Nan::ObjectWrap::Unwrap<RSDeviceHub>(info.Holder());
3522  if (me) me->DestroyMe();
3523  info.GetReturnValue().Set(Nan::Undefined());
3524  }
3525 
3526  static void New(const Nan::FunctionCallbackInfo<v8::Value>& info) {
3527  if (info.IsConstructCall()) {
3528  RSDeviceHub* obj = new RSDeviceHub();
3529  RSContext* ctx =
3530  Nan::ObjectWrap::Unwrap<RSContext>(Nan::To<v8::Object>(info[0]).ToLocalChecked());
3531  obj->ctx_ = ctx->ctx_;
3532  obj->hub_ = GetNativeResult<rs2_device_hub*>(rs2_create_device_hub,
3533  &obj->error_, obj->ctx_, &obj->error_);
3534  obj->Wrap(info.This());
3535  info.GetReturnValue().Set(info.This());
3536  }
3537  }
3538 
3539  static NAN_METHOD(WaitForDevice) {
3540  info.GetReturnValue().Set(Nan::Undefined());
3541  auto me = Nan::ObjectWrap::Unwrap<RSDeviceHub>(info.Holder());
3542  if (!me) return;
3543 
3544  auto dev = GetNativeResult<rs2_device*>(rs2_device_hub_wait_for_device,
3545  &me->error_, me->hub_, &me->error_);
3546  if (!dev) return;
3547 
3548  info.GetReturnValue().Set(RSDevice::NewInstance(dev));
3549  }
3550 
3551  static NAN_METHOD(IsConnected) {
3552  info.GetReturnValue().Set(Nan::Undefined());
3553  auto me = Nan::ObjectWrap::Unwrap<RSDeviceHub>(info.Holder());
3554  auto dev = Nan::ObjectWrap::Unwrap<RSDevice>(Nan::To<v8::Object>(info[0]).ToLocalChecked());
3555  if (!me || !dev) return;
3556 
3557  auto res = GetNativeResult<int>(rs2_device_hub_is_device_connected,
3558  &me->error_, me->hub_, dev->dev_, &me->error_);
3559  if (me->error_) return;
3560 
3561  info.GetReturnValue().Set(Nan::New(res ? true : false));
3562  }
3563 
3564  private:
3565  static Nan::Persistent<v8::Function> constructor_;
3566 
3570 };
3571 
3572 Nan::Persistent<v8::Function> RSDeviceHub::constructor_;
3573 
3574 class RSPipelineProfile : public Nan::ObjectWrap {
3575  public:
3576  static void Init(v8::Local<v8::Object> exports) {
3577  v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
3578  tpl->SetClassName(Nan::New("RSPipelineProfile").ToLocalChecked());
3579  tpl->InstanceTemplate()->SetInternalFieldCount(1);
3580 
3581  Nan::SetPrototypeMethod(tpl, "getStreams", GetStreams);
3582  Nan::SetPrototypeMethod(tpl, "getDevice", GetDevice);
3583  Nan::SetPrototypeMethod(tpl, "destroy", Destroy);
3584 
3585  v8::Local<v8::Context> context = exports->CreationContext();
3586  constructor_.Reset(tpl->GetFunction(context).ToLocalChecked());
3587  exports->Set(context, Nan::New("RSPipelineProfile").ToLocalChecked(),
3588  tpl->GetFunction(context).ToLocalChecked());
3589  }
3590 
3591  static v8::Local<v8::Object> NewInstance(rs2_pipeline_profile* profile) {
3592  Nan::EscapableHandleScope scope;
3593 
3594  v8::Local<v8::Function> cons = Nan::New<v8::Function>(constructor_);
3595  v8::Local<v8::Context> context = Nan::GetCurrentContext();
3596 
3597  v8::Local<v8::Object> instance =
3598  cons->NewInstance(context, 0, nullptr).ToLocalChecked();
3599 
3600  auto me = Nan::ObjectWrap::Unwrap<RSPipelineProfile>(instance);
3601  me->pipeline_profile_ = profile;
3602  return scope.Escape(instance);
3603  }
3604 
3605  private:
3606  RSPipelineProfile() : pipeline_profile_(nullptr), error_(nullptr) {}
3607 
3609  DestroyMe();
3610  }
3611 
3612  void DestroyMe() {
3613  if (error_) rs2_free_error(error_);
3614  error_ = nullptr;
3615 
3616  if (pipeline_profile_) rs2_delete_pipeline_profile(pipeline_profile_);
3617  pipeline_profile_ = nullptr;
3618  }
3619 
3620  static NAN_METHOD(Destroy) {
3621  auto me = Nan::ObjectWrap::Unwrap<RSPipelineProfile>(info.Holder());
3622  if (me) me->DestroyMe();
3623  info.GetReturnValue().Set(Nan::Undefined());
3624  }
3625 
3626  static void New(const Nan::FunctionCallbackInfo<v8::Value>& info) {
3627  if (info.IsConstructCall()) {
3629  obj->Wrap(info.This());
3630  info.GetReturnValue().Set(info.This());
3631  }
3632  }
3633 
3634  static NAN_METHOD(GetStreams) {
3635  info.GetReturnValue().Set(Nan::Undefined());
3636  auto me = Nan::ObjectWrap::Unwrap<RSPipelineProfile>(info.Holder());
3637  if (!me) return;
3638 
3639  rs2_stream_profile_list* list = GetNativeResult<rs2_stream_profile_list*>(
3640  rs2_pipeline_profile_get_streams, &me->error_, me->pipeline_profile_,
3641  &me->error_);
3642  if (!list) return;
3643 
3644  int32_t size = GetNativeResult<int32_t>(rs2_get_stream_profiles_count,
3645  &me->error_, list, &me->error_);
3646  if (me->error_) return;
3647 
3648  v8::Local<v8::Array> array = Nan::New<v8::Array>(size);
3649  v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
3650  for (int32_t i = 0; i < size; i++) {
3652  GetNativeResult<const rs2_stream_profile*>(rs2_get_stream_profile,
3653  &me->error_, list, i, &me->error_));
3654  array->Set(context, i, RSStreamProfile::NewInstance(profile));
3655  }
3656  info.GetReturnValue().Set(array);
3657  }
3658 
3659  static NAN_METHOD(GetDevice) {
3660  info.GetReturnValue().Set(Nan::Undefined());
3661  auto me = Nan::ObjectWrap::Unwrap<RSPipelineProfile>(info.Holder());
3662  if (!me) return;
3663 
3664  rs2_device* dev = GetNativeResult<rs2_device*>(
3665  rs2_pipeline_profile_get_device, &me->error_, me->pipeline_profile_,
3666  &me->error_);
3667  if (!dev) return;
3668 
3669  info.GetReturnValue().Set(RSDevice::NewInstance(dev));
3670  }
3671 
3672  private:
3673  static Nan::Persistent<v8::Function> constructor_;
3674 
3677 };
3678 
3679 Nan::Persistent<v8::Function> RSPipelineProfile::constructor_;
3680 
3681 class RSPipeline;
3682 class RSConfig : public Nan::ObjectWrap {
3683  public:
3684  static void Init(v8::Local<v8::Object> exports) {
3685  v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
3686  tpl->SetClassName(Nan::New("RSConfig").ToLocalChecked());
3687  tpl->InstanceTemplate()->SetInternalFieldCount(1);
3688 
3689  Nan::SetPrototypeMethod(tpl, "destroy", Destroy);
3690  Nan::SetPrototypeMethod(tpl, "enableStream", EnableStream);
3691  Nan::SetPrototypeMethod(tpl, "enableAllStreams", EnableAllStreams);
3692  Nan::SetPrototypeMethod(tpl, "enableDevice", EnableDevice);
3693  Nan::SetPrototypeMethod(tpl, "enableDeviceFromFile", EnableDeviceFromFile);
3694  Nan::SetPrototypeMethod(tpl, "enableRecordToFile", EnableRecordToFile);
3695  Nan::SetPrototypeMethod(tpl, "disableStream", DisableStream);
3696  Nan::SetPrototypeMethod(tpl, "disableAllStreams", DisableAllStreams);
3697  Nan::SetPrototypeMethod(tpl, "resolve", Resolve);
3698  Nan::SetPrototypeMethod(tpl, "canResolve", CanResolve);
3699  Nan::SetPrototypeMethod(tpl, "enableDeviceFromFileRepeatOption",
3700  EnableDeviceFromFileRepeatOption);
3701 
3702  v8::Local<v8::Context> context = exports->CreationContext();
3703  constructor_.Reset(tpl->GetFunction(context).ToLocalChecked());
3704  exports->Set(context, Nan::New("RSConfig").ToLocalChecked(),
3705  tpl->GetFunction(context).ToLocalChecked());
3706  }
3707 
3708  static v8::Local<v8::Object> NewInstance() {
3709  Nan::EscapableHandleScope scope;
3710 
3711  v8::Local<v8::Function> cons = Nan::New<v8::Function>(constructor_);
3712  v8::Local<v8::Context> context = Nan::GetCurrentContext();
3713 
3714  v8::Local<v8::Object> instance =
3715  cons->NewInstance(context, 0, nullptr).ToLocalChecked();
3716 
3717  return scope.Escape(instance);
3718  }
3719 
3720  private:
3721  RSConfig() : config_(nullptr), error_(nullptr) {}
3722 
3724  DestroyMe();
3725  }
3726 
3727  void DestroyMe() {
3728  if (error_) rs2_free_error(error_);
3729  error_ = nullptr;
3730  if (config_) rs2_delete_config(config_);
3731  config_ = nullptr;
3732  }
3733 
3734  static NAN_METHOD(Destroy) {
3735  auto me = Nan::ObjectWrap::Unwrap<RSConfig>(info.Holder());
3736  if (me) me->DestroyMe();
3737  info.GetReturnValue().Set(Nan::Undefined());
3738  }
3739 
3740  static void New(const Nan::FunctionCallbackInfo<v8::Value>& info) {
3741  if (info.IsConstructCall()) {
3742  RSConfig* obj = new RSConfig();
3743  obj->config_ = rs2_create_config(&obj->error_);
3744  obj->Wrap(info.This());
3745  info.GetReturnValue().Set(info.This());
3746  }
3747  }
3748 
3749  // TODO(halton): added all the overloads
3750  static NAN_METHOD(EnableStream) {
3751  info.GetReturnValue().Set(Nan::Undefined());
3752  auto me = Nan::ObjectWrap::Unwrap<RSConfig>(info.Holder());
3753  auto stream = Nan::To<int64_t>(info[0]).FromJust();
3754  auto index = Nan::To<int64_t>(info[1]).FromJust();
3755  auto width = Nan::To<int64_t>(info[2]).FromJust();
3756  auto height = Nan::To<int64_t>(info[3]).FromJust();
3757  auto format = Nan::To<int64_t>(info[4]).FromJust();
3758  auto framerate = Nan::To<int64_t>(info[5]).FromJust();
3759  if (!me || !me->config_) return;
3760 
3761  CallNativeFunc(rs2_config_enable_stream, &me->error_, me->config_,
3762  (rs2_stream)stream,
3763  index,
3764  width,
3765  height,
3766  (rs2_format)format,
3767  framerate,
3768  &me->error_);
3769  }
3770 
3771  static NAN_METHOD(EnableAllStreams) {
3772  info.GetReturnValue().Set(Nan::Undefined());
3773  auto me = Nan::ObjectWrap::Unwrap<RSConfig>(info.Holder());
3774  if (!me) return;
3775 
3776  CallNativeFunc(rs2_config_enable_all_stream, &me->error_, me->config_,
3777  &me->error_);
3778  }
3779 
3780  static NAN_METHOD(EnableDevice) {
3781  info.GetReturnValue().Set(Nan::Undefined());
3782  auto me = Nan::ObjectWrap::Unwrap<RSConfig>(info.Holder());
3783  if (!me) return;
3784 
3785  Nan::Utf8String value(Nan::To<v8::String>(info[0]).ToLocalChecked());
3786  CallNativeFunc(rs2_config_enable_device, &me->error_, me->config_, *value,
3787  &me->error_);
3788  }
3789 
3790  static NAN_METHOD(EnableDeviceFromFile) {
3791  info.GetReturnValue().Set(Nan::Undefined());
3792  auto me = Nan::ObjectWrap::Unwrap<RSConfig>(info.Holder());
3793  if (!me) return;
3794 
3795  Nan::Utf8String value(Nan::To<v8::String>(info[0]).ToLocalChecked());
3796  CallNativeFunc(rs2_config_enable_device_from_file, &me->error_, me->config_,
3797  *value, &me->error_);
3798  }
3799 
3800  static NAN_METHOD(EnableDeviceFromFileRepeatOption) {
3801  info.GetReturnValue().Set(Nan::Undefined());
3802  auto me = Nan::ObjectWrap::Unwrap<RSConfig>(info.Holder());
3803  if (!me) return;
3804 
3805  auto repeat = Nan::To<bool>(info[1]).FromJust();
3806  Nan::Utf8String value(Nan::To<v8::String>(info[0]).ToLocalChecked());
3808  &me->error_, me->config_, *value, repeat, &me->error_);
3809  }
3810 
3811  static NAN_METHOD(EnableRecordToFile) {
3812  info.GetReturnValue().Set(Nan::Undefined());
3813  auto me = Nan::ObjectWrap::Unwrap<RSConfig>(info.Holder());
3814  if (!me) return;
3815 
3816  Nan::Utf8String value(Nan::To<v8::String>(info[0]).ToLocalChecked());
3817  CallNativeFunc(rs2_config_enable_record_to_file, &me->error_, me->config_,
3818  *value, &me->error_);
3819  }
3820 
3821  static NAN_METHOD(DisableStream) {
3822  info.GetReturnValue().Set(Nan::Undefined());
3823  auto me = Nan::ObjectWrap::Unwrap<RSConfig>(info.Holder());
3824  if (!me) return;
3825 
3826  auto stream = Nan::To<int64_t>(info[0]).FromJust();
3827  CallNativeFunc(rs2_config_disable_stream, &me->error_, me->config_,
3828  (rs2_stream)stream, &me->error_);
3829  }
3830 
3831  static NAN_METHOD(DisableAllStreams) {
3832  info.GetReturnValue().Set(Nan::Undefined());
3833  auto me = Nan::ObjectWrap::Unwrap<RSConfig>(info.Holder());
3834  if (!me) return;
3835 
3836  CallNativeFunc(rs2_config_disable_all_streams, &me->error_, me->config_,
3837  &me->error_);
3838  }
3839  static NAN_METHOD(Resolve);
3840  static NAN_METHOD(CanResolve);
3841 
3842  private:
3843  static Nan::Persistent<v8::Function> constructor_;
3844  friend class RSPipeline;
3845 
3848 };
3849 
3850 Nan::Persistent<v8::Function> RSConfig::constructor_;
3851 
3852 class RSPipeline : public Nan::ObjectWrap {
3853  public:
3854  static void Init(v8::Local<v8::Object> exports) {
3855  v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
3856  tpl->SetClassName(Nan::New("RSPipeline").ToLocalChecked());
3857  tpl->InstanceTemplate()->SetInternalFieldCount(1);
3858 
3859  Nan::SetPrototypeMethod(tpl, "start", Start);
3860  Nan::SetPrototypeMethod(tpl, "startWithConfig", StartWithConfig);
3861  Nan::SetPrototypeMethod(tpl, "stop", Stop);
3862  Nan::SetPrototypeMethod(tpl, "waitForFrames", WaitForFrames);
3863  Nan::SetPrototypeMethod(tpl, "pollForFrames", PollForFrames);
3864  Nan::SetPrototypeMethod(tpl, "getActiveProfile", GetActiveProfile);
3865  Nan::SetPrototypeMethod(tpl, "create", Create);
3866  Nan::SetPrototypeMethod(tpl, "destroy", Destroy);
3867 
3868  v8::Local<v8::Context> context = exports->CreationContext();
3869  constructor_.Reset(tpl->GetFunction(context).ToLocalChecked());
3870  exports->Set(context, Nan::New("RSPipeline").ToLocalChecked(),
3871  tpl->GetFunction(context).ToLocalChecked());
3872  }
3873 
3874  static v8::Local<v8::Object> NewInstance() {
3875  Nan::EscapableHandleScope scope;
3876 
3877  v8::Local<v8::Function> cons = Nan::New<v8::Function>(constructor_);
3878  v8::Local<v8::Context> context = Nan::GetCurrentContext();
3879 
3880  v8::Local<v8::Object> instance =
3881  cons->NewInstance(context, 0, nullptr).ToLocalChecked();
3882  return scope.Escape(instance);
3883  }
3884 
3885  private:
3886  friend class RSConfig;
3887 
3888  RSPipeline() : pipeline_(nullptr), error_(nullptr) {}
3889 
3891  DestroyMe();
3892  }
3893 
3894  void DestroyMe() {
3896  error_ = nullptr;
3897  if (pipeline_) rs2_delete_pipeline(pipeline_);
3898  pipeline_ = nullptr;
3899  }
3900 
3901  static NAN_METHOD(Destroy) {
3902  auto me = Nan::ObjectWrap::Unwrap<RSPipeline>(info.Holder());
3903  if (me) me->DestroyMe();
3904  info.GetReturnValue().Set(Nan::Undefined());
3905  }
3906 
3907  static void New(const Nan::FunctionCallbackInfo<v8::Value>& info) {
3908  if (info.IsConstructCall()) {
3909  RSPipeline* obj = new RSPipeline();
3910  obj->Wrap(info.This());
3911  info.GetReturnValue().Set(info.This());
3912  }
3913  }
3914 
3915  static NAN_METHOD(Create) {
3916  info.GetReturnValue().Set(Nan::Undefined());
3917  auto me = Nan::ObjectWrap::Unwrap<RSPipeline>(info.Holder());
3918  auto rsctx = Nan::ObjectWrap::Unwrap<RSContext>(Nan::To<v8::Object>(info[0]).ToLocalChecked());
3919  if (!me || !rsctx) return;
3920 
3921  me->pipeline_ = GetNativeResult<rs2_pipeline*>(rs2_create_pipeline,
3922  &me->error_, rsctx->ctx_, &me->error_);
3923  }
3924 
3925  static NAN_METHOD(StartWithConfig) {
3926  info.GetReturnValue().Set(Nan::Undefined());
3927  auto me = Nan::ObjectWrap::Unwrap<RSPipeline>(info.Holder());
3928  if (!me || !me->pipeline_) return;
3929 
3930  RSConfig* config = Nan::ObjectWrap::Unwrap<RSConfig>(Nan::To<v8::Object>(info[0]).ToLocalChecked());
3931  rs2_pipeline_profile* prof = GetNativeResult<rs2_pipeline_profile*>(
3932  rs2_pipeline_start_with_config, &me->error_, me->pipeline_,
3933  config->config_, &me->error_);
3934  if (!prof) return;
3935 
3936  info.GetReturnValue().Set(RSPipelineProfile::NewInstance(prof));
3937  }
3938 
3939  static NAN_METHOD(Start) {
3940  info.GetReturnValue().Set(Nan::Undefined());
3941  auto me = Nan::ObjectWrap::Unwrap<RSPipeline>(info.Holder());
3942  if (!me || !me->pipeline_) return;
3943 
3944  rs2_pipeline_profile* prof = GetNativeResult<rs2_pipeline_profile*>(
3945  rs2_pipeline_start, &me->error_, me->pipeline_, &me->error_);
3946  if (!prof) return;
3947 
3948  info.GetReturnValue().Set(RSPipelineProfile::NewInstance(prof));
3949  }
3950 
3951  static NAN_METHOD(Stop) {
3952  info.GetReturnValue().Set(Nan::Undefined());
3953  auto me = Nan::ObjectWrap::Unwrap<RSPipeline>(info.Holder());
3954  if (!me || !me->pipeline_) return;
3955 
3956  CallNativeFunc(rs2_pipeline_stop, &me->error_, me->pipeline_, &me->error_);
3957  }
3958 
3959  static NAN_METHOD(WaitForFrames) {
3960  info.GetReturnValue().Set(Nan::False());
3961  auto me = Nan::ObjectWrap::Unwrap<RSPipeline>(info.Holder());
3962  auto frameset = Nan::ObjectWrap::Unwrap<RSFrameSet>(Nan::To<v8::Object>(info[0]).ToLocalChecked());
3963  if (!me || !frameset) return;
3964 
3965  auto timeout = Nan::To<int64_t>(info[1]).FromJust();
3966  rs2_frame* frames = GetNativeResult<rs2_frame*>(
3967  rs2_pipeline_wait_for_frames, &me->error_, me->pipeline_, timeout,
3968  &me->error_);
3969  if (!frames) return;
3970 
3971  frameset->Replace(frames);
3972  info.GetReturnValue().Set(Nan::True());
3973  }
3974 
3975  static NAN_METHOD(PollForFrames) {
3976  info.GetReturnValue().Set(Nan::False());
3977  auto me = Nan::ObjectWrap::Unwrap<RSPipeline>(info.Holder());
3978  auto frameset = Nan::ObjectWrap::Unwrap<RSFrameSet>(Nan::To<v8::Object>(info[0]).ToLocalChecked());
3979  if (!me || !frameset) return;
3980 
3981  rs2_frame* frames = nullptr;
3982  auto res = GetNativeResult<int>(rs2_pipeline_poll_for_frames, &me->error_,
3983  me->pipeline_, &frames, &me->error_);
3984  if (!res) return;
3985 
3986  frameset->Replace(frames);
3987  info.GetReturnValue().Set(Nan::True());
3988  }
3989 
3990  static NAN_METHOD(GetActiveProfile) {
3991  info.GetReturnValue().Set(Nan::Undefined());
3992  auto me = Nan::ObjectWrap::Unwrap<RSPipeline>(info.Holder());
3993  if (!me) return;
3994 
3995  rs2_pipeline_profile* prof = GetNativeResult<rs2_pipeline_profile*>(
3996  rs2_pipeline_get_active_profile, &me->error_, me->pipeline_,
3997  &me->error_);
3998  if (!prof) return;
3999 
4000  info.GetReturnValue().Set(RSPipelineProfile::NewInstance(prof));
4001  }
4002 
4003  private:
4004  static Nan::Persistent<v8::Function> constructor_;
4005 
4008 };
4009 
4010 Nan::Persistent<v8::Function> RSPipeline::constructor_;
4011 
4012 NAN_METHOD(RSConfig::Resolve) {
4013  info.GetReturnValue().Set(Nan::Undefined());
4014  auto me = Nan::ObjectWrap::Unwrap<RSConfig>(info.Holder());
4015  if (!me) return;
4016 
4017  RSPipeline* pipe = Nan::ObjectWrap::Unwrap<RSPipeline>(Nan::To<v8::Object>(info[0]).ToLocalChecked());
4018  auto pipeline_profile = GetNativeResult<rs2_pipeline_profile*>(
4019  rs2_config_resolve, &me->error_, me->config_, pipe->pipeline_,
4020  &me->error_);
4021  if (!pipeline_profile) return;
4022 
4023  info.GetReturnValue().Set(RSPipelineProfile::NewInstance(pipeline_profile));
4024 }
4025 
4026 NAN_METHOD(RSConfig::CanResolve) {
4027  info.GetReturnValue().Set(Nan::Undefined());
4028  auto me = Nan::ObjectWrap::Unwrap<RSConfig>(info.Holder());
4029  if (!me) return;
4030 
4031  RSPipeline* pipe = Nan::ObjectWrap::Unwrap<RSPipeline>(Nan::To<v8::Object>(info[0]).ToLocalChecked());
4032  auto can_resolve = GetNativeResult<int>(rs2_config_can_resolve, &me->error_,
4033  me->config_, pipe->pipeline_, &me->error_);
4034  if (me->error_) return;
4035 
4036  info.GetReturnValue().Set(Nan::New(can_resolve ? true : false));
4037 }
4038 
4039 class RSColorizer : public Nan::ObjectWrap, Options {
4040  public:
4041  static void Init(v8::Local<v8::Object> exports) {
4042  v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
4043  tpl->SetClassName(Nan::New("RSColorizer").ToLocalChecked());
4044  tpl->InstanceTemplate()->SetInternalFieldCount(1);
4045 
4046  Nan::SetPrototypeMethod(tpl, "destroy", Destroy);
4047  Nan::SetPrototypeMethod(tpl, "create", Create);
4048  Nan::SetPrototypeMethod(tpl, "colorize", Colorize);
4049  Nan::SetPrototypeMethod(tpl, "supportsOption", SupportsOption);
4050  Nan::SetPrototypeMethod(tpl, "getOption", GetOption);
4051  Nan::SetPrototypeMethod(tpl, "setOption", SetOption);
4052  Nan::SetPrototypeMethod(tpl, "getOptionRange", GetOptionRange);
4053  Nan::SetPrototypeMethod(tpl, "isOptionReadonly", IsOptionReadonly);
4054  Nan::SetPrototypeMethod(tpl, "getOptionDescription", GetOptionDescription);
4055  Nan::SetPrototypeMethod(tpl, "getOptionValueDescription",
4056  GetOptionValueDescription);
4057 
4058  v8::Local<v8::Context> context = exports->CreationContext();
4059  constructor_.Reset(tpl->GetFunction(context).ToLocalChecked());
4060  exports->Set(context, Nan::New("RSColorizer").ToLocalChecked(),
4061  tpl->GetFunction(context).ToLocalChecked());
4062  }
4063 
4064  static v8::Local<v8::Object> NewInstance() {
4065  Nan::EscapableHandleScope scope;
4066 
4067  v8::Local<v8::Function> cons = Nan::New<v8::Function>(constructor_);
4068  v8::Local<v8::Context> context = Nan::GetCurrentContext();
4069 
4070  v8::Local<v8::Object> instance =
4071  cons->NewInstance(context, 0, nullptr).ToLocalChecked();
4072 
4073  return scope.Escape(instance);
4074  }
4075 
4077  // TODO(shaoting) find better way to avoid the reinterpret_cast which was
4078  // caused the inheritance relation was hidden
4079  return reinterpret_cast<rs2_options*>(colorizer_);
4080  }
4081 
4082  private:
4083  RSColorizer() : colorizer_(nullptr), frame_queue_(nullptr), error_(nullptr) {}
4084 
4086  DestroyMe();
4087  }
4088 
4089  void DestroyMe() {
4090  if (error_) rs2_free_error(error_);
4091  error_ = nullptr;
4092  if (colorizer_) rs2_delete_processing_block(colorizer_);
4093  colorizer_ = nullptr;
4094  if (frame_queue_) rs2_delete_frame_queue(frame_queue_);
4095  frame_queue_ = nullptr;
4096  }
4097 
4098  static NAN_METHOD(Destroy) {
4099  auto me = Nan::ObjectWrap::Unwrap<RSColorizer>(info.Holder());
4100  if (me) {
4101  me->DestroyMe();
4102  }
4103  info.GetReturnValue().Set(Nan::Undefined());
4104  }
4105 
4106  static void New(const Nan::FunctionCallbackInfo<v8::Value>& info) {
4107  if (info.IsConstructCall()) {
4108  RSColorizer* obj = new RSColorizer();
4109  obj->Wrap(info.This());
4110  info.GetReturnValue().Set(info.This());
4111  }
4112  }
4113 
4114  static NAN_METHOD(Create) {
4115  info.GetReturnValue().Set(Nan::Undefined());
4116  auto me = Nan::ObjectWrap::Unwrap<RSColorizer>(info.Holder());
4117  if (!me) return;
4118 
4119  me->colorizer_ = GetNativeResult<rs2_processing_block*>(
4120  rs2_create_colorizer, &me->error_, &me->error_);
4121  if (!me->colorizer_) return;
4122 
4123  me->frame_queue_ = GetNativeResult<rs2_frame_queue*>(
4124  rs2_create_frame_queue, &me->error_, 1, &me->error_);
4125  if (!me->frame_queue_) return;
4126 
4127  auto callback = new FrameCallbackForFrameQueue(me->frame_queue_);
4128  CallNativeFunc(rs2_start_processing, &me->error_, me->colorizer_, callback,
4129  &me->error_);
4130  }
4131 
4132  static NAN_METHOD(Colorize) {
4133  info.GetReturnValue().Set(Nan::False());
4134  auto me = Nan::ObjectWrap::Unwrap<RSColorizer>(info.Holder());
4135  RSFrame* depth = Nan::ObjectWrap::Unwrap<RSFrame>(Nan::To<v8::Object>(info[0]).ToLocalChecked());
4136  RSFrame* target = Nan::ObjectWrap::Unwrap<RSFrame>(Nan::To<v8::Object>(info[1]).ToLocalChecked());
4137  if (!me || !depth || !depth->frame_ || !target) return;
4138 
4139  // rs2_process_frame will release the input frame, so we need to addref
4140  CallNativeFunc(rs2_frame_add_ref, &me->error_, depth->frame_, &me->error_);
4141  if (me->error_) return;
4142 
4143  CallNativeFunc(rs2_process_frame, &me->error_, me->colorizer_,
4144  depth->frame_, &me->error_);
4145  if (me->error_) return;
4146 
4147  rs2_frame* result = GetNativeResult<rs2_frame*>(rs2_wait_for_frame,
4148  &me->error_, me->frame_queue_, 5000, &me->error_);
4149  target->DestroyMe();
4150  if (!result) return;
4151 
4152  target->Replace(result);
4153  info.GetReturnValue().Set(Nan::True());
4154  }
4155 
4156  static NAN_METHOD(SupportsOption) {
4157  auto me = Nan::ObjectWrap::Unwrap<RSColorizer>(info.Holder());
4158  if (me) return me->SupportsOptionInternal(info);
4159 
4160  info.GetReturnValue().Set(Nan::False());
4161  }
4162 
4163  static NAN_METHOD(GetOption) {
4164  auto me = Nan::ObjectWrap::Unwrap<RSColorizer>(info.Holder());
4165  if (me) return me->GetOptionInternal(info);
4166 
4167  info.GetReturnValue().Set(Nan::Undefined());
4168  }
4169 
4170  static NAN_METHOD(GetOptionDescription) {
4171  auto me = Nan::ObjectWrap::Unwrap<RSColorizer>(info.Holder());
4172  if (me) return me->GetOptionDescriptionInternal(info);
4173 
4174  info.GetReturnValue().Set(Nan::Undefined());
4175  }
4176 
4177  static NAN_METHOD(GetOptionValueDescription) {
4178  auto me = Nan::ObjectWrap::Unwrap<RSColorizer>(info.Holder());
4179  if (me) return me->GetOptionValueDescriptionInternal(info);
4180 
4181  info.GetReturnValue().Set(Nan::Undefined());
4182  }
4183 
4184  static NAN_METHOD(SetOption) {
4185  auto me = Nan::ObjectWrap::Unwrap<RSColorizer>(info.Holder());
4186  if (me) return me->SetOptionInternal(info);
4187 
4188  info.GetReturnValue().Set(Nan::Undefined());
4189  }
4190 
4191  static NAN_METHOD(GetOptionRange) {
4192  auto me = Nan::ObjectWrap::Unwrap<RSColorizer>(info.Holder());
4193  if (me) return me->GetOptionRangeInternal(info);
4194 
4195  info.GetReturnValue().Set(Nan::Undefined());
4196  }
4197 
4198  static NAN_METHOD(IsOptionReadonly) {
4199  auto me = Nan::ObjectWrap::Unwrap<RSColorizer>(info.Holder());
4200  if (me) return me->IsOptionReadonlyInternal(info);
4201 
4202  info.GetReturnValue().Set(Nan::False());
4203  }
4204 
4205  private:
4206  static Nan::Persistent<v8::Function> constructor_;
4207 
4211 };
4212 
4213 Nan::Persistent<v8::Function> RSColorizer::constructor_;
4214 
4215 class RSAlign : public Nan::ObjectWrap {
4216  public:
4217  static void Init(v8::Local<v8::Object> exports) {
4218  v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
4219  tpl->SetClassName(Nan::New("RSAlign").ToLocalChecked());
4220  tpl->InstanceTemplate()->SetInternalFieldCount(1);
4221 
4222  Nan::SetPrototypeMethod(tpl, "destroy", Destroy);
4223  Nan::SetPrototypeMethod(tpl, "waitForFrames", WaitForFrames);
4224  Nan::SetPrototypeMethod(tpl, "process", Process);
4225 
4226  v8::Local<v8::Context> context = exports->CreationContext();
4227  constructor_.Reset(tpl->GetFunction(context).ToLocalChecked());
4228  exports->Set(context, Nan::New("RSAlign").ToLocalChecked(),
4229  tpl->GetFunction(context).ToLocalChecked());
4230  }
4231 
4232  private:
4233  RSAlign() : align_(nullptr), frame_queue_(nullptr), error_(nullptr) {}
4234 
4236  DestroyMe();
4237  }
4238 
4239  void DestroyMe() {
4240  if (error_) rs2_free_error(error_);
4241  error_ = nullptr;
4242  if (align_) rs2_delete_processing_block(align_);
4243  align_ = nullptr;
4244  if (frame_queue_) rs2_delete_frame_queue(frame_queue_);
4245  frame_queue_ = nullptr;
4246  }
4247 
4248  static NAN_METHOD(Destroy) {
4249  auto me = Nan::ObjectWrap::Unwrap<RSAlign>(info.Holder());
4250  if (me) me->DestroyMe();
4251 
4252  info.GetReturnValue().Set(Nan::Undefined());
4253  }
4254 
4255  static void New(const Nan::FunctionCallbackInfo<v8::Value>& info) {
4256  if (!info.IsConstructCall()) return;
4257 
4258  RSAlign* obj = new RSAlign();
4259  auto stream = static_cast<rs2_stream>(Nan::To<int64_t>(info[0]).FromJust());
4260  obj->align_ = GetNativeResult<rs2_processing_block*>(rs2_create_align,
4261  &obj->error_, stream, &obj->error_);
4262  if (!obj->align_) return;
4263 
4264  obj->frame_queue_ = GetNativeResult<rs2_frame_queue*>(
4265  rs2_create_frame_queue, &obj->error_, 1, &obj->error_);
4266  if (!obj->frame_queue_) return;
4267 
4270  &obj->error_);
4271 
4272  obj->Wrap(info.This());
4273  info.GetReturnValue().Set(info.This());
4274  }
4275 
4276  static NAN_METHOD(WaitForFrames) {
4277  info.GetReturnValue().Set(Nan::Undefined());
4278  auto me = Nan::ObjectWrap::Unwrap<RSAlign>(info.Holder());
4279  if (!me) return;
4280 
4281  rs2_frame* result = GetNativeResult<rs2_frame*>(rs2_wait_for_frame,
4282  &me->error_, me->frame_queue_, 5000, &me->error_);
4283  if (!result) return;
4284 
4285  info.GetReturnValue().Set(RSFrameSet::NewInstance(result));
4286  }
4287 
4288  static NAN_METHOD(Process) {
4289  info.GetReturnValue().Set(Nan::False());
4290  auto me = Nan::ObjectWrap::Unwrap<RSAlign>(info.Holder());
4291  auto frameset = Nan::ObjectWrap::Unwrap<RSFrameSet>(Nan::To<v8::Object>(info[0]).ToLocalChecked());
4292  auto target_fs = Nan::ObjectWrap::Unwrap<RSFrameSet>(Nan::To<v8::Object>(info[1]).ToLocalChecked());
4293  if (!me || !frameset || !target_fs) return;
4294 
4295  // rs2_process_frame will release the input frame, so we need to addref
4296  CallNativeFunc(rs2_frame_add_ref, &me->error_, frameset->GetFrames(),
4297  &me->error_);
4298  if (me->error_) return;
4299 
4300  CallNativeFunc(rs2_process_frame, &me->error_, me->align_,
4301  frameset->GetFrames(), &me->error_);
4302  if (me->error_) return;
4303 
4304  rs2_frame* frame = nullptr;
4305  auto ret_code = GetNativeResult<int>(rs2_poll_for_frame, &me->error_,
4306  me->frame_queue_, &frame, &me->error_);
4307  if (!ret_code) return;
4308 
4309  target_fs->Replace(frame);
4310  info.GetReturnValue().Set(Nan::True());
4311  }
4312 
4313  private:
4314  static Nan::Persistent<v8::Function> constructor_;
4315 
4319  friend class RSPipeline;
4320 };
4321 
4322 Nan::Persistent<v8::Function> RSAlign::constructor_;
4323 
4324 class RSFilter : public Nan::ObjectWrap, Options {
4325  public:
4326  enum FilterType {
4327  kFilterDecimation = 0,
4332  kFilterDepth2Disparity
4333  };
4334  static void Init(v8::Local<v8::Object> exports) {
4335  v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
4336  tpl->SetClassName(Nan::New("RSFilter").ToLocalChecked());
4337  tpl->InstanceTemplate()->SetInternalFieldCount(1);
4338 
4339  Nan::SetPrototypeMethod(tpl, "destroy", Destroy);
4340  Nan::SetPrototypeMethod(tpl, "process", Process);
4341  Nan::SetPrototypeMethod(tpl, "supportsOption", SupportsOption);
4342  Nan::SetPrototypeMethod(tpl, "getOption", GetOption);
4343  Nan::SetPrototypeMethod(tpl, "setOption", SetOption);
4344  Nan::SetPrototypeMethod(tpl, "getOptionRange", GetOptionRange);
4345  Nan::SetPrototypeMethod(tpl, "isOptionReadonly", IsOptionReadonly);
4346  Nan::SetPrototypeMethod(tpl, "getOptionDescription", GetOptionDescription);
4347  Nan::SetPrototypeMethod(tpl, "getOptionValueDescription",
4348  GetOptionValueDescription);
4349 
4350  v8::Local<v8::Context> context = exports->CreationContext();
4351  constructor_.Reset(tpl->GetFunction(context).ToLocalChecked());
4352  exports->Set(context, Nan::New("RSFilter").ToLocalChecked(),
4353  tpl->GetFunction(context).ToLocalChecked());
4354  }
4355 
4357  return reinterpret_cast<rs2_options*>(block_);
4358  }
4359 
4360  private:
4361  RSFilter() : block_(nullptr), frame_queue_(nullptr), error_(nullptr),
4362  type_(kFilterDecimation) {}
4363 
4365  DestroyMe();
4366  }
4367 
4368  void DestroyMe() {
4369  if (error_) rs2_free_error(error_);
4370  error_ = nullptr;
4371  if (block_) rs2_delete_processing_block(block_);
4372  block_ = nullptr;
4373  if (frame_queue_) rs2_delete_frame_queue(frame_queue_);
4374  frame_queue_ = nullptr;
4375  }
4376 
4377  static NAN_METHOD(Destroy) {
4378  auto me = Nan::ObjectWrap::Unwrap<RSFilter>(info.Holder());
4379  if (me) me->DestroyMe();
4380 
4381  info.GetReturnValue().Set(Nan::Undefined());
4382  }
4383 
4384  static void New(const Nan::FunctionCallbackInfo<v8::Value>& info) {
4385  if (!info.IsConstructCall()) return;
4386 
4387  Nan::Utf8String type_str(Nan::To<v8::String>(info[0]).ToLocalChecked());
4388  std::string type = std::string(*type_str);
4389  RSFilter* obj = new RSFilter();
4390  if (!(type.compare("decimation"))) {
4391  obj->type_ = kFilterDecimation;
4392  obj->block_ = GetNativeResult<rs2_processing_block*>(
4394  } else if (!(type.compare("temporal"))) {
4395  obj->type_ = kFilterTemporal;
4396  obj->block_ = GetNativeResult<rs2_processing_block*>(
4398  } else if (!(type.compare("spatial"))) {
4399  obj->type_ = kFilterSpatial;
4400  obj->block_ = GetNativeResult<rs2_processing_block*>(
4402  } else if (!(type.compare("hole-filling"))) {
4403  obj->type_ = kFilterHoleFilling;
4404  obj->block_ = GetNativeResult<rs2_processing_block*>(
4406  } else if (!(type.compare("disparity-to-depth"))) {
4407  obj->type_ = kFilterDisparity2Depth;
4408  obj->block_ = GetNativeResult<rs2_processing_block*>(
4410  } else if (!(type.compare("depth-to-disparity"))) {
4411  obj->type_ = kFilterDepth2Disparity;
4412  obj->block_ = GetNativeResult<rs2_processing_block*>(
4414  }
4415  if (!obj->block_) return;
4416 
4417  obj->frame_queue_ = GetNativeResult<rs2_frame_queue*>(
4418  rs2_create_frame_queue, &obj->error_, 1, &obj->error_);
4419  if (!obj->frame_queue_) return;
4420 
4423  &obj->error_);
4424  if (obj->error_) return;
4425 
4426  obj->Wrap(info.This());
4427  info.GetReturnValue().Set(info.This());
4428  }
4429 
4430  static NAN_METHOD(Process) {
4431  auto me = Nan::ObjectWrap::Unwrap<RSFilter>(info.Holder());
4432  auto input_frame = Nan::ObjectWrap::Unwrap<RSFrame>(Nan::To<v8::Object>(info[0]).ToLocalChecked());
4433  auto out_frame = Nan::ObjectWrap::Unwrap<RSFrame>(Nan::To<v8::Object>(info[1]).ToLocalChecked());
4434  info.GetReturnValue().Set(Nan::False());
4435  if (!me || !input_frame || !out_frame) return;
4436 
4437  // rs2_process_frame will release the input frame, so we need to addref
4438  CallNativeFunc(rs2_frame_add_ref, &me->error_, input_frame->frame_,
4439  &me->error_);
4440  if (me->error_) return;
4441 
4442  CallNativeFunc(rs2_process_frame, &me->error_, me->block_,
4443  input_frame->frame_, &me->error_);
4444  if (me->error_) return;
4445 
4446  rs2_frame* frame = nullptr;
4447  auto ret_code = GetNativeResult<int>(rs2_poll_for_frame, &me->error_,
4448  me->frame_queue_, &frame, &me->error_);
4449  if (!ret_code) return;
4450 
4451  out_frame->Replace(frame);
4452  info.GetReturnValue().Set(Nan::True());
4453  }
4454 
4455  static NAN_METHOD(SupportsOption) {
4456  auto me = Nan::ObjectWrap::Unwrap<RSFilter>(info.Holder());
4457  if (me) return me->SupportsOptionInternal(info);
4458 
4459  info.GetReturnValue().Set(Nan::False());
4460  }
4461 
4462  static NAN_METHOD(GetOption) {
4463  auto me = Nan::ObjectWrap::Unwrap<RSFilter>(info.Holder());
4464  if (me) return me->GetOptionInternal(info);
4465 
4466  info.GetReturnValue().Set(Nan::Undefined());
4467  }
4468 
4469  static NAN_METHOD(GetOptionDescription) {
4470  auto me = Nan::ObjectWrap::Unwrap<RSFilter>(info.Holder());
4471  if (me) return me->GetOptionDescriptionInternal(info);
4472 
4473  info.GetReturnValue().Set(Nan::Undefined());
4474  }
4475 
4476  static NAN_METHOD(GetOptionValueDescription) {
4477  auto me = Nan::ObjectWrap::Unwrap<RSFilter>(info.Holder());
4478  if (me) return me->GetOptionValueDescriptionInternal(info);
4479 
4480  info.GetReturnValue().Set(Nan::Undefined());
4481  }
4482 
4483  static NAN_METHOD(SetOption) {
4484  auto me = Nan::ObjectWrap::Unwrap<RSFilter>(info.Holder());
4485  if (me) return me->SetOptionInternal(info);
4486 
4487  info.GetReturnValue().Set(Nan::Undefined());
4488  }
4489 
4490  static NAN_METHOD(GetOptionRange) {
4491  auto me = Nan::ObjectWrap::Unwrap<RSFilter>(info.Holder());
4492  if (me) return me->GetOptionRangeInternal(info);
4493 
4494  info.GetReturnValue().Set(Nan::Undefined());
4495  }
4496 
4497  static NAN_METHOD(IsOptionReadonly) {
4498  auto me = Nan::ObjectWrap::Unwrap<RSFilter>(info.Holder());
4499  if (me) return me->IsOptionReadonlyInternal(info);
4500 
4501  info.GetReturnValue().Set(Nan::False());
4502  }
4503 
4504  private:
4505  static Nan::Persistent<v8::Function> constructor_;
4506 
4511 };
4512 
4513 Nan::Persistent<v8::Function> RSFilter::constructor_;
4514 
4518 //
4519 // 888b d888 888 888 //
4520 // 8888b d8888 888 888 //
4521 // 88888b.d88888 888 888 //
4522 // 888Y88888P888 .d88b. .d88888 888 888 888 .d88b. //
4523 // 888 Y888P 888 d88""88b d88" 888 888 888 888 d8P Y8b //
4524 // 888 Y8P 888 888 888 888 888 888 888 888 88888888 //
4525 // 888 " 888 Y88..88P Y88b 888 Y88b 888 888 Y8b. //
4526 // 888 888 "Y88P" "Y88888 "Y88888 888 "Y8888 //
4527 //
4530 
4531 NAN_METHOD(GlobalCleanup) {
4534  info.GetReturnValue().Set(Nan::Undefined());
4535 }
4536 
4538  rs2_error* e = nullptr;
4539  auto time = rs2_get_time(&e);
4540  info.GetReturnValue().Set(Nan::New(time));
4541 }
4542 
4543 NAN_METHOD(RegisterErrorCallback) {
4544  ErrorUtil::Init();
4546 }
4547 
4548 NAN_METHOD(GetError) {
4549  info.GetReturnValue().Set(ErrorUtil::GetJSErrorObject());
4550 }
4551 
4552 #define _FORCE_SET_ENUM(name) \
4553  Nan::DefineOwnProperty(exports, \
4554  Nan::New(#name).ToLocalChecked(), \
4555  Nan::New(static_cast<int>((name))), \
4556  static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete));
4557 
4558 void InitModule(v8::Local<v8::Object> exports) {
4559  v8::Local<v8::Context> context = exports->CreationContext();
4560 
4561  exports->Set(context, Nan::New("globalCleanup").ToLocalChecked(),
4562  Nan::New<v8::FunctionTemplate>(GlobalCleanup)->GetFunction(context).ToLocalChecked());
4563  exports->Set(context, Nan::New("getTime").ToLocalChecked(),
4564  Nan::New<v8::FunctionTemplate>(GetTime)->GetFunction(context).ToLocalChecked());
4565  exports->Set(context, Nan::New("registerErrorCallback").ToLocalChecked(),
4566  Nan::New<v8::FunctionTemplate>(RegisterErrorCallback)->GetFunction(context).ToLocalChecked());
4567  exports->Set(context, Nan::New("getError").ToLocalChecked(),
4568  Nan::New<v8::FunctionTemplate>(GetError)->GetFunction(context).ToLocalChecked());
4569  // rs2_error* error = nullptr;
4570  // rs2_log_to_console(RS2_LOG_SEVERITY_DEBUG, &error);
4571 
4572  RSContext::Init(exports);
4573  RSPointCloud::Init(exports);
4574  RSPipelineProfile::Init(exports);
4575  RSConfig::Init(exports);
4576  RSPipeline::Init(exports);
4577  RSFrameSet::Init(exports);
4578  RSSensor::Init(exports);
4579  RSDevice::Init(exports);
4580  RSDeviceList::Init(exports);
4581  RSDeviceHub::Init(exports);
4582  RSStreamProfile::Init(exports);
4583  RSColorizer::Init(exports);
4584  RSFrameQueue::Init(exports);
4585  RSFrame::Init(exports);
4586  RSSyncer::Init(exports);
4587  RSAlign::Init(exports);
4588  RSFilter::Init(exports);
4589 
4590  // rs2_exception_type
4600 
4601  // rs2_stream
4613 
4614  // rs2_format
4646 
4647  // rs2_frame_metadata_value
4685 
4686  // rs2_distortion
4694 
4695  // rs2_option
4785 
4786  // rs2_camera_info
4802 
4803 
4804  // rs2_log_severity
4813 
4814  // rs2_notification_category
4823 
4824  // rs2_timestamp_domain
4829 
4830  // rs2_calib_target_type
4833 
4834  // rs2_recording_mode
4839 
4840  // rs2_sr300_visual_preset
4853 
4854  // rs2_rs400_visual_preset
4863 
4864  // rs2_playback_status
4870 
4871 
4872  // rs2_extension
4930 
4931 
4932  // rs2_ambient_light
4935 
4936 
4937  // rs2_cah_trigger
4942 
4943 
4944  // rs2_calibration_type
4949 
4950 
4951  // rs2_calibration_status
4965 
4966 
4967  // rs2_dsm_correction_model
4972 
4973 
4974  // rs2_host_perf_mode
4979 
4980 
4981  // rs2_l500_visual_preset
4990 
4991 
4992  // rs2_matchers
5001 
5002 
5003  // rs2_sensor_mode
5008 
5009 
5010  // rs2_digital_gain
5014 }
5015 
5016 NODE_MODULE(node_librealsense, InitModule);
static void New(const Nan::FunctionCallbackInfo< v8::Value > &info)
Definition: addon.cpp:3740
static void FillAFloatVector(v8::Local< v8::Object > obj, const rs2_vector &vec)
Definition: addon.cpp:750
const char * rs2_playback_device_get_file_path(const rs2_device *device, rs2_error **error)
Definition: rs.cpp:1556
ContextType type_
Definition: addon.cpp:3396
RSFrame * pose_frame_
Definition: addon.cpp:2403
RSAlign()
Definition: addon.cpp:4233
void DestroyMe()
Definition: addon.cpp:2936
rs2_processing_block * rs2_create_decimation_filter_block(rs2_error **error)
Definition: rs.cpp:2232
static v8::Local< v8::Object > NewInstance()
Definition: addon.cpp:4064
rs2_error * error_
Definition: addon.cpp:616
int rs2_get_sensors_count(const rs2_sensor_list *info_list, rs2_error **error)
Definition: rs.cpp:267
rs2_camera_info
Read-only strings that can be queried from the device. Not all information attributes are available o...
Definition: rs_sensor.h:22
void InitModule(v8::Local< v8::Object > exports)
Definition: addon.cpp:4558
RSDevice(DeviceType type=kNormalDevice)
Definition: addon.cpp:2503
int rs2_pipeline_poll_for_frames(rs2_pipeline *pipe, rs2_frame **output_frame, rs2_error **error)
Definition: rs.cpp:1785
rs2_error * error_
Definition: addon.cpp:3847
void rs2_config_enable_stream(rs2_config *config, rs2_stream stream, int index, int width, int height, rs2_format format, int framerate, rs2_error **error)
Definition: rs.cpp:1928
static NAN_METHOD(Close)
Definition: addon.cpp:2308
void on_notification(rs2_notification *notification) override
Definition: addon.cpp:1472
void rs2_export_to_ply(const rs2_frame *frame, const char *fname, rs2_frame *texture, rs2_error **error)
Definition: rs.cpp:2162
void release() override
Definition: addon.cpp:1513
static NAN_METHOD(IsOptionReadonly)
Definition: addon.cpp:4497
virtual void Release()
Definition: addon.cpp:1433