From 1e0e68f9cda51c881b32a54d9eece71c1428f7ac Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sun, 22 Apr 2018 05:58:44 +0200 Subject: Add video and gif support Gif streams from url. Todo: Add play controls to video --- include/Cache.hpp | 14 ++++++++++- include/Channel.hpp | 3 +++ include/Chatbar.hpp | 9 +++++++ include/FileUtil.hpp | 18 ++++++++++++++ include/Gif.hpp | 47 ++++++++++++++++++++++++++++++++++++ include/Message.hpp | 6 +++-- include/MessageBoard.hpp | 1 - include/MessagePart.hpp | 7 +++--- include/StringView.hpp | 62 ++++++++++++++++++++++++++++++++++++++++++++++++ include/Video.hpp | 45 +++++++++++++++++++++++++++++++++++ 10 files changed, 205 insertions(+), 7 deletions(-) create mode 100644 include/FileUtil.hpp create mode 100644 include/Gif.hpp create mode 100644 include/StringView.hpp create mode 100644 include/Video.hpp (limited to 'include') diff --git a/include/Cache.hpp b/include/Cache.hpp index 59d997a..0314e7e 100644 --- a/include/Cache.hpp +++ b/include/Cache.hpp @@ -14,6 +14,8 @@ namespace TinyProcessLib namespace dchat { + class Gif; + struct ImageByUrlResult { enum class Type @@ -23,9 +25,19 @@ namespace dchat FAILED_DOWNLOAD }; + ImageByUrlResult() : texture(nullptr), type(Type::DOWNLOADING), isGif(false) {} + ImageByUrlResult(sf::Texture *_texture, Type _type) : texture(_texture), type(_type), isGif(false) {} + ImageByUrlResult(Gif *_gif, Type _type) : gif(_gif), type(_type), isGif(true) {} + // @texture is null if @type is DOWNLOADING or FAILED_DOWNLOAD - sf::Texture *texture; + union + { + sf::Texture *texture; + Gif *gif; + }; + Type type; + bool isGif; }; class Cache diff --git a/include/Channel.hpp b/include/Channel.hpp index fa52a4b..b70803c 100644 --- a/include/Channel.hpp +++ b/include/Channel.hpp @@ -13,6 +13,9 @@ namespace dchat Channel(); ~Channel(); + User* getLocalUser(); + MessageBoard& getMessageBoard(); + void processEvent(const sf::Event &event); void draw(sf::RenderWindow &window, Cache &cache); private: diff --git a/include/Chatbar.hpp b/include/Chatbar.hpp index 143ebba..d24b2af 100644 --- a/include/Chatbar.hpp +++ b/include/Chatbar.hpp @@ -3,9 +3,13 @@ #include #include #include +#include +#include namespace dchat { + class Channel; + class Chatbar { public: @@ -20,11 +24,16 @@ namespace dchat void moveCaretLeft(); void moveCaretRight(); + bool isFocused() const; + + void processEvent(const sf::Event &event, Channel *channel); void draw(sf::RenderWindow &window); private: sf::Text text; sf::RectangleShape background; int caretIndex; sf::Vector2f caretOffset; + sf::Clock blinkTimer; + bool focused; }; } diff --git a/include/FileUtil.hpp b/include/FileUtil.hpp new file mode 100644 index 0000000..0cfc808 --- /dev/null +++ b/include/FileUtil.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include "StringView.hpp" +#include +#include + +namespace dchat +{ + class FileException : public std::runtime_error + { + public: + FileException(const std::string &errMsg) : std::runtime_error(errMsg) {} + }; + + // Throws FileException on error. + // Returned value is allocated with malloc and should be free'd by caller. + StringView getFileContent(const boost::filesystem::path &filepath); +} diff --git a/include/Gif.hpp b/include/Gif.hpp new file mode 100644 index 0000000..1a69a52 --- /dev/null +++ b/include/Gif.hpp @@ -0,0 +1,47 @@ +#pragma once + +#include "StringView.hpp" +#include +#include +#include +#include +#include +#include +extern "C" +{ +#include +} + +namespace dchat +{ + class GifLoadException : public std::runtime_error + { + public: + GifLoadException(const std::string &errMsg) : std::runtime_error(errMsg) {} + }; + + class Gif + { + public: + // Throws GifLoadException on error + Gif(const boost::filesystem::path &filepath); + Gif(StringView &&fileContent); + ~Gif(); + + void setPosition(const sf::Vector2f &position); + void setSize(const sf::Vector2f &size); + void draw(sf::RenderWindow &window); + + static bool isDataGif(const StringView &data); + private: + void init(); + private: + gif_animation gif; + StringView fileContent; + unsigned int currentFrame; + sf::Sprite sprite; + sf::Texture texture; + double timeElapsedCs; + sf::Clock frameTimer; + }; +} diff --git a/include/Message.hpp b/include/Message.hpp index efc1f4c..7cd7fdf 100644 --- a/include/Message.hpp +++ b/include/Message.hpp @@ -13,10 +13,12 @@ namespace dchat Message(User *user); virtual ~Message(); - void addText(const std::string &text); - void addImage(const std::string &url); + void addText(const std::string &text, bool newLine = true); + void addEmoji(const std::string &url, bool newLine = true); std::vector& getParts(); + static Message* buildFromString(User *user, const std::string &str); + const User *user; private: std::vector messageParts; diff --git a/include/MessageBoard.hpp b/include/MessageBoard.hpp index 105d675..c510164 100644 --- a/include/MessageBoard.hpp +++ b/include/MessageBoard.hpp @@ -22,7 +22,6 @@ namespace dchat void draw(sf::RenderWindow &window, Cache &cache); private: sf::RenderTexture staticContentTexture; - bool useStaticContentTexture; bool dirty; bool selectingText; bool leftMouseButtonPressed; diff --git a/include/MessagePart.hpp b/include/MessagePart.hpp index d0a0a03..00544fb 100644 --- a/include/MessagePart.hpp +++ b/include/MessagePart.hpp @@ -16,7 +16,7 @@ namespace dchat EMOJI }; - MessagePart(Type _type) : type(_type) {} + MessagePart(Type _type, bool _newLine) : type(_type), newLine(_newLine) {} virtual ~MessagePart(){} static float getSizeScaled(); @@ -24,12 +24,13 @@ namespace dchat virtual sf::Vector2f getSize() const = 0; const Type type; + bool newLine; }; class MessagePartText : public MessagePart { public: - MessagePartText(const std::string &text); + MessagePartText(const std::string &text, bool newLine); static float getFontSizeScaled(); virtual sf::Vector2f getPosition() const override; @@ -41,7 +42,7 @@ namespace dchat class MessagePartEmoji : public MessagePart { public: - MessagePartEmoji(const std::string &url); + MessagePartEmoji(const std::string &url, bool newLine); static float getHeightScaled(); virtual sf::Vector2f getPosition() const override; diff --git a/include/StringView.hpp b/include/StringView.hpp new file mode 100644 index 0000000..3293358 --- /dev/null +++ b/include/StringView.hpp @@ -0,0 +1,62 @@ +#pragma once + +#include "types.hpp" +#include +#include + +namespace dchat +{ + class StringView + { + public: + StringView() : data(nullptr), size(0) + { + + } + + StringView(const StringView &other) : data(other.data), size(other.size) + { + + } + + StringView(const char *_data) : data(_data), size(strlen(_data)) + { + + } + + StringView(const char *_data, usize _size) : data(_data), size(_size) + { + + } + + StringView operator = (const StringView &other) + { + StringView result(other.data, other.size); + return result; + } + + StringView(StringView &&other) + { + data = other.data; + size = other.size; + + other.data = nullptr; + other.size = 0; + } + + bool equals(const StringView &other) const + { + if(size != other.size) return false; + return memcmp(data, other.data, size) == 0; + } + + char operator [] (usize index) const + { + assert(index < size); + return data[index]; + } + + const char *data; + usize size; + }; +} diff --git a/include/Video.hpp b/include/Video.hpp new file mode 100644 index 0000000..f148c07 --- /dev/null +++ b/include/Video.hpp @@ -0,0 +1,45 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +class mpv_handle; +class mpv_render_context; + +namespace dchat +{ + class VideoInitializationException : public std::runtime_error + { + public: + VideoInitializationException(const std::string &errMsg) : std::runtime_error(errMsg) {} + }; + + class Video + { + public: + // Throws VideoInitializationException on error + Video(unsigned int width, unsigned int height, const char *file, bool loop = false); + ~Video(); + + void setPosition(float x, float y); + void draw(sf::RenderWindow &window); + + // This counter is incremented when mpv wants to redraw content + std::atomic_int redrawCounter; + private: + sf::Context context; + mpv_handle *mpv; + mpv_render_context *mpvGl; + std::thread renderThread; + std::mutex renderMutex; + sf::Sprite sprite; + sf::Texture texture; + sf::Uint8 *textureBuffer; + }; +} -- cgit v1.2.3