From 1c8a67333eb7e9a9d286b1595fd85f3d65a805b0 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Sat, 21 Nov 2020 15:15:30 -0500 Subject: [PATCH 01/18] Fraction: Update Python __repr__ --- bindings/python/openshot.i | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/python/openshot.i b/bindings/python/openshot.i index b2c62c74..8284d1d0 100644 --- a/bindings/python/openshot.i +++ b/bindings/python/openshot.i @@ -148,7 +148,7 @@ } std::string __repr__() { std::ostringstream result; - result << $self->num << ":" << $self->den; + result << "Fraction(" << $self->num << ", " << $self->den << ")"; return result.str(); } } From 762f0e716db849bc030d724bc1075c04abcb1dc7 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Sat, 21 Nov 2020 15:17:18 -0500 Subject: [PATCH 02/18] Fraction: New ctors accept STL container args --- bindings/python/openshot.i | 2 ++ src/Fraction.cpp | 18 ++++++++++++++---- src/Fraction.h | 15 ++++++++++++++- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/bindings/python/openshot.i b/bindings/python/openshot.i index 8284d1d0..55063596 100644 --- a/bindings/python/openshot.i +++ b/bindings/python/openshot.i @@ -127,6 +127,8 @@ /* Instantiate the required template specializations */ %template() std::map; +%template() std::pair; +%template() std::vector; /* Make openshot.Fraction more Pythonic */ %extend openshot::Fraction { diff --git a/src/Fraction.cpp b/src/Fraction.cpp index 869ef35f..86671e11 100644 --- a/src/Fraction.cpp +++ b/src/Fraction.cpp @@ -29,13 +29,23 @@ */ #include "Fraction.h" +#include using namespace openshot; -// Constructor -Fraction::Fraction() : - num(1), den(1) { -} +// Delegating constructors +Fraction::Fraction() : Fraction::Fraction(1, 1) {}; + +Fraction::Fraction(std::pair pair) + : Fraction::Fraction(pair.first, pair.second) {}; + +Fraction::Fraction(std::map mapping) + : Fraction::Fraction(mapping["num"], mapping["den"]) {}; + +Fraction::Fraction(std::vector vector) + : Fraction::Fraction(vector[0], vector[1]) {}; + +// Full constructor Fraction::Fraction(int num, int den) : num(num), den(den) { } diff --git a/src/Fraction.h b/src/Fraction.h index 88c16fbc..ffb0640b 100644 --- a/src/Fraction.h +++ b/src/Fraction.h @@ -31,7 +31,10 @@ #ifndef OPENSHOT_FRACTION_H #define OPENSHOT_FRACTION_H -#include +#include // for std::string +#include // for std::pair +#include // for std::map +#include // for std::vector namespace openshot { @@ -49,9 +52,19 @@ namespace openshot { /// Default Constructor Fraction(); + /// Constructor with numerator and denominator Fraction(int num, int den); + /// Constructor that accepts a (num, den) pair + Fraction(std::pair pair); + + /// Constructor that takes a vector of length 2 (containing {num, den}) + Fraction(std::vector vector); + + /// Constructor that takes a key-value mapping (keys: 'num'. 'den') + Fraction(std::map mapping); + /// Calculate the greatest common denominator int GreatestCommonDenominator(); From 8f26846d057d11a045c1511b0bea9fae5a5a6762 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Sat, 21 Nov 2020 15:17:44 -0500 Subject: [PATCH 03/18] tests/Fraction: Unit tests for new ctors --- tests/Fraction_Tests.cpp | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/tests/Fraction_Tests.cpp b/tests/Fraction_Tests.cpp index b061ba48..4002a6e3 100644 --- a/tests/Fraction_Tests.cpp +++ b/tests/Fraction_Tests.cpp @@ -36,7 +36,10 @@ using namespace std; using namespace openshot; -TEST(Fraction_Default_Constructor) +SUITE(Fraction) +{ + +TEST(Constructors) { // Create a default fraction (should be 1/1) Fraction f1; @@ -57,7 +60,31 @@ TEST(Fraction_Default_Constructor) CHECK_CLOSE(1.0f, f1.ToDouble(), 0.00001); } -TEST(Fraction_640_480) +TEST(Alt_Constructors) +{ + // Use the delegating constructor for std::pair + std::pair args{24, 1}; + Fraction f1(args); + CHECK_EQUAL(24, f1.num); + CHECK_EQUAL(1, f1.den); + CHECK_CLOSE(24.0f, f1.ToFloat(), 0.00001); + + // Use the delegating constructor for std::vector + std::vector v{30000, 1001}; + Fraction f2(v); + CHECK_CLOSE(30000.0/1001.0, f2.ToFloat(), 0.00001); + + // Use the delegating constructor for std::map + std::map dict; + dict.insert({"num", 24000}); + dict.insert({"den", 1001}); + Fraction f3(dict); + CHECK_EQUAL(1001, f3.den); + CHECK_EQUAL(24000, f3.num); + CHECK_CLOSE(1001.0/24000.0, f3.Reciprocal().ToFloat(), 0.00001); +} + +TEST(WxH_640_480) { // Create fraction Fraction f1(640, 480); @@ -78,7 +105,7 @@ TEST(Fraction_640_480) CHECK_CLOSE(1.33333f, f1.ToDouble(), 0.00001); } -TEST(Fraction_1280_720) +TEST(WxH_1280_720) { // Create fraction Fraction f1(1280, 720); @@ -99,7 +126,7 @@ TEST(Fraction_1280_720) CHECK_CLOSE(1.77777f, f1.ToDouble(), 0.00001); } -TEST(Fraction_reciprocal) +TEST(Reciprocal) { // Create fraction Fraction f1(1280, 720); @@ -125,3 +152,5 @@ TEST(Fraction_reciprocal) CHECK_CLOSE(1.77777f, f1.ToFloat(), 0.00001); CHECK_CLOSE(1.77777f, f1.ToDouble(), 0.00001); } + +} // SUITE From fe391e9240b6d70c5170f4d97697a6b504887b66 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Sat, 21 Nov 2020 15:19:08 -0500 Subject: [PATCH 04/18] various: Tidy up some includes --- src/Clip.h | 1 - src/Coordinate.cpp | 2 +- src/Coordinate.h | 2 - src/ImageWriter.h | 8 +-- src/effects/Caption.cpp | 6 ++ src/effects/Caption.h | 151 ++++++++++++++++++++-------------------- 6 files changed, 86 insertions(+), 84 deletions(-) diff --git a/src/Clip.h b/src/Clip.h index 70a09f6f..e01d92e3 100644 --- a/src/Clip.h +++ b/src/Clip.h @@ -41,7 +41,6 @@ #include "EffectBase.h" #include "Effects.h" #include "EffectInfo.h" -#include "Fraction.h" #include "Frame.h" #include "KeyFrame.h" #include "ReaderBase.h" diff --git a/src/Coordinate.cpp b/src/Coordinate.cpp index 0d4f577a..c382607b 100644 --- a/src/Coordinate.cpp +++ b/src/Coordinate.cpp @@ -29,8 +29,8 @@ */ #include "Coordinate.h" +#include "Exceptions.h" -using namespace std; using namespace openshot; // Default constructor for a coordinate, which defaults the X and Y to zero (0,0) diff --git a/src/Coordinate.h b/src/Coordinate.h index a4b9599d..70764a14 100644 --- a/src/Coordinate.h +++ b/src/Coordinate.h @@ -32,8 +32,6 @@ #define OPENSHOT_COORDINATE_H #include -#include "Exceptions.h" -#include "Fraction.h" #include "Json.h" namespace openshot { diff --git a/src/ImageWriter.h b/src/ImageWriter.h index e483cb10..798d67d6 100644 --- a/src/ImageWriter.h +++ b/src/ImageWriter.h @@ -43,13 +43,11 @@ #include "ReaderBase.h" #include "WriterBase.h" -#include -#include -#include -#include -#include +#include +#include #include "CacheMemory.h" #include "Exceptions.h" +#include "Fraction.h" #include "OpenMPUtilities.h" #include "MagickUtilities.h" diff --git a/src/effects/Caption.cpp b/src/effects/Caption.cpp index b9ce2249..053c27de 100644 --- a/src/effects/Caption.cpp +++ b/src/effects/Caption.cpp @@ -32,6 +32,12 @@ #include "../Clip.h" #include "../Timeline.h" +#include +#include +#include +#include +#include + using namespace openshot; /// Blank constructor, useful when using Json to load the effect properties diff --git a/src/effects/Caption.h b/src/effects/Caption.h index 749b2c17..b53ec9f9 100644 --- a/src/effects/Caption.h +++ b/src/effects/Caption.h @@ -31,13 +31,14 @@ #ifndef OPENSHOT_CAPTION_EFFECT_H #define OPENSHOT_CAPTION_EFFECT_H -#include -#include #include -#include +#include +#include +#include +#include +#include #include "../Color.h" #include "../EffectBase.h" -#include "../Fraction.h" #include "../Json.h" #include "../KeyFrame.h" @@ -46,87 +47,87 @@ namespace openshot { - /** - * @brief This class adds captions/text over a video, based on timestamps. You can also animate some limited - * aspects, such as words appearing/disappearing. - * - * Adding captions can be an easy way to generate text overlays through-out a long clip. - */ - class Caption : public EffectBase - { - private: - std::vector matchedCaptions; ///< RegEx to capture cues and text - std::string caption_text; ///< Text of caption - QFontMetrics* metrics; ///< Font metrics object - QFont* font; ///< QFont object - bool is_dirty; +/** + * @brief This class adds captions/text over a video, based on timestamps. You can also animate some limited + * aspects, such as words appearing/disappearing. + * + * Adding captions can be an easy way to generate text overlays through-out a long clip. + */ +class Caption : public EffectBase +{ +private: + std::vector matchedCaptions; ///< RegEx to capture cues and text + std::string caption_text; ///< Text of caption + QFontMetrics* metrics; ///< Font metrics object + QFont* font; ///< QFont object + bool is_dirty; - /// Init effect settings - void init_effect_details(); + /// Init effect settings + void init_effect_details(); - /// Process regex capture - void process_regex(); + /// Process regex capture + void process_regex(); - public: - Color color; ///< Color of caption text - Color stroke; ///< Color of text border / stroke - Color background; ///< Color of caption area background - Keyframe background_alpha; ///< Background color alpha - Keyframe background_corner; ///< Background cornder radius - Keyframe background_padding; ///< Background padding - Keyframe stroke_width; ///< Width of text border / stroke - Keyframe font_size; ///< Font size in points - Keyframe font_alpha; ///< Font color alpha - Keyframe left; ///< Size of left bar - Keyframe top; ///< Size of top bar - Keyframe right; ///< Size of right bar - Keyframe fade_in; ///< Fade in per caption (# of seconds) - Keyframe fade_out; ///< Fade in per caption (# of seconds) - std::string font_name; ///< Font string +public: + Color color; ///< Color of caption text + Color stroke; ///< Color of text border / stroke + Color background; ///< Color of caption area background + Keyframe background_alpha; ///< Background color alpha + Keyframe background_corner; ///< Background cornder radius + Keyframe background_padding; ///< Background padding + Keyframe stroke_width; ///< Width of text border / stroke + Keyframe font_size; ///< Font size in points + Keyframe font_alpha; ///< Font color alpha + Keyframe left; ///< Size of left bar + Keyframe top; ///< Size of top bar + Keyframe right; ///< Size of right bar + Keyframe fade_in; ///< Fade in per caption (# of seconds) + Keyframe fade_out; ///< Fade in per caption (# of seconds) + std::string font_name; ///< Font string - /// Blank constructor, useful when using Json to load the effect properties - Caption(); + /// Blank constructor, useful when using Json to load the effect properties + Caption(); - /// Default constructor, which takes a string of VTT/Subrip formatted caption data, and displays them over time. - /// - /// @param captions A string with VTT/Subrip format text captions - Caption(std::string captions); + /// Default constructor, which takes a string of VTT/Subrip formatted caption data, and displays them over time. + /// + /// @param captions A string with VTT/Subrip format text captions + Caption(std::string captions); - /// @brief This method is required for all derived classes of ClipBase, and returns a - /// new openshot::Frame object. All Clip keyframes and effects are resolved into - /// pixels. - /// - /// @returns A new openshot::Frame object - /// @param frame_number The frame number (starting at 1) of the clip or effect on the timeline. - std::shared_ptr GetFrame(int64_t frame_number) override { return GetFrame(std::shared_ptr (new Frame()), frame_number); } + /// @brief This method is required for all derived classes of ClipBase, and returns a + /// new openshot::Frame object. All Clip keyframes and effects are resolved into + /// pixels. + /// + /// @returns A new openshot::Frame object + /// @param frame_number The frame number (starting at 1) of the clip or effect on the timeline. + std::shared_ptr GetFrame(int64_t frame_number) override { return GetFrame(std::shared_ptr (new Frame()), frame_number); } - /// @brief This method is required for all derived classes of ClipBase, and returns a - /// modified openshot::Frame object - /// - /// The frame object is passed into this method and used as a starting point (pixels and audio). - /// All Clip keyframes and effects are resolved into pixels. - /// - /// @returns The modified openshot::Frame object - /// @param frame The frame object that needs the clip or effect applied to it - /// @param frame_number The frame number (starting at 1) of the clip or effect on the timeline. - std::shared_ptr GetFrame(std::shared_ptr frame, int64_t frame_number) override; + /// @brief This method is required for all derived classes of ClipBase, and returns a + /// modified openshot::Frame object + /// + /// The frame object is passed into this method and used as a starting point (pixels and audio). + /// All Clip keyframes and effects are resolved into pixels. + /// + /// @returns The modified openshot::Frame object + /// @param frame The frame object that needs the clip or effect applied to it + /// @param frame_number The frame number (starting at 1) of the clip or effect on the timeline. + std::shared_ptr GetFrame(std::shared_ptr frame, int64_t frame_number) override; - // Get and Set caption data - std::string CaptionText(); ///< Set the caption string to use (see VTT format) - void CaptionText(std::string new_caption_text); ///< Get the caption string + // Get and Set caption data + std::string CaptionText(); ///< Set the caption string to use (see VTT format) + void CaptionText(std::string new_caption_text); ///< Get the caption string - /// Get and Set JSON methods - std::string Json() const override; ///< Generate JSON string of this object - void SetJson(const std::string value) override; ///< Load JSON string into this object - Json::Value JsonValue() const override; ///< Generate Json::Value for this object - void SetJsonValue(const Json::Value root) override; ///< Load Json::Value into this object + /// Get and Set JSON methods + std::string Json() const override; ///< Generate JSON string of this object + void SetJson(const std::string value) override; ///< Load JSON string into this object + Json::Value JsonValue() const override; ///< Generate Json::Value for this object + void SetJsonValue(const Json::Value root) override; ///< Load Json::Value into this object - /// Get all properties for a specific frame (perfect for a UI to display the current state - /// of all properties at any time) - std::string PropertiesJSON(int64_t requested_frame) const override; - }; + /// Get all properties for a specific frame (perfect for a UI to display the current state + /// of all properties at any time) + std::string PropertiesJSON(int64_t requested_frame) const override; +}; -} +} // namespace openshot -#endif +#endif // OPENSHOT_CAPTION_EFFECT_H From 68abf00ec70b49d0ebc83d96c077fda46beca144 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Sat, 21 Nov 2020 16:07:27 -0500 Subject: [PATCH 05/18] tests/Coordinate: Complete coverage --- tests/Coordinate_Tests.cpp | 41 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/tests/Coordinate_Tests.cpp b/tests/Coordinate_Tests.cpp index b57af38f..731850de 100644 --- a/tests/Coordinate_Tests.cpp +++ b/tests/Coordinate_Tests.cpp @@ -36,7 +36,10 @@ using namespace std; using namespace openshot; -TEST(Coordinate_Default_Constructor) +SUITE(Coordinate) +{ + +TEST(Default_Constructor) { // Create an empty coordinate Coordinate c1; @@ -45,7 +48,7 @@ TEST(Coordinate_Default_Constructor) CHECK_CLOSE(0.0f, c1.Y, 0.00001); } -TEST(Coordinate_X_Y_Constructor) +TEST(X_Y_Constructor) { // Create an empty coordinate Coordinate c1(2,8); @@ -53,3 +56,37 @@ TEST(Coordinate_X_Y_Constructor) CHECK_CLOSE(2.0f, c1.X, 0.00001); CHECK_CLOSE(8.0f, c1.Y, 0.00001); } + +TEST(Json) +{ + openshot::Coordinate c(100, 200); + openshot::Coordinate c1; + c1.X = 100; + c1.Y = 200; + // Check that JSON produced is identical + auto j = c.Json(); + auto j1 = c1.Json(); + CHECK_EQUAL(j, j1); + // Check Json::Value representation + auto jv = c.JsonValue(); + auto jv_string = jv.toStyledString(); + CHECK_EQUAL(jv_string, j1); +} + +TEST(SetJson) { + // Construct our input Json representation + const std::string json_input = R"json( + { + "X": 100.0, + "Y": 50.0 + } + )json"; + openshot::Coordinate c; + CHECK_THROW(c.SetJson("}{"), openshot::InvalidJSON); + // Check that values set via SetJson() are correct + c.SetJson(json_input); + CHECK_CLOSE(100.0, c.X, 0.01); + CHECK_CLOSE(50.0, c.Y, 0.01); +} + +} // SUITE From d6892dd3af0e0e58a92347eba21e4fc2209515d3 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Fri, 4 Dec 2020 10:04:56 -0500 Subject: [PATCH 06/18] Coordinate: Add std::pair constructor --- src/Coordinate.cpp | 13 ++++++------- src/Coordinate.h | 4 ++++ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/Coordinate.cpp b/src/Coordinate.cpp index c382607b..f8bc0606 100644 --- a/src/Coordinate.cpp +++ b/src/Coordinate.cpp @@ -33,16 +33,15 @@ using namespace openshot; -// Default constructor for a coordinate, which defaults the X and Y to zero (0,0) -Coordinate::Coordinate() : - X(0), Y(0) { -} +// Default constructor for a coordinate, delegating to the full signature +Coordinate::Coordinate() : Coordinate::Coordinate(0, 0) {}; // Constructor which also allows the user to set the X and Y -Coordinate::Coordinate(double x, double y) : - X(x), Y(y) { -} +Coordinate::Coordinate(double x, double y) : X(x), Y(y) {}; +// Constructor which accepts a std::pair for (X, Y) +Coordinate::Coordinate(const std::pair& co) + : X(co.first), Y(co.second) {}; // Generate JSON string of this object std::string Coordinate::Json() const { diff --git a/src/Coordinate.h b/src/Coordinate.h index 70764a14..2417720b 100644 --- a/src/Coordinate.h +++ b/src/Coordinate.h @@ -63,6 +63,10 @@ namespace openshot { /// @param y The Y coordinate (usually representing the value of the property being animated) Coordinate(double x, double y); + /// @brief Constructor which accepts a std::pair tuple for {X, Y} + /// @param co A std::pair tuple containing (X, Y) + Coordinate(const std::pair& co); + /// Get and Set JSON methods std::string Json() const; ///< Generate JSON string of this object Json::Value JsonValue() const; ///< Generate Json::Value for this object From de9fb417da80a1be697f00c368362cff7a6b21f6 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Fri, 4 Dec 2020 11:27:18 -0500 Subject: [PATCH 07/18] # This is a combination of 2 commits. # This is the 1st commit message: Coordinate: Add std::pair constructor # This is the commit message #2: Fix std::pair member types --- src/Coordinate.cpp | 2 +- src/Coordinate.h | 4 ++-- tests/Coordinate_Tests.cpp | 7 +++++++ 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/Coordinate.cpp b/src/Coordinate.cpp index f8bc0606..6a4abb21 100644 --- a/src/Coordinate.cpp +++ b/src/Coordinate.cpp @@ -40,7 +40,7 @@ Coordinate::Coordinate() : Coordinate::Coordinate(0, 0) {}; Coordinate::Coordinate(double x, double y) : X(x), Y(y) {}; // Constructor which accepts a std::pair for (X, Y) -Coordinate::Coordinate(const std::pair& co) +Coordinate::Coordinate(const std::pair& co) : X(co.first), Y(co.second) {}; // Generate JSON string of this object diff --git a/src/Coordinate.h b/src/Coordinate.h index 2417720b..8a3ce97c 100644 --- a/src/Coordinate.h +++ b/src/Coordinate.h @@ -64,8 +64,8 @@ namespace openshot { Coordinate(double x, double y); /// @brief Constructor which accepts a std::pair tuple for {X, Y} - /// @param co A std::pair tuple containing (X, Y) - Coordinate(const std::pair& co); + /// @param co A std::pair tuple containing (X, Y) + Coordinate(const std::pair& co); /// Get and Set JSON methods std::string Json() const; ///< Generate JSON string of this object diff --git a/tests/Coordinate_Tests.cpp b/tests/Coordinate_Tests.cpp index 731850de..b0f8e6b9 100644 --- a/tests/Coordinate_Tests.cpp +++ b/tests/Coordinate_Tests.cpp @@ -57,6 +57,13 @@ TEST(X_Y_Constructor) CHECK_CLOSE(8.0f, c1.Y, 0.00001); } +TEST(Pair_Constructor) +{ + Coordinate c1(std::pair(12, 10)); + CHECK_CLOSE(12.0f, c1.X, 0.00001); + CHECK_CLOSE(10.0f, c1.Y, 0.00001); +} + TEST(Json) { openshot::Coordinate c(100, 200); From 18844b97003cb8b886ae43bf82c77aa98d0ccad2 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Fri, 4 Dec 2020 10:07:31 -0500 Subject: [PATCH 08/18] Point: Convert to delegating ctors, constref args --- src/Point.cpp | 57 ++++++++++++--------------------------------------- src/Point.h | 6 +++--- 2 files changed, 16 insertions(+), 47 deletions(-) diff --git a/src/Point.cpp b/src/Point.cpp index 4636b437..006d84e4 100644 --- a/src/Point.cpp +++ b/src/Point.cpp @@ -33,58 +33,27 @@ using namespace std; using namespace openshot; -// Default constructor (defaults to 1,0) -Point::Point() : interpolation(BEZIER), handle_type(AUTO) -{ - // set new coorinate - co = Coordinate(1, 0); - - // set handles - Initialize_Handles(); -} +// Default constructor +Point::Point() : Point::Point(Coordinate(1, 0), BEZIER, AUTO) {}; // Constructor which creates a single coordinate at X=1 -Point::Point(float y) : - interpolation(CONSTANT), handle_type(AUTO) { - // set new coorinate - co = Coordinate(1, y); +Point::Point(float y) : Point::Point(Coordinate(1, y), CONSTANT, AUTO) {}; - // set handles - Initialize_Handles(); -} +// Constructor which creates a Bezier curve with point at (x, y) +Point::Point(float x, float y) : Point::Point(Coordinate(x, y), BEZIER, AUTO) {}; -Point::Point(float x, float y) : - interpolation(BEZIER), handle_type(AUTO) { - // set new coorinate - co = Coordinate(x, y); +// Constructor which also creates a Point, setting X,Y, and interpolation. +Point::Point(float x, float y, InterpolationType interpolation) + : Point::Point(Coordinate(x, y), interpolation, AUTO) {}; - // set handles - Initialize_Handles(); -} -// Constructor which also creates a Point and sets the X,Y, and interpolation of the Point. -Point::Point(float x, float y, InterpolationType interpolation) : - handle_type(AUTO), interpolation(interpolation) { - // set new coorinate - co = Coordinate(x, y); +// Direct Coordinate-accepting constructors +Point::Point(const Coordinate& co) : Point::Point(co, BEZIER, AUTO) {}; - // set handles - Initialize_Handles(); -} +Point::Point(const Coordinate& co, InterpolationType interpolation) + : Point::Point(co, interpolation, AUTO) {}; -Point::Point(Coordinate co) : - co(co), interpolation(BEZIER), handle_type(AUTO) { - // set handles - Initialize_Handles(); -} - -Point::Point(Coordinate co, InterpolationType interpolation) : - co(co), interpolation(interpolation), handle_type(AUTO) { - // set handles - Initialize_Handles(); -} - -Point::Point(Coordinate co, InterpolationType interpolation, HandleType handle_type) : +Point::Point(const Coordinate& co, InterpolationType interpolation, HandleType handle_type) : co(co), interpolation(interpolation), handle_type(handle_type) { // set handles Initialize_Handles(); diff --git a/src/Point.h b/src/Point.h index 4941c558..d6ff1d87 100644 --- a/src/Point.h +++ b/src/Point.h @@ -100,13 +100,13 @@ namespace openshot Point(float x, float y, InterpolationType interpolation); /// Constructor which takes a coordinate - Point(Coordinate co); + Point(const Coordinate& co); /// Constructor which takes a coordinate and interpolation mode - Point(Coordinate co, InterpolationType interpolation); + Point(const Coordinate& co, InterpolationType interpolation); /// Constructor which takes a coordinate, interpolation mode, and handle type - Point(Coordinate co, InterpolationType interpolation, HandleType handle_type); + Point(const Coordinate& co, InterpolationType interpolation, HandleType handle_type); /// Set the left and right handles to a percent of the primary coordinate (0 to 1) /// Defaults to a smooth curve (Ease in and out) From cae2e7e910cf3b8e44a0844bb880bcba1fea085c Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Fri, 4 Dec 2020 10:11:58 -0500 Subject: [PATCH 09/18] Point: Unit tests for new constructor --- tests/Point_Tests.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/Point_Tests.cpp b/tests/Point_Tests.cpp index cce78337..852145d5 100644 --- a/tests/Point_Tests.cpp +++ b/tests/Point_Tests.cpp @@ -59,6 +59,16 @@ TEST(XY_Constructor) CHECK_EQUAL(openshot::InterpolationType::BEZIER, p1.interpolation); } +TEST(Pair_Constructor) +{ + // Create a point from a std::pair + std::pair coordinates(22, 5); + openshot::Point p1(coordinates); + + CHECK_EQUAL(22, p1.co.X); + CHECK_EQUAL(5, p1.co.Y); +} + TEST(Constructor_With_Coordinate) { // Create a point with a coordinate From db7bf5f622737476b20c54670a17fabb78fe0c82 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Fri, 4 Dec 2020 10:34:44 -0500 Subject: [PATCH 10/18] Keyframe: Replace AddPoint overload w/default arg --- src/KeyFrame.cpp | 17 ++++++----------- src/KeyFrame.h | 12 ++---------- 2 files changed, 8 insertions(+), 21 deletions(-) diff --git a/src/KeyFrame.cpp b/src/KeyFrame.cpp index b113e632..9ac7a98e 100644 --- a/src/KeyFrame.cpp +++ b/src/KeyFrame.cpp @@ -29,6 +29,11 @@ */ #include "KeyFrame.h" +#include "Exceptions.h" + +#include // For assert() +#include // For std::cout +#include // For std::setprecision #include #include #include @@ -146,17 +151,7 @@ void Keyframe::AddPoint(Point p) { } } -// Add a new point on the key-frame, with some defaults set (BEZIER) -void Keyframe::AddPoint(double x, double y) -{ - // Create a point - Point new_point(x, y, BEZIER); - - // Add the point - AddPoint(new_point); -} - -// Add a new point on the key-frame, with a specific interpolation type +// Add a new point on the key-frame, interpolate is optional (default: BEZIER) void Keyframe::AddPoint(double x, double y, InterpolationType interpolate) { // Create a point diff --git a/src/KeyFrame.h b/src/KeyFrame.h index 6424473a..560bf259 100644 --- a/src/KeyFrame.h +++ b/src/KeyFrame.h @@ -31,14 +31,9 @@ #ifndef OPENSHOT_KEYFRAME_H #define OPENSHOT_KEYFRAME_H -#include -#include #include -#include #include -#include "Exceptions.h" #include "Fraction.h" -#include "Coordinate.h" #include "Point.h" #include "Json.h" @@ -76,11 +71,8 @@ namespace openshot { /// Add a new point on the key-frame. Each point has a primary coordinate, a left handle, and a right handle. void AddPoint(Point p); - /// Add a new point on the key-frame, with some defaults set (BEZIER) - void AddPoint(double x, double y); - - /// Add a new point on the key-frame, with a specific interpolation type - void AddPoint(double x, double y, InterpolationType interpolate); + /// Add a new point on the key-frame, with optional interpolation type + void AddPoint(double x, double y, InterpolationType interpolate=BEZIER); /// Does this keyframe contain a specific point bool Contains(Point p) const; From 0c938622fe409276dcc7c51e44c53ab7eafbce55 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Fri, 4 Dec 2020 11:22:33 -0500 Subject: [PATCH 11/18] Fix Point unit tests --- tests/Point_Tests.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/Point_Tests.cpp b/tests/Point_Tests.cpp index 852145d5..d08f7dbc 100644 --- a/tests/Point_Tests.cpp +++ b/tests/Point_Tests.cpp @@ -62,11 +62,11 @@ TEST(XY_Constructor) TEST(Pair_Constructor) { // Create a point from a std::pair - std::pair coordinates(22, 5); + std::pair coordinates(22, 5); openshot::Point p1(coordinates); - CHECK_EQUAL(22, p1.co.X); - CHECK_EQUAL(5, p1.co.Y); + CHECK_CLOSE(22.0f, p1.co.X, 0.00001); + CHECK_CLOSE(5.0f, p1.co.Y, 0.00001); } TEST(Constructor_With_Coordinate) @@ -75,8 +75,8 @@ TEST(Constructor_With_Coordinate) openshot::Coordinate c1(3,7); openshot::Point p1(c1); - CHECK_EQUAL(3, p1.co.X); - CHECK_EQUAL(7, p1.co.Y); + CHECK_CLOSE(3.0f, p1.co.X, 0.00001); + CHECK_CLOSE(7.0f, p1.co.Y, 0.00001); CHECK_EQUAL(openshot::InterpolationType::BEZIER, p1.interpolation); } From c9112bb08f9873e77256863f576b1abd9c818a86 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Fri, 4 Dec 2020 11:24:34 -0500 Subject: [PATCH 12/18] Keyframe: Add vector ctors --- src/KeyFrame.cpp | 10 ++++++++++ src/KeyFrame.h | 6 ++++++ 2 files changed, 16 insertions(+) diff --git a/src/KeyFrame.cpp b/src/KeyFrame.cpp index 9ac7a98e..2cc1021e 100644 --- a/src/KeyFrame.cpp +++ b/src/KeyFrame.cpp @@ -125,6 +125,16 @@ Keyframe::Keyframe(double value) { AddPoint(Point(value)); } +// Constructor which takes a vector of Points +Keyframe::Keyframe(const std::vector& points) : Points(points) {}; + +// Constructor which takes a vector of std::pair tuples (and adds them all) +Keyframe::Keyframe(const std::vector>& coordinates) { + for (const auto& pair : coordinates) { + AddPoint(Point(pair.first, pair.second)); + } +} + // Add a new point on the key-frame. Each point has a primary coordinate, // a left handle, and a right handle. void Keyframe::AddPoint(Point p) { diff --git a/src/KeyFrame.h b/src/KeyFrame.h index 560bf259..7245a5d1 100644 --- a/src/KeyFrame.h +++ b/src/KeyFrame.h @@ -68,6 +68,12 @@ namespace openshot { /// Constructor which sets the default point & coordinate at X=1 Keyframe(double value); + /// Constructor which adds a supplied vector of Points + Keyframe(const std::vector& points); + + /// Constructor which takes a vector of std::pair tuples + Keyframe(const std::vector>& coordinates); + /// Add a new point on the key-frame. Each point has a primary coordinate, a left handle, and a right handle. void AddPoint(Point p); From d0a625c9f2b92b8a5a9969ded1cc17e53cdf70bd Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Fri, 4 Dec 2020 11:24:01 -0500 Subject: [PATCH 13/18] Keyframe: Unit tests for new constructors --- tests/KeyFrame_Tests.cpp | 73 +++++++++++++++++++++++++++------------- 1 file changed, 50 insertions(+), 23 deletions(-) diff --git a/tests/KeyFrame_Tests.cpp b/tests/KeyFrame_Tests.cpp index 84025165..0cb8be36 100644 --- a/tests/KeyFrame_Tests.cpp +++ b/tests/KeyFrame_Tests.cpp @@ -36,7 +36,9 @@ using namespace std; using namespace openshot; -TEST(Keyframe_GetPoint_With_No_Points) +SUITE(Keyframe) { + +TEST(GetPoint_With_No_Points) { // Create an empty keyframe Keyframe k1; @@ -44,7 +46,7 @@ TEST(Keyframe_GetPoint_With_No_Points) CHECK_THROW(k1.GetPoint(0), OutOfBoundsPoint); } -TEST(Keyframe_GetPoint_With_1_Points) +TEST(GetPoint_With_1_Points) { // Create an empty keyframe Keyframe k1; @@ -58,7 +60,7 @@ TEST(Keyframe_GetPoint_With_1_Points) } -TEST(Keyframe_AddPoint_With_1_Point) +TEST(AddPoint_With_1_Point) { // Create an empty keyframe Keyframe k1; @@ -69,7 +71,7 @@ TEST(Keyframe_AddPoint_With_1_Point) CHECK_THROW(k1.GetPoint(1), OutOfBoundsPoint); } -TEST(Keyframe_AddPoint_With_2_Points) +TEST(AddPoint_With_2_Points) { // Create an empty keyframe Keyframe k1; @@ -82,7 +84,7 @@ TEST(Keyframe_AddPoint_With_2_Points) CHECK_THROW(k1.GetPoint(2), OutOfBoundsPoint); } -TEST(Keyframe_GetValue_For_Bezier_Curve_2_Points) +TEST(GetValue_For_Bezier_Curve_2_Points) { // Create a keyframe curve with 2 points Keyframe kf; @@ -101,7 +103,7 @@ TEST(Keyframe_GetValue_For_Bezier_Curve_2_Points) CHECK_EQUAL(51, kf.GetLength()); } -TEST(Keyframe_GetValue_For_Bezier_Curve_5_Points_40_Percent_Handle) +TEST(GetValue_For_Bezier_Curve_5_Points_40_Percent_Handle) { // Create a keyframe curve with 2 points Keyframe kf; @@ -124,7 +126,7 @@ TEST(Keyframe_GetValue_For_Bezier_Curve_5_Points_40_Percent_Handle) CHECK_EQUAL(201, kf.GetLength()); } -TEST(Keyframe_GetValue_For_Bezier_Curve_5_Points_25_Percent_Handle) +TEST(GetValue_For_Bezier_Curve_5_Points_25_Percent_Handle) { // Create a keyframe curve with 2 points Keyframe kf; @@ -147,7 +149,7 @@ TEST(Keyframe_GetValue_For_Bezier_Curve_5_Points_25_Percent_Handle) CHECK_EQUAL(201, kf.GetLength()); } -TEST(Keyframe_GetValue_For_Linear_Curve_3_Points) +TEST(GetValue_For_Linear_Curve_3_Points) { // Create a keyframe curve with 2 points Keyframe kf; @@ -167,7 +169,7 @@ TEST(Keyframe_GetValue_For_Linear_Curve_3_Points) CHECK_EQUAL(51, kf.GetLength()); } -TEST(Keyframe_GetValue_For_Constant_Curve_3_Points) +TEST(GetValue_For_Constant_Curve_3_Points) { // Create a keyframe curve with 2 points Keyframe kf; @@ -188,7 +190,7 @@ TEST(Keyframe_GetValue_For_Constant_Curve_3_Points) CHECK_EQUAL(51, kf.GetLength()); } -TEST(Keyframe_Check_Direction_and_Repeat_Fractions) +TEST(Check_Direction_and_Repeat_Fractions) { // Create a keyframe curve with 2 points Keyframe kf; @@ -223,7 +225,7 @@ TEST(Keyframe_Check_Direction_and_Repeat_Fractions) } -TEST(Keyframe_Get_Closest_Point) +TEST(Get_Closest_Point) { // Create a keyframe curve with 2 points Keyframe kf; @@ -251,7 +253,7 @@ TEST(Keyframe_Get_Closest_Point) } -TEST(Keyframe_Get_Previous_Point) +TEST(Get_Previous_Point) { // Create a keyframe curve with 2 points Keyframe kf; @@ -270,7 +272,7 @@ TEST(Keyframe_Get_Previous_Point) } -TEST(Keyframe_Get_Max_Point) +TEST(Get_Max_Point) { // Create a keyframe curve Keyframe kf; @@ -295,7 +297,7 @@ TEST(Keyframe_Get_Max_Point) CHECK_EQUAL(2.0, kf.GetMaxPoint().co.Y); } -TEST(Keyframe_Scale_Keyframe) +TEST(Scale_Keyframe) { // Create a keyframe curve with 2 points Keyframe kf; @@ -337,7 +339,7 @@ TEST(Keyframe_Scale_Keyframe) } -TEST(Keyframe_Flip_Keyframe) +TEST(Flip_Keyframe) { // Create a keyframe curve with 2 points Keyframe kf; @@ -371,7 +373,7 @@ TEST(Keyframe_Flip_Keyframe) CHECK_CLOSE(10.0f, kf.GetValue(100), 0.01); } -TEST(Keyframe_Remove_Duplicate_Point) +TEST(Remove_Duplicate_Point) { // Create a keyframe curve with 2 points Keyframe kf; @@ -384,7 +386,7 @@ TEST(Keyframe_Remove_Duplicate_Point) CHECK_CLOSE(2.0, kf.GetPoint(0).co.Y, 0.01); } -TEST(Keyframe_Large_Number_Values) +TEST(Large_Number_Values) { // Large value int64_t const large_value = 30 * 60 * 90; @@ -400,7 +402,7 @@ TEST(Keyframe_Large_Number_Values) CHECK_CLOSE(100.0, kf.GetPoint(1).co.Y, 0.01); } -TEST(Keyframe_Remove_Point) +TEST(Remove_Point) { Keyframe kf; kf.AddPoint(openshot::Point(Coordinate(1, 1), CONSTANT)); @@ -413,7 +415,7 @@ TEST(Keyframe_Remove_Point) CHECK_THROW(kf.RemovePoint(100), OutOfBoundsPoint); } -TEST(Keyframe_Constant_Interpolation_First_Segment) +TEST(Constant_Interpolation_First_Segment) { Keyframe kf; kf.AddPoint(Point(Coordinate(1, 1), CONSTANT)); @@ -426,7 +428,7 @@ TEST(Keyframe_Constant_Interpolation_First_Segment) CHECK_EQUAL(100, kf.GetInt(4)); } -TEST(Keyframe_isIncreasing) +TEST(isIncreasing) { // Which cases need to be tested to keep same behaviour as // previously? @@ -457,7 +459,7 @@ TEST(Keyframe_isIncreasing) CHECK_EQUAL(true, kf.IsIncreasing(2)); } -TEST(Keyframe_GetLength) +TEST(GetLength) { Keyframe f; CHECK_EQUAL(0, f.GetLength()); @@ -475,7 +477,7 @@ TEST(Keyframe_GetLength) CHECK_EQUAL(201, g.GetLength()); } -TEST(Keyframe_Use_Interpolation_of_Segment_End_Point) +TEST(Use_Interpolation_of_Segment_End_Point) { Keyframe f; f.AddPoint(1,0, CONSTANT); @@ -483,7 +485,7 @@ TEST(Keyframe_Use_Interpolation_of_Segment_End_Point) CHECK_CLOSE(75.9, f.GetValue(50), 0.1); } -TEST(Keyframe_Handle_Large_Segment) +TEST(Handle_Large_Segment) { Keyframe kf; kf.AddPoint(1, 0, CONSTANT); @@ -494,3 +496,28 @@ TEST(Keyframe_Handle_Large_Segment) Fraction fr = kf.GetRepeatFraction(250000); CHECK_CLOSE(0.5, (double)fr.num / fr.den, 0.01); } + +TEST(Point_Vector_Constructor) +{ + std::vector points{Point(1, 10), Point(5, 20), Point(10, 30)}; + Keyframe k1(points); + + CHECK_EQUAL(11, k1.GetLength()); + CHECK_CLOSE(30.0f, k1.GetValue(10), 0.0001); +} + +TEST(Pair_Vector_Constructor) +{ + std::vector> coordinates{ + {1, 100}, {10, 500}, {1000, 80000} + }; + Keyframe k1(coordinates); + + CHECK_EQUAL(1001, k1.GetLength()); + + auto p1 = k1.GetPoint(2); + CHECK_CLOSE(80000.0f, p1.co.Y, 0.00001); +} + + +}; // SUITE From b280fbd082565e2dc60d5d69ebb73e7b6e08c543 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Fri, 4 Dec 2020 11:26:20 -0500 Subject: [PATCH 14/18] Bindings: Add template specializations --- bindings/python/openshot.i | 2 ++ bindings/ruby/openshot.i | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/bindings/python/openshot.i b/bindings/python/openshot.i index 09639e87..5dd825a8 100644 --- a/bindings/python/openshot.i +++ b/bindings/python/openshot.i @@ -129,6 +129,8 @@ %template() std::map; %template() std::pair; %template() std::vector; +%template() std::pair; +%template() std::pair; /* Make openshot.Fraction more Pythonic */ %extend openshot::Fraction { diff --git a/bindings/ruby/openshot.i b/bindings/ruby/openshot.i index fe47f1bc..3e64af26 100644 --- a/bindings/ruby/openshot.i +++ b/bindings/ruby/openshot.i @@ -57,6 +57,13 @@ %shared_ptr(juce::AudioSampleBuffer) %shared_ptr(openshot::Frame) +/* Template specializations */ +%template() std::map; +%template() std::pair; +%template() std::vector; +%template() std::pair; +%template() std::pair; + %{ /* Ruby and FFmpeg define competing RSHIFT macros, * so we move Ruby's out of the way for now. We'll From deae5b2de2e25d424196ef0cf2294bd149f100e2 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Fri, 4 Dec 2020 12:06:26 -0500 Subject: [PATCH 15/18] Keyframe: Replace pair vector w/ CoordinateVector --- src/KeyFrame.cpp | 6 +++--- src/KeyFrame.h | 6 ++++-- tests/KeyFrame_Tests.cpp | 6 +++--- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/KeyFrame.cpp b/src/KeyFrame.cpp index 2cc1021e..eaafcb1f 100644 --- a/src/KeyFrame.cpp +++ b/src/KeyFrame.cpp @@ -129,9 +129,9 @@ Keyframe::Keyframe(double value) { Keyframe::Keyframe(const std::vector& points) : Points(points) {}; // Constructor which takes a vector of std::pair tuples (and adds them all) -Keyframe::Keyframe(const std::vector>& coordinates) { - for (const auto& pair : coordinates) { - AddPoint(Point(pair.first, pair.second)); +Keyframe::Keyframe(const std::vector& coordinates) { + for (const auto& co : coordinates) { + AddPoint(Point(co)); } } diff --git a/src/KeyFrame.h b/src/KeyFrame.h index 7245a5d1..82a21204 100644 --- a/src/KeyFrame.h +++ b/src/KeyFrame.h @@ -61,6 +61,8 @@ namespace openshot { std::vector Points; ///< Vector of all Points public: + using CoordinateVector = std::vector; + using PointsVector = std::vector; /// Default constructor for the Keyframe class Keyframe() = default; @@ -69,10 +71,10 @@ namespace openshot { Keyframe(double value); /// Constructor which adds a supplied vector of Points - Keyframe(const std::vector& points); + Keyframe(const PointsVector& points); /// Constructor which takes a vector of std::pair tuples - Keyframe(const std::vector>& coordinates); + Keyframe(const CoordinateVector& coordinates); /// Add a new point on the key-frame. Each point has a primary coordinate, a left handle, and a right handle. void AddPoint(Point p); diff --git a/tests/KeyFrame_Tests.cpp b/tests/KeyFrame_Tests.cpp index 0cb8be36..aaf2a38a 100644 --- a/tests/KeyFrame_Tests.cpp +++ b/tests/KeyFrame_Tests.cpp @@ -506,10 +506,10 @@ TEST(Point_Vector_Constructor) CHECK_CLOSE(30.0f, k1.GetValue(10), 0.0001); } -TEST(Pair_Vector_Constructor) +TEST(Coordinate_Vector_Constructor) { - std::vector> coordinates{ - {1, 100}, {10, 500}, {1000, 80000} + std::vector coordinates{ + Coordinate(1, 100), Coordinate(10, 500), Coordinate(1000, 80000) }; Keyframe k1(coordinates); From 1b82a3c97a611f00b33e66fd22f5fa052c3d4460 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Sat, 2 Jan 2021 18:33:39 -0500 Subject: [PATCH 16/18] Fraction: Restore __string__ for Python The Python code expects __string__() on a Fraction to return a "{num}:{den}" representation, which __repr__() no longer does. --- bindings/python/openshot.i | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/bindings/python/openshot.i b/bindings/python/openshot.i index 5dd825a8..cb0490c7 100644 --- a/bindings/python/openshot.i +++ b/bindings/python/openshot.i @@ -150,7 +150,12 @@ map1.insert({"den", $self->den}); return map1; } - std::string __repr__() { + const std::string __string__() { + std::ostringstream result; + result << $self->num << ":" << $self->den; + return result.str(); + } + const std::string __repr__() { std::ostringstream result; result << "Fraction(" << $self->num << ", " << $self->den << ")"; return result.str(); From 72e09dc033e0abe3e2a59bb6e26de30bd6df535f Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Wed, 27 Jan 2021 05:48:06 -0500 Subject: [PATCH 17/18] Fraction: Implement dict type methods --- bindings/python/openshot.i | 51 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/bindings/python/openshot.i b/bindings/python/openshot.i index cb0490c7..a129280d 100644 --- a/bindings/python/openshot.i +++ b/bindings/python/openshot.i @@ -137,6 +137,9 @@ %{ #include #include + + static std::vector _keys{"num", "den"}; + static int fracError = 0; %} double __float__() { return $self->ToDouble(); @@ -144,12 +147,46 @@ int __int__() { return $self->ToInt(); } + /* Dictionary-type methods */ + int __len__() { + return _keys.size(); + } + %exception __getitem__ { + $action + if (fracError == 1) { + fracError = 0; // Clear flag for reuse + PyErr_SetString(PyExc_KeyError, "Key not found"); + SWIG_fail; + } + } + const std::string __getitem__(int index) { + if (index < _keys.size()) { + return _keys[index]; + } + /* Otherwise, raise an exception */ + fracError = 1; + return ""; + } + int __getitem__(const std::string& key) { + if (key == "num") { + return $self->num; + } else if (key == "den") { + return $self->den; + } + /* Otherwise, raise an exception */ + fracError = 1; + return 0; + } + bool __contains__(const std::string& key) { + return bool(std::find(_keys.begin(), _keys.end(), key) != _keys.end()); + } std::map GetMap() { std::map map1; map1.insert({"num", $self->num}); map1.insert({"den", $self->den}); return map1; } + /* Display methods */ const std::string __string__() { std::ostringstream result; result << $self->num << ":" << $self->den; @@ -160,6 +197,20 @@ result << "Fraction(" << $self->num << ", " << $self->den << ")"; return result.str(); } + /* Implement dict methods in Python */ + %pythoncode %{ + def __iter__(self): + return iter(self.GetMap()) + def keys(self): + _items = self.GetMap() + return _items.keys() + def items(self): + _items = self.GetMap() + return _items.items() + def values(self): + _items = self.GetMap() + return _items.values() + %} } %extend openshot::OpenShotVersion { From 6bd3110bceefc5b4c900f63ded1bbdb104af343a Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Wed, 27 Jan 2021 05:48:53 -0500 Subject: [PATCH 18/18] Coordinate_Tests: include Exceptions.h --- tests/Coordinate_Tests.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/Coordinate_Tests.cpp b/tests/Coordinate_Tests.cpp index cbfbac40..7dd5886c 100644 --- a/tests/Coordinate_Tests.cpp +++ b/tests/Coordinate_Tests.cpp @@ -32,6 +32,7 @@ // Prevent name clashes with juce::UnitTest #define DONT_SET_USING_JUCE_NAMESPACE 1 #include "Coordinate.h" +#include "Exceptions.h" using namespace openshot;