// Copyright (c) The NodeRT Contributors
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the ""License""); you may
// not use this file except in compliance with the License. You may obtain a
// copy of the License at http://www.apache.org/licenses/LICENSE-2.0
//
// THIS CODE IS PROVIDED ON AN  *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
// OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY
// IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
// MERCHANTABLITY OR NON-INFRINGEMENT.
//
// See the Apache Version 2.0 License for specific language governing permissions
// and limitations under the License.

// TODO: Verify that this is is still needed..
#define NTDDI_VERSION 0x06010000

#include <v8.h>
#include "nan.h"
#include <string>
#include <ppltasks.h>
#include "CollectionsConverter.h"
#include "CollectionsWrap.h"
#include "node-async.h"
#include "NodeRtUtils.h"
#include "OpaqueWrapper.h"
#include "WrapperBase.h"

#using <Windows.WinMD>

// this undefs fixes the issues of compiling Windows.Data.Json, Windows.Storag.FileProperties, and Windows.Stroage.Search
// Some of the node header files brings windows definitions with the same names as some of the WinRT methods
#undef DocumentProperties
#undef GetObject
#undef CreateEvent
#undef FindText
#undef SendMessage

const char* REGISTRATION_TOKEN_MAP_PROPERTY_NAME = "__registrationTokenMap__";

using v8::Array;
using v8::String;
using v8::Value;
using v8::Boolean;
using v8::Integer;
using v8::FunctionTemplate;
using v8::Object;
using v8::Local;
using v8::Function;
using v8::Date;
using v8::Number;
using v8::PropertyAttribute;
using v8::Primitive;
using Nan::HandleScope;
using Nan::Persistent;
using Nan::Undefined;
using Nan::True;
using Nan::False;
using Nan::Null;
using Nan::MaybeLocal;
using Nan::EscapableHandleScope;
using Nan::HandleScope;
using Nan::TryCatch;
using namespace concurrency;

namespace NodeRT { namespace Windows { namespace Media { namespace Capture { namespace Frames { 
  v8::Local<v8::Value> WrapAudioMediaFrame(::Windows::Media::Capture::Frames::AudioMediaFrame^ wintRtInstance);
  ::Windows::Media::Capture::Frames::AudioMediaFrame^ UnwrapAudioMediaFrame(Local<Value> value);
  
  v8::Local<v8::Value> WrapBufferMediaFrame(::Windows::Media::Capture::Frames::BufferMediaFrame^ wintRtInstance);
  ::Windows::Media::Capture::Frames::BufferMediaFrame^ UnwrapBufferMediaFrame(Local<Value> value);
  
  v8::Local<v8::Value> WrapDepthMediaFrame(::Windows::Media::Capture::Frames::DepthMediaFrame^ wintRtInstance);
  ::Windows::Media::Capture::Frames::DepthMediaFrame^ UnwrapDepthMediaFrame(Local<Value> value);
  
  v8::Local<v8::Value> WrapDepthMediaFrameFormat(::Windows::Media::Capture::Frames::DepthMediaFrameFormat^ wintRtInstance);
  ::Windows::Media::Capture::Frames::DepthMediaFrameFormat^ UnwrapDepthMediaFrameFormat(Local<Value> value);
  
  v8::Local<v8::Value> WrapInfraredMediaFrame(::Windows::Media::Capture::Frames::InfraredMediaFrame^ wintRtInstance);
  ::Windows::Media::Capture::Frames::InfraredMediaFrame^ UnwrapInfraredMediaFrame(Local<Value> value);
  
  v8::Local<v8::Value> WrapMediaFrameArrivedEventArgs(::Windows::Media::Capture::Frames::MediaFrameArrivedEventArgs^ wintRtInstance);
  ::Windows::Media::Capture::Frames::MediaFrameArrivedEventArgs^ UnwrapMediaFrameArrivedEventArgs(Local<Value> value);
  
  v8::Local<v8::Value> WrapMediaFrameFormat(::Windows::Media::Capture::Frames::MediaFrameFormat^ wintRtInstance);
  ::Windows::Media::Capture::Frames::MediaFrameFormat^ UnwrapMediaFrameFormat(Local<Value> value);
  
  v8::Local<v8::Value> WrapMediaFrameReader(::Windows::Media::Capture::Frames::MediaFrameReader^ wintRtInstance);
  ::Windows::Media::Capture::Frames::MediaFrameReader^ UnwrapMediaFrameReader(Local<Value> value);
  
  v8::Local<v8::Value> WrapMediaFrameReference(::Windows::Media::Capture::Frames::MediaFrameReference^ wintRtInstance);
  ::Windows::Media::Capture::Frames::MediaFrameReference^ UnwrapMediaFrameReference(Local<Value> value);
  
  v8::Local<v8::Value> WrapMediaFrameSource(::Windows::Media::Capture::Frames::MediaFrameSource^ wintRtInstance);
  ::Windows::Media::Capture::Frames::MediaFrameSource^ UnwrapMediaFrameSource(Local<Value> value);
  
  v8::Local<v8::Value> WrapMediaFrameSourceController(::Windows::Media::Capture::Frames::MediaFrameSourceController^ wintRtInstance);
  ::Windows::Media::Capture::Frames::MediaFrameSourceController^ UnwrapMediaFrameSourceController(Local<Value> value);
  
  v8::Local<v8::Value> WrapMediaFrameSourceGetPropertyResult(::Windows::Media::Capture::Frames::MediaFrameSourceGetPropertyResult^ wintRtInstance);
  ::Windows::Media::Capture::Frames::MediaFrameSourceGetPropertyResult^ UnwrapMediaFrameSourceGetPropertyResult(Local<Value> value);
  
  v8::Local<v8::Value> WrapMediaFrameSourceGroup(::Windows::Media::Capture::Frames::MediaFrameSourceGroup^ wintRtInstance);
  ::Windows::Media::Capture::Frames::MediaFrameSourceGroup^ UnwrapMediaFrameSourceGroup(Local<Value> value);
  
  v8::Local<v8::Value> WrapMediaFrameSourceInfo(::Windows::Media::Capture::Frames::MediaFrameSourceInfo^ wintRtInstance);
  ::Windows::Media::Capture::Frames::MediaFrameSourceInfo^ UnwrapMediaFrameSourceInfo(Local<Value> value);
  
  v8::Local<v8::Value> WrapMultiSourceMediaFrameArrivedEventArgs(::Windows::Media::Capture::Frames::MultiSourceMediaFrameArrivedEventArgs^ wintRtInstance);
  ::Windows::Media::Capture::Frames::MultiSourceMediaFrameArrivedEventArgs^ UnwrapMultiSourceMediaFrameArrivedEventArgs(Local<Value> value);
  
  v8::Local<v8::Value> WrapMultiSourceMediaFrameReader(::Windows::Media::Capture::Frames::MultiSourceMediaFrameReader^ wintRtInstance);
  ::Windows::Media::Capture::Frames::MultiSourceMediaFrameReader^ UnwrapMultiSourceMediaFrameReader(Local<Value> value);
  
  v8::Local<v8::Value> WrapMultiSourceMediaFrameReference(::Windows::Media::Capture::Frames::MultiSourceMediaFrameReference^ wintRtInstance);
  ::Windows::Media::Capture::Frames::MultiSourceMediaFrameReference^ UnwrapMultiSourceMediaFrameReference(Local<Value> value);
  
  v8::Local<v8::Value> WrapVideoMediaFrame(::Windows::Media::Capture::Frames::VideoMediaFrame^ wintRtInstance);
  ::Windows::Media::Capture::Frames::VideoMediaFrame^ UnwrapVideoMediaFrame(Local<Value> value);
  
  v8::Local<v8::Value> WrapVideoMediaFrameFormat(::Windows::Media::Capture::Frames::VideoMediaFrameFormat^ wintRtInstance);
  ::Windows::Media::Capture::Frames::VideoMediaFrameFormat^ UnwrapVideoMediaFrameFormat(Local<Value> value);
  



  static void InitMediaFrameReaderAcquisitionModeEnum(const Local<Object> exports) {
    HandleScope scope;

    Local<Object> enumObject = Nan::New<Object>();

    Nan::Set(exports, Nan::New<String>("MediaFrameReaderAcquisitionMode").ToLocalChecked(), enumObject);
    Nan::Set(enumObject, Nan::New<String>("realtime").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Media::Capture::Frames::MediaFrameReaderAcquisitionMode::Realtime)));
    Nan::Set(enumObject, Nan::New<String>("buffered").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Media::Capture::Frames::MediaFrameReaderAcquisitionMode::Buffered)));
  }

