Skip to content

Commit e63aae7

Browse files
committed
Fix #14 - msgbus:send popup warning. Also add more logging.
1 parent 05672c7 commit e63aae7

11 files changed

Lines changed: 156 additions & 61 deletions

File tree

native/recorder/src/FrameProcessor.hpp

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,27 @@ class FrameProcessor
2121
public:
2222
struct StatusInfo
2323
{
24-
bool recording;
24+
bool recording = false;
2525
std::string error;
2626
std::string filename;
27-
std::uint32_t width;
28-
std::uint32_t height;
29-
std::uint64_t lastTsMilli;
30-
float fps;
31-
std::uint32_t frameBacklog;
27+
std::uint32_t width = 0;
28+
std::uint32_t height = 0;
29+
std::uint64_t lastTsMilli = 0;
30+
float fps = 60;
31+
std::uint32_t frameBacklog = 0;
32+
33+
friend std::ostream &operator<<(std::ostream &os, const StatusInfo &info)
34+
{
35+
os << "{recording=" << info.recording
36+
<< ", error='" << info.error
37+
<< "', filename='" << info.filename
38+
<< "', width=" << info.width
39+
<< ", height=" << info.height
40+
<< ", lastTsMilli=" << info.lastTsMilli
41+
<< ", fps=" << info.fps
42+
<< ", frameBacklog=" << info.frameBacklog << "}";
43+
return os;
44+
}
3245
};
3346

3447
struct Rectangle

native/recorder/src/NdiReader.cpp

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,31 @@ class NdiReader : public VideoReader
108108

109109
for (uint32_t src = 0; src < no_sources; src++)
110110
{
111+
std::string address_port = std::string(p_sources[src].p_url_address);
112+
std::string ip_address;
113+
uint16_t port = 0;
114+
size_t colon_pos = address_port.find(':');
115+
if (colon_pos != std::string::npos)
116+
{
117+
ip_address = address_port.substr(0, colon_pos);
118+
std::string port_str = address_port.substr(colon_pos + 1);
119+
try
120+
{
121+
port = static_cast<uint16_t>(std::stoi(port_str));
122+
}
123+
catch (const std::exception &)
124+
{
125+
port = 0; // fallback if conversion fails
126+
}
127+
}
128+
else
129+
{
130+
ip_address = address_port;
131+
port = 0;
132+
}
133+
111134
list.push_back(
112-
CameraInfo(p_sources[src].p_ndi_name, p_sources[src].p_url_address));
135+
CameraInfo(p_sources[src].p_ndi_name, ip_address, port));
113136
// SystemEventQueue::push("NDI", std::string("Source Found: ") +
114137
// p_sources[src].p_ndi_name + " at " + p_sources[src].p_ip_address);
115138
}
@@ -154,7 +177,7 @@ class NdiReader : public VideoReader
154177
if (!s.ipv4.empty())
155178
{
156179
list.push_back(
157-
CameraInfo(s.instance_label, s.ipv4[0]));
180+
CameraInfo(s.instance_label, s.ipv4[0], s.port));
158181
}
159182
// std::cout << s.instance << " -> " << s.host << ":" << s.port << "\n";
160183
// std::cout << "NDI Source: " << s.instance_label << " [" << s.service << "." << s.domain << "] -> "
@@ -184,13 +207,9 @@ class NdiReader : public VideoReader
184207
NDIlib_source_t p_source;
185208
CameraInfo foundCamera;
186209
std::vector<CameraInfo> cameras;
187-
while (foundCamera.name == "" && keepRunning)
188210
{
189-
{
190-
std::unique_lock<std::mutex> lock(scanMutex);
191-
cameras = camList;
192-
}
193-
for (auto camera : cameras)
211+
std::unique_lock<std::mutex> lock(scanMutex);
212+
for (auto camera : camList)
194213
{
195214
std::cout << "Found camera: " << camera.name << " looking for " << srcName << std::endl;
196215
if (camera.name.find(srcName) == 0)
@@ -203,7 +222,8 @@ class NdiReader : public VideoReader
203222

204223
if (foundCamera.name == "")
205224
{
206-
return ""; // stop received before ndi source found
225+
SystemEventQueue::push("Debug", "Error: Camera not found " + srcName);
226+
return "";
207227
}
208228

209229
std::cout << "Camera found" << std::endl;
@@ -223,10 +243,11 @@ class NdiReader : public VideoReader
223243
// Connect to the source
224244
SystemEventQueue::push("Debug", std::string("Connecting to ") +
225245
foundCamera.name + " at " +
226-
foundCamera.address);
246+
foundCamera.url);
227247
// Connect to our sources
228248
p_source.p_ndi_name = foundCamera.name.c_str();
229-
p_source.p_url_address = foundCamera.address.c_str();
249+
p_source.p_url_address = foundCamera.url.c_str();
250+
230251
NDIlib_recv_connect(ndiRecv->pNDI_recv, &p_source);
231252

232253
foundCamera.name = "";
@@ -379,7 +400,7 @@ class NdiReader : public VideoReader
379400
opt.debug_level = 2;
380401
mdns = std::make_shared<ndi_mdns::NdiMdns>(opt);
381402
mdnsScanThread = std::thread(&NdiReader::mdnsScanLoop, this);
382-
ndiScanThread = std::thread(&NdiReader::ndiScanLoop, this);
403+
// ndiScanThread = std::thread(&NdiReader::ndiScanLoop, this);
383404
auto *version = NDIlib_version();
384405
std::cout << "NDI SDK Version: " << version << std::endl;
385406
}

