|
| 1 | +// Copyright (C) <2019> Intel Corporation |
| 2 | +// |
| 3 | +// SPDX-License-Identifier: Apache-2.0 |
| 4 | + |
| 5 | +#include "AudioRankerWrapper.h" |
| 6 | +#include "MediaFramePipelineWrapper.h" |
| 7 | + |
| 8 | +using namespace v8; |
| 9 | + |
| 10 | +Nan::Persistent<Function> AudioRanker::constructor; |
| 11 | + |
| 12 | +AudioRanker::AudioRanker() {} |
| 13 | +AudioRanker::~AudioRanker() {} |
| 14 | + |
| 15 | +NAN_MODULE_INIT(AudioRanker::Init) { |
| 16 | + // Prepare constructor template |
| 17 | + Local<FunctionTemplate> tpl = Nan::New<FunctionTemplate>(New); |
| 18 | + tpl->SetClassName(Nan::New("AudioRanker").ToLocalChecked()); |
| 19 | + tpl->InstanceTemplate()->SetInternalFieldCount(1); |
| 20 | + |
| 21 | + // Prototype |
| 22 | + Nan::SetPrototypeMethod(tpl, "close", close); |
| 23 | + Nan::SetPrototypeMethod(tpl, "addOutput", addOutput); |
| 24 | + Nan::SetPrototypeMethod(tpl, "addInput", addInput); |
| 25 | + Nan::SetPrototypeMethod(tpl, "removeInput", removeInput); |
| 26 | + |
| 27 | + constructor.Reset(tpl->GetFunction()); |
| 28 | + Nan::Set(target, Nan::New("AudioRanker").ToLocalChecked(), Nan::GetFunction(tpl).ToLocalChecked()); |
| 29 | +} |
| 30 | + |
| 31 | +NAN_METHOD(AudioRanker::New) { |
| 32 | + if (info.Length() < 1) { |
| 33 | + Nan::ThrowError("Wrong number of arguments"); |
| 34 | + } |
| 35 | + |
| 36 | + if (info.IsConstructCall()) { |
| 37 | + AudioRanker* obj = new AudioRanker(); |
| 38 | + |
| 39 | + obj->asyncResource_ = new Nan::AsyncResource("RankChange"); |
| 40 | + obj->callback_ = new Nan::Callback(info[0].As<Function>()); |
| 41 | + uv_async_init(uv_default_loop(), &obj->async_, &AudioRanker::Callback); |
| 42 | + |
| 43 | + if (info.Length() > 2) { |
| 44 | + bool detectMute = Nan::To<bool>(info[1]).FromJust(); |
| 45 | + int changeInterval = Nan::To<int>(info[2]).FromJust(); |
| 46 | + obj->me = new owt_base::AudioRanker(obj, detectMute, changeInterval); |
| 47 | + } else { |
| 48 | + obj->me = new owt_base::AudioRanker(obj); |
| 49 | + } |
| 50 | + |
| 51 | + obj->Wrap(info.This()); |
| 52 | + info.GetReturnValue().Set(info.This()); |
| 53 | + } else { |
| 54 | + // Not construct call |
| 55 | + } |
| 56 | +} |
| 57 | + |
| 58 | +NAN_METHOD(AudioRanker::close) { |
| 59 | + AudioRanker* obj = Nan::ObjectWrap::Unwrap<AudioRanker>(info.Holder()); |
| 60 | + |
| 61 | + if (!uv_is_closing(reinterpret_cast<uv_handle_t*>(&obj->async_))) { |
| 62 | + uv_close(reinterpret_cast<uv_handle_t*>(&obj->async_), NULL); |
| 63 | + } |
| 64 | + |
| 65 | + delete obj->me; |
| 66 | + obj->me = nullptr; |
| 67 | + delete obj->callback_; |
| 68 | + delete obj->asyncResource_; |
| 69 | +} |
| 70 | + |
| 71 | +NAN_METHOD(AudioRanker::addOutput) { |
| 72 | + AudioRanker* obj = Nan::ObjectWrap::Unwrap<AudioRanker>(info.Holder()); |
| 73 | + owt_base::AudioRanker* me = obj->me; |
| 74 | + |
| 75 | + FrameDestination* param = node::ObjectWrap::Unwrap<FrameDestination>(info[0]->ToObject()); |
| 76 | + owt_base::FrameDestination* dest = param->dest; |
| 77 | + |
| 78 | + me->addOutput(dest); |
| 79 | +} |
| 80 | + |
| 81 | +NAN_METHOD(AudioRanker::addInput) { |
| 82 | + AudioRanker* obj = Nan::ObjectWrap::Unwrap<AudioRanker>(info.Holder()); |
| 83 | + owt_base::AudioRanker* me = obj->me; |
| 84 | + |
| 85 | + FrameSource* param = node::ObjectWrap::Unwrap<FrameSource>(info[0]->ToObject()); |
| 86 | + owt_base::FrameSource* src = param->src; |
| 87 | + |
| 88 | + Nan::Utf8String streamIdPara(Nan::To<v8::String>(info[1]).ToLocalChecked()); |
| 89 | + std::string streamId = std::string(*streamIdPara); |
| 90 | + |
| 91 | + Nan::Utf8String ownerIdPara(Nan::To<v8::String>(info[2]).ToLocalChecked()); |
| 92 | + std::string ownerId = std::string(*ownerIdPara); |
| 93 | + |
| 94 | + me->addInput(src, streamId, ownerId); |
| 95 | +} |
| 96 | + |
| 97 | +NAN_METHOD(AudioRanker::removeInput) { |
| 98 | + AudioRanker* obj = Nan::ObjectWrap::Unwrap<AudioRanker>(info.Holder()); |
| 99 | + owt_base::AudioRanker* me = obj->me; |
| 100 | + |
| 101 | + Nan::Utf8String streamIdPara(Nan::To<v8::String>(info[0]).ToLocalChecked()); |
| 102 | + std::string streamId = std::string(*streamIdPara); |
| 103 | + |
| 104 | + me->removeInput(streamId); |
| 105 | +} |
| 106 | + |
| 107 | +void AudioRanker::onRankChange(std::vector<std::pair<std::string, std::string>> updates) { |
| 108 | + boost::mutex::scoped_lock lock(mutex); |
| 109 | + std::ostringstream jsonChange; |
| 110 | + /* |
| 111 | + * The JS callback json |
| 112 | + * [ |
| 113 | + * ["streamID0", "ownerID0"], |
| 114 | + * ["streamID1", "ownerID1"], |
| 115 | + * ...... |
| 116 | + * ["streamIDn", "ownerIDn"] |
| 117 | + * ] |
| 118 | + */ |
| 119 | + jsonChange.str(""); |
| 120 | + jsonChange << "["; |
| 121 | + for (size_t i = 0; i < updates.size(); i++) { |
| 122 | + jsonChange << "[\"" << updates[i].first << "\",\"" |
| 123 | + << updates[i].second << "\"]"; |
| 124 | + if (i + 1 < updates.size()) { |
| 125 | + jsonChange << ","; |
| 126 | + } |
| 127 | + } |
| 128 | + jsonChange << "]"; |
| 129 | + this->jsonChanges.push(jsonChange.str()); |
| 130 | + async_.data = this; |
| 131 | + uv_async_send(&async_); |
| 132 | +} |
| 133 | + |
| 134 | +NAUV_WORK_CB(AudioRanker::Callback) { |
| 135 | + Nan::HandleScope scope; |
| 136 | + AudioRanker* obj = reinterpret_cast<AudioRanker*>(async->data); |
| 137 | + if (!obj || obj->me == NULL) |
| 138 | + return; |
| 139 | + boost::mutex::scoped_lock lock(obj->mutex); |
| 140 | + while (!obj->jsonChanges.empty()) { |
| 141 | + Local<Value> args[] = {Nan::New(obj->jsonChanges.front().c_str()).ToLocalChecked()}; |
| 142 | + obj->asyncResource_->runInAsyncScope( |
| 143 | + Nan::GetCurrentContext()->Global(), obj->callback_->GetFunction(), 1, args); |
| 144 | + obj->jsonChanges.pop(); |
| 145 | + } |
| 146 | +} |
| 147 | + |
0 commit comments