Some checks failed
dev release / build (push) Failing after 12s
Builds out the full v1 scope: a vendored+patched openscreen subset for low-latency Cast Streaming (Mirroring receiver 0F5096E8) alongside the existing Cast V2/HLS and new DLNA/AVTransport casting paths, breadcastd's Idle/Casting state machine with a private IPC socket, the breadcast GTK4 popup as a thin IPC client, and bread.cast.*/bread.command.cast.* breadd integration (device discovery, start/stop, mirroring lifecycle events). Also adds bakery/systemd/Forgejo CI packaging. Validated end-to-end against a real Chromecast/Google TV: negotiated Cast Streaming session, live pipeline playback, and daemon+GUI click-to-cast/ stop through the actual popup.
282 lines
12 KiB
C++
282 lines
12 KiB
C++
// Copyright 2019 The Chromium Authors
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#ifndef UTIL_TRACE_LOGGING_H_
|
|
#define UTIL_TRACE_LOGGING_H_
|
|
|
|
#include <sstream>
|
|
#include <string>
|
|
#include <type_traits>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
#include "platform/base/trace_logging_types.h"
|
|
|
|
// All compile-time macros for tracing.
|
|
// NOTE: The ternary operator is used here to ensure that the TraceLogger object
|
|
// is only constructed if tracing is enabled, but at the same time is created in
|
|
// the caller's scope. The C++ standards guide guarantees that the constructor
|
|
// should only be called when IsTraceLoggingEnabled(...) evaluates to true.
|
|
// static_cast calls are used because if the type of the result of the ternary
|
|
// operator does not match the expected type, temporary storage is used for the
|
|
// created object, which results in an extra call to the constructor and
|
|
// destructor of the tracing objects.
|
|
//
|
|
// Further details about how these macros are used can be found in
|
|
// docs/trace_logging.md.
|
|
|
|
#if defined(ENABLE_TRACE_LOGGING)
|
|
|
|
#define INCLUDING_FROM_UTIL_TRACE_LOGGING_H_
|
|
#include "util/trace_logging/macro_support.h"
|
|
#undef INCLUDING_FROM_UTIL_TRACE_LOGGING_H_
|
|
|
|
#define TRACE_SET_RESULT(result) \
|
|
do { \
|
|
if (TRACE_IS_ENABLED(openscreen::TraceCategory::kAny)) { \
|
|
openscreen::internal::ScopedTraceOperation::set_result(result); \
|
|
} \
|
|
} while (false)
|
|
#define TRACE_SET_HIERARCHY(ids) TRACE_SET_HIERARCHY_INTERNAL(__LINE__, ids)
|
|
#define TRACE_HIERARCHY \
|
|
(TRACE_IS_ENABLED(openscreen::TraceCategory::kAny) \
|
|
? openscreen::internal::ScopedTraceOperation::hierarchy() \
|
|
: openscreen::TraceIdHierarchy::Empty())
|
|
#define TRACE_CURRENT_ID \
|
|
(TRACE_IS_ENABLED(openscreen::TraceCategory::kAny) \
|
|
? openscreen::internal::ScopedTraceOperation::current_id() \
|
|
: kEmptyTraceId)
|
|
#define TRACE_ROOT_ID \
|
|
(TRACE_IS_ENABLED(openscreen::TraceCategory::kAny) \
|
|
? openscreen::internal::ScopedTraceOperation::root_id() \
|
|
: kEmptyTraceId)
|
|
|
|
namespace openscreen::internal {
|
|
|
|
template <typename T>
|
|
std::string ToString(T&& val) {
|
|
using DecayT = std::decay_t<T>;
|
|
if constexpr (std::is_constructible_v<std::string, T>) {
|
|
return std::string(std::forward<T>(val));
|
|
} else if constexpr (std::is_arithmetic_v<DecayT>) {
|
|
return std::to_string(val);
|
|
} else {
|
|
std::ostringstream oss;
|
|
oss << val;
|
|
return oss.str();
|
|
}
|
|
}
|
|
|
|
// Helper to extract a flow ID from various types (arithmetic or wrappers like
|
|
// FrameId).
|
|
template <typename T>
|
|
constexpr uint64_t ToFlowId(const T& val) {
|
|
if constexpr (std::is_arithmetic_v<T>) {
|
|
return static_cast<uint64_t>(val);
|
|
} else {
|
|
// Assume it's a numeric wrapper like FrameId with a .value() method.
|
|
return static_cast<uint64_t>(val.value());
|
|
}
|
|
}
|
|
|
|
} // namespace openscreen::internal
|
|
|
|
template <typename V1 = std::string, typename V2 = std::string>
|
|
inline std::vector<openscreen::TraceEvent::Argument> ToArgumentArray(
|
|
const char* argname = nullptr,
|
|
V1&& argval = V1(),
|
|
const char* argname_two = nullptr,
|
|
V2&& argval_two = V2()) {
|
|
std::vector<openscreen::TraceEvent::Argument> out;
|
|
if (argname) {
|
|
out.emplace_back(argname,
|
|
openscreen::internal::ToString(std::forward<V1>(argval)));
|
|
}
|
|
if (argname_two) {
|
|
out.emplace_back(argname_two, openscreen::internal::ToString(
|
|
std::forward<V2>(argval_two)));
|
|
}
|
|
return out;
|
|
}
|
|
|
|
// Synchronous Trace Macros.
|
|
//
|
|
// Scoped traces with no arguments.
|
|
#define TRACE_SCOPED(category, name, ...) \
|
|
TRACE_SCOPED_INTERNAL(__LINE__, category, name, ToArgumentArray(), \
|
|
##__VA_ARGS__)
|
|
#define TRACE_DEFAULT_SCOPED(category, ...) \
|
|
TRACE_SCOPED(category, __PRETTY_FUNCTION__, ##__VA_ARGS__)
|
|
|
|
// Scoped traces with one argument.
|
|
#define TRACE_SCOPED1(category, name, argname, argval, ...) \
|
|
TRACE_SCOPED_INTERNAL(__LINE__, category, name, \
|
|
ToArgumentArray(argname, argval), ##__VA_ARGS__)
|
|
#define TRACE_DEFAULT_SCOPED1(category, argname, argval, ...) \
|
|
TRACE_SCOPED1(category, __PRETTY_FUNCTION__, argname, argval, ##__VA_ARGS__)
|
|
|
|
// Scoped traces with two arguments.
|
|
#define TRACE_SCOPED2(category, name, argname, argval, argname_two, \
|
|
argval_two, ...) \
|
|
TRACE_SCOPED_INTERNAL( \
|
|
__LINE__, category, name, \
|
|
ToArgumentArray(argname, argval, argname_two, argval_two), \
|
|
##__VA_ARGS__)
|
|
#define TRACE_DEFAULT_SCOPED2(category, argname, argval, argname_two, \
|
|
argval_two, ...) \
|
|
TRACE_SCOPED2(category, __PRETTY_FUNCTION__, argname, argval, argname_two, \
|
|
argval_two, ##__VA_ARGS__)
|
|
|
|
// Asynchronous Trace Macros.
|
|
#define TRACE_ASYNC_START(category, name, ...) \
|
|
TRACE_ASYNC_START_INTERNAL(__LINE__, category, name, ToArgumentArray(), \
|
|
##__VA_ARGS__)
|
|
|
|
#define TRACE_ASYNC_START1(category, name, argname, argval, ...) \
|
|
TRACE_ASYNC_START_INTERNAL(__LINE__, category, name, \
|
|
ToArgumentArray(argname, argval), ##__VA_ARGS__)
|
|
|
|
#define TRACE_ASYNC_START2(category, name, argname, argval, argname_two, \
|
|
argval_two, ...) \
|
|
TRACE_ASYNC_START_INTERNAL( \
|
|
__LINE__, category, name, \
|
|
ToArgumentArray(argname, argval, argname_two, argval_two), \
|
|
##__VA_ARGS__)
|
|
|
|
#define TRACE_ASYNC_END(category, id, result) \
|
|
TRACE_IS_ENABLED(category) \
|
|
? openscreen::internal::ScopedTraceOperation::TraceAsyncEnd( \
|
|
__LINE__, __FILE__, id, result) \
|
|
: false
|
|
|
|
// Flow events are used to link trace events across different threads or
|
|
// processes. Flows are linked by their flow_id.
|
|
// - Flows can span across different trace categories.
|
|
// - If a TRACE_FLOW_BEGIN is missing (e.g. because the embedder didn't
|
|
// instrument it),
|
|
// the first TRACE_FLOW_STEP encountered will effectively start the flow
|
|
// visualization.
|
|
#define TRACE_FLOW_BEGIN(category, name, flow_id) \
|
|
TRACE_IS_ENABLED(category) \
|
|
? openscreen::internal::ScopedTraceOperation::TraceFlow( \
|
|
category, name, __FILE__, __LINE__, \
|
|
openscreen::internal::ToFlowId(flow_id), \
|
|
openscreen::FlowType::kFlowBegin) \
|
|
: false
|
|
|
|
#define TRACE_FLOW_STEP(category, name, flow_id) \
|
|
TRACE_IS_ENABLED(category) \
|
|
? openscreen::internal::ScopedTraceOperation::TraceFlow( \
|
|
category, name, __FILE__, __LINE__, \
|
|
openscreen::internal::ToFlowId(flow_id), \
|
|
openscreen::FlowType::kFlowStep) \
|
|
: false
|
|
|
|
#define TRACE_FLOW_END(category, name, flow_id) \
|
|
TRACE_IS_ENABLED(category) \
|
|
? openscreen::internal::ScopedTraceOperation::TraceFlow( \
|
|
category, name, __FILE__, __LINE__, \
|
|
openscreen::internal::ToFlowId(flow_id), \
|
|
openscreen::FlowType::kFlowEnd) \
|
|
: false
|
|
|
|
#define TRACE_FLOW_BEGIN_WITH_TIME(category, name, flow_id, timestamp) \
|
|
TRACE_IS_ENABLED(category) \
|
|
? openscreen::internal::ScopedTraceOperation::TraceFlow( \
|
|
category, name, __FILE__, __LINE__, \
|
|
openscreen::internal::ToFlowId(flow_id), \
|
|
openscreen::FlowType::kFlowBegin, timestamp) \
|
|
: false
|
|
|
|
#define TRACE_FLOW_STEP_WITH_TIME(category, name, flow_id, timestamp) \
|
|
TRACE_IS_ENABLED(category) \
|
|
? openscreen::internal::ScopedTraceOperation::TraceFlow( \
|
|
category, name, __FILE__, __LINE__, \
|
|
openscreen::internal::ToFlowId(flow_id), \
|
|
openscreen::FlowType::kFlowStep, timestamp) \
|
|
: false
|
|
|
|
#define TRACE_FLOW_END_WITH_TIME(category, name, flow_id, timestamp) \
|
|
TRACE_IS_ENABLED(category) \
|
|
? openscreen::internal::ScopedTraceOperation::TraceFlow( \
|
|
category, name, __FILE__, __LINE__, \
|
|
openscreen::internal::ToFlowId(flow_id), \
|
|
openscreen::FlowType::kFlowEnd, timestamp) \
|
|
: false
|
|
|
|
#define TRACE_FLOW_DEFAULT_BEGIN(category, flow_id) \
|
|
TRACE_FLOW_BEGIN(category, __PRETTY_FUNCTION__, flow_id)
|
|
|
|
#define TRACE_FLOW_DEFAULT_STEP(category, flow_id) \
|
|
TRACE_FLOW_STEP(category, __PRETTY_FUNCTION__, flow_id)
|
|
|
|
#define TRACE_FLOW_DEFAULT_END(category, flow_id) \
|
|
TRACE_FLOW_END(category, __PRETTY_FUNCTION__, flow_id)
|
|
|
|
#else // ENABLE_TRACE_LOGGING not defined
|
|
|
|
namespace openscreen::internal {
|
|
// Consumes `args` (to avoid "warn unused variable" errors at compile time), and
|
|
// provides a "void" result type in the macros below.
|
|
template <typename... Args>
|
|
inline void DoNothingForTracing(Args... args) {}
|
|
} // namespace openscreen::internal
|
|
|
|
#define TRACE_SET_RESULT(result) \
|
|
openscreen::internal::DoNothingForTracing(result)
|
|
#define TRACE_SET_HIERARCHY(ids) openscreen::internal::DoNothingForTracing(ids)
|
|
#define TRACE_HIERARCHY openscreen::TraceIdHierarchy::Empty()
|
|
#define TRACE_CURRENT_ID openscreen::kEmptyTraceId
|
|
#define TRACE_ROOT_ID openscreen::kEmptyTraceId
|
|
#define TRACE_SCOPED(category, name, ...) \
|
|
openscreen::internal::DoNothingForTracing(category, name, ##__VA_ARGS__)
|
|
#define TRACE_DEFAULT_SCOPED(category, ...) \
|
|
TRACE_SCOPED(category, __PRETTY_FUNCTION__, ##__VA_ARGS__)
|
|
|
|
#define TRACE_SCOPED1(category, name, argname, argval, ...) \
|
|
openscreen::internal::DoNothingForTracing(category, name, argname, argval, \
|
|
##__VA_ARGS__)
|
|
#define TRACE_DEFAULT_SCOPED1(category, argname, argval, ...) \
|
|
TRACE_SCOPED1(category, __PRETTY_FUNCTION__, argname, argval, ##__VA_ARGS__)
|
|
|
|
#define TRACE_SCOPED2(category, name, argname, argval, argname_two, \
|
|
argval_two, ...) \
|
|
openscreen::internal::DoNothingForTracing( \
|
|
category, name, argname, argval, argname_two, argval_two, ##__VA_ARGS__)
|
|
#define TRACE_DEFAULT_SCOPED2(category, argname, argval, argname_two, \
|
|
argval_two, ...) \
|
|
TRACE_SCOPED2(category, __PRETTY_FUNCTION__, argname, argval, argname_two, \
|
|
argval_two, ##__VA_ARGS__)
|
|
|
|
#define TRACE_ASYNC_START(category, name, ...) \
|
|
openscreen::internal::DoNothingForTracing(category, name, ##__VA_ARGS__)
|
|
#define TRACE_ASYNC_END(category, id, result) \
|
|
openscreen::internal::DoNothingForTracing(category, id, result)
|
|
|
|
#define TRACE_FLOW_BEGIN(category, name, flow_id) \
|
|
openscreen::internal::DoNothingForTracing(category, name, flow_id)
|
|
#define TRACE_FLOW_STEP(category, name, flow_id) \
|
|
openscreen::internal::DoNothingForTracing(category, name, flow_id)
|
|
#define TRACE_FLOW_END(category, name, flow_id) \
|
|
openscreen::internal::DoNothingForTracing(category, name, flow_id)
|
|
|
|
#define TRACE_FLOW_BEGIN_WITH_TIME(category, name, flow_id, timestamp) \
|
|
openscreen::internal::DoNothingForTracing(category, name, flow_id, timestamp)
|
|
|
|
#define TRACE_FLOW_STEP_WITH_TIME(category, name, flow_id, timestamp) \
|
|
openscreen::internal::DoNothingForTracing(category, name, flow_id, timestamp)
|
|
|
|
#define TRACE_FLOW_END_WITH_TIME(category, name, flow_id, timestamp) \
|
|
openscreen::internal::DoNothingForTracing(category, name, flow_id, timestamp)
|
|
|
|
#define TRACE_FLOW_DEFAULT_BEGIN(category, flow_id) \
|
|
openscreen::internal::DoNothingForTracing(category, flow_id)
|
|
#define TRACE_FLOW_DEFAULT_STEP(category, flow_id) \
|
|
openscreen::internal::DoNothingForTracing(category, flow_id)
|
|
#define TRACE_FLOW_DEFAULT_END(category, flow_id) \
|
|
openscreen::internal::DoNothingForTracing(category, flow_id)
|
|
|
|
#endif // defined(ENABLE_TRACE_LOGGING)
|
|
|
|
#endif // UTIL_TRACE_LOGGING_H_
|