native/recorder/src/RecorderAPI.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,8 @@ nativeVideoRecorder(const Napi::CallbackInfo &info)
172172

173173
Napi::Env env = info.Env();
174174
Napi::Object ret = Napi::Object::New(env);
175+
std::string op;
176+
VideoController::StatusInfo lastStatusInfo;
175177
ret.Set("status", Napi::String::New(env, "OK"));
176178
if (info.Length() < 1)
177179
{
@@ -189,7 +191,7 @@ nativeVideoRecorder(const Napi::CallbackInfo &info)
189191

190192
try
191193
{
192-
auto op = args.Get("op").As<Napi::String>().Utf8Value();
194+
op = args.Get("op").As<Napi::String>().Utf8Value();
193195
if (!videoController)
194196
{
195197
videoController = std::shared_ptr<VideoController>(new VideoController("ndi"));
@@ -334,6 +336,7 @@ nativeVideoRecorder(const Napi::CallbackInfo &info)
334336
if (videoController)
335337
{
336338
auto status = videoController->getStatus();
339+
lastStatusInfo = status;
337340
ret.Set("status", Napi::String::New(env, "OK"));
338341
ret.Set("error", Napi::String::New(env, status.error));
339342
ret.Set("recording", Napi::Boolean::New(env, status.recording));
@@ -520,13 +523,17 @@ nativeVideoRecorder(const Napi::CallbackInfo &info)
520523
}
521524
catch (const std::exception &e)
522525
{
526+
std::cerr << "Error while processing op=" << op << std::endl;
527+
std::cerr << "Last statusInfo=" << lastStatusInfo << std::endl;
523528
// Catch standard C++ exceptions and convert them to JavaScript errors
524529
Napi::Error::New(env, e.what()).ThrowAsJavaScriptException();
525530
}
526531
catch (...)
527532
{
528533
// Catch all other types of exceptions and throw a generic JavaScript
529534
// error
535+
std::cerr << "Error while processing op=" << op << std::endl;
536+
std::cerr << "Last statusInfo=" << lastStatusInfo << std::endl;
530537
Napi::Error::New(env, "An unknown error occurred")
531538
.ThrowAsJavaScriptException();
532539
}

native/recorder/src/VideoController.hpp

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,19 @@ class VideoController
1717
public:
1818
struct StatusInfo
1919
{
20-
bool recording;
20+
bool recording = false;
2121
std::string error;
22-
std::uint32_t recordingDuration;
22+
std::uint32_t recordingDuration = 0;
2323
FrameProcessor::StatusInfo frameProcessor;
24+
25+
friend std::ostream &operator<<(std::ostream &os, const StatusInfo &info)
26+
{
27+
os << "{recording=" << info.recording
28+
<< ", error='" << info.error << "'"
29+
<< ", duration=" << info.recordingDuration
30+
<< ", frameProcessor=" << info.frameProcessor << "}";
31+
return os;
32+
}
2433
};
2534

2635
private:
@@ -118,15 +127,17 @@ class VideoController
118127
StatusInfo getStatus()
119128
{
120129
std::lock_guard<std::recursive_mutex> lock(controlMutex);
121-
std::chrono::steady_clock::time_point endTime =
122-
std::chrono::steady_clock::now();
123-
124-
// Calculate the elapsed time in seconds
125-
std::chrono::duration<double> elapsed_seconds = endTime - startTime;
126-
uint32_t elapsedSecondsUInt =
127-
static_cast<uint32_t>(elapsed_seconds.count());
128130

131+
// compute recording and recordingDuration status fields
132+
uint32_t elapsedSecondsUInt = 0;
129133
const auto recording = frameProcessor != nullptr && status == "";
134+
if (recording)
135+
{
136+
std::chrono::steady_clock::time_point endTime =
137+
std::chrono::steady_clock::now();
138+
std::chrono::duration<double> elapsed_seconds = endTime - startTime;
139+
elapsedSecondsUInt = static_cast<uint32_t>(elapsed_seconds.count());
140+
}
130141
statusInfo.recording = recording;
131142
statusInfo.recordingDuration = recording ? elapsedSecondsUInt : 0;
132143
return statusInfo;
@@ -151,6 +162,8 @@ class VideoController
151162
{
152163
return "Video Controller already running";
153164
}
165+
166+
startTime = std::chrono::steady_clock::now();
154167
status = "";
155168
std::string retval = "";
156169
#ifdef USE_APPLE
@@ -206,7 +219,6 @@ class VideoController
206219
return fpStatus.error;
207220
}
208221

209-
startTime = std::chrono::steady_clock::now();
210222
return "";
211223
}
212224

native/recorder/src/VideoReader.hpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,21 @@ class VideoReader
1616
{
1717
std::string name;
1818
std::string address;
19+
uint16_t port;
20+
std::string url;
1921
CameraInfo() {}
20-
CameraInfo(std::string name, std::string address)
21-
: name(name), address(address) {}
22+
CameraInfo(std::string name, std::string address, uint16_t port)
23+
: name(name), address(address), port(port)
24+
{
25+
if (port == 0)
26+
{
27+
url = address;
28+
}
29+
else
30+
{
31+
url = address + ":" + std::to_string(port);
32+
}
33+
}
2234
} CameraInfo;
2335

2436
virtual std::string start(const std::string srcName,

src/main/msgbus/msgbus-main.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ ipcMain.handle('msgbus:send', (_event, dest: string, msg: any) => {
2020
const ret = msgbus.sendMessage(dest, msg);
2121
return ret;
2222
} catch (err) {
23-
return { status: `${err instanceof Error ? err.message : err}` };
23+
return {
24+
status: `${err instanceof Error ? err.message : err} sending to ${dest}: ${JSON.stringify(msg)}`,
25+
};
2426
}
2527
});

src/renderer/components/ErrorDialog.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { setDialogConfig } from './ConfirmDialog';
88
// eslint-disable-next-line @typescript-eslint/no-explicit-any
99
export const showErrorDialog = (error: any) => {
1010
const message = error instanceof Error ? error.message : String(error);
11+
console.log(`Error: ${message}`);
1112
setDialogConfig({
1213
title: 'Error',
1314
message,

src/renderer/components/HamburgerMenu.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
useRecordingPropsPending,
2121
useReportAllGaps,
2222
} from '../recorder/RecorderData';
23+
import { openNagScreen } from './NagScreen';
2324

2425
const AboutText = `CrewTimer Video Recorder ${window.platform.appVersion}`;
2526

@@ -85,6 +86,17 @@ const HamburgerMenu = () => {
8586
<ListItemText>Camera web page</ListItemText>
8687
</MenuItem>
8788
)}
89+
<MenuItem
90+
onClick={() => {
91+
handleClose();
92+
openNagScreen(true);
93+
}}
94+
>
95+
<ListItemIcon>
96+
<InfoIcon />
97+
</ListItemIcon>
98+
<ListItemText primary="What's New" />
99+
</MenuItem>
88100
<MenuItem onClick={closeAndGo('/privacy')}>
89101
<ListItemIcon>
90102
<SecurityIcon />

0 commit comments

Comments
 (0)