Skip to content

Commit

Permalink
feat: add nodejs addon loader
Browse files Browse the repository at this point in the history
  • Loading branch information
sunxilin committed Jan 10, 2025
1 parent e73dcfb commit 660e9fc
Show file tree
Hide file tree
Showing 2,403 changed files with 1,005,258 additions and 61 deletions.
18 changes: 12 additions & 6 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@
"request": "launch",
"program": "${workspaceFolder}/out/linux/x64/tests/standalone/ten_runtime_smoke_test",
"args": [
"--gtest_filter=ExtensionTest.ExtensionSendMsgToIncorrectEngine"
"--gtest_filter=AudioFrameTest.MultiDestAudioFrame"
],
"cwd": "${workspaceFolder}/out/linux/x64/tests/standalone/",
"env": {
Expand Down Expand Up @@ -492,9 +492,9 @@
"name": "app (C/C++) (lldb, launch)",
"type": "lldb",
"request": "launch",
"program": "${workspaceFolder}/out/linux/x64/tests/ten_runtime/integration/python/cpp_app_python/cpp_app_python_app/bin/cpp_app_python_app_source",
"program": "${workspaceFolder}/out/linux/x64/tests/ten_runtime/integration/nodejs/cpp_app_nodejs/cpp_app_nodejs_app/bin/cpp_app_nodejs_app_source",
"args": [],
"cwd": "${workspaceFolder}/out/linux/x64/tests/ten_runtime/integration/python/cpp_app_python/cpp_app_python_app",
"cwd": "${workspaceFolder}/out/linux/x64/tests/ten_runtime/integration/nodejs/cpp_app_nodejs/cpp_app_nodejs_app",
"env": {
"ASAN_OPTIONS": "use_sigaltstack=0",
},
Expand All @@ -503,15 +503,21 @@
"name": "app (C/C++) (cppdbg, launch)",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/out/linux/x64/tests/ten_runtime/integration/cpp/graph_env_var_1/graph_env_var_1_app/bin/graph_env_var_1_app_source",
"program": "${workspaceFolder}/out/linux/x64/tests/ten_runtime/integration/nodejs/cpp_app_nodejs/cpp_app_nodejs_app/bin/cpp_app_nodejs_app_source",
"args": [],
"cwd": "${workspaceFolder}/out/linux/x64/tests/ten_runtime/integration/cpp/graph_env_var_1/graph_env_var_1_app",
"cwd": "${workspaceFolder}/out/linux/x64/tests/ten_runtime/integration/nodejs/cpp_app_nodejs/cpp_app_nodejs_app",
"sourceFileMap": {
"${workspaceFolder}": {
"editorPath": "${workspaceFolder}",
"useForBreakpoints": "true"
}
}
},
"environment": [
{
"name": "NODE_PATH",
"value": "${workspaceFolder}/out/linux/x64/tests/ten_runtime/integration/nodejs/cpp_app_nodejs/cpp_app_nodejs_app/ten_packages/system/ten_runtime_nodejs/lib:$NODE_PATH"
}
]
},
{
"name": "app (C/C++) (cppdbg, attach)",
Expand Down
120 changes: 120 additions & 0 deletions build/ten_common/prebuilt/prebuilt.gni
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
#
# Copyright © 2025 Agora
# This file is part of TEN Framework, an open source project.
# Licensed under the Apache License, Version 2.0, with certain conditions.
# Refer to the "LICENSE" file in the root directory for more information.
#
import("//build/ten_runtime/options.gni")

template("ten_prebuilt_library") {
assert(defined(invoker.url), "Must provide dist url")

_dir_path = "prebuilt/${invoker.name}/lib"
_zip_path = "${_dir_path}/${invoker.name}.zip"

_download_target = "${target_name}_lib_download"
action(_download_target) {
script = "//build/ten_common/scripts/download.py"

_source_file = "${invoker.url}"
_dest_file = "${root_out_dir}/${_zip_path}"

args = [
_source_file,
rebase_path(_dest_file),
]

inputs = [ "//build/ten_common/scripts/download.py" ]
outputs = [ _dest_file ]
}

_is_shared_library =
defined(invoker.is_shared_library) && invoker.is_shared_library

_lib_prefix = "lib"
_lib_postfix = ""
if (_is_shared_library) {
if (is_linux) {
_lib_postfix = ".so"
} else if (is_win) {
_lib_postfix = ".dll"
} else if (is_mac) {
_lib_postfix = ".dylib"
} else {
assert(0, "Unsupported platform.")
}
} else {
_lib_postfix = ".a"
}

# Construct the actual library file name.
_lib_file_paths = []
foreach(lib, invoker.libs) {
_lib_file_paths +=
[ "${root_out_dir}/${_dir_path}/${_lib_prefix}${lib}${_lib_postfix}" ]
}

_unzip_target = "${target_name}_lib_unzip"
action(_unzip_target) {
script = "//build/ten_common/scripts/unzip.py"

_source_file = "${root_out_dir}/${_zip_path}"

args = [
rebase_path(_source_file),
rebase_path(_dir_path),
]

inputs = [
_source_file,
"//build/ten_common/scripts/unzip.py",
]

outputs = [ "${root_out_dir}/${_dir_path}" ]
outputs += _lib_file_paths

# Need to complete the downloading first.
deps = [ ":${_download_target}" ]
}

config("${target_name}_config") {
libs = invoker.libs
lib_dirs = [ rebase_path("${root_out_dir}/${_dir_path}") ]

if (defined(invoker.extra_ldflags) && invoker.extra_ldflags != []) {
if (!defined(ldflags)) {
ldflags = []
}

ldflags += invoker.extra_ldflags
}
}

group(target_name) {
forward_variables_from(invoker,
[
"deps",
"public_deps",
"data_deps",
"testonly",
"visibility",
])

if (!defined(deps)) {
deps = []
}

# Need to complete the unzip.
deps += [
# ":${_delete_zip_target}",
":${_unzip_target}",
]

# To enable the caller to 'depends' on the prebuilt libraries.
# public_deps = [ ":${_delete_zip_target}" ]
public_deps = [ ":${_unzip_target}" ]

# Inject the header file inclusion path into the caller.
public_configs = [ ":${target_name}_config" ]
}
}
20 changes: 20 additions & 0 deletions build/ten_common/scripts/download.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#
# Copyright © 2025 Agora
# This file is part of TEN Framework, an open source project.
# Licensed under the Apache License, Version 2.0, with certain conditions.
# Refer to the "LICENSE" file in the root directory for more information.
#
import sys
import requests


def download_file(url, output_path):
response = requests.get(url, stream=True)
response.raise_for_status()
with open(output_path, "wb") as file:
for chunk in response.iter_content(chunk_size=8192):
file.write(chunk)


if __name__ == "__main__":
download_file(sys.argv[1], sys.argv[2])
34 changes: 34 additions & 0 deletions build/ten_common/scripts/unzip.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#
# Copyright © 2025 Agora
# This file is part of TEN Framework, an open source project.
# Licensed under the Apache License, Version 2.0, with certain conditions.
# Refer to the "LICENSE" file in the root directory for more information.
#
import zipfile
import sys
import os


def unzip_file(src_path, dest_path) -> int | None:
if not os.path.exists(src_path):
return -1

src_dir = os.path.dirname(src_path)
dst_dir = src_dir if dest_path == "" else dest_path
if not os.path.exists(dst_dir):
os.makedirs(dst_dir)

zip_ref = zipfile.ZipFile(src_path, "r")
zip_ref.extractall(dst_dir)
zip_ref.close()


def main(argv):
if len(argv) < 2:
return -1
dest_path = "" if len(argv) < 3 else argv[2]
return unzip_file(argv[0], dest_path)


if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))
39 changes: 0 additions & 39 deletions core/src/ten_runtime/app/msg_interface/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@
#include "include_internal/ten_runtime/msg/msg.h"
#include "include_internal/ten_runtime/protocol/protocol.h"
#include "ten_runtime/app/app.h"
#include "ten_runtime/common/status_code.h"
#include "ten_runtime/msg/cmd/close_app/cmd.h"
#include "ten_runtime/msg/cmd/stop_graph/cmd.h"
#include "ten_runtime/msg/cmd_result/cmd_result.h"
#include "ten_runtime/msg/msg.h"
Expand Down Expand Up @@ -276,43 +274,6 @@ static bool ten_app_handle_stop_graph_cmd(ten_app_t *self,
return true;
}

/**
* @return true if this function handles @param cmd, false otherwise.
*/
static bool ten_app_handle_cmd_result(ten_app_t *self, ten_shared_ptr_t *cmd,
ten_error_t *err) {
TEN_ASSERT(self && ten_app_check_integrity(self, true), "Should not happen.");
TEN_ASSERT(cmd && ten_cmd_base_check_integrity(cmd), "Should not happen.");

TEN_STATUS_CODE status_code = ten_cmd_result_get_status_code(cmd);
bool is_auto_start_predefined_graph_cmd_result = false;

// Verify whether the received command result corresponds to a previously sent
// `start_graph` command for the `auto_start` predefined graph.
ten_list_foreach (&self->predefined_graph_infos, iter) {
ten_predefined_graph_info_t *predefined_graph_info =
(ten_predefined_graph_info_t *)ten_ptr_listnode_get(iter.node);

if (ten_string_is_equal_c_str(&predefined_graph_info->start_graph_cmd_id,
ten_cmd_base_get_cmd_id(cmd))) {
TEN_ASSERT(predefined_graph_info->auto_start, "Should not happen.");
is_auto_start_predefined_graph_cmd_result = true;
}
}

if (is_auto_start_predefined_graph_cmd_result &&
status_code == TEN_STATUS_CODE_ERROR) {
// If auto-starting the predefined graph fails, gracefully close the app.
ten_shared_ptr_t *close_app_cmd = ten_cmd_close_app_create();
ten_msg_clear_and_set_dest(close_app_cmd,
ten_string_get_raw_str(&self->uri), NULL, NULL,
NULL, err);
ten_env_send_cmd(self->ten_env, close_app_cmd, NULL, NULL, err);
}

return is_auto_start_predefined_graph_cmd_result;
}