  static void InitMediaFrameReaderStartStatusEnum(const Local<Object> exports) {
    HandleScope scope;

    Local<Object> enumObject = Nan::New<Object>();

    Nan::Set(exports, Nan::New<String>("MediaFrameReaderStartStatus").ToLocalChecked(), enumObject);
    Nan::Set(enumObject, Nan::New<String>("success").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Media::Capture::Frames::MediaFrameReaderStartStatus::Success)));
    Nan::Set(enumObject, Nan::New<String>("unknownFailure").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Media::Capture::Frames::MediaFrameReaderStartStatus::UnknownFailure)));
    Nan::Set(enumObject, Nan::New<String>("deviceNotAvailable").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Media::Capture::Frames::MediaFrameReaderStartStatus::DeviceNotAvailable)));
    Nan::Set(enumObject, Nan::New<String>("outputFormatNotSupported").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Media::Capture::Frames::MediaFrameReaderStartStatus::OutputFormatNotSupported)));
    Nan::Set(enumObject, Nan::New<String>("exclusiveControlNotAvailable").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Media::Capture::Frames::MediaFrameReaderStartStatus::ExclusiveControlNotAvailable)));
  }

  static void InitMediaFrameSourceGetPropertyStatusEnum(const Local<Object> exports) {
    HandleScope scope;

    Local<Object> enumObject = Nan::New<Object>();

    Nan::Set(exports, Nan::New<String>("MediaFrameSourceGetPropertyStatus").ToLocalChecked(), enumObject);
    Nan::Set(enumObject, Nan::New<String>("success").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Media::Capture::Frames::MediaFrameSourceGetPropertyStatus::Success)));
    Nan::Set(enumObject, Nan::New<String>("unknownFailure").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Media::Capture::Frames::MediaFrameSourceGetPropertyStatus::UnknownFailure)));
    Nan::Set(enumObject, Nan::New<String>("notSupported").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Media::Capture::Frames::MediaFrameSourceGetPropertyStatus::NotSupported)));
    Nan::Set(enumObject, Nan::New<String>("deviceNotAvailable").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Media::Capture::Frames::MediaFrameSourceGetPropertyStatus::DeviceNotAvailable)));
    Nan::Set(enumObject, Nan::New<String>("maxPropertyValueSizeTooSmall").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Media::Capture::Frames::MediaFrameSourceGetPropertyStatus::MaxPropertyValueSizeTooSmall)));
    Nan::Set(enumObject, Nan::New<String>("maxPropertyValueSizeRequired").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Media::Capture::Frames::MediaFrameSourceGetPropertyStatus::MaxPropertyValueSizeRequired)));
  }

  static void InitMediaFrameSourceKindEnum(const Local<Object> exports) {
    HandleScope scope;

    Local<Object> enumObject = Nan::New<Object>();

    Nan::Set(exports, Nan::New<String>("MediaFrameSourceKind").ToLocalChecked(), enumObject);
    Nan::Set(enumObject, Nan::New<String>("custom").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Media::Capture::Frames::MediaFrameSourceKind::Custom)));
    Nan::Set(enumObject, Nan::New<String>("color").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Media::Capture::Frames::MediaFrameSourceKind::Color)));
    Nan::Set(enumObject, Nan::New<String>("infrared").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Media::Capture::Frames::MediaFrameSourceKind::Infrared)));
    Nan::Set(enumObject, Nan::New<String>("depth").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Media::Capture::Frames::MediaFrameSourceKind::Depth)));
    Nan::Set(enumObject, Nan::New<String>("audio").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Media::Capture::Frames::MediaFrameSourceKind::Audio)));
    Nan::Set(enumObject, Nan::New<String>("image").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Media::Capture::Frames::MediaFrameSourceKind::Image)));
    Nan::Set(enumObject, Nan::New<String>("metadata").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Media::Capture::Frames::MediaFrameSourceKind::Metadata)));
  }

  static void InitMediaFrameSourceSetPropertyStatusEnum(const Local<Object> exports) {
    HandleScope scope;

    Local<Object> enumObject = Nan::New<Object>();

    Nan::Set(exports, Nan::New<String>("MediaFrameSourceSetPropertyStatus").ToLocalChecked(), enumObject);
    Nan::Set(enumObject, Nan::New<String>("success").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Media::Capture::Frames::MediaFrameSourceSetPropertyStatus::Success)));
    Nan::Set(enumObject, Nan::New<String>("unknownFailure").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Media::Capture::Frames::MediaFrameSourceSetPropertyStatus::UnknownFailure)));
    Nan::Set(enumObject, Nan::New<String>("notSupported").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Media::Capture::Frames::MediaFrameSourceSetPropertyStatus::NotSupported)));
    Nan::Set(enumObject, Nan::New<String>("invalidValue").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Media::Capture::Frames::MediaFrameSourceSetPropertyStatus::InvalidValue)));
    Nan::Set(enumObject, Nan::New<String>("deviceNotAvailable").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Media::Capture::Frames::MediaFrameSourceSetPropertyStatus::DeviceNotAvailable)));
    Nan::Set(enumObject, Nan::New<String>("notInControl").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Media::Capture::Frames::MediaFrameSourceSetPropertyStatus::NotInControl)));
  }

  static void InitMultiSourceMediaFrameReaderStartStatusEnum(const Local<Object> exports) {
    HandleScope scope;

    Local<Object> enumObject = Nan::New<Object>();

    Nan::Set(exports, Nan::New<String>("MultiSourceMediaFrameReaderStartStatus").ToLocalChecked(), enumObject);
    Nan::Set(enumObject, Nan::New<String>("success").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Media::Capture::Frames::MultiSourceMediaFrameReaderStartStatus::Success)));
    Nan::Set(enumObject, Nan::New<String>("notSupported").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Media::Capture::Frames::MultiSourceMediaFrameReaderStartStatus::NotSupported)));
    Nan::Set(enumObject, Nan::New<String>("insufficientResources").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Media::Capture::Frames::MultiSourceMediaFrameReaderStartStatus::InsufficientResources)));
    Nan::Set(enumObject, Nan::New<String>("deviceNotAvailable").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Media::Capture::Frames::MultiSourceMediaFrameReaderStartStatus::DeviceNotAvailable)));
    Nan::Set(enumObject, Nan::New<String>("unknownFailure").ToLocalChecked(), Nan::New<Integer>(static_cast<int>(::Windows::Media::Capture::Frames::MultiSourceMediaFrameReaderStartStatus::UnknownFailure)));
  }



  class AudioMediaFrame : public WrapperBase {
    public:
      
      static void Init(const Local<Object> exports) {
        HandleScope scope;

        Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(New);
        s_constructorTemplate.Reset(localRef);
        localRef->SetClassName(Nan::New<String>("AudioMediaFrame").ToLocalChecked());
        localRef->InstanceTemplate()->SetInternalFieldCount(1);


          
            Nan::SetPrototypeMethod(localRef, "getAudioFrame", GetAudioFrame);
          



          
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("audioEncodingProperties").ToLocalChecked(), AudioEncodingPropertiesGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("frameReference").ToLocalChecked(), FrameReferenceGetter);

        Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
        Nan::SetMethod(constructor, "castFrom", CastFrom);



        Nan::Set(exports, Nan::New<String>("AudioMediaFrame").ToLocalChecked(), constructor);
      }

      virtual ::Platform::Object^ GetObjectInstance() const override {
        return _instance;
      }

    private:

      AudioMediaFrame(::Windows::Media::Capture::Frames::AudioMediaFrame^ instance) {
        _instance = instance;
      }

      
    static void New(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(s_constructorTemplate);

      // in case the constructor was called without the new operator
      if (!localRef->HasInstance(info.This())) {
        if (info.Length() > 0) {
          std::unique_ptr<Local<Value> []> constructorArgs(new Local<Value>[info.Length()]);

          Local<Value> *argsPtr = constructorArgs.get();
          for (int i = 0; i < info.Length(); i++) {
            argsPtr[i] = info[i];
          }

          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), constructorArgs.get());
          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        } else {
          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), nullptr);

          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        }
      }

      ::Windows::Media::Capture::Frames::AudioMediaFrame^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::AudioMediaFrame^>(info[0])) {
        try {
          winRtInstance = (::Windows::Media::Capture::Frames::AudioMediaFrame^) NodeRT::Utils::GetObjectInstance(info[0]);
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no suitable constructor found")));
        return;
      }

      NodeRT::Utils::SetHiddenValue(info.This(), Nan::New<String>("__winRtInstance__").ToLocalChecked(), True());

      AudioMediaFrame *wrapperInstance = new AudioMediaFrame(winRtInstance);
      wrapperInstance->Wrap(info.This());

      info.GetReturnValue().Set(info.This());
    }


      
    static void CastFrom(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;
      if (info.Length() < 1 || !NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::AudioMediaFrame^>(info[0])) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no object provided, or given object could not be casted to requested type")));
        return;
      }

      ::Windows::Media::Capture::Frames::AudioMediaFrame^ winRtInstance;
      try {
        winRtInstance = (::Windows::Media::Capture::Frames::AudioMediaFrame^) NodeRT::Utils::GetObjectInstance(info[0]);
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }

      info.GetReturnValue().Set(WrapAudioMediaFrame(winRtInstance));
    }


    static void GetAudioFrame(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::AudioMediaFrame^>(info.This())) {
        return;
      }

      AudioMediaFrame *wrapper = AudioMediaFrame::Unwrap<AudioMediaFrame>(info.This());

      if (info.Length() == 0)
      {
        try
        {
          ::Windows::Media::AudioFrame^ result;
          result = wrapper->_instance->GetAudioFrame();
          info.GetReturnValue().Set(NodeRT::Utils::CreateExternalWinRTObject("Windows.Media", "AudioFrame", result));
          return;
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }
    }



    static void AudioEncodingPropertiesGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::AudioMediaFrame^>(info.This())) {
        return;
      }

      AudioMediaFrame *wrapper = AudioMediaFrame::Unwrap<AudioMediaFrame>(info.This());

      try  {
        ::Windows::Media::MediaProperties::AudioEncodingProperties^ result = wrapper->_instance->AudioEncodingProperties;
        info.GetReturnValue().Set(NodeRT::Utils::CreateExternalWinRTObject("Windows.Media.MediaProperties", "AudioEncodingProperties", result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void FrameReferenceGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::AudioMediaFrame^>(info.This())) {
        return;
      }

      AudioMediaFrame *wrapper = AudioMediaFrame::Unwrap<AudioMediaFrame>(info.This());

      try  {
        ::Windows::Media::Capture::Frames::MediaFrameReference^ result = wrapper->_instance->FrameReference;
        info.GetReturnValue().Set(WrapMediaFrameReference(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      


    private:
      ::Windows::Media::Capture::Frames::AudioMediaFrame^ _instance;
      static Persistent<FunctionTemplate> s_constructorTemplate;

      friend v8::Local<v8::Value> WrapAudioMediaFrame(::Windows::Media::Capture::Frames::AudioMediaFrame^ wintRtInstance);
      friend ::Windows::Media::Capture::Frames::AudioMediaFrame^ UnwrapAudioMediaFrame(Local<Value> value);
  };

  Persistent<FunctionTemplate> AudioMediaFrame::s_constructorTemplate;

  v8::Local<v8::Value> WrapAudioMediaFrame(::Windows::Media::Capture::Frames::AudioMediaFrame^ winRtInstance) {
    EscapableHandleScope scope;

    if (winRtInstance == nullptr) {
      return scope.Escape(Undefined());
    }

    Local<Value> opaqueWrapper = CreateOpaqueWrapper(winRtInstance);
    Local<Value> args[] = {opaqueWrapper};
    Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(AudioMediaFrame::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::Media::Capture::Frames::AudioMediaFrame^ UnwrapAudioMediaFrame(Local<Value> value) {
     return AudioMediaFrame::Unwrap<AudioMediaFrame>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitAudioMediaFrame(Local<Object> exports) {
    AudioMediaFrame::Init(exports);
  }

  class BufferMediaFrame : public WrapperBase {
    public:
      
      static void Init(const Local<Object> exports) {
        HandleScope scope;

        Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(New);
        s_constructorTemplate.Reset(localRef);
        localRef->SetClassName(Nan::New<String>("BufferMediaFrame").ToLocalChecked());
        localRef->InstanceTemplate()->SetInternalFieldCount(1);





          
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("buffer").ToLocalChecked(), BufferGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("frameReference").ToLocalChecked(), FrameReferenceGetter);

        Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
        Nan::SetMethod(constructor, "castFrom", CastFrom);



        Nan::Set(exports, Nan::New<String>("BufferMediaFrame").ToLocalChecked(), constructor);
      }

      virtual ::Platform::Object^ GetObjectInstance() const override {
        return _instance;
      }

    private:

      BufferMediaFrame(::Windows::Media::Capture::Frames::BufferMediaFrame^ instance) {
        _instance = instance;
      }

      
    static void New(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(s_constructorTemplate);

      // in case the constructor was called without the new operator
      if (!localRef->HasInstance(info.This())) {
        if (info.Length() > 0) {
          std::unique_ptr<Local<Value> []> constructorArgs(new Local<Value>[info.Length()]);

          Local<Value> *argsPtr = constructorArgs.get();
          for (int i = 0; i < info.Length(); i++) {
            argsPtr[i] = info[i];
          }

          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), constructorArgs.get());
          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        } else {
          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), nullptr);

          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        }
      }

      ::Windows::Media::Capture::Frames::BufferMediaFrame^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::BufferMediaFrame^>(info[0])) {
        try {
          winRtInstance = (::Windows::Media::Capture::Frames::BufferMediaFrame^) NodeRT::Utils::GetObjectInstance(info[0]);
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no suitable constructor found")));
        return;
      }

      NodeRT::Utils::SetHiddenValue(info.This(), Nan::New<String>("__winRtInstance__").ToLocalChecked(), True());

      BufferMediaFrame *wrapperInstance = new BufferMediaFrame(winRtInstance);
      wrapperInstance->Wrap(info.This());

      info.GetReturnValue().Set(info.This());
    }


      
    static void CastFrom(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;
      if (info.Length() < 1 || !NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::BufferMediaFrame^>(info[0])) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no object provided, or given object could not be casted to requested type")));
        return;
      }

      ::Windows::Media::Capture::Frames::BufferMediaFrame^ winRtInstance;
      try {
        winRtInstance = (::Windows::Media::Capture::Frames::BufferMediaFrame^) NodeRT::Utils::GetObjectInstance(info[0]);
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }

      info.GetReturnValue().Set(WrapBufferMediaFrame(winRtInstance));
    }





    static void BufferGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::BufferMediaFrame^>(info.This())) {
        return;
      }

      BufferMediaFrame *wrapper = BufferMediaFrame::Unwrap<BufferMediaFrame>(info.This());

      try  {
        ::Windows::Storage::Streams::IBuffer^ result = wrapper->_instance->Buffer;
        info.GetReturnValue().Set(NodeRT::Utils::CreateExternalWinRTObject("Windows.Storage.Streams", "IBuffer", result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void FrameReferenceGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::BufferMediaFrame^>(info.This())) {
        return;
      }

      BufferMediaFrame *wrapper = BufferMediaFrame::Unwrap<BufferMediaFrame>(info.This());

      try  {
        ::Windows::Media::Capture::Frames::MediaFrameReference^ result = wrapper->_instance->FrameReference;
        info.GetReturnValue().Set(WrapMediaFrameReference(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      


    private:
      ::Windows::Media::Capture::Frames::BufferMediaFrame^ _instance;
      static Persistent<FunctionTemplate> s_constructorTemplate;

      friend v8::Local<v8::Value> WrapBufferMediaFrame(::Windows::Media::Capture::Frames::BufferMediaFrame^ wintRtInstance);
      friend ::Windows::Media::Capture::Frames::BufferMediaFrame^ UnwrapBufferMediaFrame(Local<Value> value);
  };

  Persistent<FunctionTemplate> BufferMediaFrame::s_constructorTemplate;

  v8::Local<v8::Value> WrapBufferMediaFrame(::Windows::Media::Capture::Frames::BufferMediaFrame^ winRtInstance) {
    EscapableHandleScope scope;

    if (winRtInstance == nullptr) {
      return scope.Escape(Undefined());
    }

    Local<Value> opaqueWrapper = CreateOpaqueWrapper(winRtInstance);
    Local<Value> args[] = {opaqueWrapper};
    Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(BufferMediaFrame::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::Media::Capture::Frames::BufferMediaFrame^ UnwrapBufferMediaFrame(Local<Value> value) {
     return BufferMediaFrame::Unwrap<BufferMediaFrame>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitBufferMediaFrame(Local<Object> exports) {
    BufferMediaFrame::Init(exports);
  }

  class DepthMediaFrame : public WrapperBase {
    public:
      
      static void Init(const Local<Object> exports) {
        HandleScope scope;

        Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(New);
        s_constructorTemplate.Reset(localRef);
        localRef->SetClassName(Nan::New<String>("DepthMediaFrame").ToLocalChecked());
        localRef->InstanceTemplate()->SetInternalFieldCount(1);


          
            Nan::SetPrototypeMethod(localRef, "tryCreateCoordinateMapper", TryCreateCoordinateMapper);
          



          
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("depthFormat").ToLocalChecked(), DepthFormatGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("frameReference").ToLocalChecked(), FrameReferenceGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("videoMediaFrame").ToLocalChecked(), VideoMediaFrameGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("maxReliableDepth").ToLocalChecked(), MaxReliableDepthGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("minReliableDepth").ToLocalChecked(), MinReliableDepthGetter);

        Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
        Nan::SetMethod(constructor, "castFrom", CastFrom);



        Nan::Set(exports, Nan::New<String>("DepthMediaFrame").ToLocalChecked(), constructor);
      }

      virtual ::Platform::Object^ GetObjectInstance() const override {
        return _instance;
      }

    private:

      DepthMediaFrame(::Windows::Media::Capture::Frames::DepthMediaFrame^ instance) {
        _instance = instance;
      }

      
    static void New(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(s_constructorTemplate);

      // in case the constructor was called without the new operator
      if (!localRef->HasInstance(info.This())) {
        if (info.Length() > 0) {
          std::unique_ptr<Local<Value> []> constructorArgs(new Local<Value>[info.Length()]);

          Local<Value> *argsPtr = constructorArgs.get();
          for (int i = 0; i < info.Length(); i++) {
            argsPtr[i] = info[i];
          }

          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), constructorArgs.get());
          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        } else {
          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), nullptr);

          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        }
      }

      ::Windows::Media::Capture::Frames::DepthMediaFrame^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::DepthMediaFrame^>(info[0])) {
        try {
          winRtInstance = (::Windows::Media::Capture::Frames::DepthMediaFrame^) NodeRT::Utils::GetObjectInstance(info[0]);
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no suitable constructor found")));
        return;
      }

      NodeRT::Utils::SetHiddenValue(info.This(), Nan::New<String>("__winRtInstance__").ToLocalChecked(), True());

      DepthMediaFrame *wrapperInstance = new DepthMediaFrame(winRtInstance);
      wrapperInstance->Wrap(info.This());

      info.GetReturnValue().Set(info.This());
    }


      
    static void CastFrom(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;
      if (info.Length() < 1 || !NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::DepthMediaFrame^>(info[0])) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no object provided, or given object could not be casted to requested type")));
        return;
      }

      ::Windows::Media::Capture::Frames::DepthMediaFrame^ winRtInstance;
      try {
        winRtInstance = (::Windows::Media::Capture::Frames::DepthMediaFrame^) NodeRT::Utils::GetObjectInstance(info[0]);
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }

      info.GetReturnValue().Set(WrapDepthMediaFrame(winRtInstance));
    }


    static void TryCreateCoordinateMapper(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::DepthMediaFrame^>(info.This())) {
        return;
      }

      DepthMediaFrame *wrapper = DepthMediaFrame::Unwrap<DepthMediaFrame>(info.This());

      if (info.Length() == 2
        && NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Devices::Core::CameraIntrinsics^>(info[0])
        && NodeRT::Utils::IsWinRtWrapperOf<::Windows::Perception::Spatial::SpatialCoordinateSystem^>(info[1]))
      {
        try
        {
          ::Windows::Media::Devices::Core::CameraIntrinsics^ arg0 = dynamic_cast<::Windows::Media::Devices::Core::CameraIntrinsics^>(NodeRT::Utils::GetObjectInstance(info[0]));
          ::Windows::Perception::Spatial::SpatialCoordinateSystem^ arg1 = dynamic_cast<::Windows::Perception::Spatial::SpatialCoordinateSystem^>(NodeRT::Utils::GetObjectInstance(info[1]));
          
          ::Windows::Media::Devices::Core::DepthCorrelatedCoordinateMapper^ result;
          result = wrapper->_instance->TryCreateCoordinateMapper(arg0, arg1);
          info.GetReturnValue().Set(NodeRT::Utils::CreateExternalWinRTObject("Windows.Media.Devices.Core", "DepthCorrelatedCoordinateMapper", result));
          return;
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }
    }



    static void DepthFormatGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::DepthMediaFrame^>(info.This())) {
        return;
      }

      DepthMediaFrame *wrapper = DepthMediaFrame::Unwrap<DepthMediaFrame>(info.This());

      try  {
        ::Windows::Media::Capture::Frames::DepthMediaFrameFormat^ result = wrapper->_instance->DepthFormat;
        info.GetReturnValue().Set(WrapDepthMediaFrameFormat(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void FrameReferenceGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::DepthMediaFrame^>(info.This())) {
        return;
      }

      DepthMediaFrame *wrapper = DepthMediaFrame::Unwrap<DepthMediaFrame>(info.This());

      try  {
        ::Windows::Media::Capture::Frames::MediaFrameReference^ result = wrapper->_instance->FrameReference;
        info.GetReturnValue().Set(WrapMediaFrameReference(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void VideoMediaFrameGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::DepthMediaFrame^>(info.This())) {
        return;
      }

      DepthMediaFrame *wrapper = DepthMediaFrame::Unwrap<DepthMediaFrame>(info.This());

      try  {
        ::Windows::Media::Capture::Frames::VideoMediaFrame^ result = wrapper->_instance->VideoMediaFrame;
        info.GetReturnValue().Set(WrapVideoMediaFrame(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void MaxReliableDepthGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::DepthMediaFrame^>(info.This())) {
        return;
      }

      DepthMediaFrame *wrapper = DepthMediaFrame::Unwrap<DepthMediaFrame>(info.This());

      try  {
        unsigned int result = wrapper->_instance->MaxReliableDepth;
        info.GetReturnValue().Set(Nan::New<Integer>(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void MinReliableDepthGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::DepthMediaFrame^>(info.This())) {
        return;
      }

      DepthMediaFrame *wrapper = DepthMediaFrame::Unwrap<DepthMediaFrame>(info.This());

      try  {
        unsigned int result = wrapper->_instance->MinReliableDepth;
        info.GetReturnValue().Set(Nan::New<Integer>(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      


    private:
      ::Windows::Media::Capture::Frames::DepthMediaFrame^ _instance;
      static Persistent<FunctionTemplate> s_constructorTemplate;

      friend v8::Local<v8::Value> WrapDepthMediaFrame(::Windows::Media::Capture::Frames::DepthMediaFrame^ wintRtInstance);
      friend ::Windows::Media::Capture::Frames::DepthMediaFrame^ UnwrapDepthMediaFrame(Local<Value> value);
  };

  Persistent<FunctionTemplate> DepthMediaFrame::s_constructorTemplate;

  v8::Local<v8::Value> WrapDepthMediaFrame(::Windows::Media::Capture::Frames::DepthMediaFrame^ winRtInstance) {
    EscapableHandleScope scope;

    if (winRtInstance == nullptr) {
      return scope.Escape(Undefined());
    }

    Local<Value> opaqueWrapper = CreateOpaqueWrapper(winRtInstance);
    Local<Value> args[] = {opaqueWrapper};
    Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(DepthMediaFrame::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::Media::Capture::Frames::DepthMediaFrame^ UnwrapDepthMediaFrame(Local<Value> value) {
     return DepthMediaFrame::Unwrap<DepthMediaFrame>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitDepthMediaFrame(Local<Object> exports) {
    DepthMediaFrame::Init(exports);
  }

  class DepthMediaFrameFormat : public WrapperBase {
    public:
      
      static void Init(const Local<Object> exports) {
        HandleScope scope;

        Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(New);
        s_constructorTemplate.Reset(localRef);
        localRef->SetClassName(Nan::New<String>("DepthMediaFrameFormat").ToLocalChecked());
        localRef->InstanceTemplate()->SetInternalFieldCount(1);





          
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("depthScaleInMeters").ToLocalChecked(), DepthScaleInMetersGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("videoFormat").ToLocalChecked(), VideoFormatGetter);

        Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
        Nan::SetMethod(constructor, "castFrom", CastFrom);



        Nan::Set(exports, Nan::New<String>("DepthMediaFrameFormat").ToLocalChecked(), constructor);
      }

      virtual ::Platform::Object^ GetObjectInstance() const override {
        return _instance;
      }

    private:

      DepthMediaFrameFormat(::Windows::Media::Capture::Frames::DepthMediaFrameFormat^ instance) {
        _instance = instance;
      }

      
    static void New(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(s_constructorTemplate);

      // in case the constructor was called without the new operator
      if (!localRef->HasInstance(info.This())) {
        if (info.Length() > 0) {
          std::unique_ptr<Local<Value> []> constructorArgs(new Local<Value>[info.Length()]);

          Local<Value> *argsPtr = constructorArgs.get();
          for (int i = 0; i < info.Length(); i++) {
            argsPtr[i] = info[i];
          }

          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), constructorArgs.get());
          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        } else {
          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), nullptr);

          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        }
      }

      ::Windows::Media::Capture::Frames::DepthMediaFrameFormat^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::DepthMediaFrameFormat^>(info[0])) {
        try {
          winRtInstance = (::Windows::Media::Capture::Frames::DepthMediaFrameFormat^) NodeRT::Utils::GetObjectInstance(info[0]);
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no suitable constructor found")));
        return;
      }

      NodeRT::Utils::SetHiddenValue(info.This(), Nan::New<String>("__winRtInstance__").ToLocalChecked(), True());

      DepthMediaFrameFormat *wrapperInstance = new DepthMediaFrameFormat(winRtInstance);
      wrapperInstance->Wrap(info.This());

      info.GetReturnValue().Set(info.This());
    }


      
    static void CastFrom(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;
      if (info.Length() < 1 || !NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::DepthMediaFrameFormat^>(info[0])) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no object provided, or given object could not be casted to requested type")));
        return;
      }

      ::Windows::Media::Capture::Frames::DepthMediaFrameFormat^ winRtInstance;
      try {
        winRtInstance = (::Windows::Media::Capture::Frames::DepthMediaFrameFormat^) NodeRT::Utils::GetObjectInstance(info[0]);
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }

      info.GetReturnValue().Set(WrapDepthMediaFrameFormat(winRtInstance));
    }





    static void DepthScaleInMetersGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::DepthMediaFrameFormat^>(info.This())) {
        return;
      }

      DepthMediaFrameFormat *wrapper = DepthMediaFrameFormat::Unwrap<DepthMediaFrameFormat>(info.This());

      try  {
        double result = wrapper->_instance->DepthScaleInMeters;
        info.GetReturnValue().Set(Nan::New<Number>(static_cast<double>(result)));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void VideoFormatGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::DepthMediaFrameFormat^>(info.This())) {
        return;
      }

      DepthMediaFrameFormat *wrapper = DepthMediaFrameFormat::Unwrap<DepthMediaFrameFormat>(info.This());

      try  {
        ::Windows::Media::Capture::Frames::VideoMediaFrameFormat^ result = wrapper->_instance->VideoFormat;
        info.GetReturnValue().Set(WrapVideoMediaFrameFormat(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      


    private:
      ::Windows::Media::Capture::Frames::DepthMediaFrameFormat^ _instance;
      static Persistent<FunctionTemplate> s_constructorTemplate;

      friend v8::Local<v8::Value> WrapDepthMediaFrameFormat(::Windows::Media::Capture::Frames::DepthMediaFrameFormat^ wintRtInstance);
      friend ::Windows::Media::Capture::Frames::DepthMediaFrameFormat^ UnwrapDepthMediaFrameFormat(Local<Value> value);
  };

  Persistent<FunctionTemplate> DepthMediaFrameFormat::s_constructorTemplate;

  v8::Local<v8::Value> WrapDepthMediaFrameFormat(::Windows::Media::Capture::Frames::DepthMediaFrameFormat^ winRtInstance) {
    EscapableHandleScope scope;

    if (winRtInstance == nullptr) {
      return scope.Escape(Undefined());
    }

    Local<Value> opaqueWrapper = CreateOpaqueWrapper(winRtInstance);
    Local<Value> args[] = {opaqueWrapper};
    Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(DepthMediaFrameFormat::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::Media::Capture::Frames::DepthMediaFrameFormat^ UnwrapDepthMediaFrameFormat(Local<Value> value) {
     return DepthMediaFrameFormat::Unwrap<DepthMediaFrameFormat>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitDepthMediaFrameFormat(Local<Object> exports) {
    DepthMediaFrameFormat::Init(exports);
  }

  class InfraredMediaFrame : public WrapperBase {
    public:
      
      static void Init(const Local<Object> exports) {
        HandleScope scope;

        Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(New);
        s_constructorTemplate.Reset(localRef);
        localRef->SetClassName(Nan::New<String>("InfraredMediaFrame").ToLocalChecked());
        localRef->InstanceTemplate()->SetInternalFieldCount(1);





          
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("frameReference").ToLocalChecked(), FrameReferenceGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("isIlluminated").ToLocalChecked(), IsIlluminatedGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("videoMediaFrame").ToLocalChecked(), VideoMediaFrameGetter);

        Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
        Nan::SetMethod(constructor, "castFrom", CastFrom);



        Nan::Set(exports, Nan::New<String>("InfraredMediaFrame").ToLocalChecked(), constructor);
      }

      virtual ::Platform::Object^ GetObjectInstance() const override {
        return _instance;
      }

    private:

      InfraredMediaFrame(::Windows::Media::Capture::Frames::InfraredMediaFrame^ instance) {
        _instance = instance;
      }

      
    static void New(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(s_constructorTemplate);

      // in case the constructor was called without the new operator
      if (!localRef->HasInstance(info.This())) {
        if (info.Length() > 0) {
          std::unique_ptr<Local<Value> []> constructorArgs(new Local<Value>[info.Length()]);

          Local<Value> *argsPtr = constructorArgs.get();
          for (int i = 0; i < info.Length(); i++) {
            argsPtr[i] = info[i];
          }

          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), constructorArgs.get());
          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        } else {
          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), nullptr);

          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        }
      }

      ::Windows::Media::Capture::Frames::InfraredMediaFrame^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::InfraredMediaFrame^>(info[0])) {
        try {
          winRtInstance = (::Windows::Media::Capture::Frames::InfraredMediaFrame^) NodeRT::Utils::GetObjectInstance(info[0]);
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no suitable constructor found")));
        return;
      }

      NodeRT::Utils::SetHiddenValue(info.This(), Nan::New<String>("__winRtInstance__").ToLocalChecked(), True());

      InfraredMediaFrame *wrapperInstance = new InfraredMediaFrame(winRtInstance);
      wrapperInstance->Wrap(info.This());

      info.GetReturnValue().Set(info.This());
    }


      
    static void CastFrom(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;
      if (info.Length() < 1 || !NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::InfraredMediaFrame^>(info[0])) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no object provided, or given object could not be casted to requested type")));
        return;
      }

      ::Windows::Media::Capture::Frames::InfraredMediaFrame^ winRtInstance;
      try {
        winRtInstance = (::Windows::Media::Capture::Frames::InfraredMediaFrame^) NodeRT::Utils::GetObjectInstance(info[0]);
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }

      info.GetReturnValue().Set(WrapInfraredMediaFrame(winRtInstance));
    }





    static void FrameReferenceGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::InfraredMediaFrame^>(info.This())) {
        return;
      }

      InfraredMediaFrame *wrapper = InfraredMediaFrame::Unwrap<InfraredMediaFrame>(info.This());

      try  {
        ::Windows::Media::Capture::Frames::MediaFrameReference^ result = wrapper->_instance->FrameReference;
        info.GetReturnValue().Set(WrapMediaFrameReference(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void IsIlluminatedGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::InfraredMediaFrame^>(info.This())) {
        return;
      }

      InfraredMediaFrame *wrapper = InfraredMediaFrame::Unwrap<InfraredMediaFrame>(info.This());

      try  {
        bool result = wrapper->_instance->IsIlluminated;
        info.GetReturnValue().Set(Nan::New<Boolean>(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void VideoMediaFrameGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::InfraredMediaFrame^>(info.This())) {
        return;
      }

      InfraredMediaFrame *wrapper = InfraredMediaFrame::Unwrap<InfraredMediaFrame>(info.This());

      try  {
        ::Windows::Media::Capture::Frames::VideoMediaFrame^ result = wrapper->_instance->VideoMediaFrame;
        info.GetReturnValue().Set(WrapVideoMediaFrame(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      


    private:
      ::Windows::Media::Capture::Frames::InfraredMediaFrame^ _instance;
      static Persistent<FunctionTemplate> s_constructorTemplate;

      friend v8::Local<v8::Value> WrapInfraredMediaFrame(::Windows::Media::Capture::Frames::InfraredMediaFrame^ wintRtInstance);
      friend ::Windows::Media::Capture::Frames::InfraredMediaFrame^ UnwrapInfraredMediaFrame(Local<Value> value);
  };

  Persistent<FunctionTemplate> InfraredMediaFrame::s_constructorTemplate;

  v8::Local<v8::Value> WrapInfraredMediaFrame(::Windows::Media::Capture::Frames::InfraredMediaFrame^ winRtInstance) {
    EscapableHandleScope scope;

    if (winRtInstance == nullptr) {
      return scope.Escape(Undefined());
    }

    Local<Value> opaqueWrapper = CreateOpaqueWrapper(winRtInstance);
    Local<Value> args[] = {opaqueWrapper};
    Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(InfraredMediaFrame::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::Media::Capture::Frames::InfraredMediaFrame^ UnwrapInfraredMediaFrame(Local<Value> value) {
     return InfraredMediaFrame::Unwrap<InfraredMediaFrame>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitInfraredMediaFrame(Local<Object> exports) {
    InfraredMediaFrame::Init(exports);
  }

  class MediaFrameArrivedEventArgs : public WrapperBase {
    public:
      
      static void Init(const Local<Object> exports) {
        HandleScope scope;

        Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(New);
        s_constructorTemplate.Reset(localRef);
        localRef->SetClassName(Nan::New<String>("MediaFrameArrivedEventArgs").ToLocalChecked());
        localRef->InstanceTemplate()->SetInternalFieldCount(1);






        Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
        Nan::SetMethod(constructor, "castFrom", CastFrom);



        Nan::Set(exports, Nan::New<String>("MediaFrameArrivedEventArgs").ToLocalChecked(), constructor);
      }

      virtual ::Platform::Object^ GetObjectInstance() const override {
        return _instance;
      }

    private:

      MediaFrameArrivedEventArgs(::Windows::Media::Capture::Frames::MediaFrameArrivedEventArgs^ instance) {
        _instance = instance;
      }

      
    static void New(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(s_constructorTemplate);

      // in case the constructor was called without the new operator
      if (!localRef->HasInstance(info.This())) {
        if (info.Length() > 0) {
          std::unique_ptr<Local<Value> []> constructorArgs(new Local<Value>[info.Length()]);

          Local<Value> *argsPtr = constructorArgs.get();
          for (int i = 0; i < info.Length(); i++) {
            argsPtr[i] = info[i];
          }

          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), constructorArgs.get());
          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        } else {
          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), nullptr);

          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        }
      }

      ::Windows::Media::Capture::Frames::MediaFrameArrivedEventArgs^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameArrivedEventArgs^>(info[0])) {
        try {
          winRtInstance = (::Windows::Media::Capture::Frames::MediaFrameArrivedEventArgs^) NodeRT::Utils::GetObjectInstance(info[0]);
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no suitable constructor found")));
        return;
      }

      NodeRT::Utils::SetHiddenValue(info.This(), Nan::New<String>("__winRtInstance__").ToLocalChecked(), True());

      MediaFrameArrivedEventArgs *wrapperInstance = new MediaFrameArrivedEventArgs(winRtInstance);
      wrapperInstance->Wrap(info.This());

      info.GetReturnValue().Set(info.This());
    }


      
    static void CastFrom(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;
      if (info.Length() < 1 || !NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameArrivedEventArgs^>(info[0])) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no object provided, or given object could not be casted to requested type")));
        return;
      }

      ::Windows::Media::Capture::Frames::MediaFrameArrivedEventArgs^ winRtInstance;
      try {
        winRtInstance = (::Windows::Media::Capture::Frames::MediaFrameArrivedEventArgs^) NodeRT::Utils::GetObjectInstance(info[0]);
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }

      info.GetReturnValue().Set(WrapMediaFrameArrivedEventArgs(winRtInstance));
    }







    private:
      ::Windows::Media::Capture::Frames::MediaFrameArrivedEventArgs^ _instance;
      static Persistent<FunctionTemplate> s_constructorTemplate;

      friend v8::Local<v8::Value> WrapMediaFrameArrivedEventArgs(::Windows::Media::Capture::Frames::MediaFrameArrivedEventArgs^ wintRtInstance);
      friend ::Windows::Media::Capture::Frames::MediaFrameArrivedEventArgs^ UnwrapMediaFrameArrivedEventArgs(Local<Value> value);
  };

  Persistent<FunctionTemplate> MediaFrameArrivedEventArgs::s_constructorTemplate;

  v8::Local<v8::Value> WrapMediaFrameArrivedEventArgs(::Windows::Media::Capture::Frames::MediaFrameArrivedEventArgs^ winRtInstance) {
    EscapableHandleScope scope;

    if (winRtInstance == nullptr) {
      return scope.Escape(Undefined());
    }

    Local<Value> opaqueWrapper = CreateOpaqueWrapper(winRtInstance);
    Local<Value> args[] = {opaqueWrapper};
    Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(MediaFrameArrivedEventArgs::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::Media::Capture::Frames::MediaFrameArrivedEventArgs^ UnwrapMediaFrameArrivedEventArgs(Local<Value> value) {
     return MediaFrameArrivedEventArgs::Unwrap<MediaFrameArrivedEventArgs>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitMediaFrameArrivedEventArgs(Local<Object> exports) {
    MediaFrameArrivedEventArgs::Init(exports);
  }

  class MediaFrameFormat : public WrapperBase {
    public:
      
      static void Init(const Local<Object> exports) {
        HandleScope scope;

        Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(New);
        s_constructorTemplate.Reset(localRef);
        localRef->SetClassName(Nan::New<String>("MediaFrameFormat").ToLocalChecked());
        localRef->InstanceTemplate()->SetInternalFieldCount(1);





          
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("frameRate").ToLocalChecked(), FrameRateGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("majorType").ToLocalChecked(), MajorTypeGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("properties").ToLocalChecked(), PropertiesGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("subtype").ToLocalChecked(), SubtypeGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("videoFormat").ToLocalChecked(), VideoFormatGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("audioEncodingProperties").ToLocalChecked(), AudioEncodingPropertiesGetter);

        Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
        Nan::SetMethod(constructor, "castFrom", CastFrom);



        Nan::Set(exports, Nan::New<String>("MediaFrameFormat").ToLocalChecked(), constructor);
      }

      virtual ::Platform::Object^ GetObjectInstance() const override {
        return _instance;
      }

    private:

      MediaFrameFormat(::Windows::Media::Capture::Frames::MediaFrameFormat^ instance) {
        _instance = instance;
      }

      
    static void New(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(s_constructorTemplate);

      // in case the constructor was called without the new operator
      if (!localRef->HasInstance(info.This())) {
        if (info.Length() > 0) {
          std::unique_ptr<Local<Value> []> constructorArgs(new Local<Value>[info.Length()]);

          Local<Value> *argsPtr = constructorArgs.get();
          for (int i = 0; i < info.Length(); i++) {
            argsPtr[i] = info[i];
          }

          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), constructorArgs.get());
          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        } else {
          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), nullptr);

          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        }
      }

      ::Windows::Media::Capture::Frames::MediaFrameFormat^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameFormat^>(info[0])) {
        try {
          winRtInstance = (::Windows::Media::Capture::Frames::MediaFrameFormat^) NodeRT::Utils::GetObjectInstance(info[0]);
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no suitable constructor found")));
        return;
      }

      NodeRT::Utils::SetHiddenValue(info.This(), Nan::New<String>("__winRtInstance__").ToLocalChecked(), True());

      MediaFrameFormat *wrapperInstance = new MediaFrameFormat(winRtInstance);
      wrapperInstance->Wrap(info.This());

      info.GetReturnValue().Set(info.This());
    }


      
    static void CastFrom(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;
      if (info.Length() < 1 || !NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameFormat^>(info[0])) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no object provided, or given object could not be casted to requested type")));
        return;
      }

      ::Windows::Media::Capture::Frames::MediaFrameFormat^ winRtInstance;
      try {
        winRtInstance = (::Windows::Media::Capture::Frames::MediaFrameFormat^) NodeRT::Utils::GetObjectInstance(info[0]);
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }

      info.GetReturnValue().Set(WrapMediaFrameFormat(winRtInstance));
    }





    static void FrameRateGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameFormat^>(info.This())) {
        return;
      }

      MediaFrameFormat *wrapper = MediaFrameFormat::Unwrap<MediaFrameFormat>(info.This());

      try  {
        ::Windows::Media::MediaProperties::MediaRatio^ result = wrapper->_instance->FrameRate;
        info.GetReturnValue().Set(NodeRT::Utils::CreateExternalWinRTObject("Windows.Media.MediaProperties", "MediaRatio", result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void MajorTypeGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameFormat^>(info.This())) {
        return;
      }

      MediaFrameFormat *wrapper = MediaFrameFormat::Unwrap<MediaFrameFormat>(info.This());

      try  {
        Platform::String^ result = wrapper->_instance->MajorType;
        info.GetReturnValue().Set(NodeRT::Utils::NewString(result->Data()));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void PropertiesGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameFormat^>(info.This())) {
        return;
      }

      MediaFrameFormat *wrapper = MediaFrameFormat::Unwrap<MediaFrameFormat>(info.This());

      try  {
        ::Windows::Foundation::Collections::IMapView<::Platform::Guid, ::Platform::Object^>^ result = wrapper->_instance->Properties;
        info.GetReturnValue().Set(NodeRT::Collections::MapViewWrapper<::Platform::Guid,::Platform::Object^>::CreateMapViewWrapper(result, 
            [](::Platform::Guid val) -> Local<Value> {
              return NodeRT::Utils::GuidToJs(val);
            },
            [](Local<Value> value) -> bool {
              return NodeRT::Utils::IsGuid(value);
            },
            [](Local<Value> value) -> ::Platform::Guid {
              return NodeRT::Utils::GuidFromJs(value);
            },
            [](::Platform::Object^ val) -> Local<Value> {
              return CreateOpaqueWrapper(val);
            }
          ));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void SubtypeGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameFormat^>(info.This())) {
        return;
      }

      MediaFrameFormat *wrapper = MediaFrameFormat::Unwrap<MediaFrameFormat>(info.This());

      try  {
        Platform::String^ result = wrapper->_instance->Subtype;
        info.GetReturnValue().Set(NodeRT::Utils::NewString(result->Data()));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void VideoFormatGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameFormat^>(info.This())) {
        return;
      }

      MediaFrameFormat *wrapper = MediaFrameFormat::Unwrap<MediaFrameFormat>(info.This());

      try  {
        ::Windows::Media::Capture::Frames::VideoMediaFrameFormat^ result = wrapper->_instance->VideoFormat;
        info.GetReturnValue().Set(WrapVideoMediaFrameFormat(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void AudioEncodingPropertiesGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameFormat^>(info.This())) {
        return;
      }

      MediaFrameFormat *wrapper = MediaFrameFormat::Unwrap<MediaFrameFormat>(info.This());

      try  {
        ::Windows::Media::MediaProperties::AudioEncodingProperties^ result = wrapper->_instance->AudioEncodingProperties;
        info.GetReturnValue().Set(NodeRT::Utils::CreateExternalWinRTObject("Windows.Media.MediaProperties", "AudioEncodingProperties", result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      


    private:
      ::Windows::Media::Capture::Frames::MediaFrameFormat^ _instance;
      static Persistent<FunctionTemplate> s_constructorTemplate;

      friend v8::Local<v8::Value> WrapMediaFrameFormat(::Windows::Media::Capture::Frames::MediaFrameFormat^ wintRtInstance);
      friend ::Windows::Media::Capture::Frames::MediaFrameFormat^ UnwrapMediaFrameFormat(Local<Value> value);
  };

  Persistent<FunctionTemplate> MediaFrameFormat::s_constructorTemplate;

  v8::Local<v8::Value> WrapMediaFrameFormat(::Windows::Media::Capture::Frames::MediaFrameFormat^ winRtInstance) {
    EscapableHandleScope scope;

    if (winRtInstance == nullptr) {
      return scope.Escape(Undefined());
    }

    Local<Value> opaqueWrapper = CreateOpaqueWrapper(winRtInstance);
    Local<Value> args[] = {opaqueWrapper};
    Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(MediaFrameFormat::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::Media::Capture::Frames::MediaFrameFormat^ UnwrapMediaFrameFormat(Local<Value> value) {
     return MediaFrameFormat::Unwrap<MediaFrameFormat>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitMediaFrameFormat(Local<Object> exports) {
    MediaFrameFormat::Init(exports);
  }

  class MediaFrameReader : public WrapperBase {
    public:
      
      static void Init(const Local<Object> exports) {
        HandleScope scope;

        Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(New);
        s_constructorTemplate.Reset(localRef);
        localRef->SetClassName(Nan::New<String>("MediaFrameReader").ToLocalChecked());
        localRef->InstanceTemplate()->SetInternalFieldCount(1);

        Local<Function> func;
        Local<FunctionTemplate> funcTemplate;

          
            Nan::SetPrototypeMethod(localRef, "tryAcquireLatestFrame", TryAcquireLatestFrame);
            Nan::SetPrototypeMethod(localRef, "close", Close);
          

          
            Nan::SetPrototypeMethod(localRef, "startAsync", StartAsync);
            Nan::SetPrototypeMethod(localRef, "stopAsync", StopAsync);
          

          
          Nan::SetPrototypeMethod(localRef,"addListener", AddListener);
          Nan::SetPrototypeMethod(localRef,"on", AddListener);
          Nan::SetPrototypeMethod(localRef,"removeListener", RemoveListener);
          Nan::SetPrototypeMethod(localRef, "off", RemoveListener);

          
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("acquisitionMode").ToLocalChecked(), AcquisitionModeGetter, AcquisitionModeSetter);

        Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
        Nan::SetMethod(constructor, "castFrom", CastFrom);



        Nan::Set(exports, Nan::New<String>("MediaFrameReader").ToLocalChecked(), constructor);
      }

      virtual ::Platform::Object^ GetObjectInstance() const override {
        return _instance;
      }

    private:

      MediaFrameReader(::Windows::Media::Capture::Frames::MediaFrameReader^ instance) {
        _instance = instance;
      }

      
    static void New(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(s_constructorTemplate);

      // in case the constructor was called without the new operator
      if (!localRef->HasInstance(info.This())) {
        if (info.Length() > 0) {
          std::unique_ptr<Local<Value> []> constructorArgs(new Local<Value>[info.Length()]);

          Local<Value> *argsPtr = constructorArgs.get();
          for (int i = 0; i < info.Length(); i++) {
            argsPtr[i] = info[i];
          }

          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), constructorArgs.get());
          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        } else {
          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), nullptr);

          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        }
      }

      ::Windows::Media::Capture::Frames::MediaFrameReader^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameReader^>(info[0])) {
        try {
          winRtInstance = (::Windows::Media::Capture::Frames::MediaFrameReader^) NodeRT::Utils::GetObjectInstance(info[0]);
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no suitable constructor found")));
        return;
      }

      NodeRT::Utils::SetHiddenValue(info.This(), Nan::New<String>("__winRtInstance__").ToLocalChecked(), True());

      MediaFrameReader *wrapperInstance = new MediaFrameReader(winRtInstance);
      wrapperInstance->Wrap(info.This());

      info.GetReturnValue().Set(info.This());
    }


      
    static void CastFrom(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;
      if (info.Length() < 1 || !NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameReader^>(info[0])) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no object provided, or given object could not be casted to requested type")));
        return;
      }

      ::Windows::Media::Capture::Frames::MediaFrameReader^ winRtInstance;
      try {
        winRtInstance = (::Windows::Media::Capture::Frames::MediaFrameReader^) NodeRT::Utils::GetObjectInstance(info[0]);
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }

      info.GetReturnValue().Set(WrapMediaFrameReader(winRtInstance));
    }

    static void StartAsync(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameReader^>(info.This())) {
        return;
      }

      if (info.Length() == 0 || !info[info.Length() -1]->IsFunction()) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: No callback was given")));
        return;
      }

      MediaFrameReader *wrapper = MediaFrameReader::Unwrap<MediaFrameReader>(info.This());

      ::Windows::Foundation::IAsyncOperation<::Windows::Media::Capture::Frames::MediaFrameReaderStartStatus>^ op;


      if (info.Length() == 1)
      {
        try
        {
          op = wrapper->_instance->StartAsync();
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }

      auto opTask = create_task(op);
      uv_async_t* asyncToken = NodeUtils::Async::GetAsyncToken(info[info.Length() -1].As<Function>());

      opTask.then( [asyncToken] (task<::Windows::Media::Capture::Frames::MediaFrameReaderStartStatus> t) {
        try {
          auto result = t.get();
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [result](NodeUtils::InvokeCallbackDelegate invokeCallback) {


            Local<Value> error;
            Local<Value> arg1;
            {
              TryCatch tryCatch;
              arg1 = Nan::New<Integer>(static_cast<int>(result));
              if (tryCatch.HasCaught())
              {
                error = Nan::To<Object>(tryCatch.Exception()).ToLocalChecked();
              }
              else
              {
                error = Undefined();
              }
              if (arg1.IsEmpty()) arg1 = Undefined();
            }
            Local<Value> args[] = {error, arg1};


            invokeCallback(_countof(args), args);
          });
        } catch (Platform::Exception^ exception) {
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [exception](NodeUtils::InvokeCallbackDelegate invokeCallback) {
            Local<Value> error = NodeRT::Utils::WinRtExceptionToJsError(exception);

            Local<Value> args[] = {error};
            invokeCallback(_countof(args), args);
          });
        }
      });
    }
    static void StopAsync(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameReader^>(info.This())) {
        return;
      }

      if (info.Length() == 0 || !info[info.Length() -1]->IsFunction()) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: No callback was given")));
        return;
      }

      MediaFrameReader *wrapper = MediaFrameReader::Unwrap<MediaFrameReader>(info.This());

      ::Windows::Foundation::IAsyncAction^ op;


      if (info.Length() == 1)
      {
        try
        {
          op = wrapper->_instance->StopAsync();
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }

      auto opTask = create_task(op);
      uv_async_t* asyncToken = NodeUtils::Async::GetAsyncToken(info[info.Length() -1].As<Function>());

      opTask.then( [asyncToken] (task<void> t) {
        try {
          t.get();
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [](NodeUtils::InvokeCallbackDelegate invokeCallback) {


            Local<Value> args[] = {Undefined()};


            invokeCallback(_countof(args), args);
          });
        } catch (Platform::Exception^ exception) {
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [exception](NodeUtils::InvokeCallbackDelegate invokeCallback) {
            Local<Value> error = NodeRT::Utils::WinRtExceptionToJsError(exception);

            Local<Value> args[] = {error};
            invokeCallback(_countof(args), args);
          });
        }
      });
    }

    static void TryAcquireLatestFrame(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameReader^>(info.This())) {
        return;
      }

      MediaFrameReader *wrapper = MediaFrameReader::Unwrap<MediaFrameReader>(info.This());

      if (info.Length() == 0)
      {
        try
        {
          ::Windows::Media::Capture::Frames::MediaFrameReference^ result;
          result = wrapper->_instance->TryAcquireLatestFrame();
          info.GetReturnValue().Set(WrapMediaFrameReference(result));
          return;
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }
    }

    static void Close(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameReader^>(info.This())) {
        return;
      }

      MediaFrameReader *wrapper = MediaFrameReader::Unwrap<MediaFrameReader>(info.This());

      if (info.Length() == 0) {
        try {
          delete wrapper->_instance;
          wrapper->_instance = nullptr;
          return;
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      } else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }
    }



    static void AcquisitionModeGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameReader^>(info.This())) {
        return;
      }

      MediaFrameReader *wrapper = MediaFrameReader::Unwrap<MediaFrameReader>(info.This());

      try  {
        ::Windows::Media::Capture::Frames::MediaFrameReaderAcquisitionMode result = wrapper->_instance->AcquisitionMode;
        info.GetReturnValue().Set(Nan::New<Integer>(static_cast<int>(result)));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void AcquisitionModeSetter(Local<String> property, Local<Value> value, const Nan::PropertyCallbackInfo<void> &info) {
      HandleScope scope;

      if (!value->IsInt32()) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameReader^>(info.This())) {
        return;
      }

      MediaFrameReader *wrapper = MediaFrameReader::Unwrap<MediaFrameReader>(info.This());

      try {

        ::Windows::Media::Capture::Frames::MediaFrameReaderAcquisitionMode winRtValue = static_cast<::Windows::Media::Capture::Frames::MediaFrameReaderAcquisitionMode>(Nan::To<int32_t>(value).FromMaybe(0));

        wrapper->_instance->AcquisitionMode = winRtValue;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
      


    static void AddListener(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (info.Length() < 2 || !info[0]->IsString() || !info[1]->IsFunction()) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"wrong arguments, expected arguments are eventName(string),callback(function)")));
        return;
      }

      String::Value eventName(v8::Isolate::GetCurrent(), info[0]);
      auto str = *eventName;

      Local<Function> callback = info[1].As<Function>();

      ::Windows::Foundation::EventRegistrationToken registrationToken;
      if (NodeRT::Utils::CaseInsenstiveEquals(L"frameArrived", str))
      {
        if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameReader^>(info.This()))
        {
          Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
      return;
        }
        MediaFrameReader *wrapper = MediaFrameReader::Unwrap<MediaFrameReader>(info.This());
      
        try {
          Persistent<Object>* perstPtr = new Persistent<Object>();
          perstPtr->Reset(NodeRT::Utils::CreateCallbackObjectInDomain(callback));
          std::shared_ptr<Persistent<Object>> callbackObjPtr(perstPtr,
            [] (Persistent<Object> *ptr ) {
              NodeUtils::Async::RunOnMain([ptr]() {
                ptr->Reset();
                delete ptr;
            });
          });

          registrationToken = wrapper->_instance->FrameArrived::add(
            ref new ::Windows::Foundation::TypedEventHandler<::Windows::Media::Capture::Frames::MediaFrameReader^, ::Windows::Media::Capture::Frames::MediaFrameArrivedEventArgs^>(
            [callbackObjPtr](::Windows::Media::Capture::Frames::MediaFrameReader^ arg0, ::Windows::Media::Capture::Frames::MediaFrameArrivedEventArgs^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
                HandleScope scope;


                Local<Value> wrappedArg0;
                Local<Value> wrappedArg1;

                {
                  TryCatch tryCatch;


                  wrappedArg0 = WrapMediaFrameReader(arg0);
                  wrappedArg1 = WrapMediaFrameArrivedEventArgs(arg1);


                  if (wrappedArg0.IsEmpty()) wrappedArg0 = Undefined();
                  if (wrappedArg1.IsEmpty()) wrappedArg1 = Undefined();
                }

                Local<Value> args[] = { wrappedArg0, wrappedArg1 };
                Local<Object> callbackObjLocalRef = Nan::New<Object>(*callbackObjPtr);
                NodeRT::Utils::CallCallbackInDomain(callbackObjLocalRef, _countof(args), args);
              });
            })
          );
        }
        catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }

      }
 else  {
        Nan::ThrowError(Nan::Error(String::Concat(v8::Isolate::GetCurrent(), NodeRT::Utils::NewString(L"given event name isn't supported: "), info[0].As<String>())));
        return;
      }

      Local<Value> tokenMapVal = NodeRT::Utils::GetHiddenValue(callback, Nan::New<String>(REGISTRATION_TOKEN_MAP_PROPERTY_NAME).ToLocalChecked());
      Local<Object> tokenMap;

      if (tokenMapVal.IsEmpty() || Nan::Equals(tokenMapVal, Undefined()).FromMaybe(false)) {
        tokenMap = Nan::New<Object>();
        NodeRT::Utils::SetHiddenValueWithObject(callback, Nan::New<String>(REGISTRATION_TOKEN_MAP_PROPERTY_NAME).ToLocalChecked(), tokenMap);
      } else {
        tokenMap = Nan::To<Object>(tokenMapVal).ToLocalChecked();
      }

      Nan::Set(tokenMap, info[0], CreateOpaqueWrapper(::Windows::Foundation::PropertyValue::CreateInt64(registrationToken.Value)));
    }

    static void RemoveListener(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (info.Length() < 2 || !info[0]->IsString() || !info[1]->IsFunction()) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"wrong arguments, expected a string and a callback")));
        return;
      }

      String::Value eventName(v8::Isolate::GetCurrent(), info[0]);
      auto str = *eventName;

      if ((!NodeRT::Utils::CaseInsenstiveEquals(L"frameArrived", str))) {
        Nan::ThrowError(Nan::Error(String::Concat(v8::Isolate::GetCurrent(), NodeRT::Utils::NewString(L"given event name isn't supported: "), info[0].As<String>())));
        return;
      }

      Local<Function> callback = info[1].As<Function>();
      Local<Value> tokenMap = NodeRT::Utils::GetHiddenValue(callback, Nan::New<String>(REGISTRATION_TOKEN_MAP_PROPERTY_NAME).ToLocalChecked());

      if (tokenMap.IsEmpty() || Nan::Equals(tokenMap, Undefined()).FromMaybe(false)) {
        return;
      }

      Local<Value> opaqueWrapperObj =  Nan::Get(Nan::To<Object>(tokenMap).ToLocalChecked(), info[0]).ToLocalChecked();

      if (opaqueWrapperObj.IsEmpty() || Nan::Equals(opaqueWrapperObj,Undefined()).FromMaybe(false)) {
        return;
      }

      OpaqueWrapper *opaqueWrapper = OpaqueWrapper::Unwrap<OpaqueWrapper>(opaqueWrapperObj.As<Object>());

      long long tokenValue = (long long) opaqueWrapper->GetObjectInstance();
      ::Windows::Foundation::EventRegistrationToken registrationToken;
      registrationToken.Value = tokenValue;

      try  {
        if (NodeRT::Utils::CaseInsenstiveEquals(L"frameArrived", str)) {
          if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameReader^>(info.This()))
          {
            Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
            return;
          }
          MediaFrameReader *wrapper = MediaFrameReader::Unwrap<MediaFrameReader>(info.This());
          wrapper->_instance->FrameArrived::remove(registrationToken);
        }
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }

      Nan::Delete(Nan::To<Object>(tokenMap).ToLocalChecked(), Nan::To<String>(info[0]).ToLocalChecked());
    }
    private:
      ::Windows::Media::Capture::Frames::MediaFrameReader^ _instance;
      static Persistent<FunctionTemplate> s_constructorTemplate;

      friend v8::Local<v8::Value> WrapMediaFrameReader(::Windows::Media::Capture::Frames::MediaFrameReader^ wintRtInstance);
      friend ::Windows::Media::Capture::Frames::MediaFrameReader^ UnwrapMediaFrameReader(Local<Value> value);
  };

  Persistent<FunctionTemplate> MediaFrameReader::s_constructorTemplate;

  v8::Local<v8::Value> WrapMediaFrameReader(::Windows::Media::Capture::Frames::MediaFrameReader^ winRtInstance) {
    EscapableHandleScope scope;

    if (winRtInstance == nullptr) {
      return scope.Escape(Undefined());
    }

    Local<Value> opaqueWrapper = CreateOpaqueWrapper(winRtInstance);
    Local<Value> args[] = {opaqueWrapper};
    Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(MediaFrameReader::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::Media::Capture::Frames::MediaFrameReader^ UnwrapMediaFrameReader(Local<Value> value) {
     return MediaFrameReader::Unwrap<MediaFrameReader>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitMediaFrameReader(Local<Object> exports) {
    MediaFrameReader::Init(exports);
  }

  class MediaFrameReference : public WrapperBase {
    public:
      
      static void Init(const Local<Object> exports) {
        HandleScope scope;

        Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(New);
        s_constructorTemplate.Reset(localRef);
        localRef->SetClassName(Nan::New<String>("MediaFrameReference").ToLocalChecked());
        localRef->InstanceTemplate()->SetInternalFieldCount(1);


          
            Nan::SetPrototypeMethod(localRef, "close", Close);
          



          
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("bufferMediaFrame").ToLocalChecked(), BufferMediaFrameGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("coordinateSystem").ToLocalChecked(), CoordinateSystemGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("duration").ToLocalChecked(), DurationGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("format").ToLocalChecked(), FormatGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("properties").ToLocalChecked(), PropertiesGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("sourceKind").ToLocalChecked(), SourceKindGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("systemRelativeTime").ToLocalChecked(), SystemRelativeTimeGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("videoMediaFrame").ToLocalChecked(), VideoMediaFrameGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("audioMediaFrame").ToLocalChecked(), AudioMediaFrameGetter);

        Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
        Nan::SetMethod(constructor, "castFrom", CastFrom);



        Nan::Set(exports, Nan::New<String>("MediaFrameReference").ToLocalChecked(), constructor);
      }

      virtual ::Platform::Object^ GetObjectInstance() const override {
        return _instance;
      }

    private:

      MediaFrameReference(::Windows::Media::Capture::Frames::MediaFrameReference^ instance) {
        _instance = instance;
      }

      
    static void New(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(s_constructorTemplate);

      // in case the constructor was called without the new operator
      if (!localRef->HasInstance(info.This())) {
        if (info.Length() > 0) {
          std::unique_ptr<Local<Value> []> constructorArgs(new Local<Value>[info.Length()]);

          Local<Value> *argsPtr = constructorArgs.get();
          for (int i = 0; i < info.Length(); i++) {
            argsPtr[i] = info[i];
          }

          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), constructorArgs.get());
          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        } else {
          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), nullptr);

          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        }
      }

      ::Windows::Media::Capture::Frames::MediaFrameReference^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameReference^>(info[0])) {
        try {
          winRtInstance = (::Windows::Media::Capture::Frames::MediaFrameReference^) NodeRT::Utils::GetObjectInstance(info[0]);
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no suitable constructor found")));
        return;
      }

      NodeRT::Utils::SetHiddenValue(info.This(), Nan::New<String>("__winRtInstance__").ToLocalChecked(), True());

      MediaFrameReference *wrapperInstance = new MediaFrameReference(winRtInstance);
      wrapperInstance->Wrap(info.This());

      info.GetReturnValue().Set(info.This());
    }


      
    static void CastFrom(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;
      if (info.Length() < 1 || !NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameReference^>(info[0])) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no object provided, or given object could not be casted to requested type")));
        return;
      }

      ::Windows::Media::Capture::Frames::MediaFrameReference^ winRtInstance;
      try {
        winRtInstance = (::Windows::Media::Capture::Frames::MediaFrameReference^) NodeRT::Utils::GetObjectInstance(info[0]);
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }

      info.GetReturnValue().Set(WrapMediaFrameReference(winRtInstance));
    }



    static void Close(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameReference^>(info.This())) {
        return;
      }

      MediaFrameReference *wrapper = MediaFrameReference::Unwrap<MediaFrameReference>(info.This());

      if (info.Length() == 0) {
        try {
          delete wrapper->_instance;
          wrapper->_instance = nullptr;
          return;
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      } else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }
    }



    static void BufferMediaFrameGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameReference^>(info.This())) {
        return;
      }

      MediaFrameReference *wrapper = MediaFrameReference::Unwrap<MediaFrameReference>(info.This());

      try  {
        ::Windows::Media::Capture::Frames::BufferMediaFrame^ result = wrapper->_instance->BufferMediaFrame;
        info.GetReturnValue().Set(WrapBufferMediaFrame(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void CoordinateSystemGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameReference^>(info.This())) {
        return;
      }

      MediaFrameReference *wrapper = MediaFrameReference::Unwrap<MediaFrameReference>(info.This());

      try  {
        ::Windows::Perception::Spatial::SpatialCoordinateSystem^ result = wrapper->_instance->CoordinateSystem;
        info.GetReturnValue().Set(NodeRT::Utils::CreateExternalWinRTObject("Windows.Perception.Spatial", "SpatialCoordinateSystem", result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void DurationGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameReference^>(info.This())) {
        return;
      }

      MediaFrameReference *wrapper = MediaFrameReference::Unwrap<MediaFrameReference>(info.This());

      try  {
        ::Windows::Foundation::TimeSpan result = wrapper->_instance->Duration;
        info.GetReturnValue().Set(Nan::New<Number>(result.Duration/10000.0));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void FormatGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameReference^>(info.This())) {
        return;
      }

      MediaFrameReference *wrapper = MediaFrameReference::Unwrap<MediaFrameReference>(info.This());

      try  {
        ::Windows::Media::Capture::Frames::MediaFrameFormat^ result = wrapper->_instance->Format;
        info.GetReturnValue().Set(WrapMediaFrameFormat(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void PropertiesGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameReference^>(info.This())) {
        return;
      }

      MediaFrameReference *wrapper = MediaFrameReference::Unwrap<MediaFrameReference>(info.This());

      try  {
        ::Windows::Foundation::Collections::IMapView<::Platform::Guid, ::Platform::Object^>^ result = wrapper->_instance->Properties;
        info.GetReturnValue().Set(NodeRT::Collections::MapViewWrapper<::Platform::Guid,::Platform::Object^>::CreateMapViewWrapper(result, 
            [](::Platform::Guid val) -> Local<Value> {
              return NodeRT::Utils::GuidToJs(val);
            },
            [](Local<Value> value) -> bool {
              return NodeRT::Utils::IsGuid(value);
            },
            [](Local<Value> value) -> ::Platform::Guid {
              return NodeRT::Utils::GuidFromJs(value);
            },
            [](::Platform::Object^ val) -> Local<Value> {
              return CreateOpaqueWrapper(val);
            }
          ));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void SourceKindGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameReference^>(info.This())) {
        return;
      }

      MediaFrameReference *wrapper = MediaFrameReference::Unwrap<MediaFrameReference>(info.This());

      try  {
        ::Windows::Media::Capture::Frames::MediaFrameSourceKind result = wrapper->_instance->SourceKind;
        info.GetReturnValue().Set(Nan::New<Integer>(static_cast<int>(result)));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void SystemRelativeTimeGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameReference^>(info.This())) {
        return;
      }

      MediaFrameReference *wrapper = MediaFrameReference::Unwrap<MediaFrameReference>(info.This());

      try  {
        ::Platform::IBox<::Windows::Foundation::TimeSpan>^ result = wrapper->_instance->SystemRelativeTime;
        info.GetReturnValue().Set(result ? static_cast<Local<Value>>(Nan::New<Number>(result->Value.Duration/10000.0)) : Undefined());
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void VideoMediaFrameGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameReference^>(info.This())) {
        return;
      }

      MediaFrameReference *wrapper = MediaFrameReference::Unwrap<MediaFrameReference>(info.This());

      try  {
        ::Windows::Media::Capture::Frames::VideoMediaFrame^ result = wrapper->_instance->VideoMediaFrame;
        info.GetReturnValue().Set(WrapVideoMediaFrame(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void AudioMediaFrameGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameReference^>(info.This())) {
        return;
      }

      MediaFrameReference *wrapper = MediaFrameReference::Unwrap<MediaFrameReference>(info.This());

      try  {
        ::Windows::Media::Capture::Frames::AudioMediaFrame^ result = wrapper->_instance->AudioMediaFrame;
        info.GetReturnValue().Set(WrapAudioMediaFrame(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      


    private:
      ::Windows::Media::Capture::Frames::MediaFrameReference^ _instance;
      static Persistent<FunctionTemplate> s_constructorTemplate;

      friend v8::Local<v8::Value> WrapMediaFrameReference(::Windows::Media::Capture::Frames::MediaFrameReference^ wintRtInstance);
      friend ::Windows::Media::Capture::Frames::MediaFrameReference^ UnwrapMediaFrameReference(Local<Value> value);
  };

  Persistent<FunctionTemplate> MediaFrameReference::s_constructorTemplate;

  v8::Local<v8::Value> WrapMediaFrameReference(::Windows::Media::Capture::Frames::MediaFrameReference^ winRtInstance) {
    EscapableHandleScope scope;

    if (winRtInstance == nullptr) {
      return scope.Escape(Undefined());
    }

    Local<Value> opaqueWrapper = CreateOpaqueWrapper(winRtInstance);
    Local<Value> args[] = {opaqueWrapper};
    Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(MediaFrameReference::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::Media::Capture::Frames::MediaFrameReference^ UnwrapMediaFrameReference(Local<Value> value) {
     return MediaFrameReference::Unwrap<MediaFrameReference>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitMediaFrameReference(Local<Object> exports) {
    MediaFrameReference::Init(exports);
  }

  class MediaFrameSource : public WrapperBase {
    public:
      
      static void Init(const Local<Object> exports) {
        HandleScope scope;

        Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(New);
        s_constructorTemplate.Reset(localRef);
        localRef->SetClassName(Nan::New<String>("MediaFrameSource").ToLocalChecked());
        localRef->InstanceTemplate()->SetInternalFieldCount(1);

        Local<Function> func;
        Local<FunctionTemplate> funcTemplate;

          
            Nan::SetPrototypeMethod(localRef, "tryGetCameraIntrinsics", TryGetCameraIntrinsics);
          

          
            Nan::SetPrototypeMethod(localRef, "setFormatAsync", SetFormatAsync);
          

          
          Nan::SetPrototypeMethod(localRef,"addListener", AddListener);
          Nan::SetPrototypeMethod(localRef,"on", AddListener);
          Nan::SetPrototypeMethod(localRef,"removeListener", RemoveListener);
          Nan::SetPrototypeMethod(localRef, "off", RemoveListener);

          
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("controller").ToLocalChecked(), ControllerGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("currentFormat").ToLocalChecked(), CurrentFormatGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("info").ToLocalChecked(), InfoGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("supportedFormats").ToLocalChecked(), SupportedFormatsGetter);

        Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
        Nan::SetMethod(constructor, "castFrom", CastFrom);



        Nan::Set(exports, Nan::New<String>("MediaFrameSource").ToLocalChecked(), constructor);
      }

      virtual ::Platform::Object^ GetObjectInstance() const override {
        return _instance;
      }

    private:

      MediaFrameSource(::Windows::Media::Capture::Frames::MediaFrameSource^ instance) {
        _instance = instance;
      }

      
    static void New(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(s_constructorTemplate);

      // in case the constructor was called without the new operator
      if (!localRef->HasInstance(info.This())) {
        if (info.Length() > 0) {
          std::unique_ptr<Local<Value> []> constructorArgs(new Local<Value>[info.Length()]);

          Local<Value> *argsPtr = constructorArgs.get();
          for (int i = 0; i < info.Length(); i++) {
            argsPtr[i] = info[i];
          }

          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), constructorArgs.get());
          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        } else {
          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), nullptr);

          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        }
      }

      ::Windows::Media::Capture::Frames::MediaFrameSource^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameSource^>(info[0])) {
        try {
          winRtInstance = (::Windows::Media::Capture::Frames::MediaFrameSource^) NodeRT::Utils::GetObjectInstance(info[0]);
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no suitable constructor found")));
        return;
      }

      NodeRT::Utils::SetHiddenValue(info.This(), Nan::New<String>("__winRtInstance__").ToLocalChecked(), True());

      MediaFrameSource *wrapperInstance = new MediaFrameSource(winRtInstance);
      wrapperInstance->Wrap(info.This());

      info.GetReturnValue().Set(info.This());
    }


      
    static void CastFrom(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;
      if (info.Length() < 1 || !NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameSource^>(info[0])) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no object provided, or given object could not be casted to requested type")));
        return;
      }

      ::Windows::Media::Capture::Frames::MediaFrameSource^ winRtInstance;
      try {
        winRtInstance = (::Windows::Media::Capture::Frames::MediaFrameSource^) NodeRT::Utils::GetObjectInstance(info[0]);
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }

      info.GetReturnValue().Set(WrapMediaFrameSource(winRtInstance));
    }

    static void SetFormatAsync(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameSource^>(info.This())) {
        return;
      }

      if (info.Length() == 0 || !info[info.Length() -1]->IsFunction()) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: No callback was given")));
        return;
      }

      MediaFrameSource *wrapper = MediaFrameSource::Unwrap<MediaFrameSource>(info.This());

      ::Windows::Foundation::IAsyncAction^ op;


      if (info.Length() == 2
        && NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameFormat^>(info[0]))
      {
        try
        {
          ::Windows::Media::Capture::Frames::MediaFrameFormat^ arg0 = UnwrapMediaFrameFormat(info[0]);
          
          op = wrapper->_instance->SetFormatAsync(arg0);
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }

      auto opTask = create_task(op);
      uv_async_t* asyncToken = NodeUtils::Async::GetAsyncToken(info[info.Length() -1].As<Function>());

      opTask.then( [asyncToken] (task<void> t) {
        try {
          t.get();
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [](NodeUtils::InvokeCallbackDelegate invokeCallback) {


            Local<Value> args[] = {Undefined()};


            invokeCallback(_countof(args), args);
          });
        } catch (Platform::Exception^ exception) {
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [exception](NodeUtils::InvokeCallbackDelegate invokeCallback) {
            Local<Value> error = NodeRT::Utils::WinRtExceptionToJsError(exception);

            Local<Value> args[] = {error};
            invokeCallback(_countof(args), args);
          });
        }
      });
    }

    static void TryGetCameraIntrinsics(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameSource^>(info.This())) {
        return;
      }

      MediaFrameSource *wrapper = MediaFrameSource::Unwrap<MediaFrameSource>(info.This());

      if (info.Length() == 1
        && NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameFormat^>(info[0]))
      {
        try
        {
          ::Windows::Media::Capture::Frames::MediaFrameFormat^ arg0 = UnwrapMediaFrameFormat(info[0]);
          
          ::Windows::Media::Devices::Core::CameraIntrinsics^ result;
          result = wrapper->_instance->TryGetCameraIntrinsics(arg0);
          info.GetReturnValue().Set(NodeRT::Utils::CreateExternalWinRTObject("Windows.Media.Devices.Core", "CameraIntrinsics", result));
          return;
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }
    }



    static void ControllerGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameSource^>(info.This())) {
        return;
      }

      MediaFrameSource *wrapper = MediaFrameSource::Unwrap<MediaFrameSource>(info.This());

      try  {
        ::Windows::Media::Capture::Frames::MediaFrameSourceController^ result = wrapper->_instance->Controller;
        info.GetReturnValue().Set(WrapMediaFrameSourceController(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void CurrentFormatGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameSource^>(info.This())) {
        return;
      }

      MediaFrameSource *wrapper = MediaFrameSource::Unwrap<MediaFrameSource>(info.This());

      try  {
        ::Windows::Media::Capture::Frames::MediaFrameFormat^ result = wrapper->_instance->CurrentFormat;
        info.GetReturnValue().Set(WrapMediaFrameFormat(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void InfoGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameSource^>(info.This())) {
        return;
      }

      MediaFrameSource *wrapper = MediaFrameSource::Unwrap<MediaFrameSource>(info.This());

      try  {
        ::Windows::Media::Capture::Frames::MediaFrameSourceInfo^ result = wrapper->_instance->Info;
        info.GetReturnValue().Set(WrapMediaFrameSourceInfo(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void SupportedFormatsGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameSource^>(info.This())) {
        return;
      }

      MediaFrameSource *wrapper = MediaFrameSource::Unwrap<MediaFrameSource>(info.This());

      try  {
        ::Windows::Foundation::Collections::IVectorView<::Windows::Media::Capture::Frames::MediaFrameFormat^>^ result = wrapper->_instance->SupportedFormats;
        info.GetReturnValue().Set(NodeRT::Collections::VectorViewWrapper<::Windows::Media::Capture::Frames::MediaFrameFormat^>::CreateVectorViewWrapper(result, 
            [](::Windows::Media::Capture::Frames::MediaFrameFormat^ val) -> Local<Value> {
              return WrapMediaFrameFormat(val);
            },
            [](Local<Value> value) -> bool {
              return NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameFormat^>(value);
            },
            [](Local<Value> value) -> ::Windows::Media::Capture::Frames::MediaFrameFormat^ {
              return UnwrapMediaFrameFormat(value);
            }
          ));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      


    static void AddListener(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (info.Length() < 2 || !info[0]->IsString() || !info[1]->IsFunction()) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"wrong arguments, expected arguments are eventName(string),callback(function)")));
        return;
      }

      String::Value eventName(v8::Isolate::GetCurrent(), info[0]);
      auto str = *eventName;

      Local<Function> callback = info[1].As<Function>();

      ::Windows::Foundation::EventRegistrationToken registrationToken;
      if (NodeRT::Utils::CaseInsenstiveEquals(L"formatChanged", str))
      {
        if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameSource^>(info.This()))
        {
          Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
      return;
        }
        MediaFrameSource *wrapper = MediaFrameSource::Unwrap<MediaFrameSource>(info.This());
      
        try {
          Persistent<Object>* perstPtr = new Persistent<Object>();
          perstPtr->Reset(NodeRT::Utils::CreateCallbackObjectInDomain(callback));
          std::shared_ptr<Persistent<Object>> callbackObjPtr(perstPtr,
            [] (Persistent<Object> *ptr ) {
              NodeUtils::Async::RunOnMain([ptr]() {
                ptr->Reset();
                delete ptr;
            });
          });

          registrationToken = wrapper->_instance->FormatChanged::add(
            ref new ::Windows::Foundation::TypedEventHandler<::Windows::Media::Capture::Frames::MediaFrameSource^, ::Platform::Object^>(
            [callbackObjPtr](::Windows::Media::Capture::Frames::MediaFrameSource^ arg0, ::Platform::Object^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
                HandleScope scope;


                Local<Value> wrappedArg0;
                Local<Value> wrappedArg1;

                {
                  TryCatch tryCatch;


                  wrappedArg0 = WrapMediaFrameSource(arg0);
                  wrappedArg1 = CreateOpaqueWrapper(arg1);


                  if (wrappedArg0.IsEmpty()) wrappedArg0 = Undefined();
                  if (wrappedArg1.IsEmpty()) wrappedArg1 = Undefined();
                }

                Local<Value> args[] = { wrappedArg0, wrappedArg1 };
                Local<Object> callbackObjLocalRef = Nan::New<Object>(*callbackObjPtr);
                NodeRT::Utils::CallCallbackInDomain(callbackObjLocalRef, _countof(args), args);
              });
            })
          );
        }
        catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }

      }
 else  {
        Nan::ThrowError(Nan::Error(String::Concat(v8::Isolate::GetCurrent(), NodeRT::Utils::NewString(L"given event name isn't supported: "), info[0].As<String>())));
        return;
      }

      Local<Value> tokenMapVal = NodeRT::Utils::GetHiddenValue(callback, Nan::New<String>(REGISTRATION_TOKEN_MAP_PROPERTY_NAME).ToLocalChecked());
      Local<Object> tokenMap;

      if (tokenMapVal.IsEmpty() || Nan::Equals(tokenMapVal, Undefined()).FromMaybe(false)) {
        tokenMap = Nan::New<Object>();
        NodeRT::Utils::SetHiddenValueWithObject(callback, Nan::New<String>(REGISTRATION_TOKEN_MAP_PROPERTY_NAME).ToLocalChecked(), tokenMap);
      } else {
        tokenMap = Nan::To<Object>(tokenMapVal).ToLocalChecked();
      }

      Nan::Set(tokenMap, info[0], CreateOpaqueWrapper(::Windows::Foundation::PropertyValue::CreateInt64(registrationToken.Value)));
    }

    static void RemoveListener(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (info.Length() < 2 || !info[0]->IsString() || !info[1]->IsFunction()) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"wrong arguments, expected a string and a callback")));
        return;
      }

      String::Value eventName(v8::Isolate::GetCurrent(), info[0]);
      auto str = *eventName;

      if ((!NodeRT::Utils::CaseInsenstiveEquals(L"formatChanged", str))) {
        Nan::ThrowError(Nan::Error(String::Concat(v8::Isolate::GetCurrent(), NodeRT::Utils::NewString(L"given event name isn't supported: "), info[0].As<String>())));
        return;
      }

      Local<Function> callback = info[1].As<Function>();
      Local<Value> tokenMap = NodeRT::Utils::GetHiddenValue(callback, Nan::New<String>(REGISTRATION_TOKEN_MAP_PROPERTY_NAME).ToLocalChecked());

      if (tokenMap.IsEmpty() || Nan::Equals(tokenMap, Undefined()).FromMaybe(false)) {
        return;
      }

      Local<Value> opaqueWrapperObj =  Nan::Get(Nan::To<Object>(tokenMap).ToLocalChecked(), info[0]).ToLocalChecked();

      if (opaqueWrapperObj.IsEmpty() || Nan::Equals(opaqueWrapperObj,Undefined()).FromMaybe(false)) {
        return;
      }

      OpaqueWrapper *opaqueWrapper = OpaqueWrapper::Unwrap<OpaqueWrapper>(opaqueWrapperObj.As<Object>());

      long long tokenValue = (long long) opaqueWrapper->GetObjectInstance();
      ::Windows::Foundation::EventRegistrationToken registrationToken;
      registrationToken.Value = tokenValue;

      try  {
        if (NodeRT::Utils::CaseInsenstiveEquals(L"formatChanged", str)) {
          if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameSource^>(info.This()))
          {
            Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
            return;
          }
          MediaFrameSource *wrapper = MediaFrameSource::Unwrap<MediaFrameSource>(info.This());
          wrapper->_instance->FormatChanged::remove(registrationToken);
        }
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }

      Nan::Delete(Nan::To<Object>(tokenMap).ToLocalChecked(), Nan::To<String>(info[0]).ToLocalChecked());
    }
    private:
      ::Windows::Media::Capture::Frames::MediaFrameSource^ _instance;
      static Persistent<FunctionTemplate> s_constructorTemplate;

      friend v8::Local<v8::Value> WrapMediaFrameSource(::Windows::Media::Capture::Frames::MediaFrameSource^ wintRtInstance);
      friend ::Windows::Media::Capture::Frames::MediaFrameSource^ UnwrapMediaFrameSource(Local<Value> value);
  };

  Persistent<FunctionTemplate> MediaFrameSource::s_constructorTemplate;

  v8::Local<v8::Value> WrapMediaFrameSource(::Windows::Media::Capture::Frames::MediaFrameSource^ winRtInstance) {
    EscapableHandleScope scope;

    if (winRtInstance == nullptr) {
      return scope.Escape(Undefined());
    }

    Local<Value> opaqueWrapper = CreateOpaqueWrapper(winRtInstance);
    Local<Value> args[] = {opaqueWrapper};
    Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(MediaFrameSource::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::Media::Capture::Frames::MediaFrameSource^ UnwrapMediaFrameSource(Local<Value> value) {
     return MediaFrameSource::Unwrap<MediaFrameSource>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitMediaFrameSource(Local<Object> exports) {
    MediaFrameSource::Init(exports);
  }

  class MediaFrameSourceController : public WrapperBase {
    public:
      
      static void Init(const Local<Object> exports) {
        HandleScope scope;

        Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(New);
        s_constructorTemplate.Reset(localRef);
        localRef->SetClassName(Nan::New<String>("MediaFrameSourceController").ToLocalChecked());
        localRef->InstanceTemplate()->SetInternalFieldCount(1);

        Local<Function> func;
        Local<FunctionTemplate> funcTemplate;


          
            Nan::SetPrototypeMethod(localRef, "getPropertyAsync", GetPropertyAsync);
            Nan::SetPrototypeMethod(localRef, "setPropertyAsync", SetPropertyAsync);
            Nan::SetPrototypeMethod(localRef, "getPropertyByExtendedIdAsync", GetPropertyByExtendedIdAsync);
            Nan::SetPrototypeMethod(localRef, "setPropertyByExtendedIdAsync", SetPropertyByExtendedIdAsync);
          


          
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("videoDeviceController").ToLocalChecked(), VideoDeviceControllerGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("audioDeviceController").ToLocalChecked(), AudioDeviceControllerGetter);

        Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
        Nan::SetMethod(constructor, "castFrom", CastFrom);



        Nan::Set(exports, Nan::New<String>("MediaFrameSourceController").ToLocalChecked(), constructor);
      }

      virtual ::Platform::Object^ GetObjectInstance() const override {
        return _instance;
      }

    private:

      MediaFrameSourceController(::Windows::Media::Capture::Frames::MediaFrameSourceController^ instance) {
        _instance = instance;
      }

      
    static void New(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(s_constructorTemplate);

      // in case the constructor was called without the new operator
      if (!localRef->HasInstance(info.This())) {
        if (info.Length() > 0) {
          std::unique_ptr<Local<Value> []> constructorArgs(new Local<Value>[info.Length()]);

          Local<Value> *argsPtr = constructorArgs.get();
          for (int i = 0; i < info.Length(); i++) {
            argsPtr[i] = info[i];
          }

          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), constructorArgs.get());
          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        } else {
          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), nullptr);

          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        }
      }

      ::Windows::Media::Capture::Frames::MediaFrameSourceController^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameSourceController^>(info[0])) {
        try {
          winRtInstance = (::Windows::Media::Capture::Frames::MediaFrameSourceController^) NodeRT::Utils::GetObjectInstance(info[0]);
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no suitable constructor found")));
        return;
      }

      NodeRT::Utils::SetHiddenValue(info.This(), Nan::New<String>("__winRtInstance__").ToLocalChecked(), True());

      MediaFrameSourceController *wrapperInstance = new MediaFrameSourceController(winRtInstance);
      wrapperInstance->Wrap(info.This());

      info.GetReturnValue().Set(info.This());
    }


      
    static void CastFrom(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;
      if (info.Length() < 1 || !NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameSourceController^>(info[0])) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no object provided, or given object could not be casted to requested type")));
        return;
      }

      ::Windows::Media::Capture::Frames::MediaFrameSourceController^ winRtInstance;
      try {
        winRtInstance = (::Windows::Media::Capture::Frames::MediaFrameSourceController^) NodeRT::Utils::GetObjectInstance(info[0]);
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }

      info.GetReturnValue().Set(WrapMediaFrameSourceController(winRtInstance));
    }

    static void GetPropertyAsync(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameSourceController^>(info.This())) {
        return;
      }

      if (info.Length() == 0 || !info[info.Length() -1]->IsFunction()) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: No callback was given")));
        return;
      }

      MediaFrameSourceController *wrapper = MediaFrameSourceController::Unwrap<MediaFrameSourceController>(info.This());

      ::Windows::Foundation::IAsyncOperation<::Windows::Media::Capture::Frames::MediaFrameSourceGetPropertyResult^>^ op;


      if (info.Length() == 2
        && info[0]->IsString())
      {
        try
        {
          Platform::String^ arg0 = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(v8::Isolate::GetCurrent(), info[0])));
          
          op = wrapper->_instance->GetPropertyAsync(arg0);
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }

      auto opTask = create_task(op);
      uv_async_t* asyncToken = NodeUtils::Async::GetAsyncToken(info[info.Length() -1].As<Function>());

      opTask.then( [asyncToken] (task<::Windows::Media::Capture::Frames::MediaFrameSourceGetPropertyResult^> t) {
        try {
          auto result = t.get();
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [result](NodeUtils::InvokeCallbackDelegate invokeCallback) {


            Local<Value> error;
            Local<Value> arg1;
            {
              TryCatch tryCatch;
              arg1 = WrapMediaFrameSourceGetPropertyResult(result);
              if (tryCatch.HasCaught())
              {
                error = Nan::To<Object>(tryCatch.Exception()).ToLocalChecked();
              }
              else
              {
                error = Undefined();
              }
              if (arg1.IsEmpty()) arg1 = Undefined();
            }
            Local<Value> args[] = {error, arg1};


            invokeCallback(_countof(args), args);
          });
        } catch (Platform::Exception^ exception) {
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [exception](NodeUtils::InvokeCallbackDelegate invokeCallback) {
            Local<Value> error = NodeRT::Utils::WinRtExceptionToJsError(exception);

            Local<Value> args[] = {error};
            invokeCallback(_countof(args), args);
          });
        }
      });
    }
    static void SetPropertyAsync(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameSourceController^>(info.This())) {
        return;
      }

      if (info.Length() == 0 || !info[info.Length() -1]->IsFunction()) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: No callback was given")));
        return;
      }

      MediaFrameSourceController *wrapper = MediaFrameSourceController::Unwrap<MediaFrameSourceController>(info.This());

      ::Windows::Foundation::IAsyncOperation<::Windows::Media::Capture::Frames::MediaFrameSourceSetPropertyStatus>^ op;


      if (info.Length() == 3
        && info[0]->IsString()
        && NodeRT::Utils::IsWinRtWrapperOf<::Platform::Object^>(info[1]))
      {
        try
        {
          Platform::String^ arg0 = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(v8::Isolate::GetCurrent(), info[0])));
          ::Platform::Object^ arg1 = dynamic_cast<::Platform::Object^>(NodeRT::Utils::GetObjectInstance(info[1]));
          
          op = wrapper->_instance->SetPropertyAsync(arg0,arg1);
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }

      auto opTask = create_task(op);
      uv_async_t* asyncToken = NodeUtils::Async::GetAsyncToken(info[info.Length() -1].As<Function>());

      opTask.then( [asyncToken] (task<::Windows::Media::Capture::Frames::MediaFrameSourceSetPropertyStatus> t) {
        try {
          auto result = t.get();
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [result](NodeUtils::InvokeCallbackDelegate invokeCallback) {


            Local<Value> error;
            Local<Value> arg1;
            {
              TryCatch tryCatch;
              arg1 = Nan::New<Integer>(static_cast<int>(result));
              if (tryCatch.HasCaught())
              {
                error = Nan::To<Object>(tryCatch.Exception()).ToLocalChecked();
              }
              else
              {
                error = Undefined();
              }
              if (arg1.IsEmpty()) arg1 = Undefined();
            }
            Local<Value> args[] = {error, arg1};


            invokeCallback(_countof(args), args);
          });
        } catch (Platform::Exception^ exception) {
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [exception](NodeUtils::InvokeCallbackDelegate invokeCallback) {
            Local<Value> error = NodeRT::Utils::WinRtExceptionToJsError(exception);

            Local<Value> args[] = {error};
            invokeCallback(_countof(args), args);
          });
        }
      });
    }
    static void GetPropertyByExtendedIdAsync(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameSourceController^>(info.This())) {
        return;
      }

      if (info.Length() == 0 || !info[info.Length() -1]->IsFunction()) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: No callback was given")));
        return;
      }

      MediaFrameSourceController *wrapper = MediaFrameSourceController::Unwrap<MediaFrameSourceController>(info.This());

      ::Windows::Foundation::IAsyncOperation<::Windows::Media::Capture::Frames::MediaFrameSourceGetPropertyResult^>^ op;


      if (info.Length() == 3
        && (NodeRT::Utils::IsWinRtWrapperOf<::Platform::Array<unsigned char>^>(info[0]) || info[0]->IsArray())
        && info[1]->IsUint32())
      {
        try
        {
          ::Platform::Array<unsigned char>^ arg0 = 
            [] (v8::Local<v8::Value> value) -> ::Platform::Array<unsigned char>^
            {
              if (value->IsArray())
              {
                return NodeRT::Collections::JsArrayToWinrtArray<unsigned char>(value.As<Array>(), 
                 [](Local<Value> value) -> bool {
                   return value->IsInt32();
                 },
                 [](Local<Value> value) -> unsigned char {
                   return static_cast<unsigned char>(Nan::To<int32_t>(value).FromMaybe(0));
                 }
                );
              }
              else
              {
                return dynamic_cast<::Platform::Array<unsigned char>^>(NodeRT::Utils::GetObjectInstance(value));
              }
            } (info[0]);
          ::Platform::IBox<unsigned int>^ arg1 = ref new ::Platform::Box<unsigned int>(static_cast<unsigned int>(Nan::To<uint32_t>(info[1]).FromMaybe(0)));
          
          op = wrapper->_instance->GetPropertyByExtendedIdAsync(arg0,arg1);
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }

      auto opTask = create_task(op);
      uv_async_t* asyncToken = NodeUtils::Async::GetAsyncToken(info[info.Length() -1].As<Function>());

      opTask.then( [asyncToken] (task<::Windows::Media::Capture::Frames::MediaFrameSourceGetPropertyResult^> t) {
        try {
          auto result = t.get();
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [result](NodeUtils::InvokeCallbackDelegate invokeCallback) {


            Local<Value> error;
            Local<Value> arg1;
            {
              TryCatch tryCatch;
              arg1 = WrapMediaFrameSourceGetPropertyResult(result);
              if (tryCatch.HasCaught())
              {
                error = Nan::To<Object>(tryCatch.Exception()).ToLocalChecked();
              }
              else
              {
                error = Undefined();
              }
              if (arg1.IsEmpty()) arg1 = Undefined();
            }
            Local<Value> args[] = {error, arg1};


            invokeCallback(_countof(args), args);
          });
        } catch (Platform::Exception^ exception) {
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [exception](NodeUtils::InvokeCallbackDelegate invokeCallback) {
            Local<Value> error = NodeRT::Utils::WinRtExceptionToJsError(exception);

            Local<Value> args[] = {error};
            invokeCallback(_countof(args), args);
          });
        }
      });
    }
    static void SetPropertyByExtendedIdAsync(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameSourceController^>(info.This())) {
        return;
      }

      if (info.Length() == 0 || !info[info.Length() -1]->IsFunction()) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: No callback was given")));
        return;
      }

      MediaFrameSourceController *wrapper = MediaFrameSourceController::Unwrap<MediaFrameSourceController>(info.This());

      ::Windows::Foundation::IAsyncOperation<::Windows::Media::Capture::Frames::MediaFrameSourceSetPropertyStatus>^ op;


      if (info.Length() == 3
        && (NodeRT::Utils::IsWinRtWrapperOf<::Platform::Array<unsigned char>^>(info[0]) || info[0]->IsArray())
        && (NodeRT::Utils::IsWinRtWrapperOf<::Platform::Array<unsigned char>^>(info[1]) || info[1]->IsArray()))
      {
        try
        {
          ::Platform::Array<unsigned char>^ arg0 = 
            [] (v8::Local<v8::Value> value) -> ::Platform::Array<unsigned char>^
            {
              if (value->IsArray())
              {
                return NodeRT::Collections::JsArrayToWinrtArray<unsigned char>(value.As<Array>(), 
                 [](Local<Value> value) -> bool {
                   return value->IsInt32();
                 },
                 [](Local<Value> value) -> unsigned char {
                   return static_cast<unsigned char>(Nan::To<int32_t>(value).FromMaybe(0));
                 }
                );
              }
              else
              {
                return dynamic_cast<::Platform::Array<unsigned char>^>(NodeRT::Utils::GetObjectInstance(value));
              }
            } (info[0]);
          ::Platform::Array<unsigned char>^ arg1 = 
            [] (v8::Local<v8::Value> value) -> ::Platform::Array<unsigned char>^
            {
              if (value->IsArray())
              {
                return NodeRT::Collections::JsArrayToWinrtArray<unsigned char>(value.As<Array>(), 
                 [](Local<Value> value) -> bool {
                   return value->IsInt32();
                 },
                 [](Local<Value> value) -> unsigned char {
                   return static_cast<unsigned char>(Nan::To<int32_t>(value).FromMaybe(0));
                 }
                );
              }
              else
              {
                return dynamic_cast<::Platform::Array<unsigned char>^>(NodeRT::Utils::GetObjectInstance(value));
              }
            } (info[1]);
          
          op = wrapper->_instance->SetPropertyByExtendedIdAsync(arg0,arg1);
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }

      auto opTask = create_task(op);
      uv_async_t* asyncToken = NodeUtils::Async::GetAsyncToken(info[info.Length() -1].As<Function>());

      opTask.then( [asyncToken] (task<::Windows::Media::Capture::Frames::MediaFrameSourceSetPropertyStatus> t) {
        try {
          auto result = t.get();
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [result](NodeUtils::InvokeCallbackDelegate invokeCallback) {


            Local<Value> error;
            Local<Value> arg1;
            {
              TryCatch tryCatch;
              arg1 = Nan::New<Integer>(static_cast<int>(result));
              if (tryCatch.HasCaught())
              {
                error = Nan::To<Object>(tryCatch.Exception()).ToLocalChecked();
              }
              else
              {
                error = Undefined();
              }
              if (arg1.IsEmpty()) arg1 = Undefined();
            }
            Local<Value> args[] = {error, arg1};


            invokeCallback(_countof(args), args);
          });
        } catch (Platform::Exception^ exception) {
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [exception](NodeUtils::InvokeCallbackDelegate invokeCallback) {
            Local<Value> error = NodeRT::Utils::WinRtExceptionToJsError(exception);

            Local<Value> args[] = {error};
            invokeCallback(_countof(args), args);
          });
        }
      });
    }




    static void VideoDeviceControllerGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameSourceController^>(info.This())) {
        return;
      }

      MediaFrameSourceController *wrapper = MediaFrameSourceController::Unwrap<MediaFrameSourceController>(info.This());

      try  {
        ::Windows::Media::Devices::VideoDeviceController^ result = wrapper->_instance->VideoDeviceController;
        info.GetReturnValue().Set(NodeRT::Utils::CreateExternalWinRTObject("Windows.Media.Devices", "VideoDeviceController", result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void AudioDeviceControllerGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameSourceController^>(info.This())) {
        return;
      }

      MediaFrameSourceController *wrapper = MediaFrameSourceController::Unwrap<MediaFrameSourceController>(info.This());

      try  {
        ::Windows::Media::Devices::AudioDeviceController^ result = wrapper->_instance->AudioDeviceController;
        info.GetReturnValue().Set(NodeRT::Utils::CreateExternalWinRTObject("Windows.Media.Devices", "AudioDeviceController", result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      


    private:
      ::Windows::Media::Capture::Frames::MediaFrameSourceController^ _instance;
      static Persistent<FunctionTemplate> s_constructorTemplate;

      friend v8::Local<v8::Value> WrapMediaFrameSourceController(::Windows::Media::Capture::Frames::MediaFrameSourceController^ wintRtInstance);
      friend ::Windows::Media::Capture::Frames::MediaFrameSourceController^ UnwrapMediaFrameSourceController(Local<Value> value);
  };

  Persistent<FunctionTemplate> MediaFrameSourceController::s_constructorTemplate;

  v8::Local<v8::Value> WrapMediaFrameSourceController(::Windows::Media::Capture::Frames::MediaFrameSourceController^ winRtInstance) {
    EscapableHandleScope scope;

    if (winRtInstance == nullptr) {
      return scope.Escape(Undefined());
    }

    Local<Value> opaqueWrapper = CreateOpaqueWrapper(winRtInstance);
    Local<Value> args[] = {opaqueWrapper};
    Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(MediaFrameSourceController::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::Media::Capture::Frames::MediaFrameSourceController^ UnwrapMediaFrameSourceController(Local<Value> value) {
     return MediaFrameSourceController::Unwrap<MediaFrameSourceController>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitMediaFrameSourceController(Local<Object> exports) {
    MediaFrameSourceController::Init(exports);
  }

  class MediaFrameSourceGetPropertyResult : public WrapperBase {
    public:
      
      static void Init(const Local<Object> exports) {
        HandleScope scope;

        Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(New);
        s_constructorTemplate.Reset(localRef);
        localRef->SetClassName(Nan::New<String>("MediaFrameSourceGetPropertyResult").ToLocalChecked());
        localRef->InstanceTemplate()->SetInternalFieldCount(1);





          
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("status").ToLocalChecked(), StatusGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("value").ToLocalChecked(), ValueGetter);

        Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
        Nan::SetMethod(constructor, "castFrom", CastFrom);



        Nan::Set(exports, Nan::New<String>("MediaFrameSourceGetPropertyResult").ToLocalChecked(), constructor);
      }

      virtual ::Platform::Object^ GetObjectInstance() const override {
        return _instance;
      }

    private:

      MediaFrameSourceGetPropertyResult(::Windows::Media::Capture::Frames::MediaFrameSourceGetPropertyResult^ instance) {
        _instance = instance;
      }

      
    static void New(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(s_constructorTemplate);

      // in case the constructor was called without the new operator
      if (!localRef->HasInstance(info.This())) {
        if (info.Length() > 0) {
          std::unique_ptr<Local<Value> []> constructorArgs(new Local<Value>[info.Length()]);

          Local<Value> *argsPtr = constructorArgs.get();
          for (int i = 0; i < info.Length(); i++) {
            argsPtr[i] = info[i];
          }

          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), constructorArgs.get());
          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        } else {
          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), nullptr);

          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        }
      }

      ::Windows::Media::Capture::Frames::MediaFrameSourceGetPropertyResult^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameSourceGetPropertyResult^>(info[0])) {
        try {
          winRtInstance = (::Windows::Media::Capture::Frames::MediaFrameSourceGetPropertyResult^) NodeRT::Utils::GetObjectInstance(info[0]);
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no suitable constructor found")));
        return;
      }

      NodeRT::Utils::SetHiddenValue(info.This(), Nan::New<String>("__winRtInstance__").ToLocalChecked(), True());

      MediaFrameSourceGetPropertyResult *wrapperInstance = new MediaFrameSourceGetPropertyResult(winRtInstance);
      wrapperInstance->Wrap(info.This());

      info.GetReturnValue().Set(info.This());
    }


      
    static void CastFrom(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;
      if (info.Length() < 1 || !NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameSourceGetPropertyResult^>(info[0])) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no object provided, or given object could not be casted to requested type")));
        return;
      }

      ::Windows::Media::Capture::Frames::MediaFrameSourceGetPropertyResult^ winRtInstance;
      try {
        winRtInstance = (::Windows::Media::Capture::Frames::MediaFrameSourceGetPropertyResult^) NodeRT::Utils::GetObjectInstance(info[0]);
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }

      info.GetReturnValue().Set(WrapMediaFrameSourceGetPropertyResult(winRtInstance));
    }





    static void StatusGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameSourceGetPropertyResult^>(info.This())) {
        return;
      }

      MediaFrameSourceGetPropertyResult *wrapper = MediaFrameSourceGetPropertyResult::Unwrap<MediaFrameSourceGetPropertyResult>(info.This());

      try  {
        ::Windows::Media::Capture::Frames::MediaFrameSourceGetPropertyStatus result = wrapper->_instance->Status;
        info.GetReturnValue().Set(Nan::New<Integer>(static_cast<int>(result)));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void ValueGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameSourceGetPropertyResult^>(info.This())) {
        return;
      }

      MediaFrameSourceGetPropertyResult *wrapper = MediaFrameSourceGetPropertyResult::Unwrap<MediaFrameSourceGetPropertyResult>(info.This());

      try  {
        ::Platform::Object^ result = wrapper->_instance->Value;
        info.GetReturnValue().Set(CreateOpaqueWrapper(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      


    private:
      ::Windows::Media::Capture::Frames::MediaFrameSourceGetPropertyResult^ _instance;
      static Persistent<FunctionTemplate> s_constructorTemplate;

      friend v8::Local<v8::Value> WrapMediaFrameSourceGetPropertyResult(::Windows::Media::Capture::Frames::MediaFrameSourceGetPropertyResult^ wintRtInstance);
      friend ::Windows::Media::Capture::Frames::MediaFrameSourceGetPropertyResult^ UnwrapMediaFrameSourceGetPropertyResult(Local<Value> value);
  };

  Persistent<FunctionTemplate> MediaFrameSourceGetPropertyResult::s_constructorTemplate;

  v8::Local<v8::Value> WrapMediaFrameSourceGetPropertyResult(::Windows::Media::Capture::Frames::MediaFrameSourceGetPropertyResult^ winRtInstance) {
    EscapableHandleScope scope;

    if (winRtInstance == nullptr) {
      return scope.Escape(Undefined());
    }

    Local<Value> opaqueWrapper = CreateOpaqueWrapper(winRtInstance);
    Local<Value> args[] = {opaqueWrapper};
    Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(MediaFrameSourceGetPropertyResult::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::Media::Capture::Frames::MediaFrameSourceGetPropertyResult^ UnwrapMediaFrameSourceGetPropertyResult(Local<Value> value) {
     return MediaFrameSourceGetPropertyResult::Unwrap<MediaFrameSourceGetPropertyResult>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitMediaFrameSourceGetPropertyResult(Local<Object> exports) {
    MediaFrameSourceGetPropertyResult::Init(exports);
  }

  class MediaFrameSourceGroup : public WrapperBase {
    public:
      
      static void Init(const Local<Object> exports) {
        HandleScope scope;

        Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(New);
        s_constructorTemplate.Reset(localRef);
        localRef->SetClassName(Nan::New<String>("MediaFrameSourceGroup").ToLocalChecked());
        localRef->InstanceTemplate()->SetInternalFieldCount(1);

        Local<Function> func;
        Local<FunctionTemplate> funcTemplate;




          
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("displayName").ToLocalChecked(), DisplayNameGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("id").ToLocalChecked(), IdGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("sourceInfos").ToLocalChecked(), SourceInfosGetter);

        Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
        Nan::SetMethod(constructor, "castFrom", CastFrom);

        Nan::SetMethod(constructor, "getDeviceSelector", GetDeviceSelector);
        func = Nan::GetFunction(Nan::New<FunctionTemplate>(FindAllAsync)).ToLocalChecked();
        Nan::Set(constructor, Nan::New<String>("findAllAsync").ToLocalChecked(), func);
        func = Nan::GetFunction(Nan::New<FunctionTemplate>(FromIdAsync)).ToLocalChecked();
        Nan::Set(constructor, Nan::New<String>("fromIdAsync").ToLocalChecked(), func);


        Nan::Set(exports, Nan::New<String>("MediaFrameSourceGroup").ToLocalChecked(), constructor);
      }

      virtual ::Platform::Object^ GetObjectInstance() const override {
        return _instance;
      }

    private:

      MediaFrameSourceGroup(::Windows::Media::Capture::Frames::MediaFrameSourceGroup^ instance) {
        _instance = instance;
      }

      
    static void New(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(s_constructorTemplate);

      // in case the constructor was called without the new operator
      if (!localRef->HasInstance(info.This())) {
        if (info.Length() > 0) {
          std::unique_ptr<Local<Value> []> constructorArgs(new Local<Value>[info.Length()]);

          Local<Value> *argsPtr = constructorArgs.get();
          for (int i = 0; i < info.Length(); i++) {
            argsPtr[i] = info[i];
          }

          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), constructorArgs.get());
          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        } else {
          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), nullptr);

          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        }
      }

      ::Windows::Media::Capture::Frames::MediaFrameSourceGroup^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameSourceGroup^>(info[0])) {
        try {
          winRtInstance = (::Windows::Media::Capture::Frames::MediaFrameSourceGroup^) NodeRT::Utils::GetObjectInstance(info[0]);
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no suitable constructor found")));
        return;
      }

      NodeRT::Utils::SetHiddenValue(info.This(), Nan::New<String>("__winRtInstance__").ToLocalChecked(), True());

      MediaFrameSourceGroup *wrapperInstance = new MediaFrameSourceGroup(winRtInstance);
      wrapperInstance->Wrap(info.This());

      info.GetReturnValue().Set(info.This());
    }


      
    static void CastFrom(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;
      if (info.Length() < 1 || !NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameSourceGroup^>(info[0])) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no object provided, or given object could not be casted to requested type")));
        return;
      }

      ::Windows::Media::Capture::Frames::MediaFrameSourceGroup^ winRtInstance;
      try {
        winRtInstance = (::Windows::Media::Capture::Frames::MediaFrameSourceGroup^) NodeRT::Utils::GetObjectInstance(info[0]);
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }

      info.GetReturnValue().Set(WrapMediaFrameSourceGroup(winRtInstance));
    }




    static void FindAllAsync(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (info.Length() == 0 || !info[info.Length() -1]->IsFunction()) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: No callback was given")));
        return;
      }

      ::Windows::Foundation::IAsyncOperation<::Windows::Foundation::Collections::IVectorView<::Windows::Media::Capture::Frames::MediaFrameSourceGroup^>^>^ op;


      if (info.Length() == 1)
      {
        try
        {
          op = ::Windows::Media::Capture::Frames::MediaFrameSourceGroup::FindAllAsync();
        } catch (Platform::Exception ^exception) {
            NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
            return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }

      auto opTask = create_task(op);
      uv_async_t* asyncToken = NodeUtils::Async::GetAsyncToken(info[info.Length() -1].As<Function>());

      opTask.then( [asyncToken] (task<::Windows::Foundation::Collections::IVectorView<::Windows::Media::Capture::Frames::MediaFrameSourceGroup^>^> t)
      {
        try {
          auto result = t.get();
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [result](NodeUtils::InvokeCallbackDelegate invokeCallback) {


            Local<Value> error;
            Local<Value> arg1;
            {
              TryCatch tryCatch;
              arg1 = NodeRT::Collections::VectorViewWrapper<::Windows::Media::Capture::Frames::MediaFrameSourceGroup^>::CreateVectorViewWrapper(result, 
            [](::Windows::Media::Capture::Frames::MediaFrameSourceGroup^ val) -> Local<Value> {
              return WrapMediaFrameSourceGroup(val);
            },
            [](Local<Value> value) -> bool {
              return NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameSourceGroup^>(value);
            },
            [](Local<Value> value) -> ::Windows::Media::Capture::Frames::MediaFrameSourceGroup^ {
              return UnwrapMediaFrameSourceGroup(value);
            }
          );
              if (tryCatch.HasCaught())
              {
                error = Nan::To<Object>(tryCatch.Exception()).ToLocalChecked();
              }
              else
              {
                error = Undefined();
              }
              if (arg1.IsEmpty()) arg1 = Undefined();
            }
            Local<Value> args[] = {error, arg1};


            invokeCallback(_countof(args), args);
          });
        }
        catch (Platform::Exception^ exception)
        {
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [exception](NodeUtils::InvokeCallbackDelegate invokeCallback) {

            Local<Value> error = NodeRT::Utils::WinRtExceptionToJsError(exception);

            Local<Value> args[] = {error};
            invokeCallback(_countof(args), args);
          });
        }
      });
    }

    static void FromIdAsync(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (info.Length() == 0 || !info[info.Length() -1]->IsFunction()) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: No callback was given")));
        return;
      }

      ::Windows::Foundation::IAsyncOperation<::Windows::Media::Capture::Frames::MediaFrameSourceGroup^>^ op;


      if (info.Length() == 2
          && info[0]->IsString())
      {
        try
        {
          Platform::String^ arg0 = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(v8::Isolate::GetCurrent(), info[0])));
            
          op = ::Windows::Media::Capture::Frames::MediaFrameSourceGroup::FromIdAsync(arg0);
        } catch (Platform::Exception ^exception) {
            NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
            return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }

      auto opTask = create_task(op);
      uv_async_t* asyncToken = NodeUtils::Async::GetAsyncToken(info[info.Length() -1].As<Function>());

      opTask.then( [asyncToken] (task<::Windows::Media::Capture::Frames::MediaFrameSourceGroup^> t)
      {
        try {
          auto result = t.get();
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [result](NodeUtils::InvokeCallbackDelegate invokeCallback) {


            Local<Value> error;
            Local<Value> arg1;
            {
              TryCatch tryCatch;
              arg1 = WrapMediaFrameSourceGroup(result);
              if (tryCatch.HasCaught())
              {
                error = Nan::To<Object>(tryCatch.Exception()).ToLocalChecked();
              }
              else
              {
                error = Undefined();
              }
              if (arg1.IsEmpty()) arg1 = Undefined();
            }
            Local<Value> args[] = {error, arg1};


            invokeCallback(_countof(args), args);
          });
        }
        catch (Platform::Exception^ exception)
        {
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [exception](NodeUtils::InvokeCallbackDelegate invokeCallback) {

            Local<Value> error = NodeRT::Utils::WinRtExceptionToJsError(exception);

            Local<Value> args[] = {error};
            invokeCallback(_countof(args), args);
          });
        }
      });
    }


    static void GetDeviceSelector(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (info.Length() == 0)
      {
        try
        {
          Platform::String^ result;
          result = ::Windows::Media::Capture::Frames::MediaFrameSourceGroup::GetDeviceSelector();
          info.GetReturnValue().Set(NodeRT::Utils::NewString(result->Data()));
          return;
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else  {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }
    }

    static void DisplayNameGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameSourceGroup^>(info.This())) {
        return;
      }

      MediaFrameSourceGroup *wrapper = MediaFrameSourceGroup::Unwrap<MediaFrameSourceGroup>(info.This());

      try  {
        Platform::String^ result = wrapper->_instance->DisplayName;
        info.GetReturnValue().Set(NodeRT::Utils::NewString(result->Data()));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void IdGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameSourceGroup^>(info.This())) {
        return;
      }

      MediaFrameSourceGroup *wrapper = MediaFrameSourceGroup::Unwrap<MediaFrameSourceGroup>(info.This());

      try  {
        Platform::String^ result = wrapper->_instance->Id;
        info.GetReturnValue().Set(NodeRT::Utils::NewString(result->Data()));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void SourceInfosGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameSourceGroup^>(info.This())) {
        return;
      }

      MediaFrameSourceGroup *wrapper = MediaFrameSourceGroup::Unwrap<MediaFrameSourceGroup>(info.This());

      try  {
        ::Windows::Foundation::Collections::IVectorView<::Windows::Media::Capture::Frames::MediaFrameSourceInfo^>^ result = wrapper->_instance->SourceInfos;
        info.GetReturnValue().Set(NodeRT::Collections::VectorViewWrapper<::Windows::Media::Capture::Frames::MediaFrameSourceInfo^>::CreateVectorViewWrapper(result, 
            [](::Windows::Media::Capture::Frames::MediaFrameSourceInfo^ val) -> Local<Value> {
              return WrapMediaFrameSourceInfo(val);
            },
            [](Local<Value> value) -> bool {
              return NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameSourceInfo^>(value);
            },
            [](Local<Value> value) -> ::Windows::Media::Capture::Frames::MediaFrameSourceInfo^ {
              return UnwrapMediaFrameSourceInfo(value);
            }
          ));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      


    private:
      ::Windows::Media::Capture::Frames::MediaFrameSourceGroup^ _instance;
      static Persistent<FunctionTemplate> s_constructorTemplate;

      friend v8::Local<v8::Value> WrapMediaFrameSourceGroup(::Windows::Media::Capture::Frames::MediaFrameSourceGroup^ wintRtInstance);
      friend ::Windows::Media::Capture::Frames::MediaFrameSourceGroup^ UnwrapMediaFrameSourceGroup(Local<Value> value);
  };

  Persistent<FunctionTemplate> MediaFrameSourceGroup::s_constructorTemplate;

  v8::Local<v8::Value> WrapMediaFrameSourceGroup(::Windows::Media::Capture::Frames::MediaFrameSourceGroup^ winRtInstance) {
    EscapableHandleScope scope;

    if (winRtInstance == nullptr) {
      return scope.Escape(Undefined());
    }

    Local<Value> opaqueWrapper = CreateOpaqueWrapper(winRtInstance);
    Local<Value> args[] = {opaqueWrapper};
    Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(MediaFrameSourceGroup::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::Media::Capture::Frames::MediaFrameSourceGroup^ UnwrapMediaFrameSourceGroup(Local<Value> value) {
     return MediaFrameSourceGroup::Unwrap<MediaFrameSourceGroup>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitMediaFrameSourceGroup(Local<Object> exports) {
    MediaFrameSourceGroup::Init(exports);
  }

  class MediaFrameSourceInfo : public WrapperBase {
    public:
      
      static void Init(const Local<Object> exports) {
        HandleScope scope;

        Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(New);
        s_constructorTemplate.Reset(localRef);
        localRef->SetClassName(Nan::New<String>("MediaFrameSourceInfo").ToLocalChecked());
        localRef->InstanceTemplate()->SetInternalFieldCount(1);


          
            Nan::SetPrototypeMethod(localRef, "getRelativePanel", GetRelativePanel);
          



          
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("coordinateSystem").ToLocalChecked(), CoordinateSystemGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("deviceInformation").ToLocalChecked(), DeviceInformationGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("id").ToLocalChecked(), IdGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("mediaStreamType").ToLocalChecked(), MediaStreamTypeGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("properties").ToLocalChecked(), PropertiesGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("sourceGroup").ToLocalChecked(), SourceGroupGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("sourceKind").ToLocalChecked(), SourceKindGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("profileId").ToLocalChecked(), ProfileIdGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("videoProfileMediaDescription").ToLocalChecked(), VideoProfileMediaDescriptionGetter);

        Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
        Nan::SetMethod(constructor, "castFrom", CastFrom);



        Nan::Set(exports, Nan::New<String>("MediaFrameSourceInfo").ToLocalChecked(), constructor);
      }

      virtual ::Platform::Object^ GetObjectInstance() const override {
        return _instance;
      }

    private:

      MediaFrameSourceInfo(::Windows::Media::Capture::Frames::MediaFrameSourceInfo^ instance) {
        _instance = instance;
      }

      
    static void New(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(s_constructorTemplate);

      // in case the constructor was called without the new operator
      if (!localRef->HasInstance(info.This())) {
        if (info.Length() > 0) {
          std::unique_ptr<Local<Value> []> constructorArgs(new Local<Value>[info.Length()]);

          Local<Value> *argsPtr = constructorArgs.get();
          for (int i = 0; i < info.Length(); i++) {
            argsPtr[i] = info[i];
          }

          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), constructorArgs.get());
          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        } else {
          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), nullptr);

          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        }
      }

      ::Windows::Media::Capture::Frames::MediaFrameSourceInfo^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameSourceInfo^>(info[0])) {
        try {
          winRtInstance = (::Windows::Media::Capture::Frames::MediaFrameSourceInfo^) NodeRT::Utils::GetObjectInstance(info[0]);
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no suitable constructor found")));
        return;
      }

      NodeRT::Utils::SetHiddenValue(info.This(), Nan::New<String>("__winRtInstance__").ToLocalChecked(), True());

      MediaFrameSourceInfo *wrapperInstance = new MediaFrameSourceInfo(winRtInstance);
      wrapperInstance->Wrap(info.This());

      info.GetReturnValue().Set(info.This());
    }


      
    static void CastFrom(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;
      if (info.Length() < 1 || !NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameSourceInfo^>(info[0])) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no object provided, or given object could not be casted to requested type")));
        return;
      }

      ::Windows::Media::Capture::Frames::MediaFrameSourceInfo^ winRtInstance;
      try {
        winRtInstance = (::Windows::Media::Capture::Frames::MediaFrameSourceInfo^) NodeRT::Utils::GetObjectInstance(info[0]);
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }

      info.GetReturnValue().Set(WrapMediaFrameSourceInfo(winRtInstance));
    }


    static void GetRelativePanel(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameSourceInfo^>(info.This())) {
        return;
      }

      MediaFrameSourceInfo *wrapper = MediaFrameSourceInfo::Unwrap<MediaFrameSourceInfo>(info.This());

      if (info.Length() == 1
        && NodeRT::Utils::IsWinRtWrapperOf<::Windows::UI::WindowManagement::DisplayRegion^>(info[0]))
      {
        try
        {
          ::Windows::UI::WindowManagement::DisplayRegion^ arg0 = dynamic_cast<::Windows::UI::WindowManagement::DisplayRegion^>(NodeRT::Utils::GetObjectInstance(info[0]));
          
          ::Windows::Devices::Enumeration::Panel result;
          result = wrapper->_instance->GetRelativePanel(arg0);
          info.GetReturnValue().Set(Nan::New<Integer>(static_cast<int>(result)));
          return;
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }
    }



    static void CoordinateSystemGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameSourceInfo^>(info.This())) {
        return;
      }

      MediaFrameSourceInfo *wrapper = MediaFrameSourceInfo::Unwrap<MediaFrameSourceInfo>(info.This());

      try  {
        ::Windows::Perception::Spatial::SpatialCoordinateSystem^ result = wrapper->_instance->CoordinateSystem;
        info.GetReturnValue().Set(NodeRT::Utils::CreateExternalWinRTObject("Windows.Perception.Spatial", "SpatialCoordinateSystem", result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void DeviceInformationGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameSourceInfo^>(info.This())) {
        return;
      }

      MediaFrameSourceInfo *wrapper = MediaFrameSourceInfo::Unwrap<MediaFrameSourceInfo>(info.This());

      try  {
        ::Windows::Devices::Enumeration::DeviceInformation^ result = wrapper->_instance->DeviceInformation;
        info.GetReturnValue().Set(NodeRT::Utils::CreateExternalWinRTObject("Windows.Devices.Enumeration", "DeviceInformation", result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void IdGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameSourceInfo^>(info.This())) {
        return;
      }

      MediaFrameSourceInfo *wrapper = MediaFrameSourceInfo::Unwrap<MediaFrameSourceInfo>(info.This());

      try  {
        Platform::String^ result = wrapper->_instance->Id;
        info.GetReturnValue().Set(NodeRT::Utils::NewString(result->Data()));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void MediaStreamTypeGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameSourceInfo^>(info.This())) {
        return;
      }

      MediaFrameSourceInfo *wrapper = MediaFrameSourceInfo::Unwrap<MediaFrameSourceInfo>(info.This());

      try  {
        ::Windows::Media::Capture::MediaStreamType result = wrapper->_instance->MediaStreamType;
        info.GetReturnValue().Set(Nan::New<Integer>(static_cast<int>(result)));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void PropertiesGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameSourceInfo^>(info.This())) {
        return;
      }

      MediaFrameSourceInfo *wrapper = MediaFrameSourceInfo::Unwrap<MediaFrameSourceInfo>(info.This());

      try  {
        ::Windows::Foundation::Collections::IMapView<::Platform::Guid, ::Platform::Object^>^ result = wrapper->_instance->Properties;
        info.GetReturnValue().Set(NodeRT::Collections::MapViewWrapper<::Platform::Guid,::Platform::Object^>::CreateMapViewWrapper(result, 
            [](::Platform::Guid val) -> Local<Value> {
              return NodeRT::Utils::GuidToJs(val);
            },
            [](Local<Value> value) -> bool {
              return NodeRT::Utils::IsGuid(value);
            },
            [](Local<Value> value) -> ::Platform::Guid {
              return NodeRT::Utils::GuidFromJs(value);
            },
            [](::Platform::Object^ val) -> Local<Value> {
              return CreateOpaqueWrapper(val);
            }
          ));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void SourceGroupGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameSourceInfo^>(info.This())) {
        return;
      }

      MediaFrameSourceInfo *wrapper = MediaFrameSourceInfo::Unwrap<MediaFrameSourceInfo>(info.This());

      try  {
        ::Windows::Media::Capture::Frames::MediaFrameSourceGroup^ result = wrapper->_instance->SourceGroup;
        info.GetReturnValue().Set(WrapMediaFrameSourceGroup(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void SourceKindGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameSourceInfo^>(info.This())) {
        return;
      }

      MediaFrameSourceInfo *wrapper = MediaFrameSourceInfo::Unwrap<MediaFrameSourceInfo>(info.This());

      try  {
        ::Windows::Media::Capture::Frames::MediaFrameSourceKind result = wrapper->_instance->SourceKind;
        info.GetReturnValue().Set(Nan::New<Integer>(static_cast<int>(result)));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void ProfileIdGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameSourceInfo^>(info.This())) {
        return;
      }

      MediaFrameSourceInfo *wrapper = MediaFrameSourceInfo::Unwrap<MediaFrameSourceInfo>(info.This());

      try  {
        Platform::String^ result = wrapper->_instance->ProfileId;
        info.GetReturnValue().Set(NodeRT::Utils::NewString(result->Data()));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void VideoProfileMediaDescriptionGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MediaFrameSourceInfo^>(info.This())) {
        return;
      }

      MediaFrameSourceInfo *wrapper = MediaFrameSourceInfo::Unwrap<MediaFrameSourceInfo>(info.This());

      try  {
        ::Windows::Foundation::Collections::IVectorView<::Windows::Media::Capture::MediaCaptureVideoProfileMediaDescription^>^ result = wrapper->_instance->VideoProfileMediaDescription;
        info.GetReturnValue().Set(NodeRT::Collections::VectorViewWrapper<::Windows::Media::Capture::MediaCaptureVideoProfileMediaDescription^>::CreateVectorViewWrapper(result, 
            [](::Windows::Media::Capture::MediaCaptureVideoProfileMediaDescription^ val) -> Local<Value> {
              return NodeRT::Utils::CreateExternalWinRTObject("Windows.Media.Capture", "MediaCaptureVideoProfileMediaDescription", val);
            },
            [](Local<Value> value) -> bool {
              return NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::MediaCaptureVideoProfileMediaDescription^>(value);
            },
            [](Local<Value> value) -> ::Windows::Media::Capture::MediaCaptureVideoProfileMediaDescription^ {
              return dynamic_cast<::Windows::Media::Capture::MediaCaptureVideoProfileMediaDescription^>(NodeRT::Utils::GetObjectInstance(value));
            }
          ));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      


    private:
      ::Windows::Media::Capture::Frames::MediaFrameSourceInfo^ _instance;
      static Persistent<FunctionTemplate> s_constructorTemplate;

      friend v8::Local<v8::Value> WrapMediaFrameSourceInfo(::Windows::Media::Capture::Frames::MediaFrameSourceInfo^ wintRtInstance);
      friend ::Windows::Media::Capture::Frames::MediaFrameSourceInfo^ UnwrapMediaFrameSourceInfo(Local<Value> value);
  };

  Persistent<FunctionTemplate> MediaFrameSourceInfo::s_constructorTemplate;

  v8::Local<v8::Value> WrapMediaFrameSourceInfo(::Windows::Media::Capture::Frames::MediaFrameSourceInfo^ winRtInstance) {
    EscapableHandleScope scope;

    if (winRtInstance == nullptr) {
      return scope.Escape(Undefined());
    }

    Local<Value> opaqueWrapper = CreateOpaqueWrapper(winRtInstance);
    Local<Value> args[] = {opaqueWrapper};
    Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(MediaFrameSourceInfo::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::Media::Capture::Frames::MediaFrameSourceInfo^ UnwrapMediaFrameSourceInfo(Local<Value> value) {
     return MediaFrameSourceInfo::Unwrap<MediaFrameSourceInfo>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitMediaFrameSourceInfo(Local<Object> exports) {
    MediaFrameSourceInfo::Init(exports);
  }

  class MultiSourceMediaFrameArrivedEventArgs : public WrapperBase {
    public:
      
      static void Init(const Local<Object> exports) {
        HandleScope scope;

        Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(New);
        s_constructorTemplate.Reset(localRef);
        localRef->SetClassName(Nan::New<String>("MultiSourceMediaFrameArrivedEventArgs").ToLocalChecked());
        localRef->InstanceTemplate()->SetInternalFieldCount(1);






        Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
        Nan::SetMethod(constructor, "castFrom", CastFrom);



        Nan::Set(exports, Nan::New<String>("MultiSourceMediaFrameArrivedEventArgs").ToLocalChecked(), constructor);
      }

      virtual ::Platform::Object^ GetObjectInstance() const override {
        return _instance;
      }

    private:

      MultiSourceMediaFrameArrivedEventArgs(::Windows::Media::Capture::Frames::MultiSourceMediaFrameArrivedEventArgs^ instance) {
        _instance = instance;
      }

      
    static void New(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(s_constructorTemplate);

      // in case the constructor was called without the new operator
      if (!localRef->HasInstance(info.This())) {
        if (info.Length() > 0) {
          std::unique_ptr<Local<Value> []> constructorArgs(new Local<Value>[info.Length()]);

          Local<Value> *argsPtr = constructorArgs.get();
          for (int i = 0; i < info.Length(); i++) {
            argsPtr[i] = info[i];
          }

          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), constructorArgs.get());
          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        } else {
          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), nullptr);

          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        }
      }

      ::Windows::Media::Capture::Frames::MultiSourceMediaFrameArrivedEventArgs^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MultiSourceMediaFrameArrivedEventArgs^>(info[0])) {
        try {
          winRtInstance = (::Windows::Media::Capture::Frames::MultiSourceMediaFrameArrivedEventArgs^) NodeRT::Utils::GetObjectInstance(info[0]);
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no suitable constructor found")));
        return;
      }

      NodeRT::Utils::SetHiddenValue(info.This(), Nan::New<String>("__winRtInstance__").ToLocalChecked(), True());

      MultiSourceMediaFrameArrivedEventArgs *wrapperInstance = new MultiSourceMediaFrameArrivedEventArgs(winRtInstance);
      wrapperInstance->Wrap(info.This());

      info.GetReturnValue().Set(info.This());
    }


      
    static void CastFrom(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;
      if (info.Length() < 1 || !NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MultiSourceMediaFrameArrivedEventArgs^>(info[0])) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no object provided, or given object could not be casted to requested type")));
        return;
      }

      ::Windows::Media::Capture::Frames::MultiSourceMediaFrameArrivedEventArgs^ winRtInstance;
      try {
        winRtInstance = (::Windows::Media::Capture::Frames::MultiSourceMediaFrameArrivedEventArgs^) NodeRT::Utils::GetObjectInstance(info[0]);
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }

      info.GetReturnValue().Set(WrapMultiSourceMediaFrameArrivedEventArgs(winRtInstance));
    }







    private:
      ::Windows::Media::Capture::Frames::MultiSourceMediaFrameArrivedEventArgs^ _instance;
      static Persistent<FunctionTemplate> s_constructorTemplate;

      friend v8::Local<v8::Value> WrapMultiSourceMediaFrameArrivedEventArgs(::Windows::Media::Capture::Frames::MultiSourceMediaFrameArrivedEventArgs^ wintRtInstance);
      friend ::Windows::Media::Capture::Frames::MultiSourceMediaFrameArrivedEventArgs^ UnwrapMultiSourceMediaFrameArrivedEventArgs(Local<Value> value);
  };

  Persistent<FunctionTemplate> MultiSourceMediaFrameArrivedEventArgs::s_constructorTemplate;

  v8::Local<v8::Value> WrapMultiSourceMediaFrameArrivedEventArgs(::Windows::Media::Capture::Frames::MultiSourceMediaFrameArrivedEventArgs^ winRtInstance) {
    EscapableHandleScope scope;

    if (winRtInstance == nullptr) {
      return scope.Escape(Undefined());
    }

    Local<Value> opaqueWrapper = CreateOpaqueWrapper(winRtInstance);
    Local<Value> args[] = {opaqueWrapper};
    Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(MultiSourceMediaFrameArrivedEventArgs::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::Media::Capture::Frames::MultiSourceMediaFrameArrivedEventArgs^ UnwrapMultiSourceMediaFrameArrivedEventArgs(Local<Value> value) {
     return MultiSourceMediaFrameArrivedEventArgs::Unwrap<MultiSourceMediaFrameArrivedEventArgs>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitMultiSourceMediaFrameArrivedEventArgs(Local<Object> exports) {
    MultiSourceMediaFrameArrivedEventArgs::Init(exports);
  }

  class MultiSourceMediaFrameReader : public WrapperBase {
    public:
      
      static void Init(const Local<Object> exports) {
        HandleScope scope;

        Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(New);
        s_constructorTemplate.Reset(localRef);
        localRef->SetClassName(Nan::New<String>("MultiSourceMediaFrameReader").ToLocalChecked());
        localRef->InstanceTemplate()->SetInternalFieldCount(1);

        Local<Function> func;
        Local<FunctionTemplate> funcTemplate;

          
            Nan::SetPrototypeMethod(localRef, "tryAcquireLatestFrame", TryAcquireLatestFrame);
            Nan::SetPrototypeMethod(localRef, "close", Close);
          

          
            Nan::SetPrototypeMethod(localRef, "startAsync", StartAsync);
            Nan::SetPrototypeMethod(localRef, "stopAsync", StopAsync);
          

          
          Nan::SetPrototypeMethod(localRef,"addListener", AddListener);
          Nan::SetPrototypeMethod(localRef,"on", AddListener);
          Nan::SetPrototypeMethod(localRef,"removeListener", RemoveListener);
          Nan::SetPrototypeMethod(localRef, "off", RemoveListener);

          
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("acquisitionMode").ToLocalChecked(), AcquisitionModeGetter, AcquisitionModeSetter);

        Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
        Nan::SetMethod(constructor, "castFrom", CastFrom);



        Nan::Set(exports, Nan::New<String>("MultiSourceMediaFrameReader").ToLocalChecked(), constructor);
      }

      virtual ::Platform::Object^ GetObjectInstance() const override {
        return _instance;
      }

    private:

      MultiSourceMediaFrameReader(::Windows::Media::Capture::Frames::MultiSourceMediaFrameReader^ instance) {
        _instance = instance;
      }

      
    static void New(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(s_constructorTemplate);

      // in case the constructor was called without the new operator
      if (!localRef->HasInstance(info.This())) {
        if (info.Length() > 0) {
          std::unique_ptr<Local<Value> []> constructorArgs(new Local<Value>[info.Length()]);

          Local<Value> *argsPtr = constructorArgs.get();
          for (int i = 0; i < info.Length(); i++) {
            argsPtr[i] = info[i];
          }

          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), constructorArgs.get());
          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        } else {
          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), nullptr);

          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        }
      }

      ::Windows::Media::Capture::Frames::MultiSourceMediaFrameReader^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MultiSourceMediaFrameReader^>(info[0])) {
        try {
          winRtInstance = (::Windows::Media::Capture::Frames::MultiSourceMediaFrameReader^) NodeRT::Utils::GetObjectInstance(info[0]);
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no suitable constructor found")));
        return;
      }

      NodeRT::Utils::SetHiddenValue(info.This(), Nan::New<String>("__winRtInstance__").ToLocalChecked(), True());

      MultiSourceMediaFrameReader *wrapperInstance = new MultiSourceMediaFrameReader(winRtInstance);
      wrapperInstance->Wrap(info.This());

      info.GetReturnValue().Set(info.This());
    }


      
    static void CastFrom(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;
      if (info.Length() < 1 || !NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MultiSourceMediaFrameReader^>(info[0])) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no object provided, or given object could not be casted to requested type")));
        return;
      }

      ::Windows::Media::Capture::Frames::MultiSourceMediaFrameReader^ winRtInstance;
      try {
        winRtInstance = (::Windows::Media::Capture::Frames::MultiSourceMediaFrameReader^) NodeRT::Utils::GetObjectInstance(info[0]);
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }

      info.GetReturnValue().Set(WrapMultiSourceMediaFrameReader(winRtInstance));
    }

    static void StartAsync(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MultiSourceMediaFrameReader^>(info.This())) {
        return;
      }

      if (info.Length() == 0 || !info[info.Length() -1]->IsFunction()) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: No callback was given")));
        return;
      }

      MultiSourceMediaFrameReader *wrapper = MultiSourceMediaFrameReader::Unwrap<MultiSourceMediaFrameReader>(info.This());

      ::Windows::Foundation::IAsyncOperation<::Windows::Media::Capture::Frames::MultiSourceMediaFrameReaderStartStatus>^ op;


      if (info.Length() == 1)
      {
        try
        {
          op = wrapper->_instance->StartAsync();
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }

      auto opTask = create_task(op);
      uv_async_t* asyncToken = NodeUtils::Async::GetAsyncToken(info[info.Length() -1].As<Function>());

      opTask.then( [asyncToken] (task<::Windows::Media::Capture::Frames::MultiSourceMediaFrameReaderStartStatus> t) {
        try {
          auto result = t.get();
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [result](NodeUtils::InvokeCallbackDelegate invokeCallback) {


            Local<Value> error;
            Local<Value> arg1;
            {
              TryCatch tryCatch;
              arg1 = Nan::New<Integer>(static_cast<int>(result));
              if (tryCatch.HasCaught())
              {
                error = Nan::To<Object>(tryCatch.Exception()).ToLocalChecked();
              }
              else
              {
                error = Undefined();
              }
              if (arg1.IsEmpty()) arg1 = Undefined();
            }
            Local<Value> args[] = {error, arg1};


            invokeCallback(_countof(args), args);
          });
        } catch (Platform::Exception^ exception) {
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [exception](NodeUtils::InvokeCallbackDelegate invokeCallback) {
            Local<Value> error = NodeRT::Utils::WinRtExceptionToJsError(exception);

            Local<Value> args[] = {error};
            invokeCallback(_countof(args), args);
          });
        }
      });
    }
    static void StopAsync(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MultiSourceMediaFrameReader^>(info.This())) {
        return;
      }

      if (info.Length() == 0 || !info[info.Length() -1]->IsFunction()) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: No callback was given")));
        return;
      }

      MultiSourceMediaFrameReader *wrapper = MultiSourceMediaFrameReader::Unwrap<MultiSourceMediaFrameReader>(info.This());

      ::Windows::Foundation::IAsyncAction^ op;


      if (info.Length() == 1)
      {
        try
        {
          op = wrapper->_instance->StopAsync();
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }

      auto opTask = create_task(op);
      uv_async_t* asyncToken = NodeUtils::Async::GetAsyncToken(info[info.Length() -1].As<Function>());

      opTask.then( [asyncToken] (task<void> t) {
        try {
          t.get();
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [](NodeUtils::InvokeCallbackDelegate invokeCallback) {


            Local<Value> args[] = {Undefined()};


            invokeCallback(_countof(args), args);
          });
        } catch (Platform::Exception^ exception) {
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [exception](NodeUtils::InvokeCallbackDelegate invokeCallback) {
            Local<Value> error = NodeRT::Utils::WinRtExceptionToJsError(exception);

            Local<Value> args[] = {error};
            invokeCallback(_countof(args), args);
          });
        }
      });
    }

    static void TryAcquireLatestFrame(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MultiSourceMediaFrameReader^>(info.This())) {
        return;
      }

      MultiSourceMediaFrameReader *wrapper = MultiSourceMediaFrameReader::Unwrap<MultiSourceMediaFrameReader>(info.This());

      if (info.Length() == 0)
      {
        try
        {
          ::Windows::Media::Capture::Frames::MultiSourceMediaFrameReference^ result;
          result = wrapper->_instance->TryAcquireLatestFrame();
          info.GetReturnValue().Set(WrapMultiSourceMediaFrameReference(result));
          return;
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }
    }

    static void Close(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MultiSourceMediaFrameReader^>(info.This())) {
        return;
      }

      MultiSourceMediaFrameReader *wrapper = MultiSourceMediaFrameReader::Unwrap<MultiSourceMediaFrameReader>(info.This());

      if (info.Length() == 0) {
        try {
          delete wrapper->_instance;
          wrapper->_instance = nullptr;
          return;
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      } else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }
    }



    static void AcquisitionModeGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MultiSourceMediaFrameReader^>(info.This())) {
        return;
      }

      MultiSourceMediaFrameReader *wrapper = MultiSourceMediaFrameReader::Unwrap<MultiSourceMediaFrameReader>(info.This());

      try  {
        ::Windows::Media::Capture::Frames::MediaFrameReaderAcquisitionMode result = wrapper->_instance->AcquisitionMode;
        info.GetReturnValue().Set(Nan::New<Integer>(static_cast<int>(result)));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void AcquisitionModeSetter(Local<String> property, Local<Value> value, const Nan::PropertyCallbackInfo<void> &info) {
      HandleScope scope;

      if (!value->IsInt32()) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MultiSourceMediaFrameReader^>(info.This())) {
        return;
      }

      MultiSourceMediaFrameReader *wrapper = MultiSourceMediaFrameReader::Unwrap<MultiSourceMediaFrameReader>(info.This());

      try {

        ::Windows::Media::Capture::Frames::MediaFrameReaderAcquisitionMode winRtValue = static_cast<::Windows::Media::Capture::Frames::MediaFrameReaderAcquisitionMode>(Nan::To<int32_t>(value).FromMaybe(0));

        wrapper->_instance->AcquisitionMode = winRtValue;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
      


    static void AddListener(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (info.Length() < 2 || !info[0]->IsString() || !info[1]->IsFunction()) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"wrong arguments, expected arguments are eventName(string),callback(function)")));
        return;
      }

      String::Value eventName(v8::Isolate::GetCurrent(), info[0]);
      auto str = *eventName;

      Local<Function> callback = info[1].As<Function>();

      ::Windows::Foundation::EventRegistrationToken registrationToken;
      if (NodeRT::Utils::CaseInsenstiveEquals(L"frameArrived", str))
      {
        if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MultiSourceMediaFrameReader^>(info.This()))
        {
          Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
      return;
        }
        MultiSourceMediaFrameReader *wrapper = MultiSourceMediaFrameReader::Unwrap<MultiSourceMediaFrameReader>(info.This());
      
        try {
          Persistent<Object>* perstPtr = new Persistent<Object>();
          perstPtr->Reset(NodeRT::Utils::CreateCallbackObjectInDomain(callback));
          std::shared_ptr<Persistent<Object>> callbackObjPtr(perstPtr,
            [] (Persistent<Object> *ptr ) {
              NodeUtils::Async::RunOnMain([ptr]() {
                ptr->Reset();
                delete ptr;
            });
          });

          registrationToken = wrapper->_instance->FrameArrived::add(
            ref new ::Windows::Foundation::TypedEventHandler<::Windows::Media::Capture::Frames::MultiSourceMediaFrameReader^, ::Windows::Media::Capture::Frames::MultiSourceMediaFrameArrivedEventArgs^>(
            [callbackObjPtr](::Windows::Media::Capture::Frames::MultiSourceMediaFrameReader^ arg0, ::Windows::Media::Capture::Frames::MultiSourceMediaFrameArrivedEventArgs^ arg1) {
              NodeUtils::Async::RunOnMain([callbackObjPtr , arg0, arg1]() {
                HandleScope scope;


                Local<Value> wrappedArg0;
                Local<Value> wrappedArg1;

                {
                  TryCatch tryCatch;


                  wrappedArg0 = WrapMultiSourceMediaFrameReader(arg0);
                  wrappedArg1 = WrapMultiSourceMediaFrameArrivedEventArgs(arg1);


                  if (wrappedArg0.IsEmpty()) wrappedArg0 = Undefined();
                  if (wrappedArg1.IsEmpty()) wrappedArg1 = Undefined();
                }

                Local<Value> args[] = { wrappedArg0, wrappedArg1 };
                Local<Object> callbackObjLocalRef = Nan::New<Object>(*callbackObjPtr);
                NodeRT::Utils::CallCallbackInDomain(callbackObjLocalRef, _countof(args), args);
              });
            })
          );
        }
        catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }

      }
 else  {
        Nan::ThrowError(Nan::Error(String::Concat(v8::Isolate::GetCurrent(), NodeRT::Utils::NewString(L"given event name isn't supported: "), info[0].As<String>())));
        return;
      }

      Local<Value> tokenMapVal = NodeRT::Utils::GetHiddenValue(callback, Nan::New<String>(REGISTRATION_TOKEN_MAP_PROPERTY_NAME).ToLocalChecked());
      Local<Object> tokenMap;

      if (tokenMapVal.IsEmpty() || Nan::Equals(tokenMapVal, Undefined()).FromMaybe(false)) {
        tokenMap = Nan::New<Object>();
        NodeRT::Utils::SetHiddenValueWithObject(callback, Nan::New<String>(REGISTRATION_TOKEN_MAP_PROPERTY_NAME).ToLocalChecked(), tokenMap);
      } else {
        tokenMap = Nan::To<Object>(tokenMapVal).ToLocalChecked();
      }

      Nan::Set(tokenMap, info[0], CreateOpaqueWrapper(::Windows::Foundation::PropertyValue::CreateInt64(registrationToken.Value)));
    }

    static void RemoveListener(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (info.Length() < 2 || !info[0]->IsString() || !info[1]->IsFunction()) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"wrong arguments, expected a string and a callback")));
        return;
      }

      String::Value eventName(v8::Isolate::GetCurrent(), info[0]);
      auto str = *eventName;

      if ((!NodeRT::Utils::CaseInsenstiveEquals(L"frameArrived", str))) {
        Nan::ThrowError(Nan::Error(String::Concat(v8::Isolate::GetCurrent(), NodeRT::Utils::NewString(L"given event name isn't supported: "), info[0].As<String>())));
        return;
      }

      Local<Function> callback = info[1].As<Function>();
      Local<Value> tokenMap = NodeRT::Utils::GetHiddenValue(callback, Nan::New<String>(REGISTRATION_TOKEN_MAP_PROPERTY_NAME).ToLocalChecked());

      if (tokenMap.IsEmpty() || Nan::Equals(tokenMap, Undefined()).FromMaybe(false)) {
        return;
      }

      Local<Value> opaqueWrapperObj =  Nan::Get(Nan::To<Object>(tokenMap).ToLocalChecked(), info[0]).ToLocalChecked();

      if (opaqueWrapperObj.IsEmpty() || Nan::Equals(opaqueWrapperObj,Undefined()).FromMaybe(false)) {
        return;
      }

      OpaqueWrapper *opaqueWrapper = OpaqueWrapper::Unwrap<OpaqueWrapper>(opaqueWrapperObj.As<Object>());

      long long tokenValue = (long long) opaqueWrapper->GetObjectInstance();
      ::Windows::Foundation::EventRegistrationToken registrationToken;
      registrationToken.Value = tokenValue;

      try  {
        if (NodeRT::Utils::CaseInsenstiveEquals(L"frameArrived", str)) {
          if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MultiSourceMediaFrameReader^>(info.This()))
          {
            Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"The caller of this method isn't of the expected type or internal WinRt object was disposed")));
            return;
          }
          MultiSourceMediaFrameReader *wrapper = MultiSourceMediaFrameReader::Unwrap<MultiSourceMediaFrameReader>(info.This());
          wrapper->_instance->FrameArrived::remove(registrationToken);
        }
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }

      Nan::Delete(Nan::To<Object>(tokenMap).ToLocalChecked(), Nan::To<String>(info[0]).ToLocalChecked());
    }
    private:
      ::Windows::Media::Capture::Frames::MultiSourceMediaFrameReader^ _instance;
      static Persistent<FunctionTemplate> s_constructorTemplate;

      friend v8::Local<v8::Value> WrapMultiSourceMediaFrameReader(::Windows::Media::Capture::Frames::MultiSourceMediaFrameReader^ wintRtInstance);
      friend ::Windows::Media::Capture::Frames::MultiSourceMediaFrameReader^ UnwrapMultiSourceMediaFrameReader(Local<Value> value);
  };

  Persistent<FunctionTemplate> MultiSourceMediaFrameReader::s_constructorTemplate;

  v8::Local<v8::Value> WrapMultiSourceMediaFrameReader(::Windows::Media::Capture::Frames::MultiSourceMediaFrameReader^ winRtInstance) {
    EscapableHandleScope scope;

    if (winRtInstance == nullptr) {
      return scope.Escape(Undefined());
    }

    Local<Value> opaqueWrapper = CreateOpaqueWrapper(winRtInstance);
    Local<Value> args[] = {opaqueWrapper};
    Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(MultiSourceMediaFrameReader::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::Media::Capture::Frames::MultiSourceMediaFrameReader^ UnwrapMultiSourceMediaFrameReader(Local<Value> value) {
     return MultiSourceMediaFrameReader::Unwrap<MultiSourceMediaFrameReader>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitMultiSourceMediaFrameReader(Local<Object> exports) {
    MultiSourceMediaFrameReader::Init(exports);
  }

  class MultiSourceMediaFrameReference : public WrapperBase {
    public:
      
      static void Init(const Local<Object> exports) {
        HandleScope scope;

        Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(New);
        s_constructorTemplate.Reset(localRef);
        localRef->SetClassName(Nan::New<String>("MultiSourceMediaFrameReference").ToLocalChecked());
        localRef->InstanceTemplate()->SetInternalFieldCount(1);


          
            Nan::SetPrototypeMethod(localRef, "tryGetFrameReferenceBySourceId", TryGetFrameReferenceBySourceId);
            Nan::SetPrototypeMethod(localRef, "close", Close);
          




        Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
        Nan::SetMethod(constructor, "castFrom", CastFrom);



        Nan::Set(exports, Nan::New<String>("MultiSourceMediaFrameReference").ToLocalChecked(), constructor);
      }

      virtual ::Platform::Object^ GetObjectInstance() const override {
        return _instance;
      }

    private:

      MultiSourceMediaFrameReference(::Windows::Media::Capture::Frames::MultiSourceMediaFrameReference^ instance) {
        _instance = instance;
      }

      
    static void New(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(s_constructorTemplate);

      // in case the constructor was called without the new operator
      if (!localRef->HasInstance(info.This())) {
        if (info.Length() > 0) {
          std::unique_ptr<Local<Value> []> constructorArgs(new Local<Value>[info.Length()]);

          Local<Value> *argsPtr = constructorArgs.get();
          for (int i = 0; i < info.Length(); i++) {
            argsPtr[i] = info[i];
          }

          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), constructorArgs.get());
          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        } else {
          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), nullptr);

          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        }
      }

      ::Windows::Media::Capture::Frames::MultiSourceMediaFrameReference^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MultiSourceMediaFrameReference^>(info[0])) {
        try {
          winRtInstance = (::Windows::Media::Capture::Frames::MultiSourceMediaFrameReference^) NodeRT::Utils::GetObjectInstance(info[0]);
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no suitable constructor found")));
        return;
      }

      NodeRT::Utils::SetHiddenValue(info.This(), Nan::New<String>("__winRtInstance__").ToLocalChecked(), True());

      MultiSourceMediaFrameReference *wrapperInstance = new MultiSourceMediaFrameReference(winRtInstance);
      wrapperInstance->Wrap(info.This());

      info.GetReturnValue().Set(info.This());
    }


      
    static void CastFrom(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;
      if (info.Length() < 1 || !NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MultiSourceMediaFrameReference^>(info[0])) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no object provided, or given object could not be casted to requested type")));
        return;
      }

      ::Windows::Media::Capture::Frames::MultiSourceMediaFrameReference^ winRtInstance;
      try {
        winRtInstance = (::Windows::Media::Capture::Frames::MultiSourceMediaFrameReference^) NodeRT::Utils::GetObjectInstance(info[0]);
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }

      info.GetReturnValue().Set(WrapMultiSourceMediaFrameReference(winRtInstance));
    }


    static void TryGetFrameReferenceBySourceId(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MultiSourceMediaFrameReference^>(info.This())) {
        return;
      }

      MultiSourceMediaFrameReference *wrapper = MultiSourceMediaFrameReference::Unwrap<MultiSourceMediaFrameReference>(info.This());

      if (info.Length() == 1
        && info[0]->IsString())
      {
        try
        {
          Platform::String^ arg0 = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(v8::Isolate::GetCurrent(), info[0])));
          
          ::Windows::Media::Capture::Frames::MediaFrameReference^ result;
          result = wrapper->_instance->TryGetFrameReferenceBySourceId(arg0);
          info.GetReturnValue().Set(WrapMediaFrameReference(result));
          return;
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }
    }

    static void Close(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::MultiSourceMediaFrameReference^>(info.This())) {
        return;
      }

      MultiSourceMediaFrameReference *wrapper = MultiSourceMediaFrameReference::Unwrap<MultiSourceMediaFrameReference>(info.This());

      if (info.Length() == 0) {
        try {
          delete wrapper->_instance;
          wrapper->_instance = nullptr;
          return;
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      } else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }
    }





    private:
      ::Windows::Media::Capture::Frames::MultiSourceMediaFrameReference^ _instance;
      static Persistent<FunctionTemplate> s_constructorTemplate;

      friend v8::Local<v8::Value> WrapMultiSourceMediaFrameReference(::Windows::Media::Capture::Frames::MultiSourceMediaFrameReference^ wintRtInstance);
      friend ::Windows::Media::Capture::Frames::MultiSourceMediaFrameReference^ UnwrapMultiSourceMediaFrameReference(Local<Value> value);
  };

  Persistent<FunctionTemplate> MultiSourceMediaFrameReference::s_constructorTemplate;

  v8::Local<v8::Value> WrapMultiSourceMediaFrameReference(::Windows::Media::Capture::Frames::MultiSourceMediaFrameReference^ winRtInstance) {
    EscapableHandleScope scope;

    if (winRtInstance == nullptr) {
      return scope.Escape(Undefined());
    }

    Local<Value> opaqueWrapper = CreateOpaqueWrapper(winRtInstance);
    Local<Value> args[] = {opaqueWrapper};
    Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(MultiSourceMediaFrameReference::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::Media::Capture::Frames::MultiSourceMediaFrameReference^ UnwrapMultiSourceMediaFrameReference(Local<Value> value) {
     return MultiSourceMediaFrameReference::Unwrap<MultiSourceMediaFrameReference>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitMultiSourceMediaFrameReference(Local<Object> exports) {
    MultiSourceMediaFrameReference::Init(exports);
  }

  class VideoMediaFrame : public WrapperBase {
    public:
      
      static void Init(const Local<Object> exports) {
        HandleScope scope;

        Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(New);
        s_constructorTemplate.Reset(localRef);
        localRef->SetClassName(Nan::New<String>("VideoMediaFrame").ToLocalChecked());
        localRef->InstanceTemplate()->SetInternalFieldCount(1);


          
            Nan::SetPrototypeMethod(localRef, "getVideoFrame", GetVideoFrame);
          



          
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("cameraIntrinsics").ToLocalChecked(), CameraIntrinsicsGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("depthMediaFrame").ToLocalChecked(), DepthMediaFrameGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("direct3DSurface").ToLocalChecked(), Direct3DSurfaceGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("frameReference").ToLocalChecked(), FrameReferenceGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("infraredMediaFrame").ToLocalChecked(), InfraredMediaFrameGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("softwareBitmap").ToLocalChecked(), SoftwareBitmapGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("videoFormat").ToLocalChecked(), VideoFormatGetter);

        Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
        Nan::SetMethod(constructor, "castFrom", CastFrom);



        Nan::Set(exports, Nan::New<String>("VideoMediaFrame").ToLocalChecked(), constructor);
      }

      virtual ::Platform::Object^ GetObjectInstance() const override {
        return _instance;
      }

    private:

      VideoMediaFrame(::Windows::Media::Capture::Frames::VideoMediaFrame^ instance) {
        _instance = instance;
      }

      
    static void New(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(s_constructorTemplate);

      // in case the constructor was called without the new operator
      if (!localRef->HasInstance(info.This())) {
        if (info.Length() > 0) {
          std::unique_ptr<Local<Value> []> constructorArgs(new Local<Value>[info.Length()]);

          Local<Value> *argsPtr = constructorArgs.get();
          for (int i = 0; i < info.Length(); i++) {
            argsPtr[i] = info[i];
          }

          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), constructorArgs.get());
          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        } else {
          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), nullptr);

          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        }
      }

      ::Windows::Media::Capture::Frames::VideoMediaFrame^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::VideoMediaFrame^>(info[0])) {
        try {
          winRtInstance = (::Windows::Media::Capture::Frames::VideoMediaFrame^) NodeRT::Utils::GetObjectInstance(info[0]);
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no suitable constructor found")));
        return;
      }

      NodeRT::Utils::SetHiddenValue(info.This(), Nan::New<String>("__winRtInstance__").ToLocalChecked(), True());

      VideoMediaFrame *wrapperInstance = new VideoMediaFrame(winRtInstance);
      wrapperInstance->Wrap(info.This());

      info.GetReturnValue().Set(info.This());
    }


      
    static void CastFrom(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;
      if (info.Length() < 1 || !NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::VideoMediaFrame^>(info[0])) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no object provided, or given object could not be casted to requested type")));
        return;
      }

      ::Windows::Media::Capture::Frames::VideoMediaFrame^ winRtInstance;
      try {
        winRtInstance = (::Windows::Media::Capture::Frames::VideoMediaFrame^) NodeRT::Utils::GetObjectInstance(info[0]);
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }

      info.GetReturnValue().Set(WrapVideoMediaFrame(winRtInstance));
    }


    static void GetVideoFrame(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::VideoMediaFrame^>(info.This())) {
        return;
      }

      VideoMediaFrame *wrapper = VideoMediaFrame::Unwrap<VideoMediaFrame>(info.This());

      if (info.Length() == 0)
      {
        try
        {
          ::Windows::Media::VideoFrame^ result;
          result = wrapper->_instance->GetVideoFrame();
          info.GetReturnValue().Set(NodeRT::Utils::CreateExternalWinRTObject("Windows.Media", "VideoFrame", result));
          return;
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return;
      }
    }



    static void CameraIntrinsicsGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::VideoMediaFrame^>(info.This())) {
        return;
      }

      VideoMediaFrame *wrapper = VideoMediaFrame::Unwrap<VideoMediaFrame>(info.This());

      try  {
        ::Windows::Media::Devices::Core::CameraIntrinsics^ result = wrapper->_instance->CameraIntrinsics;
        info.GetReturnValue().Set(NodeRT::Utils::CreateExternalWinRTObject("Windows.Media.Devices.Core", "CameraIntrinsics", result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void DepthMediaFrameGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::VideoMediaFrame^>(info.This())) {
        return;
      }

      VideoMediaFrame *wrapper = VideoMediaFrame::Unwrap<VideoMediaFrame>(info.This());

      try  {
        ::Windows::Media::Capture::Frames::DepthMediaFrame^ result = wrapper->_instance->DepthMediaFrame;
        info.GetReturnValue().Set(WrapDepthMediaFrame(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void Direct3DSurfaceGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::VideoMediaFrame^>(info.This())) {
        return;
      }

      VideoMediaFrame *wrapper = VideoMediaFrame::Unwrap<VideoMediaFrame>(info.This());

      try  {
        ::Windows::Graphics::DirectX::Direct3D11::IDirect3DSurface^ result = wrapper->_instance->Direct3DSurface;
        info.GetReturnValue().Set(NodeRT::Utils::CreateExternalWinRTObject("Windows.Graphics.DirectX.Direct3D11", "IDirect3DSurface", result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void FrameReferenceGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::VideoMediaFrame^>(info.This())) {
        return;
      }

      VideoMediaFrame *wrapper = VideoMediaFrame::Unwrap<VideoMediaFrame>(info.This());

      try  {
        ::Windows::Media::Capture::Frames::MediaFrameReference^ result = wrapper->_instance->FrameReference;
        info.GetReturnValue().Set(WrapMediaFrameReference(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void InfraredMediaFrameGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::VideoMediaFrame^>(info.This())) {
        return;
      }

      VideoMediaFrame *wrapper = VideoMediaFrame::Unwrap<VideoMediaFrame>(info.This());

      try  {
        ::Windows::Media::Capture::Frames::InfraredMediaFrame^ result = wrapper->_instance->InfraredMediaFrame;
        info.GetReturnValue().Set(WrapInfraredMediaFrame(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void SoftwareBitmapGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::VideoMediaFrame^>(info.This())) {
        return;
      }

      VideoMediaFrame *wrapper = VideoMediaFrame::Unwrap<VideoMediaFrame>(info.This());

      try  {
        ::Windows::Graphics::Imaging::SoftwareBitmap^ result = wrapper->_instance->SoftwareBitmap;
        info.GetReturnValue().Set(NodeRT::Utils::CreateExternalWinRTObject("Windows.Graphics.Imaging", "SoftwareBitmap", result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void VideoFormatGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::VideoMediaFrame^>(info.This())) {
        return;
      }

      VideoMediaFrame *wrapper = VideoMediaFrame::Unwrap<VideoMediaFrame>(info.This());

      try  {
        ::Windows::Media::Capture::Frames::VideoMediaFrameFormat^ result = wrapper->_instance->VideoFormat;
        info.GetReturnValue().Set(WrapVideoMediaFrameFormat(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      


    private:
      ::Windows::Media::Capture::Frames::VideoMediaFrame^ _instance;
      static Persistent<FunctionTemplate> s_constructorTemplate;

      friend v8::Local<v8::Value> WrapVideoMediaFrame(::Windows::Media::Capture::Frames::VideoMediaFrame^ wintRtInstance);
      friend ::Windows::Media::Capture::Frames::VideoMediaFrame^ UnwrapVideoMediaFrame(Local<Value> value);
  };

  Persistent<FunctionTemplate> VideoMediaFrame::s_constructorTemplate;

  v8::Local<v8::Value> WrapVideoMediaFrame(::Windows::Media::Capture::Frames::VideoMediaFrame^ winRtInstance) {
    EscapableHandleScope scope;

    if (winRtInstance == nullptr) {
      return scope.Escape(Undefined());
    }

    Local<Value> opaqueWrapper = CreateOpaqueWrapper(winRtInstance);
    Local<Value> args[] = {opaqueWrapper};
    Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(VideoMediaFrame::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::Media::Capture::Frames::VideoMediaFrame^ UnwrapVideoMediaFrame(Local<Value> value) {
     return VideoMediaFrame::Unwrap<VideoMediaFrame>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitVideoMediaFrame(Local<Object> exports) {
    VideoMediaFrame::Init(exports);
  }

  class VideoMediaFrameFormat : public WrapperBase {
    public:
      
      static void Init(const Local<Object> exports) {
        HandleScope scope;

        Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(New);
        s_constructorTemplate.Reset(localRef);
        localRef->SetClassName(Nan::New<String>("VideoMediaFrameFormat").ToLocalChecked());
        localRef->InstanceTemplate()->SetInternalFieldCount(1);





          
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("depthFormat").ToLocalChecked(), DepthFormatGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("height").ToLocalChecked(), HeightGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("mediaFrameFormat").ToLocalChecked(), MediaFrameFormatGetter);
            Nan::SetAccessor(localRef->PrototypeTemplate(), Nan::New<String>("width").ToLocalChecked(), WidthGetter);

        Local<Object> constructor = Nan::To<Object>(Nan::GetFunction(localRef).ToLocalChecked()).ToLocalChecked();
        Nan::SetMethod(constructor, "castFrom", CastFrom);



        Nan::Set(exports, Nan::New<String>("VideoMediaFrameFormat").ToLocalChecked(), constructor);
      }

      virtual ::Platform::Object^ GetObjectInstance() const override {
        return _instance;
      }

    private:

      VideoMediaFrameFormat(::Windows::Media::Capture::Frames::VideoMediaFrameFormat^ instance) {
        _instance = instance;
      }

      
    static void New(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;

      Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(s_constructorTemplate);

      // in case the constructor was called without the new operator
      if (!localRef->HasInstance(info.This())) {
        if (info.Length() > 0) {
          std::unique_ptr<Local<Value> []> constructorArgs(new Local<Value>[info.Length()]);

          Local<Value> *argsPtr = constructorArgs.get();
          for (int i = 0; i < info.Length(); i++) {
            argsPtr[i] = info[i];
          }

          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), constructorArgs.get());
          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        } else {
          MaybeLocal<Object> res = Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(), info.Length(), nullptr);

          if (res.IsEmpty()) {
            return;
          }

          info.GetReturnValue().Set(res.ToLocalChecked());
          return;
        }
      }

      ::Windows::Media::Capture::Frames::VideoMediaFrameFormat^ winRtInstance;


      if (info.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(info[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::VideoMediaFrameFormat^>(info[0])) {
        try {
          winRtInstance = (::Windows::Media::Capture::Frames::VideoMediaFrameFormat^) NodeRT::Utils::GetObjectInstance(info[0]);
        } catch (Platform::Exception ^exception) {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return;
        }
      }
 else {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no suitable constructor found")));
        return;
      }

      NodeRT::Utils::SetHiddenValue(info.This(), Nan::New<String>("__winRtInstance__").ToLocalChecked(), True());

      VideoMediaFrameFormat *wrapperInstance = new VideoMediaFrameFormat(winRtInstance);
      wrapperInstance->Wrap(info.This());

      info.GetReturnValue().Set(info.This());
    }


      
    static void CastFrom(Nan::NAN_METHOD_ARGS_TYPE info) {
      HandleScope scope;
      if (info.Length() < 1 || !NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::VideoMediaFrameFormat^>(info[0])) {
        Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"Invalid arguments, no object provided, or given object could not be casted to requested type")));
        return;
      }

      ::Windows::Media::Capture::Frames::VideoMediaFrameFormat^ winRtInstance;
      try {
        winRtInstance = (::Windows::Media::Capture::Frames::VideoMediaFrameFormat^) NodeRT::Utils::GetObjectInstance(info[0]);
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }

      info.GetReturnValue().Set(WrapVideoMediaFrameFormat(winRtInstance));
    }





    static void DepthFormatGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::VideoMediaFrameFormat^>(info.This())) {
        return;
      }

      VideoMediaFrameFormat *wrapper = VideoMediaFrameFormat::Unwrap<VideoMediaFrameFormat>(info.This());

      try  {
        ::Windows::Media::Capture::Frames::DepthMediaFrameFormat^ result = wrapper->_instance->DepthFormat;
        info.GetReturnValue().Set(WrapDepthMediaFrameFormat(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void HeightGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::VideoMediaFrameFormat^>(info.This())) {
        return;
      }

      VideoMediaFrameFormat *wrapper = VideoMediaFrameFormat::Unwrap<VideoMediaFrameFormat>(info.This());

      try  {
        unsigned int result = wrapper->_instance->Height;
        info.GetReturnValue().Set(Nan::New<Integer>(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void MediaFrameFormatGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::VideoMediaFrameFormat^>(info.This())) {
        return;
      }

      VideoMediaFrameFormat *wrapper = VideoMediaFrameFormat::Unwrap<VideoMediaFrameFormat>(info.This());

      try  {
        ::Windows::Media::Capture::Frames::MediaFrameFormat^ result = wrapper->_instance->MediaFrameFormat;
        info.GetReturnValue().Set(WrapMediaFrameFormat(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      
    static void WidthGetter(Local<String> property, const Nan::PropertyCallbackInfo<v8::Value> &info) {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Media::Capture::Frames::VideoMediaFrameFormat^>(info.This())) {
        return;
      }

      VideoMediaFrameFormat *wrapper = VideoMediaFrameFormat::Unwrap<VideoMediaFrameFormat>(info.This());

      try  {
        unsigned int result = wrapper->_instance->Width;
        info.GetReturnValue().Set(Nan::New<Integer>(result));
        return;
      } catch (Platform::Exception ^exception) {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return;
      }
    }
      


    private:
      ::Windows::Media::Capture::Frames::VideoMediaFrameFormat^ _instance;
      static Persistent<FunctionTemplate> s_constructorTemplate;

      friend v8::Local<v8::Value> WrapVideoMediaFrameFormat(::Windows::Media::Capture::Frames::VideoMediaFrameFormat^ wintRtInstance);
      friend ::Windows::Media::Capture::Frames::VideoMediaFrameFormat^ UnwrapVideoMediaFrameFormat(Local<Value> value);
  };

  Persistent<FunctionTemplate> VideoMediaFrameFormat::s_constructorTemplate;

  v8::Local<v8::Value> WrapVideoMediaFrameFormat(::Windows::Media::Capture::Frames::VideoMediaFrameFormat^ winRtInstance) {
    EscapableHandleScope scope;

    if (winRtInstance == nullptr) {
      return scope.Escape(Undefined());
    }

    Local<Value> opaqueWrapper = CreateOpaqueWrapper(winRtInstance);
    Local<Value> args[] = {opaqueWrapper};
    Local<FunctionTemplate> localRef = Nan::New<FunctionTemplate>(VideoMediaFrameFormat::s_constructorTemplate);
    return scope.Escape(Nan::NewInstance(Nan::GetFunction(localRef).ToLocalChecked(),_countof(args), args).ToLocalChecked());
  }

  ::Windows::Media::Capture::Frames::VideoMediaFrameFormat^ UnwrapVideoMediaFrameFormat(Local<Value> value) {
     return VideoMediaFrameFormat::Unwrap<VideoMediaFrameFormat>(Nan::To<Object>(value).ToLocalChecked())->_instance;
  }

  void InitVideoMediaFrameFormat(Local<Object> exports) {
    VideoMediaFrameFormat::Init(exports);
  }


} } } } } 

NAN_MODULE_INIT(init) {
  // We ignore failures for now since it probably means that
  // the initialization already happened for STA, and that's cool

  CoInitializeEx(nullptr, COINIT_MULTITHREADED);

  /*
  if (FAILED(CoInitializeEx(nullptr, COINIT_MULTITHREADED))) {
    Nan::ThrowError(Nan::Error(NodeRT::Utils::NewString(L"error in CoInitializeEx()")));
    return;
  }
  */

      NodeRT::Windows::Media::Capture::Frames::InitMediaFrameReaderAcquisitionModeEnum(target);
      NodeRT::Windows::Media::Capture::Frames::InitMediaFrameReaderStartStatusEnum(target);
      NodeRT::Windows::Media::Capture::Frames::InitMediaFrameSourceGetPropertyStatusEnum(target);
      NodeRT::Windows::Media::Capture::Frames::InitMediaFrameSourceKindEnum(target);
      NodeRT::Windows::Media::Capture::Frames::InitMediaFrameSourceSetPropertyStatusEnum(target);
      NodeRT::Windows::Media::Capture::Frames::InitMultiSourceMediaFrameReaderStartStatusEnum(target);
      NodeRT::Windows::Media::Capture::Frames::InitAudioMediaFrame(target);
      NodeRT::Windows::Media::Capture::Frames::InitBufferMediaFrame(target);
      NodeRT::Windows::Media::Capture::Frames::InitDepthMediaFrame(target);
      NodeRT::Windows::Media::Capture::Frames::InitDepthMediaFrameFormat(target);
      NodeRT::Windows::Media::Capture::Frames::InitInfraredMediaFrame(target);
      NodeRT::Windows::Media::Capture::Frames::InitMediaFrameArrivedEventArgs(target);
      NodeRT::Windows::Media::Capture::Frames::InitMediaFrameFormat(target);
      NodeRT::Windows::Media::Capture::Frames::InitMediaFrameReader(target);
      NodeRT::Windows::Media::Capture::Frames::InitMediaFrameReference(target);
      NodeRT::Windows::Media::Capture::Frames::InitMediaFrameSource(target);
      NodeRT::Windows::Media::Capture::Frames::InitMediaFrameSourceController(target);
      NodeRT::Windows::Media::Capture::Frames::InitMediaFrameSourceGetPropertyResult(target);
      NodeRT::Windows::Media::Capture::Frames::InitMediaFrameSourceGroup(target);
      NodeRT::Windows::Media::Capture::Frames::InitMediaFrameSourceInfo(target);
      NodeRT::Windows::Media::Capture::Frames::InitMultiSourceMediaFrameArrivedEventArgs(target);
      NodeRT::Windows::Media::Capture::Frames::InitMultiSourceMediaFrameReader(target);
      NodeRT::Windows::Media::Capture::Frames::InitMultiSourceMediaFrameReference(target);
      NodeRT::Windows::Media::Capture::Frames::InitVideoMediaFrame(target);
      NodeRT::Windows::Media::Capture::Frames::InitVideoMediaFrameFormat(target);


  NodeRT::Utils::RegisterNameSpace("Windows.Media.Capture.Frames", target);
}



NODE_MODULE(binding, init)
