Implement Cast Streaming mirroring, DLNA casting, daemon+GUI, and breadd integration
Some checks failed
dev release / build (push) Failing after 12s
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.
This commit is contained in:
parent
887c29002f
commit
8c745d18e0
283 changed files with 36788 additions and 0 deletions
217
breadcast-caststream-sys/vendor/openscreen/util/weak_ptr.h
vendored
Normal file
217
breadcast-caststream-sys/vendor/openscreen/util/weak_ptr.h
vendored
Normal file
|
|
@ -0,0 +1,217 @@
|
|||
// 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_WEAK_PTR_H_
|
||||
#define UTIL_WEAK_PTR_H_
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "util/osp_logging.h"
|
||||
|
||||
namespace openscreen {
|
||||
|
||||
// Weak pointers are pointers to an object that do not affect its lifetime,
|
||||
// and which may be invalidated (i.e. reset to nullptr) by the object, or its
|
||||
// owner, at any time; most commonly when the object is about to be deleted.
|
||||
//
|
||||
// Weak pointers are useful when an object needs to be accessed safely by one
|
||||
// or more objects other than its owner, and those callers can cope with the
|
||||
// object vanishing and e.g. tasks posted to it being silently dropped.
|
||||
// Reference-counting such an object would complicate the ownership graph and
|
||||
// make it harder to reason about the object's lifetime.
|
||||
//
|
||||
// EXAMPLE:
|
||||
//
|
||||
// class Controller {
|
||||
// public:
|
||||
// void SpawnWorker() { new Worker(weak_factory_.GetWeakPtr()); }
|
||||
// void WorkComplete(const Result& result) { ... }
|
||||
// private:
|
||||
// // Member variables should appear before the WeakPtrFactory, to ensure
|
||||
// // that any WeakPtrs to Controller are invalidated before its members
|
||||
// // variable's destructors are executed, rendering them invalid.
|
||||
// WeakPtrFactory<Controller> weak_factory_{this};
|
||||
// };
|
||||
//
|
||||
// class Worker {
|
||||
// public:
|
||||
// explicit Worker(WeakPtr<Controller> controller)
|
||||
// : controller_(std::move(controller)) {}
|
||||
// private:
|
||||
// void DidCompleteAsynchronousProcessing(const Result& result) {
|
||||
// if (controller_)
|
||||
// controller_->WorkComplete(result);
|
||||
// delete this;
|
||||
// }
|
||||
// const WeakPtr<Controller> controller_;
|
||||
// };
|
||||
//
|
||||
// With this implementation a caller may use SpawnWorker() to dispatch multiple
|
||||
// Workers and subsequently delete the Controller, without waiting for all
|
||||
// Workers to have completed.
|
||||
//
|
||||
// ------------------------- IMPORTANT: Thread-safety -------------------------
|
||||
//
|
||||
// Generally, Open Screen code is meant to be single-threaded. For the few
|
||||
// exceptional cases, the following is relevant:
|
||||
//
|
||||
// WeakPtrs may be created from WeakPtrFactory, and also duplicated/moved on any
|
||||
// thread/sequence. However, they may only be dereferenced on the same
|
||||
// thread/sequence that will ultimately execute the WeakPtrFactory destructor or
|
||||
// call InvalidateWeakPtrs(). Otherwise, use-during-free or use-after-free is
|
||||
// possible.
|
||||
//
|
||||
// openscreen::WeakPtr and WeakPtrFactory are similar, but not identical, to
|
||||
// Chromium's base::WeakPtrFactory. Open Screen WeakPtrs may be safely created
|
||||
// from WeakPtrFactory on any thread/sequence, since they are backed by the
|
||||
// thread-safe bookkeeping of std::shared_ptr<>.
|
||||
|
||||
template <typename T>
|
||||
class WeakPtrFactory;
|
||||
|
||||
template <typename T>
|
||||
class WeakPtr {
|
||||
public:
|
||||
WeakPtr() = default;
|
||||
~WeakPtr() = default;
|
||||
|
||||
// Copy/Move constructors and assignment operators.
|
||||
WeakPtr(const WeakPtr& other) : impl_(other.impl_) {}
|
||||
|
||||
WeakPtr(WeakPtr&& other) noexcept : impl_(std::move(other.impl_)) {}
|
||||
|
||||
WeakPtr& operator=(const WeakPtr& other) {
|
||||
impl_ = other.impl_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
WeakPtr& operator=(WeakPtr&& other) noexcept {
|
||||
impl_ = std::move(other.impl_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Create/Assign from nullptr.
|
||||
WeakPtr(std::nullptr_t) {} // NOLINT
|
||||
|
||||
WeakPtr& operator=(std::nullptr_t) {
|
||||
impl_.reset();
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Copy/Move constructors and assignment operators with upcast conversion.
|
||||
template <typename U>
|
||||
WeakPtr(const WeakPtr<U>& other) : impl_(other.as_std_weak_ptr()) {}
|
||||
|
||||
template <typename U>
|
||||
WeakPtr(WeakPtr<U>&& other) noexcept
|
||||
: impl_(std::move(other).as_std_weak_ptr()) {}
|
||||
|
||||
template <typename U>
|
||||
WeakPtr& operator=(const WeakPtr<U>& other) {
|
||||
impl_ = other.as_std_weak_ptr();
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
WeakPtr& operator=(WeakPtr<U>&& other) noexcept {
|
||||
impl_ = std::move(other).as_std_weak_ptr();
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Accessors.
|
||||
T* get() const { return impl_.lock().get(); }
|
||||
|
||||
T& operator*() const {
|
||||
T* const pointer = get();
|
||||
OSP_CHECK(pointer);
|
||||
return *pointer;
|
||||
}
|
||||
|
||||
T* operator->() const {
|
||||
T* const pointer = get();
|
||||
OSP_CHECK(pointer);
|
||||
return pointer;
|
||||
}
|
||||
|
||||
// Allow conditionals to test validity, e.g. if (weak_ptr) {...}
|
||||
explicit operator bool() const { return get() != nullptr; }
|
||||
|
||||
// Conversion to std::weak_ptr<T>. It is unsafe to convert in the other
|
||||
// direction. See comments for private constructors, below.
|
||||
const std::weak_ptr<T>& as_std_weak_ptr() const& { return impl_; }
|
||||
std::weak_ptr<T> as_std_weak_ptr() && { return std::move(impl_); }
|
||||
|
||||
private:
|
||||
friend class WeakPtrFactory<T>;
|
||||
|
||||
// Called by WeakPtrFactory<T> and the WeakPtr<T> upcast conversion
|
||||
// constructors and assigners. These are purposely not being exposed publicly
|
||||
// because that would allow a WeakPtr<T> to be valid/invalid by a different
|
||||
// ownership/threading model than the intended one (see top-level comments).
|
||||
template <typename U>
|
||||
explicit WeakPtr(const std::weak_ptr<U>& other) : impl_(other) {}
|
||||
|
||||
template <typename U>
|
||||
explicit WeakPtr(std::weak_ptr<U>&& other) noexcept
|
||||
: impl_(std::move(other)) {}
|
||||
|
||||
std::weak_ptr<T> impl_;
|
||||
};
|
||||
|
||||
// Allow callers to compare WeakPtrs against nullptr to test validity.
|
||||
template <typename T>
|
||||
bool operator!=(const WeakPtr<T>& weak_ptr, std::nullptr_t) {
|
||||
return weak_ptr.get() != nullptr;
|
||||
}
|
||||
template <typename T>
|
||||
bool operator!=(std::nullptr_t, const WeakPtr<T>& weak_ptr) {
|
||||
return weak_ptr.get() != nullptr;
|
||||
}
|
||||
template <typename T>
|
||||
bool operator==(const WeakPtr<T>& weak_ptr, std::nullptr_t) {
|
||||
return weak_ptr.get() == nullptr;
|
||||
}
|
||||
template <typename T>
|
||||
bool operator==(std::nullptr_t, const WeakPtr<T>& weak_ptr) {
|
||||
return weak_ptr == nullptr;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
class WeakPtrFactory {
|
||||
public:
|
||||
explicit WeakPtrFactory(T* instance) { Reset(instance); }
|
||||
WeakPtrFactory(WeakPtrFactory&& other) noexcept = default;
|
||||
WeakPtrFactory& operator=(WeakPtrFactory&& other) noexcept = default;
|
||||
|
||||
// Thread-safe: WeakPtrs may be created on any thread/seuence. They may also
|
||||
// be copied and moved on any thread/sequence. However, they MUST only be
|
||||
// dereferenced on the same thread/sequence that calls the destructor or
|
||||
// InvalidateWeakPtrs().
|
||||
WeakPtr<T> GetWeakPtr() const {
|
||||
return WeakPtr<T>(std::weak_ptr<T>(bookkeeper_));
|
||||
}
|
||||
|
||||
// Destruction and Invalidation: These must be called on the same
|
||||
// thread/sequence that dereferences any WeakPtrs to avoid use-after-free
|
||||
// bugs.
|
||||
~WeakPtrFactory() = default;
|
||||
void InvalidateWeakPtrs() { Reset(bookkeeper_.get()); }
|
||||
|
||||
private:
|
||||
WeakPtrFactory(const WeakPtrFactory& other) = delete;
|
||||
WeakPtrFactory& operator=(const WeakPtrFactory& other) = delete;
|
||||
|
||||
void Reset(T* instance) {
|
||||
// T is owned externally to WeakPtrFactory. Thus, provide a no-op Deleter.
|
||||
bookkeeper_ = {instance, [](T*) {}};
|
||||
}
|
||||
|
||||
// Manages the std::weak_ptr's referring to T. Does not own T.
|
||||
std::shared_ptr<T> bookkeeper_;
|
||||
};
|
||||
|
||||
} // namespace openscreen
|
||||
|
||||
#endif // UTIL_WEAK_PTR_H_
|
||||
Loading…
Add table
Add a link
Reference in a new issue