bool ten_app_dispatch_msg(ten_app_t *self, ten_shared_ptr_t *msg,
ten_error_t *err) {
// The source of the out message is the current app.
Expand Down
2 changes: 1 addition & 1 deletion core/src/ten_runtime/binding/nodejs/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion core/src/ten_runtime/binding/nodejs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"build": "tsc --listEmittedFiles"
},
"devDependencies": {
"@types/node": "^18.14.5",
"@types/node": "^18.19.70",
"source-map-support": "^0.5.21",
"typescript": "^5.7.2"
},
Expand Down
5 changes: 5 additions & 0 deletions core/src/ten_runtime/engine/msg_interface/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,11 @@ bool ten_engine_dispatch_msg(ten_engine_t *self, ten_shared_ptr_t *msg) {
"When this function is executed, there should be only one "
"destination remaining in the message's dest.");

if (ten_engine_is_closing(self)) {
// Do not dispatch the message if the engine is closing.
return true;
}

ten_loc_t *dest_loc = ten_msg_get_first_dest_loc(msg);
TEN_ASSERT(dest_loc && ten_loc_check_integrity(dest_loc),
"Should not happen.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ static void on_addon_create_extension_done(ten_env_t *ten_env,
} else {
// Failed to create the specified extension.

TEN_LOGE(
TEN_LOGI(
"Failed to create extension %s",
ten_string_get_raw_str(&create_extension_done_ctx->extension_name));

Expand Down
3 changes: 0 additions & 3 deletions core/src/ten_runtime/extension_thread/extension_thread.c
Original file line number Diff line number Diff line change
Expand Up @@ -510,9 +510,6 @@ static void ten_engine_on_all_extension_threads_are_ready(

ten_shared_ptr_t *cmd_result = NULL;
if (error_occurred) {
TEN_LOGE("[%s] Failed to start the graph successfully, shutting it down.",
ten_engine_get_id(self, true));

cmd_result = ten_cmd_result_create_from_cmd(TEN_STATUS_CODE_ERROR,
state_requester_cmd);
} else {
Expand Down
2 changes: 1 addition & 1 deletion core/ten_gn
17 changes: 17 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion packages/core_addon_loaders/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ group("core_addon_loaders") {
deps = []

if (ten_enable_python_binding) {
deps += [ "python_addon_loader" ]
deps += [
"nodejs_addon_loader",
"python_addon_loader",
]
}
}
Loading

0 comments on commit 660e9fc

Please sign in to comment.