/*
* Copyright 2026 LiveKit
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "livekit/local_data_track.h"
#include "data_track.pb.h"
#include "data_track_proto_converter.h"
#include "ffi.pb.h"
#include "ffi_client.h"
#include "livekit/data_track_error.h"
#include "lk_log.h"
namespace livekit {
LocalDataTrack::LocalDataTrack(const proto::OwnedLocalDataTrack& owned)
: handle_(static_cast(owned.handle().id())), info_(fromProto(owned.info())) {}
Result LocalDataTrack::tryPush(const DataTrackFrame& frame) {
return tryPush(frame.payload.data(), frame.payload.size(), frame.user_timestamp);
}
Result LocalDataTrack::tryPush(std::vector&& payload,
std::optional user_timestamp) {
const DataTrackFrame frame(std::move(payload), user_timestamp);
return tryPush(frame);
}
Result LocalDataTrack::tryPush(const std::uint8_t* data, std::size_t size,
std::optional user_timestamp) {
if (!handle_.valid()) {
return Result::failure(LocalDataTrackTryPushError{
LocalDataTrackTryPushErrorCode::INVALID_HANDLE, "LocalDataTrack::tryPush: invalid FFI handle"});
}
if (size == 0) {
return Result::success();
}
if (data == nullptr) {
return Result::failure(LocalDataTrackTryPushError{
LocalDataTrackTryPushErrorCode::INTERNAL, "LocalDataTrack::tryPush: payload pointer is null"});
}
try {
proto::FfiRequest req;
auto* msg = req.mutable_local_data_track_try_push();
msg->set_track_handle(static_cast(handle_.get()));
auto* pf = msg->mutable_frame();
pf->set_payload(data, size);
if (user_timestamp.has_value()) {
pf->set_user_timestamp(user_timestamp.value());
}
const proto::FfiResponse resp = FfiClient::instance().sendRequest(req);
const auto& r = resp.local_data_track_try_push();
if (r.has_error()) {
return Result::failure(LocalDataTrackTryPushError::fromProto(r.error()));
}
return Result::success();
} catch (const std::exception& e) {
return Result::failure(
LocalDataTrackTryPushError{LocalDataTrackTryPushErrorCode::INTERNAL, e.what()});
}
}
bool LocalDataTrack::isPublished() const {
if (!handle_.valid()) {
return false;
}
proto::FfiRequest req;
auto* msg = req.mutable_local_data_track_is_published();
msg->set_track_handle(static_cast(handle_.get()));
const proto::FfiResponse resp = FfiClient::instance().sendRequest(req);
return resp.local_data_track_is_published().is_published();
}
void LocalDataTrack::unpublishDataTrack() {
if (!handle_.valid()) {
return;
}
proto::FfiRequest req;
auto* msg = req.mutable_local_data_track_unpublish();
msg->set_track_handle(static_cast(handle_.get()));
(void)FfiClient::instance().sendRequest(req);
}
} // namespace livekit