#ifndef _GI_GST_GST_EXTRA_DEF_HPP_ #define _GI_GST_GST_EXTRA_DEF_HPP_ #include #include #include #include namespace gi { namespace repository { namespace Gst { // connection helpers namespace internal { class PadProbeConnection : public detail::connection_impl { public: // using connection_impl::connection_impl; PadProbeConnection(gulong id, detail::connection_status s, Pad pad) : connection_impl(id, s), pad_(pad) {} void disconnect() { pad_.remove_probe(id_); } private: Pad pad_; }; template struct Range { T min; T max; explicit constexpr Range(T _min = std::numeric_limits::min(), T _max = std::numeric_limits::max()) : min(_min), max(_max) {} constexpr bool operator==(const Range &other) { return min == other.min && max == other.max; } constexpr bool operator!=(const Range &other) { return !(*this == other); } }; template struct StepRange : public Range { T step; explicit constexpr StepRange(T _min, T _max, T _step = 1) : Range(_min, _max), step(_step) {} constexpr bool operator==(const StepRange &other) { return Range::operator==(*this, other) && step == other.step; } constexpr bool operator!=(const StepRange &other) { return !(*this == other); } }; class ios_flags_saver { std::ostream &out; std::ios old; public: ios_flags_saver(std::ostream &_out) : out(_out), old(nullptr) { old.copyfmt(out); } ~ios_flags_saver() { out.copyfmt(old); } }; template inline std::ostream & operator<<(std::ostream &out, const Range &v) { return out << "Range(" << v.min << ", " << v.max << ')'; } template inline std::ostream & operator<<(std::ostream &out, const StepRange &v) { return out << "Range(" << v.min << ", " << v.max << ", " << v.step << ')'; } } // namespace internal using PadProbeConnection = detail::connection; using PadProbeScopedConnection = detail::scoped_connection; // make Rank a more convenient numeric GI_ENUM_NUMERIC(Rank) // iterator helper template class IteratorAdapter { Iterator it_; public: IteratorAdapter(Iterator _it) : it_(std::move(_it)) {} class iterator { private: Iterator_Ref it_; GObject::Value val_; T value_{}; IteratorResult result_{IteratorResult::DONE_}; public: // traits typedef T difference_type; typedef T value_type; typedef T *pointer; typedef T &reference; typedef std::input_iterator_tag category; iterator() {} iterator(Iterator_Ref _it) : it_(_it) { ++(*this); } // only prefix required iterator &operator++() { if (it_) { val_.unset(); result_ = it_.next(val_); value_ = val_.get_value(); // clear iterator when done to ensure end() comparison if (result_ == IteratorResult::DONE_) it_ = nullptr; } return *this; } T &operator*() { if (result_ != IteratorResult::OK_ && result_ != IteratorResult::DONE_) detail::try_throw(std::runtime_error( "GstIterator error result " + std::to_string((int)result_))); return value_; } void operator->() { return &value_; } bool operator==(const iterator &other) const { return other.it_ == it_ && other.result_ == result_; } bool operator!=(const iterator &other) const { return !(*this == other); } }; iterator begin() const { return iterator(it_); } iterator end() const { return iterator(); } }; // GstValue helpers struct Bitmask { guint64 mask; constexpr Bitmask(guint64 _mask = 0) : mask(_mask) {} constexpr operator guint64() const { return mask; } }; inline std::ostream & operator<<(std::ostream &out, const Bitmask &v) { internal::ios_flags_saver s(out); return out << std::showbase << std::hex << "Bitmask(" << (guint64)v << ')'; } struct FlagSet { guint flags; guint mask; explicit constexpr FlagSet(guint _flags, guint _mask) : flags(_flags), mask(_mask) {} constexpr bool operator==(const FlagSet &other) { return flags == other.flags && mask == other.mask; } constexpr bool operator!=(const FlagSet &other) { return !(*this == other); } }; inline std::ostream & operator<<(std::ostream &out, const FlagSet &v) { internal::ios_flags_saver s(out); return out << std::showbase << std::hex << "FlagSet(" << v.flags << " , " << v.mask << ')'; } struct Fraction { gint num; gint den; constexpr Fraction(gint _num = 0, gint _den = 1) : num(_num), den(_den) {} constexpr bool operator==(const Fraction &other) { return num == other.num && den == other.den; } constexpr bool operator!=(const Fraction &other) { return !(*this == other); } Fraction operator*(const Fraction &other) { Fraction result; if (gst_util_fraction_multiply( num, den, other.num, other.den, &result.num, &result.den)) { return result; } else { detail::try_throw(std::overflow_error("multiplying Fraction")); } } Fraction operator/(const Fraction &other) { return *this * Fraction(other.den, other.num); } Fraction &operator*=(const Fraction &other) { *this = *this * other; return *this; } Fraction &operator/=(const Fraction &other) { *this = *this / other; return *this; } Fraction operator+(const Fraction &other) { Fraction result; if (gst_util_fraction_add( num, den, other.num, other.den, &result.num, &result.den)) { return result; } else { detail::try_throw(std::overflow_error("adding Fraction")); } } Fraction operator-(const Fraction &other) { return *this * Fraction(-other.num, other.den); } Fraction &operator+=(const Fraction &other) { *this = *this + other; return *this; } Fraction &operator-=(const Fraction &other) { *this = *this - other; return *this; } }; inline std::ostream & operator<<(std::ostream &out, const Fraction &v) { return out << "Fraction(" << v.num << ", " << v.den << ')'; } using DoubleRange = internal::Range; using IntRange = internal::StepRange; using Int64Range = internal::StepRange; using FractionRange = internal::Range; } // namespace Gst template<> struct declare_gtype_of { static GType get_type() { return GST_TYPE_BITMASK; } static Gst::Bitmask get_value(const GValue *val) { return Gst::Bitmask(gst_value_get_bitmask(val)); } static void set_value(GValue *val, const Gst::Bitmask &r) { gst_value_set_bitmask(val, r); } }; template<> struct declare_gtype_of { static GType get_type() { return GST_TYPE_FLAG_SET; } static Gst::FlagSet get_value(const GValue *val) { return Gst::FlagSet( gst_value_get_flagset_flags(val), gst_value_get_flagset_mask(val)); } static void set_value(GValue *val, const Gst::FlagSet &r) { gst_value_set_flagset(val, r.flags, r.mask); } }; template<> struct declare_gtype_of { static GType get_type() { return GST_TYPE_FRACTION; } static Gst::Fraction get_value(const GValue *val) { return Gst::Fraction(gst_value_get_fraction_numerator(val), gst_value_get_fraction_denominator(val)); } static void set_value(GValue *val, const Gst::Fraction &f) { gst_value_set_fraction(val, f.num, f.den); } }; template<> struct declare_gtype_of { static GType get_type() { return GST_TYPE_FRACTION_RANGE; } static Gst::FractionRange get_value(const GValue *val) { const GValue *vmin = gst_value_get_fraction_range_min(val); const GValue *vmax = gst_value_get_fraction_range_max(val); return Gst::FractionRange( Gst::Fraction(gst_value_get_fraction_numerator(vmin), gst_value_get_fraction_denominator(vmin)), Gst::Fraction(gst_value_get_fraction_numerator(vmax), gst_value_get_fraction_denominator(vmax))); } static void set_value(GValue *val, const Gst::FractionRange &f) { gst_value_set_fraction_range_full( val, f.min.num, f.min.den, f.max.num, f.max.den); } }; template<> struct declare_gtype_of { static GType get_type() { return GST_TYPE_DOUBLE_RANGE; } static Gst::DoubleRange get_value(const GValue *val) { return Gst::DoubleRange(gst_value_get_double_range_min(val), gst_value_get_double_range_max(val)); } static void set_value(GValue *val, const Gst::DoubleRange &r) { gst_value_set_double_range(val, r.min, r.max); } }; template<> struct declare_gtype_of { static GType get_type() { return GST_TYPE_INT_RANGE; } static Gst::IntRange get_value(const GValue *val) { return Gst::IntRange(gst_value_get_int_range_min(val), gst_value_get_int_range_max(val), gst_value_get_int_range_step(val)); } static void set_value(GValue *val, const Gst::IntRange &r) { gst_value_set_int_range_step(val, r.min, r.max, r.step); } }; template<> struct declare_gtype_of { static GType get_type() { return GST_TYPE_INT64_RANGE; } static Gst::Int64Range get_value(const GValue *val) { return Gst::Int64Range(gst_value_get_int64_range_min(val), gst_value_get_int64_range_max(val), gst_value_get_int64_range_step(val)); } static void set_value(GValue *val, const Gst::Int64Range &r) { gst_value_set_int64_range_step(val, r.min, r.max, r.step); } }; } // namespace repository inline repository::Gst::PadProbeConnection make_connection(gulong id, const repository::GLib::SourceFunc &func, repository::Gst::Pad pad) { return repository::Gst::PadProbeConnection(id, func.connection(), pad); } } // namespace gi #endif