• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

kunitoki / popsicle / 8195308623

07 Mar 2024 09:55PM UTC coverage: 20.126% (+1.3%) from 18.801%
8195308623

Pull #24

github

kunitoki
More pixel tests
Pull Request #24: More tests coverage

283 of 398 new or added lines in 6 files covered. (71.11%)

45 existing lines in 5 files now uncovered.

23757 of 118043 relevant lines covered (20.13%)

3617.26 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

54.8
/modules/juce_python/bindings/ScriptJuceCoreBindings.h
1
/**
2
 * juce_python - Python bindings for the JUCE framework.
3
 *
4
 * This file is part of the popsicle project.
5
 *
6
 * Copyright (c) 2024 - kunitoki <kunitoki@gmail.com>
7
 *
8
 * popsicle is an open source library subject to commercial or open-source licensing.
9
 *
10
 * By using popsicle, you agree to the terms of the popsicle License Agreement, which can
11
 * be found at https://raw.githubusercontent.com/kunitoki/popsicle/master/LICENSE
12
 *
13
 * Or: You may also use this code under the terms of the GPL v3 (see www.gnu.org/licenses).
14
 *
15
 * POPSICLE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER EXPRESSED
16
 * OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE DISCLAIMED.
17
 */
18

19
#pragma once
20

21
#include <juce_core/juce_core.h>
22

23
#define JUCE_PYTHON_INCLUDE_PYBIND11_OPERATORS
24
#define JUCE_PYTHON_INCLUDE_PYBIND11_STL
25
#include "../utilities/PyBind11Includes.h"
26

27
#include "../utilities/ClassDemangling.h"
28
#include "../utilities/PythonInterop.h"
29
#include "../utilities/PythonTypes.h"
30

31
#include <cstddef>
32
#include <functional>
33
#include <memory>
34
#include <typeinfo>
35
#include <type_traits>
36
#include <utility>
37

38
namespace PYBIND11_NAMESPACE {
39
namespace detail {
40

41
// =================================================================================================
42

43
template <>
44
struct type_caster<juce::StringRef>
45
{
46
public:
47
    PYBIND11_TYPE_CASTER (juce::StringRef, const_name (PYBIND11_STRING_NAME));
498✔
48

49
    bool load (handle src, bool convert);
50

51
    static handle cast (const juce::StringRef& src, return_value_policy policy, handle parent);
52

53
private:
54
    bool load_raw (handle src);
55
};
56

57
// =================================================================================================
58

59
template <>
60
struct type_caster<juce::String>
61
{
62
public:
63
    PYBIND11_TYPE_CASTER (juce::String, const_name (PYBIND11_STRING_NAME));
752✔
64

65
    bool load (handle src, bool convert);
66

67
    static handle cast (const juce::String& src, return_value_policy policy, handle parent);
68

69
private:
70
    bool load_raw (handle src);
71
};
72

73
// =================================================================================================
74

75
template <>
76
struct type_caster<juce::Identifier> : public type_caster_base<juce::Identifier>
77
{
78
    using base_type = type_caster_base<juce::Identifier>;
79

80
public:
81
    PYBIND11_TYPE_CASTER (juce::Identifier, const_name ("popsicle.Identifier"));
12,380✔
82

83
    bool load (handle src, bool convert);
84

85
    static handle cast (const juce::Identifier& src, return_value_policy policy, handle parent);
86

87
private:
88
    bool load_raw (handle src);
89
};
90

91
// =================================================================================================
92

93
template <>
94
struct type_caster<juce::var>
95
{
96
public:
97
    PYBIND11_TYPE_CASTER (juce::var, const_name ("popsicle.var"));
10,195✔
98

99
    bool load (handle src, bool convert);
100

101
    static handle cast (const juce::var& src, return_value_policy policy, handle parent);
102
};
103

104
} // namespace detail
105
} // namespace PYBIND11_NAMESPACE
106

