Skip to content

Commit bdb4cd2

Browse files
better scoping of local participants
1 parent 402e6fb commit bdb4cd2

8 files changed

Lines changed: 111 additions & 87 deletions

File tree

hello_livekit/sender/main.cpp

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -84,27 +84,31 @@ int main(int argc, char* argv[]) {
8484
return 1;
8585
}
8686

87-
auto lp = room->localParticipant().lock();
88-
assert(lp);
87+
std::shared_ptr<LocalDataTrack> data_track;
88+
std::shared_ptr<LocalVideoTrack> video_track;
89+
std::shared_ptr<VideoSource> video_source;
90+
{
91+
auto lp = room->localParticipant().lock();
92+
assert(lp);
8993

90-
std::cout << "[info] [sender] Connected as identity='" << lp->identity() << "' room='" << room->roomInfo().name
91-
<< "' — pass this identity to HelloLivekitReceiver\n";
94+
std::cout << "[info] [sender] Connected as identity='" << lp->identity() << "' room='" << room->roomInfo().name
95+
<< "' — pass this identity to HelloLivekitReceiver\n";
9296

93-
auto video_source = std::make_shared<VideoSource>(kWidth, kHeight);
97+
video_source = std::make_shared<VideoSource>(kWidth, kHeight);
9498

95-
std::shared_ptr<LocalVideoTrack> video_track =
96-
lp->publishVideoTrack(kVideoTrackName, video_source, TrackSource::SOURCE_CAMERA);
99+
video_track = lp->publishVideoTrack(kVideoTrackName, video_source, TrackSource::SOURCE_CAMERA);
97100

98-
auto publish_result = lp->publishDataTrack(kDataTrackName);
99-
if (!publish_result) {
100-
const auto& error = publish_result.error();
101-
std::cerr << "[error] Failed to publish data track: code=" << static_cast<std::uint32_t>(error.code)
102-
<< " message=" << error.message << "\n";
103-
room.reset();
104-
livekit::shutdown();
105-
return 1;
101+
auto publish_result = lp->publishDataTrack(kDataTrackName);
102+
if (!publish_result) {
103+
const auto& error = publish_result.error();
104+
std::cerr << "[error] Failed to publish data track: code=" << static_cast<std::uint32_t>(error.code)
105+
<< " message=" << error.message << "\n";
106+
room.reset();
107+
livekit::shutdown();
108+
return 1;
109+
}
110+
data_track = publish_result.value();
106111
}
107-
std::shared_ptr<LocalDataTrack> data_track = publish_result.value();
108112

109113
const auto t0 = std::chrono::steady_clock::now();
110114
std::uint64_t count = 0;

ping_pong/ping/main.cpp

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -98,24 +98,27 @@ int main(int argc, char* argv[]) {
9898
return 1;
9999
}
100100

101-
auto local_participant = room->localParticipant().lock();
102-
assert(local_participant);
103-
104-
std::cout << "[info] ping connected as identity='" << local_participant->identity() << "' room='"
105-
<< room->roomInfo().name << "'\n";
106-
107-
auto publish_result = local_participant->publishDataTrack(ping_pong::kPingTrackName);
108-
if (!publish_result) {
109-
const auto& error = publish_result.error();
110-
std::cerr << "[error] Failed to publish ping data track: code=" << static_cast<std::uint32_t>(error.code)
111-
<< " message=" << error.message << "\n";
112-
room->setDelegate(nullptr);
113-
room.reset();
114-
livekit::shutdown();
115-
return 1;
101+
std::shared_ptr<LocalDataTrack> ping_track;
102+
{
103+
auto local_participant = room->localParticipant().lock();
104+
assert(local_participant);
105+
106+
std::cout << "[info] ping connected as identity='" << local_participant->identity() << "' room='"
107+
<< room->roomInfo().name << "'\n";
108+
109+
auto publish_result = local_participant->publishDataTrack(ping_pong::kPingTrackName);
110+
if (!publish_result) {
111+
const auto& error = publish_result.error();
112+
std::cerr << "[error] Failed to publish ping data track: code=" << static_cast<std::uint32_t>(error.code)
113+
<< " message=" << error.message << "\n";
114+
room->setDelegate(nullptr);
115+
room.reset();
116+
livekit::shutdown();
117+
return 1;
118+
}
119+
ping_track = publish_result.value();
116120
}
117121

118-
std::shared_ptr<LocalDataTrack> ping_track = publish_result.value();
119122
std::unordered_map<std::uint64_t, ping_pong::PingMessage> sent_messages;
120123
std::mutex sent_messages_mutex;
121124

ping_pong/pong/main.cpp

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -77,25 +77,28 @@ int main(int argc, char* argv[]) {
7777
return 1;
7878
}
7979

80-
auto local_participant = room->localParticipant().lock();
81-
assert(local_participant);
82-
83-
std::cout << "[info] pong connected as identity='" << local_participant->identity() << "' room='"
84-
<< room->roomInfo().name << "'\n";
85-
86-
auto publish_result = local_participant->publishDataTrack(ping_pong::kPongTrackName);
87-
if (!publish_result) {
88-
const auto& error = publish_result.error();
89-
std::cerr << "[error] Failed to publish pong data track: code=" << static_cast<std::uint32_t>(error.code)
90-
<< " message=" << error.message << "\n";
91-
room->setDelegate(nullptr);
92-
room.reset();
93-
livekit::shutdown();
94-
return 1;
80+
std::shared_ptr<LocalDataTrack> pong_track;
81+
{
82+
// limit the scope of the local participant
83+
auto local_participant = room->localParticipant().lock();
84+
assert(local_participant);
85+
86+
std::cout << "[info] pong connected as identity='" << local_participant->identity() << "' room='"
87+
<< room->roomInfo().name << "'\n";
88+
89+
auto publish_result = local_participant->publishDataTrack(ping_pong::kPongTrackName);
90+
if (!publish_result) {
91+
const auto& error = publish_result.error();
92+
std::cerr << "[error] Failed to publish pong data track: code=" << static_cast<std::uint32_t>(error.code)
93+
<< " message=" << error.message << "\n";
94+
room->setDelegate(nullptr);
95+
room.reset();
96+
livekit::shutdown();
97+
return 1;
98+
}
99+
pong_track = publish_result.value();
95100
}
96101

97-
std::shared_ptr<LocalDataTrack> pong_track = publish_result.value();
98-
99102
const auto callback_id = room->addOnDataFrameCallback(
100103
ping_pong::kPingParticipantIdentity, ping_pong::kPingTrackName,
101104
[pong_track](const std::vector<std::uint8_t>& payload, std::optional<std::uint64_t> /*user_timestamp*/) {

simple_joystick/receiver/main.cpp

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -77,27 +77,27 @@ int main(int argc, char* argv[]) {
7777
std::cout << "[Receiver] Connected to room: " << info.name << "\n";
7878
std::cout << "[Receiver] Waiting for sender peer (up to 2 minutes)...\n";
7979

80-
// Register RPC handler for joystick commands
81-
auto lp = room->localParticipant().lock();
82-
if (!lp) {
83-
std::cerr << "[Receiver] No local participant; cannot register RPC handler.\n";
84-
room->setDelegate(nullptr);
85-
room.reset();
86-
livekit::shutdown();
87-
return 1;
88-
}
89-
lp->registerRpcMethod("joystick_command", [](const RpcInvocationData& data) -> std::optional<std::string> {
90-
try {
91-
auto cmd = simple_joystick::json_to_joystick(data.payload);
92-
g_sender_connected.store(true);
93-
std::cout << "[Receiver] Joystick from '" << data.caller_identity << "': x=" << cmd.x << " y=" << cmd.y
94-
<< " z=" << cmd.z << "\n";
95-
return std::optional<std::string>{"ok"};
96-
} catch (const std::exception& e) {
97-
std::cerr << "[Receiver] Bad joystick payload: " << e.what() << "\n";
98-
throw;
80+
{
81+
// Register RPC handler for joystick commands
82+
auto lp = room->localParticipant().lock();
83+
if (!lp) {
84+
std::cerr << "[Receiver] No local participant; cannot register RPC handler.\n";
85+
livekit::shutdown();
86+
return 1;
9987
}
100-
});
88+
lp->registerRpcMethod("joystick_command", [](const RpcInvocationData& data) -> std::optional<std::string> {
89+
try {
90+
auto cmd = simple_joystick::json_to_joystick(data.payload);
91+
g_sender_connected.store(true);
92+
std::cout << "[Receiver] Joystick from '" << data.caller_identity << "': x=" << cmd.x << " y=" << cmd.y
93+
<< " z=" << cmd.z << "\n";
94+
return std::optional<std::string>{"ok"};
95+
} catch (const std::exception& e) {
96+
std::cerr << "[Receiver] Bad joystick payload: " << e.what() << "\n";
97+
throw;
98+
}
99+
});
100+
}
101101

102102
std::cout << "[Receiver] RPC handler 'joystick_command' registered. "
103103
<< "Listening for commands...\n";

simple_joystick/sender/main.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ int main(int argc, char* argv[]) {
159159
auto now = std::chrono::steady_clock::now();
160160
if (now - last_receiver_check >= 2s) {
161161
last_receiver_check = now;
162-
bool receiver_present = (room->remoteParticipant("robot").lock() != nullptr);
162+
bool receiver_present = !room->remoteParticipant("robot").expired();
163163

164164
if (receiver_present && !receiver_connected) {
165165
std::cout << "[Sender] Receiver connected! Use keys to send commands.\n";

simple_rpc/main.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ bool waitForParticipant(Room* room, const std::string& identity, std::chrono::mi
6666
auto start = std::chrono::steady_clock::now();
6767

6868
while (std::chrono::steady_clock::now() - start < timeout) {
69-
if (room->remoteParticipant(identity).lock() != nullptr) {
69+
if (!room->remoteParticipant(identity).expired()) {
7070
return true;
7171
}
7272
std::this_thread::sleep_for(100ms);
@@ -210,7 +210,7 @@ void registerReceiverMethods(Room* greeters_room, Room* math_genius_room) {
210210
auto greeter_lp = greeters_room->localParticipant().lock();
211211
auto math_genius_lp = math_genius_room->localParticipant().lock();
212212
if (!greeter_lp || !math_genius_lp) {
213-
throw std::runtime_error("local participant unavailable");
213+
throw std::runtime_error("local participants unavailable");
214214
}
215215

216216
// arrival
@@ -320,8 +320,7 @@ void performQuantumHyperGeometricSeries(Room* room) {
320320
std::string payload = makeNumberJson("number", 42.0);
321321
auto lp = room->localParticipant().lock();
322322
if (!lp) throw std::runtime_error("local participant unavailable");
323-
std::string response =
324-
lp->performRpc("math-genius", "quantum-hypergeometric-series", payload, std::nullopt);
323+
std::string response = lp->performRpc("math-genius", "quantum-hypergeometric-series", payload, std::nullopt);
325324
double t1 = nowMs();
326325
std::cout << "[Caller] (Unexpected success) RTT=" << (t1 - t0) << " ms\n";
327326
std::cout << "[Caller] Result: " << response << "\n";

user_timestamped_video/consumer/main.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ class UserTimestampedVideoConsumerDelegate : public RoomDelegate {
6262
for (const auto& weak_participant : room_.remoteParticipants()) {
6363
if (auto participant = weak_participant.lock()) {
6464
registerRemoteVideoCallback(participant->identity());
65+
} else {
66+
throw std::runtime_error("unable to lock provided remote participant");
6567
}
6668
}
6769
}
@@ -163,10 +165,13 @@ int main(int argc, char* argv[]) {
163165
std::cerr << "[consumer] failed to connect\n";
164166
exit_code = 1;
165167
} else {
166-
auto lp = room.localParticipant().lock();
167-
std::cout << "[consumer] connected as " << (lp ? lp->identity() : std::string("<unknown>")) << " to room '"
168-
<< room.roomInfo().name << "' with user timestamp "
169-
<< (cli_options.use_user_timestamp ? "enabled" : "ignored") << "\n";
168+
if (auto lp = room.localParticipant().lock()) {
169+
std::cout << "[consumer] connected as " << (lp ? lp->identity() : std::string("<unknown>")) << " to room '"
170+
<< room.roomInfo().name << "' with user timestamp "
171+
<< (cli_options.use_user_timestamp ? "enabled" : "ignored") << "\n";
172+
} else {
173+
throw std::runtime_error("unable to lock local participant");
174+
}
170175

171176
delegate.registerExistingParticipants();
172177

@@ -177,6 +182,8 @@ int main(int argc, char* argv[]) {
177182
for (const auto& weak_participant : room.remoteParticipants()) {
178183
if (auto participant = weak_participant.lock()) {
179184
room.clearOnVideoFrameCallback(participant->identity(), std::string(kTrackName));
185+
} else {
186+
throw std::runtime_error("unable to lock provided remote participant");
180187
}
181188
}
182189
}

user_timestamped_video/producer/main.cpp

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,11 @@ int main(int argc, char* argv[]) {
9393
std::cerr << "[producer] failed to connect\n";
9494
exit_code = 1;
9595
} else {
96-
auto lp = room.localParticipant().lock();
97-
std::cout << "[producer] connected as " << (lp ? lp->identity() : std::string("<unknown>")) << " to room '"
98-
<< room.roomInfo().name << "'\n";
96+
{
97+
auto lp = room.localParticipant().lock();
98+
std::cout << "[producer] connected as " << (lp ? lp->identity() : std::string("<unknown>")) << " to room '"
99+
<< room.roomInfo().name << "'\n";
100+
}
99101

100102
auto source = std::make_shared<VideoSource>(kFrameWidth, kFrameHeight);
101103
auto track = LocalVideoTrack::createLocalVideoTrack("timestamped-camera", source);
@@ -105,10 +107,13 @@ int main(int argc, char* argv[]) {
105107
publish_options.source = TrackSource::SOURCE_CAMERA;
106108
publish_options.packet_trailer_features.user_timestamp = cli_options.use_user_timestamp;
107109

108-
if (!lp) throw std::runtime_error("local participant unavailable");
109-
lp->publishTrack(track, publish_options);
110-
std::cout << "[producer] published camera track with user timestamp "
111-
<< (cli_options.use_user_timestamp ? "enabled" : "disabled") << "\n";
110+
{
111+
auto lp = room.localParticipant().lock();
112+
if (!lp) throw std::runtime_error("local participant unavailable");
113+
lp->publishTrack(track, publish_options);
114+
std::cout << "[producer] published camera track with user timestamp "
115+
<< (cli_options.use_user_timestamp ? "enabled" : "disabled") << "\n";
116+
}
112117

113118
VideoFrame frame = VideoFrame::create(kFrameWidth, kFrameHeight, VideoBufferType::BGRA);
114119
const auto capture_start = std::chrono::steady_clock::now();
@@ -149,8 +154,11 @@ int main(int argc, char* argv[]) {
149154
exit_code = 1;
150155
}
151156

152-
if (lp && track->publication()) {
153-
lp->unpublishTrack(track->publication()->sid());
157+
// best effort unpublish
158+
if (auto lp = room.localParticipant().lock()) {
159+
if (lp && track->publication()) {
160+
lp->unpublishTrack(track->publication()->sid());
161+
}
154162
}
155163
}
156164
}

0 commit comments

Comments
 (0)