noobs 0.0.145 → 0.0.147
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/noobs.node +0 -0
- package/package.json +1 -1
- package/src/obs_interface.cpp +44 -4
- package/src/obs_interface.h +1 -0
- package/src/utils.cpp +46 -67
package/dist/noobs.node
CHANGED
|
Binary file
|
package/package.json
CHANGED
package/src/obs_interface.cpp
CHANGED
|
@@ -10,14 +10,20 @@
|
|
|
10
10
|
|
|
11
11
|
void call_jscb(Napi::Env env, Napi::Function cb, SignalData* sd) {
|
|
12
12
|
Napi::Object obj = Napi::Object::New(env);
|
|
13
|
+
|
|
13
14
|
obj.Set("type", Napi::String::New(env, sd->type));
|
|
14
15
|
obj.Set("id", Napi::String::New(env, sd->id));
|
|
15
16
|
obj.Set("code", Napi::Number::New(env, sd->code));
|
|
17
|
+
|
|
16
18
|
|
|
17
19
|
if (sd->value.has_value()) {
|
|
18
20
|
obj.Set("value", Napi::Number::New(env, sd->value.value()));
|
|
19
21
|
}
|
|
20
22
|
|
|
23
|
+
if (sd->error.has_value()) {
|
|
24
|
+
obj.Set("error", Napi::String::New(env, sd->error.value()));
|
|
25
|
+
}
|
|
26
|
+
|
|
21
27
|
cb.Call({ obj });
|
|
22
28
|
delete sd;
|
|
23
29
|
}
|
|
@@ -55,6 +61,22 @@ void ObsInterface::list_output_types()
|
|
|
55
61
|
}
|
|
56
62
|
}
|
|
57
63
|
|
|
64
|
+
bool log_adapter(void *param, const char *node, uint32_t idx)
|
|
65
|
+
{
|
|
66
|
+
blog(LOG_INFO, " - %d: %s", idx, node);
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
void list_adapters()
|
|
71
|
+
{
|
|
72
|
+
// Pretty sure OBS logs all this stuff anyway but do it ourselves for good measure.
|
|
73
|
+
obs_enter_graphics();
|
|
74
|
+
uint32_t count = gs_get_adapter_count();
|
|
75
|
+
blog(LOG_INFO, "Adapter count: %d", count);
|
|
76
|
+
gs_enum_adapters(log_adapter, NULL);
|
|
77
|
+
obs_leave_graphics();
|
|
78
|
+
}
|
|
79
|
+
|
|
58
80
|
void ObsInterface::load_module(const char* module, const char* data, bool allowFail) {
|
|
59
81
|
blog(LOG_INFO, "Loading module: %s", module);
|
|
60
82
|
blog(LOG_INFO, "Data path: %s", data);
|
|
@@ -145,7 +167,7 @@ bool ObsInterface::reset_audio() {
|
|
|
145
167
|
}
|
|
146
168
|
|
|
147
169
|
void ObsInterface::init_obs(const std::string& distPath) {
|
|
148
|
-
blog(LOG_INFO, "
|
|
170
|
+
blog(LOG_INFO, "Initializing OBS");
|
|
149
171
|
auto success = obs_startup("en-US", NULL, NULL);
|
|
150
172
|
|
|
151
173
|
if (!success) {
|
|
@@ -218,10 +240,12 @@ void ObsInterface::init_obs(const std::string& distPath) {
|
|
|
218
240
|
list_encoders();
|
|
219
241
|
list_source_types();
|
|
220
242
|
list_output_types();
|
|
243
|
+
list_adapters();
|
|
221
244
|
|
|
222
|
-
blog(LOG_INFO, "
|
|
245
|
+
blog(LOG_INFO, "Initializing complete");
|
|
223
246
|
}
|
|
224
247
|
|
|
248
|
+
|
|
225
249
|
void ObsInterface::create_output() {
|
|
226
250
|
blog(LOG_INFO, "Create outputs");
|
|
227
251
|
|
|
@@ -571,11 +595,25 @@ obs_properties_t* ObsInterface::getSourceProperties(std::string name) {
|
|
|
571
595
|
|
|
572
596
|
void ObsInterface::output_signal_handler(void *data, calldata_t *cd) {
|
|
573
597
|
long long code = calldata_int(cd, "code");
|
|
598
|
+
const char *err = calldata_string(cd, "last_error");
|
|
599
|
+
|
|
600
|
+
std::optional<std::string> error;
|
|
601
|
+
|
|
602
|
+
if (err) {
|
|
603
|
+
error = std::string(err);
|
|
604
|
+
}
|
|
574
605
|
|
|
575
606
|
SignalContext* ctx = static_cast<SignalContext*>(data);
|
|
576
607
|
ObsInterface* self = ctx->self;
|
|
577
608
|
|
|
578
|
-
SignalData* sd = new SignalData{
|
|
609
|
+
SignalData* sd = new SignalData{
|
|
610
|
+
"output",
|
|
611
|
+
ctx->id.c_str(),
|
|
612
|
+
code,
|
|
613
|
+
std::nullopt, // No value, that's only used for volmeters.
|
|
614
|
+
error,
|
|
615
|
+
};
|
|
616
|
+
|
|
579
617
|
self->jscb.NonBlockingCall(sd, call_jscb);
|
|
580
618
|
}
|
|
581
619
|
|
|
@@ -896,7 +934,7 @@ ObsInterface::ObsInterface(
|
|
|
896
934
|
}
|
|
897
935
|
|
|
898
936
|
ObsInterface::~ObsInterface() {
|
|
899
|
-
blog(LOG_DEBUG, "
|
|
937
|
+
blog(LOG_DEBUG, "Shutting down");
|
|
900
938
|
|
|
901
939
|
for (auto& kv : volmeters) {
|
|
902
940
|
obs_volmeter_t* volmeter = kv.second;
|
|
@@ -969,6 +1007,8 @@ ObsInterface::~ObsInterface() {
|
|
|
969
1007
|
blog(LOG_DEBUG, "Releasing JavaScript callback");
|
|
970
1008
|
jscb.Release();
|
|
971
1009
|
}
|
|
1010
|
+
|
|
1011
|
+
blog(LOG_DEBUG, "Shutdown complete");
|
|
972
1012
|
}
|
|
973
1013
|
|
|
974
1014
|
void ObsInterface::setBuffering(bool value) {
|
package/src/obs_interface.h
CHANGED
package/src/utils.cpp
CHANGED
|
@@ -7,77 +7,56 @@
|
|
|
7
7
|
#include "utils.h"
|
|
8
8
|
|
|
9
9
|
void log_handler(int lvl, const char *msg, va_list args, void *p) {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
static std::ofstream logFile;
|
|
11
|
+
static bool initialized = false;
|
|
12
|
+
|
|
13
|
+
if (!initialized) {
|
|
14
|
+
// Build log filename
|
|
15
|
+
auto now = std::chrono::system_clock::now();
|
|
16
|
+
auto t = std::chrono::system_clock::to_time_t(now);
|
|
17
|
+
std::stringstream filename;
|
|
18
|
+
filename << "OBS-" << std::put_time(std::localtime(&t), "%Y-%m-%d") << ".log";
|
|
19
|
+
|
|
20
|
+
std::string log_dir = static_cast<const char*>(p);
|
|
21
|
+
if (!log_dir.empty() && log_dir.back() != '\\' && log_dir.back() != '/')
|
|
22
|
+
log_dir += '\\';
|
|
23
|
+
|
|
24
|
+
logFile.open(log_dir + filename.str(), std::ios::app);
|
|
25
|
+
initialized = true;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (!logFile.is_open()) return;
|
|
29
|
+
|
|
30
|
+
// Timestamp
|
|
15
31
|
auto now = std::chrono::system_clock::now();
|
|
16
|
-
auto
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
32
|
+
auto t = std::chrono::system_clock::to_time_t(now);
|
|
33
|
+
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
|
|
34
|
+
now.time_since_epoch()) % 1000;
|
|
35
|
+
|
|
36
|
+
std::stringstream timestamp;
|
|
37
|
+
timestamp << "[" << std::put_time(std::localtime(&t), "%Y-%m-%d %H:%M:%S")
|
|
38
|
+
<< "." << std::setfill('0') << std::setw(3) << ms.count() << "] ";
|
|
23
39
|
|
|
24
|
-
//
|
|
25
|
-
|
|
26
|
-
|
|
40
|
+
// Log level
|
|
41
|
+
const char* level_str = "UNKNOWN";
|
|
42
|
+
switch (lvl) {
|
|
43
|
+
case LOG_ERROR: level_str = "ERROR"; break;
|
|
44
|
+
case LOG_WARNING: level_str = "WARN"; break;
|
|
45
|
+
case LOG_INFO: level_str = "INFO"; break;
|
|
46
|
+
case LOG_DEBUG: level_str = "DEBUG"; break;
|
|
27
47
|
}
|
|
48
|
+
timestamp << "[" << level_str << "] ";
|
|
28
49
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
// Convert log level to string
|
|
40
|
-
const char* level_str;
|
|
41
|
-
switch (lvl) {
|
|
42
|
-
case LOG_ERROR: level_str = "ERROR"; break;
|
|
43
|
-
case LOG_WARNING: level_str = "WARN"; break;
|
|
44
|
-
case LOG_INFO: level_str = "INFO"; break;
|
|
45
|
-
case LOG_DEBUG: level_str = "DEBUG"; break;
|
|
46
|
-
default: level_str = "UNKNOWN"; break;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// Format the log message
|
|
50
|
-
char buffer[4096];
|
|
51
|
-
vsnprintf(buffer, sizeof(buffer), msg, args);
|
|
52
|
-
|
|
53
|
-
// Create timestamp string
|
|
54
|
-
std::stringstream timestamp;
|
|
55
|
-
timestamp << std::put_time(std::localtime(&time_t), "%Y-%m-%d %H:%M:%S");
|
|
56
|
-
timestamp << "." << std::setfill('0') << std::setw(3) << ms.count();
|
|
57
|
-
|
|
58
|
-
std::string timestamp_str = "[" + timestamp.str() + "] [" + level_str + "] ";
|
|
59
|
-
|
|
60
|
-
// Split the message by newlines and add timestamp to each line
|
|
61
|
-
std::string message(buffer);
|
|
62
|
-
std::istringstream iss(message);
|
|
63
|
-
std::string line;
|
|
64
|
-
std::string formatted_output;
|
|
65
|
-
|
|
66
|
-
while (std::getline(iss, line)) {
|
|
67
|
-
formatted_output += timestamp_str + line + "\n";
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// Remove the last newline if it exists
|
|
71
|
-
if (!formatted_output.empty() && formatted_output.back() == '\n') {
|
|
72
|
-
formatted_output.pop_back();
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// Write to log file
|
|
76
|
-
std::ofstream logFile(log_filename, std::ios::app);
|
|
77
|
-
if (logFile.is_open()) {
|
|
78
|
-
logFile << formatted_output << std::endl;
|
|
79
|
-
logFile.close();
|
|
80
|
-
}
|
|
50
|
+
// Format message
|
|
51
|
+
char buffer[4096];
|
|
52
|
+
vsnprintf(buffer, sizeof(buffer), msg, args);
|
|
53
|
+
|
|
54
|
+
// Prepend timestamp and flush per line
|
|
55
|
+
std::istringstream iss(buffer);
|
|
56
|
+
std::string line;
|
|
57
|
+
while (std::getline(iss, line)) {
|
|
58
|
+
logFile << timestamp.str() << line << std::endl; // std::endl flushes
|
|
59
|
+
}
|
|
81
60
|
}
|
|
82
61
|
|
|
83
62
|
Napi::Object data_to_napi(Napi::Env env, obs_data_t* data) {
|