107
namespace popsicle::Bindings {
108

109
// =================================================================================================
110

111
void registerJuceCoreBindings (pybind11::module_& m);
112

113
// ============================================================================================
114

115
template <class T, class = void>
116
struct isEqualityComparable : std::false_type {};
117

118
template <class T>
119
struct isEqualityComparable<T, std::void_t<decltype(std::declval<T>() == std::declval<T>())>> : std::true_type {};
120

121
// =================================================================================================
122

123
template <class T>
124
struct PyArrayElementComparator
125
{
126
    PyArrayElementComparator() = default;
127

128
    int compareElements (const T& first, const T& second)
17✔
129
    {
130
        pybind11::gil_scoped_acquire gil;
34✔
131

132
        if (pybind11::function override_ = pybind11::get_override (static_cast<PyArrayElementComparator*> (this), "compareElements"); override_)
17✔
133
        {
134
            auto result = override_ (first, second);
34✔
135

136
            return result.template cast<int>();
34✔
137
        }
138

NEW
139
        pybind11::pybind11_fail("Tried to call pure virtual function \"Array.Comparator.compareElements\"");
×
140
    }
141
};
142

143
// ============================================================================================
144

145
template <template <class, class, int> class Class, class... Types>
146
void registerArray (pybind11::module_& m)
2✔
147
{
148
    using namespace juce;
149

150
    namespace py = pybind11;
151
    using namespace py::literals;
152

153
    auto type = py::hasattr (m, "Array") ? m.attr ("Array").cast<py::dict>() : py::dict{};
2✔
154

155
    ([&]
19✔
156
    {
157
        using ValueType = underlying_type_t<Types>;
158
        using T = Class<ValueType, DummyCriticalSection, 0>;
159

160
        const auto className = popsicle::Helpers::pythonizeCompoundClassName ("Array", typeid (ValueType).name());
12✔
161

162
        py::class_<T> class_ (m, className.toRawUTF8());
12✔
163
        py::class_<PyArrayElementComparator<ValueType>> classComparator_ (class_, "Comparator");
6✔
164

165
        classComparator_
166
            .def (py::init<>())
6✔
167
            .def ("compareElements", &PyArrayElementComparator<ValueType>::compareElements)
6✔
168
        ;
169

170
        class_
171
            .def (py::init<>())
6✔
172
            .def (py::init<const ValueType&>())
6✔
173
            .def (py::init<const T&>())
6✔
174
            .def (py::init ([](py::list list)
9✔
175
            {
176
                auto result = T();
6✔
177
                result.ensureStorageAllocated (static_cast<int> (list.size()));
3✔
178

179
                for (auto item : list)
12✔
180
                {
NEW
181
                    py::detail::make_caster<ValueType> conv;
×
182

183
                    if (! conv.load (item, true))
9✔
NEW
184
                        py::pybind11_fail("Invalid value type used to feed \"Array\" constructor");
×
185

186
                    result.add (py::detail::cast_op<ValueType&&> (std::move (conv)));
9✔
187
                }
188

189
                return result;
6✔
190
            }))
191
            .def (py::init ([](py::args args)
127✔
192
            {
193
                auto result = T();
242✔
194
                result.ensureStorageAllocated (static_cast<int> (args.size()));
121✔
195

196
                for (auto item : args)
524✔
197
                {
NEW
198
                    py::detail::make_caster<ValueType> conv;
×
199

200
                    if (! conv.load (item, true))
403✔
NEW
201
                        py::pybind11_fail("Invalid value type used to feed \"Array\" constructor");
×
202

203
                    result.add (py::detail::cast_op<ValueType&&> (std::move (conv)));
403✔
204
                }
205

206
                return result;
242✔
207
            }))
208
            .def ("clear", &T::clear)
6✔
209
            .def ("clearQuick", &T::clearQuick)
6✔
210
            .def ("fill", &T::fill)
6✔
211
            .def ("size", &T::size)
6✔
212
            .def ("isEmpty", &T::isEmpty)
6✔
213
            .def ("__getitem__", &T::operator[])
6✔
214
            .def ("__setitem__", &T::set)
6✔
215
            .def ("getUnchecked", &T::getUnchecked)
6✔
216
            .def ("getReference", py::overload_cast<int> (&T::getReference), py::return_value_policy::reference)
6✔
217
            .def ("getFirst", &T::getFirst)
6✔
218
            .def ("getLast", &T::getLast)
6✔
219
        //.def ("getRawDataPointer", &T::getRawDataPointer)
220
            .def("__iter__", [](T& self)
11✔
221
            {
222
                return py::make_iterator (self.begin(), self.end());
5✔
223
            }, py::keep_alive<0, 1>())
×
224
            .def ("add", [](T& self, const ValueType& arg)
12✔
225
            {
226
                self.add (arg);
3✔
227
            })
228
            .def ("add", [](T& self, py::list list)
6✔
229
            {
NEW
230
                self.ensureStorageAllocated (self.size() + static_cast<int> (list.size()));
×
231

NEW
232
                for (auto item : list)
×
233
                {
NEW
234
                    py::detail::make_caster<ValueType> conv;
×
235

NEW
236
                    if (! conv.load (item, true))
×
NEW
237
                        py::pybind11_fail("Invalid value type used to feed \"Array.add\"");
×
238

NEW
239
                    self.add (py::detail::cast_op<ValueType&&> (std::move (conv)));
×
240
                }
241
            })
242
            .def ("add", [](T& self, py::args args)
6✔
243
            {
NEW
244
                self.ensureStorageAllocated (self.size() + static_cast<int> (args.size()));
×
245

UNCOV
246
                for (auto item : args)
×
247
                {
248
                    py::detail::make_caster<ValueType> conv;
×
249

250
                    if (! conv.load (item, true))
×
NEW
251
                        py::pybind11_fail("Invalid value type used to feed \"Array.add\"");
×
252

253
                    self.add (py::detail::cast_op<ValueType&&> (std::move (conv)));
×
254
                }
255
            })
256
            .def ("insert", &T::insert)
6✔
257
            .def ("insertMultiple", &T::insertMultiple)
6✔
258
        //.def ("insertArray", &T::insertArray)
259
            .def ("set", &T::set)
6✔
260
            .def ("setUnchecked", &T::setUnchecked)
6✔
261
        //.def ("addArray", &T::addArray)
262
            .def ("addArray", [](T& self, py::list list)
6✔
263
            {
264
                for (auto item : list)
×
265
                {
266
                    py::detail::make_caster<ValueType> conv;
×
267

268
                    if (! conv.load (item, true))
×
NEW
269
                        py::pybind11_fail("Invalid value type used to feed \"Array.addArray\"");
×
270

271
                    self.add (py::detail::cast_op<ValueType&&> (std::move (conv)));
×
272
                }
273
            })
274
            .def ("swapWith", &T::template swapWith<T>)
6✔
275
            .def ("addArray", py::overload_cast<const T&> (&T::template addArray<T>))
6✔
276
            .def ("resize", &T::resize)
6✔
277
            .def ("remove", py::overload_cast<int> (&T::remove))
6✔
278
            .def ("removeAndReturn", &T::removeAndReturn)
6✔
279
            .def ("remove", py::overload_cast<const ValueType*> (&T::remove))
6✔
280
            .def ("removeIf", [](T& self, py::function predicate)
9✔
281
            {
282
                return self.removeIf ([&predicate](const ValueType& value)
21✔
283
                {
284
                    return predicate (py::cast (value)).template cast<bool>();
15✔
285
                });
6✔
286
            })
287
            .def ("removeRange", &T::removeRange)
6✔
288
            .def ("removeLast", &T::removeLast)
6✔
289
            .def ("swap", &T::swap)
6✔
290
            .def ("move", &T::move, "currentIndex"_a, "newIndex"_a)
6✔
291
            .def ("minimiseStorageOverheads", &T::minimiseStorageOverheads)
6✔
292
            .def ("ensureStorageAllocated", &T::ensureStorageAllocated, "minNumElements"_a)
6✔
293
            .def ("getLock", &T::getLock)
6✔
294
            .def ("__len__", &T::size)
6✔
295
            .def ("__repr__", [className](T& self)
6✔
296
            {
297
                String result;
×
298
                result
299
                    << "<" << Helpers::pythonizeModuleClassName (PythonModuleName, typeid (T).name(), 1)
×
300
                    << " object at " << String::formatted ("%p", std::addressof (self)) << ">";
×
301
                return result;
×
302
            })
303
        ;
304

305
        if constexpr (! std::is_same_v<ValueType, Types>)
306
            class_.def (py::init ([](Types value) { return T (static_cast<ValueType> (value)); }));
307

308
        if constexpr (isEqualityComparable<ValueType>::value)
309
        {
310
            class_
311
                .def (py::self == py::self)
5✔
312
                .def (py::self != py::self)
5✔
313
                .def ("indexOf", &T::indexOf)
5✔
314
                .def ("contains", &T::contains)
5✔
315
                .def ("addIfNotAlreadyThere", &T::addIfNotAlreadyThere)
5✔
316
                .def ("addUsingDefaultSort", &T::addUsingDefaultSort)
5✔
317
                .def ("addSorted", [](T& self, PyArrayElementComparator<ValueType>& comparator, ValueType value)
23✔
318
                {
319
                    self.addSorted (comparator, value);
9✔
320
                })
321
                .def ("indexOfSorted", [](const T& self, PyArrayElementComparator<ValueType>& comparator, ValueType value)
5✔
322
                {
NEW
323
                    return self.indexOfSorted (comparator, value);
×
324
                })
325
                .def ("removeValuesIn", &T::template removeValuesIn<T>)
5✔
326
                .def ("removeValuesNotIn", &T::template removeValuesNotIn<T>)
5✔
327
                .def ("removeFirstMatchingValue", &T::removeFirstMatchingValue)
5✔
328
                .def ("removeAllInstancesOf", &T::removeAllInstancesOf)
5✔
329
                .def ("sort", [](T& self) { self.sort(); })
8✔
330
                .def ("sort", [](T& self, PyArrayElementComparator<ValueType>& comparator, int retainOrderOfEquivalentItems)
5✔
331
                {
NEW
332
                    self.sort (comparator, retainOrderOfEquivalentItems);
×
333
                }, "comparator"_a, "retainOrderOfEquivalentItems"_a = false)
10✔
334
            ;
335
        }
336

337
        type[py::type::of (py::cast (Types{}))] = class_;
6✔
338

339
        return true;
12✔
340
    }() && ...);
2✔
341

342
    m.attr ("Array") = type;
2✔
343
}
2✔
344

345
// =================================================================================================
346

347
struct PyThreadID
348
{
349
    explicit PyThreadID (juce::Thread::ThreadID value) noexcept
3✔
350
        : value (value)
3✔
351
    {
352
    }
3✔
353

354
    operator juce::Thread::ThreadID() const noexcept
×
355
    {
356
        return value;
×
357
    }
358

359
    bool operator==(const PyThreadID& other) const noexcept
1✔
360
    {
361
        return value == other.value;
1✔
362
    }
363

364
    bool operator!=(const PyThreadID& other) const noexcept
1✔
365
    {
366
        return value != other.value;
1✔
367
    }
368

369
private:
370
    juce::Thread::ThreadID value;
371
};
372

373
// =================================================================================================
374

375
template <class Base = juce::InputStream>
376
struct PyInputStream : Base
377
{
378
private:
379
#if JUCE_WINDOWS && ! JUCE_MINGW
380
    using ssize_t = juce::pointer_sized_int;
381
#endif
382

383
public:
384
    using Base::Base;
385

386
    juce::int64 getTotalLength() override
5✔
387
    {
388
        PYBIND11_OVERRIDE_PURE (juce::int64, Base, getTotalLength);
5✔
389
    }
390

391
    bool isExhausted() override
1✔
392
    {
393
        PYBIND11_OVERRIDE_PURE (bool, Base, isExhausted);
1✔
394
    }
395

396
    int read (void* destBuffer, int maxBytesToRead) override
44✔
397
    {
398
        pybind11::gil_scoped_acquire gil;
88✔
399

400
        if (pybind11::function override_ = pybind11::get_override (static_cast<Base*> (this), "read"); override_)
44✔
401
        {
402
            auto result = override_ (pybind11::memoryview::from_memory (destBuffer, static_cast<ssize_t> (maxBytesToRead)));
88✔
403

404
            return result.cast<int>();
88✔
405
        }
406

NEW
407
        pybind11::pybind11_fail("Tried to call pure virtual function \"InputStream.read\"");
×
408
    }
409

410
    char readByte() override
29✔
411
    {
412
        PYBIND11_OVERRIDE (char, Base, readByte);
58✔
413
    }
414

415
    short readShort() override
1✔
416
    {
417
        PYBIND11_OVERRIDE (short, Base, readShort);
2✔
418
    }
419

420
    short readShortBigEndian() override
1✔
421
    {
422
        PYBIND11_OVERRIDE (short, Base, readShortBigEndian);
2✔
423
    }
424

425
    int readInt() override
2✔
426
    {
427
        PYBIND11_OVERRIDE (int, Base, readInt);
4✔
428
    }
429

430
    int readIntBigEndian() override
2✔
431
    {
432
        PYBIND11_OVERRIDE (int, Base, readIntBigEndian);
4✔
433
    }
434

435
    juce::int64 readInt64() override
2✔
436
    {
437
        PYBIND11_OVERRIDE (juce::int64, Base, readInt64);
4✔
438
    }
439

440
    juce::int64 readInt64BigEndian() override
2✔
441
    {
442
        PYBIND11_OVERRIDE (juce::int64, Base, readInt64BigEndian);
4✔
443
    }
444

445
    float readFloat() override
1✔
446
    {
447
        PYBIND11_OVERRIDE (float, Base, readFloat);
2✔
448
    }
449

450
    float readFloatBigEndian() override
1✔
451
    {
452
        PYBIND11_OVERRIDE (float, Base, readFloatBigEndian);
2✔
453
    }
454

455
    double readDouble() override
1✔
456
    {
457
        PYBIND11_OVERRIDE (double, Base, readDouble);
2✔
458
    }
459

460
    double readDoubleBigEndian() override
1✔
461
    {
462
        PYBIND11_OVERRIDE (double, Base, readDoubleBigEndian);
2✔
463
    }
464

465
    int readCompressedInt() override
×
466
    {
NEW
467
        PYBIND11_OVERRIDE (int, Base, readCompressedInt);
×
468
    }
469

470
    juce::String readNextLine() override
2✔
471
    {
472
        PYBIND11_OVERRIDE (juce::String, Base, readNextLine);
4✔
473
    }
474

475
    juce::String readString() override
2✔
476
    {
477
        PYBIND11_OVERRIDE (juce::String, Base, readString);
4✔
478
    }
479

480
    juce::String readEntireStreamAsString() override
1✔
481
    {
482
        PYBIND11_OVERRIDE (juce::String, Base, readEntireStreamAsString);
2✔
483
    }
484

485
    size_t readIntoMemoryBlock (juce::MemoryBlock& destBlock, ssize_t maxNumBytesToRead) override
4✔
486
    {
487
        PYBIND11_OVERRIDE (size_t, Base, readIntoMemoryBlock, destBlock, maxNumBytesToRead);
8✔
488
    }
489

490
    juce::int64 getPosition() override
5✔
491
    {
492
        PYBIND11_OVERRIDE_PURE (juce::int64, Base, getPosition);
5✔
493
    }
494

495
    bool setPosition (juce::int64 newPosition) override
×
496
    {
NEW
497
        PYBIND11_OVERRIDE_PURE (bool, Base, setPosition, newPosition);
×
498
    }
499

500
    void skipNextBytes (juce::int64 newPosition) override
1✔
501
    {
502
        PYBIND11_OVERRIDE (void, Base, skipNextBytes, newPosition);
2✔
503
    }
504
};
505

506
// =================================================================================================
507

508
template <class Base = juce::InputSource>
509
struct PyInputSource : Base
510
{
511
    using Base::Base;
512

513
    juce::InputStream* createInputStream() override
×
514
    {
NEW
515
        PYBIND11_OVERRIDE_PURE (juce::InputStream*, Base, createInputStream);
×
516
    }
517

518
    juce::InputStream* createInputStreamFor (const juce::String& relatedItemPath) override
×
519
    {
NEW
520
        PYBIND11_OVERRIDE_PURE (juce::InputStream*, Base, createInputStreamFor, relatedItemPath);
×
521
    }
522

523
    juce::int64 hashCode() const override
×
524
    {
NEW
525
        PYBIND11_OVERRIDE_PURE (juce::int64, Base, hashCode);
×
526
    }
527
};
528

529
// =================================================================================================
530

531
template <class Base = juce::OutputStream>
532
struct PyOutputStream : Base
533
{
534
private:
535
#if JUCE_WINDOWS && ! JUCE_MINGW
536
    using ssize_t = juce::pointer_sized_int;
537
#endif
538

539
public:
540
    using Base::Base;
541

542
    void flush() override
×
543
    {
NEW
544
        PYBIND11_OVERRIDE_PURE (void, Base, flush);
×
545
    }
546

547
    bool setPosition (juce::int64 newPosition) override
×
548
    {
NEW
549
        PYBIND11_OVERRIDE_PURE (bool, Base, setPosition, newPosition);
×
550
    }
551

552
    juce::int64 getPosition() override
×
553
    {
NEW
554
        PYBIND11_OVERRIDE_PURE (juce::int64, Base, getPosition);
×
555
    }
556

557
    bool write (const void* dataToWrite, size_t numberOfBytes) override
×
558
    {
NEW
559
        pybind11::gil_scoped_acquire gil;
×
560

NEW
561
        if (pybind11::function override_ = pybind11::get_override (static_cast<Base*> (this), "write"); override_)
×
562
        {
NEW
563
            auto result = override_ (pybind11::memoryview::from_memory (dataToWrite, static_cast<ssize_t> (numberOfBytes)));
×
564

NEW
565
            return result.cast<bool>();
×
566
        }
567

NEW
568
        pybind11::pybind11_fail("Tried to call pure virtual function \"OutputStream.write\"");
×
569
    }
570

571
    bool writeByte (char value) override
×
572
    {
NEW
573
        PYBIND11_OVERRIDE (bool, Base, writeByte, value);
×
574
    }
575

576
    bool writeBool (bool value) override
×
577
    {
NEW
578
        PYBIND11_OVERRIDE (bool, Base, writeBool, value);
×
579
    }
580

581
    bool writeShort (short value) override
×
582
    {
NEW
583
        PYBIND11_OVERRIDE (bool, Base, writeShort, value);
×
584
    }
585

586
    bool writeShortBigEndian (short value) override
×
587
    {
NEW
588
        PYBIND11_OVERRIDE (bool, Base, writeShortBigEndian, value);
×
589
    }
590

UNCOV
591
    bool writeInt (int value) override
×
592
    {
NEW
593
        PYBIND11_OVERRIDE (bool, Base, writeInt, value);
×
594
    }
595

596
    bool writeIntBigEndian (int value) override
×
597
    {
NEW
598
        PYBIND11_OVERRIDE (bool, Base, writeIntBigEndian, value);
×
599
    }
600

601
    bool writeInt64 (juce::int64 value) override
×
602
    {
NEW
603
        PYBIND11_OVERRIDE (bool, Base, writeInt64, value);
×
604
    }
605

606
    bool writeInt64BigEndian (juce::int64 value) override
×
607
    {
NEW
608
        PYBIND11_OVERRIDE (bool, Base, writeInt64BigEndian, value);
×
609
    }
610

611
    bool writeFloat (float value) override
×
612
    {
NEW
613
        PYBIND11_OVERRIDE (bool, Base, writeFloat, value);
×
614
    }
615

616
    bool writeFloatBigEndian (float value) override
×
617
    {
NEW
618
        PYBIND11_OVERRIDE (bool, Base, writeFloatBigEndian, value);
×
619
    }
620

621
    bool writeDouble (double value) override
×
622
    {
NEW
623
        PYBIND11_OVERRIDE (bool, Base, writeDouble, value);
×
624
    }
625

626
    bool writeDoubleBigEndian (double value) override
×
627
    {
NEW
628
        PYBIND11_OVERRIDE (bool, Base, writeDoubleBigEndian, value);
×
629
    }
630

631
    bool writeRepeatedByte (juce::uint8 byte, size_t numTimesToRepeat) override
×
632
    {
NEW
633
        PYBIND11_OVERRIDE (bool, Base, writeRepeatedByte, byte, numTimesToRepeat);
×
634
    }
635

636
    bool writeCompressedInt (int value) override
×
637
    {
NEW
638
        PYBIND11_OVERRIDE (bool, Base, writeCompressedInt, value);
×
639
    }
640

641
    bool writeString (const juce::String& text) override
×
642
    {
NEW
643
        PYBIND11_OVERRIDE (bool, Base, writeString, text);
×
644
    }
645

646
    bool writeText (const juce::String& text, bool asUTF16, bool writeUTF16ByteOrderMark, const char* lineEndings) override
×
647
    {
NEW
648
        PYBIND11_OVERRIDE (bool, Base, writeText, text, asUTF16, writeUTF16ByteOrderMark, lineEndings);
×
649
    }
650

651
    juce::int64 writeFromInputStream (juce::InputStream& source, juce::int64 maxNumBytesToWrite) override
×
652
    {
NEW
653
        PYBIND11_OVERRIDE (juce::int64, Base, writeFromInputStream, source, maxNumBytesToWrite);
×
654
    }
655
};
656

657
// =================================================================================================
658

659
template <class Base = juce::FileFilter>
660
struct PyFileFilter : Base
661
{
662
    using Base::Base;
663

664
    bool isFileSuitable (const juce::File& file) const override
×
665
    {
NEW
666
        PYBIND11_OVERRIDE_PURE (bool, Base, isFileSuitable, file);
×
667
    }
668

669
    bool isDirectorySuitable (const juce::File& file) const override
×
670
    {
NEW
671
        PYBIND11_OVERRIDE_PURE (bool, Base, isDirectorySuitable, file);
×
672
    }
673
};
674

675
// =================================================================================================
676

677
struct PyURLDownloadTaskListener : public juce::URL::DownloadTaskListener
678
{
679
    void finished (juce::URL::DownloadTask* task, bool success) override
×
680
    {
681
        PYBIND11_OVERRIDE_PURE(void, juce::URL::DownloadTaskListener, finished, task, success);
×
682
    }
683

684
    void progress (juce::URL::DownloadTask* task, juce::int64 bytesDownloaded, juce::int64 totalLength) override
×
685
    {
686
        PYBIND11_OVERRIDE_PURE(void, juce::URL::DownloadTaskListener, progress, task, bytesDownloaded, totalLength);
×
687
    }
688
};
689

690
// =================================================================================================
691

692
struct PyXmlElementComparator
693
{
694
    PyXmlElementComparator() = default;
695

696
    int compareElements (const juce::XmlElement* first, const juce::XmlElement* second)
3✔
697
    {
698
        pybind11::gil_scoped_acquire gil;
6✔
699

700
        if (pybind11::function override_ = pybind11::get_override (static_cast<PyXmlElementComparator*> (this), "compareElements"); override_)
3✔
701
        {
702
            auto result = override_ (first, second);
6✔
703

704
            return result.cast<int>();
6✔
705
        }
706

NEW
707
        pybind11::pybind11_fail("Tried to call pure virtual function \"XmlElement.Comparator.compareElements\"");
×
708
    }
709
};
710

711
struct PyXmlElementCallableComparator
712
{
713
    explicit PyXmlElementCallableComparator(pybind11::function f)
1✔
714
        : fn (std::move (f))
1✔
715
    {
716
    }
1✔
717

718
    int compareElements (const juce::XmlElement* first, const juce::XmlElement* second)
3✔
719
    {
720
        pybind11::gil_scoped_acquire gil;
6✔
721

722
        if (fn)
3✔
723
        {
724
            auto result = fn (first, second);
6✔
725

726
            return result.cast<int>();
6✔
727
        }
728

NEW
729
        pybind11::pybind11_fail("Tried to call function \"XmlElement.Comparator.compareElements\" without a callable");
×
730
    }
731

732
private:
733
    pybind11::function fn;
734
};
735

736
// =================================================================================================
737

738
struct PyHighResolutionTimer : public juce::HighResolutionTimer
739
{
740
    void hiResTimerCallback() override
×
741
    {
742
        PYBIND11_OVERRIDE_PURE(void, juce::HighResolutionTimer, hiResTimerCallback);
×
743
    }
744
};
745

746
// =================================================================================================
747

748
template <class T>
749
struct PyGenericScopedLock
750
{
751
    PyGenericScopedLock (const T& mutex)
1✔
752
        : mutex (mutex)
1✔
753
    {
754
    }
1✔
755

756
    PyGenericScopedLock (const PyGenericScopedLock&) = delete;
757
    PyGenericScopedLock (PyGenericScopedLock&&) = default;
758

759
    ~PyGenericScopedLock()
1✔
760
    {
761
        exit();
1✔
762
    }
1✔
763

764
    void enter()
1✔
765
    {
766
        mutex.enter();
1✔
767
    }
1✔
768

769
    void exit()
2✔
770
    {
771
        mutex.exit();
2✔
772
    }
2✔
773

774
private:
775
    const T& mutex;
776
};
777

778
template <class T>
779
struct PyGenericScopedUnlock
780
{
NEW
781
    PyGenericScopedUnlock (const T& mutex)
×
NEW
782
        : mutex (mutex)
×
783
    {
NEW
784
    }
×
785

786
    PyGenericScopedUnlock (const PyGenericScopedUnlock&) = delete;
787
    PyGenericScopedUnlock (PyGenericScopedUnlock&&) = default;
788

NEW
789
    ~PyGenericScopedUnlock()
×
790
    {
NEW
791
        exit();
×
NEW
792
    }
×
793

NEW
794
    void enter()
×
795
    {
NEW
796
        mutex.exit();
×
NEW
797
    }
×
798

NEW
799
    void exit()
×
800
    {
NEW
801
        mutex.enter();
×
NEW
802
    }
×
803

804
private:
805
    const T& mutex;
806
};
807

808
template <class T>
809
struct PyGenericScopedTryLock
810
{
NEW
811
    PyGenericScopedTryLock (const T& mutex, bool acquireLockOnInitialisation = true)
×
812
        : mutex (mutex)
NEW
813
        , lockWasSuccessful (acquireLockOnInitialisation && mutex.tryEnter())
×
NEW
814
        , acquireLockOnInitialisation (acquireLockOnInitialisation)
×
815
    {
NEW
816
    }
×
817

818
    PyGenericScopedTryLock (const PyGenericScopedTryLock&) = delete;
819
    PyGenericScopedTryLock (PyGenericScopedTryLock&&) = default;
820

NEW
821
    ~PyGenericScopedTryLock()
×
822
    {
NEW
823
        exit();
×
NEW
824
    }
×
825

826
    bool isLocked() const noexcept
827
    {
828
        return lockWasSuccessful;
829
    }
830

NEW
831
    bool retryLock() const
×
832
    {
NEW
833
        lockWasSuccessful = mutex.tryEnter();
×
NEW
834
        return lockWasSuccessful;
×
835
    }
836

NEW
837
    void enter()
×
838
    {
NEW
839
        if (! acquireLockOnInitialisation)
×
NEW
840
            retryLock();
×
NEW
841
    }
×
842

NEW
843
    void exit()
×
844
    {
NEW
845
        if (lockWasSuccessful)
×
NEW
846
            mutex.exit();
×
NEW
847
    }
×
848

849
private:
850
    const T& mutex;
851
    mutable bool lockWasSuccessful;
852
    bool acquireLockOnInitialisation;
853
};
854

855
// =================================================================================================
856

857
template <class Base = juce::Thread>
858
struct PyThread : Base
859
{
860
    using Base::Base;
861

862
    void run() override
2✔
863
    {
864
#if JUCE_PYTHON_THREAD_CATCH_EXCEPTION
865
        try
866
        {
867
#endif
868
            PYBIND11_OVERRIDE_PURE (void, Base, run);
2✔
869

870
#if JUCE_PYTHON_THREAD_CATCH_EXCEPTION
871
        }
872
        catch (const pybind11::error_already_set& e)
×
873
        {
874
            pybind11::gil_scoped_acquire acquire;
×
NEW
875
            pybind11::print ("The \"Thread.run\" method mustn't throw any exceptions!");
×
876
            pybind11::module_::import ("traceback").attr ("print_exception") (e.type(), e.value(), e.trace());
×
877
        }
878
        catch (const std::exception& e)
×
879
        {
880
            pybind11::gil_scoped_acquire acquire;
×
NEW
881
            auto exception = juce::String ("The \"Thread.run\" method mustn't throw any exceptions: ") + e.what();
×
882
            pybind11::print (exception);
×
883
        }
884
        catch (...)
×
885
        {
886
            pybind11::gil_scoped_acquire acquire;
×
NEW
887
            auto exception = juce::String ("The \"Thread.run\" method mustn't throw any exceptions: Unhandled python exeption");
×
888
            pybind11::print (exception);
×
889
        }
890
#endif
891
    }
892
};
893

894
// =================================================================================================
895

896
struct PyThreadListener : juce::Thread::Listener
897
{
898
    using juce::Thread::Listener::Listener;
899

900
    void exitSignalSent() override
1✔
901
    {
902
        PYBIND11_OVERRIDE_PURE (void, juce::Thread::Listener, exitSignalSent);
1✔
903
    }
904
};
905

906
// =================================================================================================
907

908
struct PyThreadPoolJob : juce::ThreadPoolJob
909
{
910
    using juce::ThreadPoolJob::ThreadPoolJob;
911

912
    JobStatus runJob() override
6✔
913
    {
914
        PYBIND11_OVERRIDE_PURE (JobStatus, juce::ThreadPoolJob, runJob);
6✔
915
    }
916
};
917

918
// =================================================================================================
919

920
struct PyThreadPoolJobSelector : juce::ThreadPool::JobSelector
921
{
922
    using juce::ThreadPool::JobSelector::JobSelector;
923

924
    bool isJobSuitable (juce::ThreadPoolJob* job) override
×
925
    {
926
        PYBIND11_OVERRIDE_PURE (bool, juce::ThreadPool::JobSelector, isJobSuitable, job);
×
927
    }
928
};
929

930
// =================================================================================================
931

932
struct PyTimeSliceClient : juce::TimeSliceClient
933
{
934
    using juce::TimeSliceClient::TimeSliceClient;
935

936
    int useTimeSlice() override
×
937
    {
938
        PYBIND11_OVERRIDE_PURE (int, juce::TimeSliceClient, useTimeSlice);
×
939
    }
940
};
941

942
} // namespace popsicle::Bindings
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc