From 703d25fadd57e3b1eb37ff56931216e0bd428297 Mon Sep 17 00:00:00 2001 From: jean-millot Date: Thu, 8 Jun 2017 18:56:17 +0200 Subject: [PATCH 001/148] Server code cleaning --- CMakeLists.txt | 10 + Modules/KiwiServer/KiwiServer_Server.cpp | 381 +++++++++++++++++++++++ Modules/KiwiServer/KiwiServer_Server.h | 196 ++++++++++++ Server/Source/KiwiServer_Server.cpp | 217 ------------- Server/Source/KiwiServer_Server.h | 119 ------- Server/Source/KiwiServer_ServerBase.cpp | 282 ----------------- Server/Source/KiwiServer_ServerBase.h | 187 ----------- Server/Source/Main.cpp | 15 +- 8 files changed, 594 insertions(+), 813 deletions(-) create mode 100644 Modules/KiwiServer/KiwiServer_Server.cpp create mode 100644 Modules/KiwiServer/KiwiServer_Server.h delete mode 100644 Server/Source/KiwiServer_Server.cpp delete mode 100644 Server/Source/KiwiServer_Server.h delete mode 100644 Server/Source/KiwiServer_ServerBase.cpp delete mode 100644 Server/Source/KiwiServer_ServerBase.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 358db481..41aab38c 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -383,12 +383,22 @@ source_group_rec("${KIWI_ENGINE_SRC}" ${ROOT_DIR}/Modules/KiwiEngine) # Server #---------------------------------- +file(GLOB_RECURSE KIWI_SERVER_SRC ${ROOT_DIR}/Modules/KiwiServer/*.[c|h]pp + ${ROOT_DIR}/Modules/KiwiServer/*.h) +add_library(KiwiServer ${KIWI_SERVER_SRC}) +target_include_directories(KiwiServer PUBLIC ${JSON_INCLUDE_DIRS}) +target_add_dependency(KiwiServer KiwiModel) +target_add_dependency(KiwiServer Juce) +set_target_properties(KiwiServer PROPERTIES FOLDER Modules) +source_group_rec("${KIWI_SERVER_SRC}" ${ROOT_DIR}/Modules/KiwiServer) + file(GLOB_RECURSE SERVER_SRC ${ROOT_DIR}/Server/Source/*.[c|h]pp ${ROOT_DIR}/Server/Source/*.h) add_executable(Server ${SERVER_SRC}) target_include_directories(Server PUBLIC ${JSON_INCLUDE_DIRS}) target_add_dependency(Server KiwiModel) target_add_dependency(Server Juce) +target_add_dependency(Server KiwiServer) source_group_rec("${SERVER_SRC}" ${ROOT_DIR}/Server/Source) #---------------------------------- diff --git a/Modules/KiwiServer/KiwiServer_Server.cpp b/Modules/KiwiServer/KiwiServer_Server.cpp new file mode 100644 index 00000000..86912e94 --- /dev/null +++ b/Modules/KiwiServer/KiwiServer_Server.cpp @@ -0,0 +1,381 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include "KiwiServer_Server.h" + +#include +#include +#include + +#include +#include +#include + +namespace kiwi +{ + namespace server + { + // ================================================================================ // + // SERVER // + // ================================================================================ // + + std::string hexadecimal_convert(uint64_t hexa_decimal) + { + std::stringstream converter; + converter << std::hex << hexa_decimal; + + return converter.str(); + } + + const char* Server::kiwi_file_extension = "kiwi"; + + Server::Server(uint16_t port, std::string const& backend_directory) : + m_running(false), + m_backend_directory(backend_directory), + m_sessions(), + m_socket(*this, port), + m_ports() + { + if (m_backend_directory.exists() && !m_backend_directory.isDirectory()) + { + throw std::runtime_error("Specified backend directory is a file"); + } + else if(!m_backend_directory.exists()) + { + m_backend_directory.createDirectory(); + } + } + + Server::~Server() + { + m_socket.reset(); + } + + void Server::process() + { + m_socket.process(); + } + + void Server::run() + { + if(!m_running) + { + flip::RunLoopTimer run_loop ([this] + { + process(); + return m_running.load(); + }, 0.02); + + m_running.store(true); + + run_loop.run(); + } + } + + void Server::stop() + { + m_running.store(false); + std::cout << "[server] - stopped" << std::endl; + } + + bool Server::isRunning() const noexcept + { + return m_running; + } + + juce::File Server::getSessionFile(uint64_t session_id) + { + return m_backend_directory.getChildFile(juce::String(hexadecimal_convert(session_id))) + .withFileExtension(kiwi_file_extension); + } + + void Server::createSession(uint64_t session_id) + { + const auto session_file = getSessionFile(session_id); + + m_sessions.insert(std::move(std::make_pair(session_id, Session(session_id, session_file)))); + } + + void Server::onConnected(flip::PortBase & port) + { + if(m_sessions.find(port.session()) == m_sessions.end()) + { + createSession(port.session()); + } + + m_sessions.find(port.session())->second.bind(port); + } + + void Server::onDisconnected(flip::PortBase & port) + { + port.impl_activate(false); + + for(auto session_it = m_sessions.begin(); session_it != m_sessions.end();) + { + Session & session = session_it->second; + + if (session.hasUser(port.user())) + { + session.unbind(port); + + if (session.getConnectedUsers().empty()) + { + session_it = m_sessions.erase(session_it); + } + else + { + ++session_it; + } + } + else + { + ++session_it; + } + } + } + + void Server::port_factory_add(flip::PortBase& port) + { + port.impl_bind (*this); + + m_ports.insert (&port); + } + + void Server::port_factory_remove(flip::PortBase& port) + { + if (m_ports.erase (&port)) {port.impl_unbind (*this);} + + onDisconnected(port); + } + + void Server::port_greet(flip::PortBase& port) + { + if (m_ports.erase (&port)) { port.impl_unbind (*this); } + + onConnected(port); + } + + void Server::port_commit(flip::PortBase& /* port */, const flip::Transaction& /* tx */) + { + // nothing + } + + void Server::port_squash(flip::PortBase& /* port */, const flip::TxIdRange& /* range */, const flip::Transaction& /* tx */) + { + // nothing + } + + void Server::port_push(flip::PortBase& /* port */, const flip::Transaction& /* tx */) + { + // port was rebound in greet + flip_FATAL; + } + + void Server::port_signal(flip::PortBase& /* port */, const flip::SignalData& /* data */) + { + // port was rebound in greet + flip_FATAL; + } + + // ================================================================================ // + // SERVER SESSION // + // ================================================================================ // + + Server::Session::Session(Session && other) + : m_identifier(std::move(other.m_identifier)) + , m_validator(std::move(other.m_validator)) + , m_document(std::move(other.m_document)) + , m_signal_connections(std::move(other.m_signal_connections)) + , m_backend_file(other.m_backend_file) + { + ; + } + + Server::Session::Session(uint64_t identifier, juce::File const& backend_file) + : m_identifier(identifier) + , m_validator(new model::PatcherValidator()) + , m_document(new flip::DocumentServer(model::DataModel::use(), *m_validator, m_identifier)) + , m_signal_connections() + , m_backend_file(backend_file) + { + DBG("[server] - creating new session for session_id : " << hexadecimal_convert(m_identifier)); + + model::Patcher& patcher = m_document->root(); + + auto cnx = patcher.signal_get_connected_users.connect(std::bind(&Server::Session::sendConnectedUsers, this)); + + m_signal_connections.emplace_back(std::move(cnx)); + + if (m_backend_file.exists()) + { + DBG("[server] - loading session file for session_id : " << hexadecimal_convert(m_identifier)); + + load(); + } + else + { + DBG("[server] - initializing with empty document for session_id : " << hexadecimal_convert(m_identifier)); + } + } + + Server::Session::~Session() + { + if (m_document) + { + std::set ports = m_document->ports(); + + for (std::set::iterator port = ports.begin(); port != ports.end(); ++port) + { + m_document->port_factory_remove(**port); + } + } + } + + uint64_t Server::Session::getId() const + { + return m_identifier; + } + + void Server::Session::save() const + { + flip::BackEndIR backend(m_document->write()); + + flip::DataConsumerFile consumer(m_backend_file.getFullPathName().toStdString().c_str()); + + backend.write(consumer); + } + + void Server::Session::load() + { + flip::BackEndIR backend; + backend.register_backend(); + + flip::DataProviderFile provider(m_backend_file.getFullPathName().toStdString().c_str()); + backend.read(provider); + + m_document->read(backend); + m_document->commit(); + } + + bool Server::Session::authenticateUser(uint64_t user, std::string metadate) const + { + // @todo check token received in port metadata + + return true; + } + + void Server::Session::bind(flip::PortBase & port) + { + DBG("[server] - User: " + << std::to_string(port.user()) + << " connecting to session : " + << hexadecimal_convert(m_identifier)); + + if (authenticateUser(port.user(), port.metadata())) + { + m_document->port_factory_add(port); + + m_document->port_greet(port); + + model::Patcher& patcher = m_document->root(); + + // send a list of connected users to the user that is connecting. + m_document->send_signal_if(patcher.signal_receive_connected_users.make(getConnectedUsers()), + [&port](flip::PortBase& current_port) + { + return port.user() == current_port.user(); + }); + + // Notify other users that this one is connected. + m_document->send_signal_if(patcher.signal_user_connect.make(port.user()), + [&port](flip::PortBase& current_port) + { + return port.user() != current_port.user(); + }); + } + else + { + throw std::runtime_error("authentication failed"); + } + } + + void Server::Session::unbind(flip::PortBase & port) + { + DBG("[server] - User " << std::to_string(port.user()) + << " disconnecting from session: " << hexadecimal_convert(m_identifier)); + + model::Patcher& patcher = m_document->root(); + + m_document->send_signal_if(patcher.signal_user_disconnect.make(port.user()), + [](flip::PortBase& port) + { + return true; + }); + + m_document->port_factory_remove(port); + + if (m_document->ports().empty()) + { + if(!m_backend_file.exists()) + { + m_backend_file.create(); + } + + DBG("[server] - Saving session : " << hexadecimal_convert(m_identifier) + << " in file : " + << m_backend_file.getFileName()); + + save(); + } + } + + bool Server::Session::hasUser(uint64_t user_id) const + { + auto const& ports = m_document->ports(); + + return std::find_if(ports.begin(), ports.end(), [user_id](flip::PortBase * port) + { + return port->user() == user_id; + }) != ports.end(); + } + + std::vector Server::Session::getConnectedUsers() const + { + std::vector users; + + auto const& ports = m_document->ports(); + + for(auto const& port : ports) + { + users.emplace_back(port->user()); + } + + return users; + } + + void Server::Session::sendConnectedUsers() const + { + model::Patcher& patcher = m_document->root(); + + m_document->reply_signal(patcher.signal_receive_connected_users.make(getConnectedUsers())); + } + } +} diff --git a/Modules/KiwiServer/KiwiServer_Server.h b/Modules/KiwiServer/KiwiServer_Server.h new file mode 100644 index 00000000..2bbe4690 --- /dev/null +++ b/Modules/KiwiServer/KiwiServer_Server.h @@ -0,0 +1,196 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include + + +namespace kiwi +{ + namespace server + { + // ================================================================================ // + // SERVER // + // ================================================================================ // + + //! @brief Converts and int64_t into a string representing it. + std::string hexadecimal_convert(uint64_t hexa_decimal); + + //! @brief The Server class. + class Server : public flip::PortFactoryListener, public flip::PortListener + { + public: // classes + + class Session; + + public: // methods + + //! @brief Constructor. + Server(uint16_t port, std::string const& backend_directory); + + //! @brief Destructor. + //! @details Disconnect all users and clean sessions. + ~Server(); + + //! @brief Process the socket hence process all sessions. + void process(); + + //! @brief Run the server. + //! @details This will run a loop that call ServerBase::process regularly. + //! @see stop + void run(); + + //! @brief Stops the server. + //! @see Run, isRunning + void stop(); + + //! @brief Returns true if the server is running. + bool isRunning() const noexcept; + + private: // methods + + //! @brief Creates a new session for server. + void createSession(uint64_t session_id); + + //! @brief Called when a user connects to a document + void onConnected(flip::PortBase & port); + + //! @brief Called when a user has been disconnected from a document + void onDisconnected(flip::PortBase & port); + + //! @brief Get the path for a given session. + juce::File getSessionFile(uint64_t session_id); + + private: // methods + + // PortFactoryListener + void port_factory_add(flip::PortBase & port) override final; + + void port_factory_remove(flip::PortBase & port) override final; + + // PortListener + void port_greet(flip::PortBase& port) override final; + + void port_commit(flip::PortBase& port, flip::Transaction const & tx) override final; + + void port_squash(flip::PortBase& port, + flip::TxIdRange const& range, + flip::Transaction const& tx) override final; + + void port_push(flip::PortBase& port, flip::Transaction const& tx) override final; + + void port_signal(flip::PortBase& port, const flip::SignalData & data) override final; + + private: // variables + + std::atomic_bool m_running; + juce::File m_backend_directory; + std::map m_sessions; + flip::PortTransportServerTcp m_socket; + std::set m_ports; + + static const char* kiwi_file_extension; + + private: // deleted methods + + Server(Server const& other) = delete; + Server(Server &&other) = delete; + Server &operator=(Server const& other) = delete; + Server &operator=(Server &&other) = delete; + }; + + // ================================================================================ // + // SERVER SESSION // + // ================================================================================ // + + class Server::Session final + { + public: // methods + + //! @brief Constructor. + //! @details Create a Session by moving another Session. + Session(Session && rhs); + + //! @brief Constructor + //! @detailss Initialized with an empty document. + Session(uint64_t identifier, juce::File const& backend_file); + + //! @brief Destructor. + //! @details Unbinds all documents and ports. + ~Session(); + + uint64_t getId() const; + + //! @brief Returns a backend holding full presentation of the document hold by this session. + void save() const; + + //! @brief Loads the session's document from the designated Backend entity. + void load(); + + //! @brief Binds user to session. + void bind(flip::PortBase & port); + + //! @brief Unbind user to session. + void unbind(flip::PortBase & port); + + //! @brief Returns wether a certain user is connected to session. + bool hasUser(uint64_t user_id) const; + + //! @brief Returns a list of connected users. + std::vector getConnectedUsers() const; + + private: // methods + + //! @brief Checks if user has access to this particuliar session. + bool authenticateUser(uint64_t user_id, std::string metadata) const; + + //! @brief Replies to a client with a list of connected users. + void sendConnectedUsers() const; + + private: // variables + + const uint64_t m_identifier; + std::unique_ptr m_validator; + std::unique_ptr m_document; + std::vector m_signal_connections; + juce::File m_backend_file; + + private: // variables + + Session() = delete; + Session(const Session & rhs) = delete; + Session& operator = (const Session & rhs) = delete; + Session& operator = (Session && rhs) = delete; + }; + } +} diff --git a/Server/Source/KiwiServer_Server.cpp b/Server/Source/KiwiServer_Server.cpp deleted file mode 100644 index 6bc08dc9..00000000 --- a/Server/Source/KiwiServer_Server.cpp +++ /dev/null @@ -1,217 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#include "flip/contrib/DataProviderFile.h" -#include "flip/contrib/DataConsumerFile.h" - -#include -#include -#include - -#include "KiwiServer_Server.h" - -namespace kiwi -{ - namespace server - { - // ================================================================================ // - // SERVER // - // ================================================================================ // - - const char* Server::kiwi_file_extension = "kiwi"; - - Server::Server(uint16_t port, std::string const& backend_directory) : - ServerBase(model::DataModel::use(), port), - m_port(port), - m_running(false), - m_backend_directory(backend_directory) - { - if (m_backend_directory.exists() && !m_backend_directory.isDirectory()) - { - throw std::runtime_error("Specified backend directory is a file"); - } - else if(!m_backend_directory.exists()) - { - m_backend_directory.createDirectory(); - } - } - - Server::~Server() - { - ; - } - - void Server::run() - { - if(!m_running) - { - flip::RunLoopTimer run_loop ([this] { - process(); - return m_running.load(); - }, 0.02); - - std::cout << "[server] - running on port " << getPort() << std::endl;; - - m_running.store(true); - run_loop.run(); - } - } - - void Server::stop() - { - m_running.store(false); - std::cout << "[server] - stopped" << std::endl; - } - - bool Server::isRunning() const noexcept - { - return m_running; - } - - juce::File Server::getSessionFile(uint64_t session_id) - { - return m_backend_directory.getChildFile(juce::String(hexadecimal_convert(session_id))) - .withFileExtension(kiwi_file_extension); - } - - uint16_t Server::getPort() const noexcept - { - return m_port; - } - - std::unique_ptr Server::createValidator(uint64_t session_id) - { - DBG("[server] - createValidator for session_id : " << hexadecimal_convert(session_id)); - - return std::make_unique(); - } - - void Server::initEmptyDocument(uint64_t session_id, flip::DocumentBase& document) - { - DBG("[server] - initEmptyDocument for session_id : " << hexadecimal_convert(session_id)); - } - - flip::BackEndIR Server::readSessionBackend(uint64_t session_id) - { - DBG("[server] - readSessionBackend for session_id : " << hexadecimal_convert(session_id)); - - flip::BackEndIR backend; - - const auto session_file = getSessionFile(session_id); - - if (session_file.exists()) - { - flip::DataProviderFile provider(session_file.getFullPathName().toStdString().c_str()); - - backend.register_backend(); - backend.read(provider); - } - - return backend; - } - - void Server::writeSessionBackend(uint64_t session_id, flip::BackEndIR const& backend) - { - const auto session_file = getSessionFile(session_id); - - if(!session_file.exists()) - { - session_file.create(); - } - - DBG("[server] - Saving session : " << hexadecimal_convert(session_id) << " in file : " << session_file.getFileName()); - - flip::DataConsumerFile consumer(session_file.getFullPathName().toStdString().c_str()); - backend.write(consumer); - } - - bool Server::authenticateUser(uint64_t user_id, uint64_t session_id, std::string metadata) - { - // @todo do something here - - DBG("[server] - Authenticate user: " << std::to_string(user_id) << " for session: " << hexadecimal_convert(session_id)); - - return true; - } - - /* - uint64_t Server::hexadecimal_convert(std::string const& hexa_string) - { - uint64_t hexa_decimal = 0ul; - std::stringstream converter(hexa_string); - converter >> std::hex >> hexa_decimal; - - return hexa_decimal; - } - */ - - std::string Server::hexadecimal_convert(uint64_t hexa_decimal) - { - std::stringstream converter; - converter << std::hex << hexa_decimal; - - return converter.str(); - } - - void Server::sessionCreated(Session& session) - { - auto& document = session.document(); - auto& patcher = document.root(); - - auto cnx = patcher.signal_get_connected_users.connect([&patcher, &document, &session] { - - document.reply_signal(patcher.signal_receive_connected_users.make(session.getConnectedUsers())); - - }); - - session.storeSignalConnection(std::move(cnx)); - } - - void Server::onConnected(Session& session, uint64_t user_id) - { - auto& document = session.document(); - auto& patcher = document.root(); - - // send a list of connected users to the user that is connecting. - document.send_signal_if(patcher.signal_receive_connected_users.make(session.getConnectedUsers()), - [user_id](flip::PortBase& port){return port.user() == user_id;}); - - // Notify other users that this one is connected. - document.send_signal_if(patcher.signal_user_connect.make(user_id), - [user_id](flip::PortBase& port){return port.user() != user_id;}); - - DBG("[server] - User " << std::to_string(user_id) - << " connected to session: " << hexadecimal_convert(session.identifier())); - } - - void Server::onDisconnected(Session& session, uint64_t user_id) - { - auto& document = session.document(); - auto& patcher = document.root(); - - document.send_signal_if(patcher.signal_user_disconnect.make(user_id), - [](flip::PortBase& port){return true;}); - - DBG("[server] - User " << std::to_string(user_id) - << " disconnected from session: " << hexadecimal_convert(session.identifier())); - } - } -} diff --git a/Server/Source/KiwiServer_Server.h b/Server/Source/KiwiServer_Server.h deleted file mode 100644 index 06cd16dd..00000000 --- a/Server/Source/KiwiServer_Server.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#pragma once - -#include "flip/contrib/ServerSimple.h" -#include "flip/BackEndBinary.h" - -#include - -#include - -#include - -#include "KiwiServer_ServerBase.h" - -namespace kiwi -{ - namespace server - { - // ================================================================================ // - // SERVER // - // ================================================================================ // - - //! @brief The Server class. - class Server : public ServerBase - { - public: // methods - - //! @brief Constructor. - Server(uint16_t port, std::string const& backend_directory); - - //! @brief Destructor. - ~Server(); - - //! @brief Run the server. - //! @details This will run a loop that call ServerBase::process regularly. - //! @see stop - void run(); - - //! @brief Stops the server. - //! @see Run, isRunning - void stop(); - - //! @brief Returns true if the server is running. - bool isRunning() const noexcept; - - //! @brief Get the server running port - uint16_t getPort() const noexcept; - - private: // methods - - //! @brief Initialise a new empty patcher - std::unique_ptr createValidator(uint64_t session_id) override; - - //! @brief Initialise a new empty patcher - void initEmptyDocument(uint64_t session_id, flip::DocumentBase & document) override; - - //! @brief read a session backend. - flip::BackEndIR readSessionBackend(uint64_t session_id) override; - - //! @brief write a session backend. - void writeSessionBackend(uint64_t session_id, flip::BackEndIR const& backend) override; - - //! @brief Authenticate a user. - bool authenticateUser(uint64_t user_id, uint64_t session_id, std::string metadata) override; - - //! @brief Called when a new session has been created. - void sessionCreated(Session& session) override; - - //! @brief Called when a user connects to a document - void onConnected(Session& session, uint64_t user_id) override; - - //! @brief Called when a user has been disconnected from a document - void onDisconnected(Session& session, uint64_t user_id) override; - - //! @brief Get the path for a given session. - juce::File getSessionFile(uint64_t session_id); - - private: // methods - - //static uint64_t hexadecimal_convert(std::string const& hexa_string); - static std::string hexadecimal_convert(uint64_t hexa_decimal); - - private: // variables - - const uint16_t m_port; - std::atomic_bool m_running; - juce::File m_backend_directory; - - static const char* kiwi_file_extension; - - private: // deleted methods - - Server(Server const& other) = delete; - Server(Server &&other) = delete; - Server &operator=(Server const& other) = delete; - Server &operator=(Server &&other) = delete; - }; - } -} diff --git a/Server/Source/KiwiServer_ServerBase.cpp b/Server/Source/KiwiServer_ServerBase.cpp deleted file mode 100644 index c621de98..00000000 --- a/Server/Source/KiwiServer_ServerBase.cpp +++ /dev/null @@ -1,282 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot& Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#include "KiwiServer_ServerBase.h" - -#include "flip/DocumentValidatorVoid.h" -#include "flip/detail/def.h" -#include "flip/detail/fnc.h" - -#include - -namespace kiwi -{ - namespace server - { - // ================================================================================ // - // SERVER SESSION // - // ================================================================================ // - - ServerBase::Session::Session(Session && rhs) - : m_parent(rhs.m_parent) - , m_identifier(std::move(rhs.m_identifier)) - , m_validator_uptr(std::move(rhs.m_validator_uptr)) - , m_document_uptr(std::move(rhs.m_document_uptr)) - { - ; - } - - ServerBase::Session::Session(ServerBase& parent, - uint64_t identifier, - std::unique_ptr && document_uptr, - std::unique_ptr && validator_uptr) - : m_parent(parent) - , m_identifier(identifier) - , m_validator_uptr(std::move(validator_uptr)) - , m_document_uptr(std::move(document_uptr)) - { - ; - } - - uint64_t ServerBase::Session::identifier() const - { - return m_identifier; - } - - flip::DocumentServer& ServerBase::Session::document() - { - return *m_document_uptr; - } - - void ServerBase::Session::write() - { - m_parent.writeSession(document(), identifier()); - } - - std::vector ServerBase::Session::getConnectedUsers() - { - std::vector users; - auto const& ports = m_document_uptr->ports(); - - for(auto const& port : ports) - { - users.emplace_back(port->user()); - } - - return users; - } - - void ServerBase::Session::storeSignalConnection(flip::SignalConnection && cnx) - { - m_signal_connections.emplace_back(std::forward(cnx)); - } - - // ================================================================================ // - // SERVER // - // ================================================================================ // - - ServerBase::ServerBase(flip::DataModelBase const& data_model, uint16_t port) - : m_data_model(data_model) - , m_port(*this, port) - , m_sessions() - { - } - - ServerBase::~ServerBase() - { - for(auto& pair : m_sessions) - { - auto& server = pair.second.document(); - - auto ports = server.ports(); - - for(auto* port_ptr : ports) - { - server.port_factory_remove(*port_ptr); - port_ptr->impl_bind(*this); - } - } - - m_sessions.clear(); - - m_port.reset(); - } - - void ServerBase::process() - { - m_port.process(); - } - - size_t ServerBase::getNumberOfSessions() const - { - return m_sessions.size(); - } - - void ServerBase::writeSession(flip::DocumentServer& server, uint64_t session_id) - { - auto backend = server.write(); - writeSessionBackend(session_id, backend); - } - - void ServerBase::port_factory_add(flip::PortBase& port) - { - port.impl_bind(*this); - } - - void ServerBase::port_factory_remove(flip::PortBase& port) - { - port.impl_activate(false); - - bool was_attached_flag = false; - - auto it = m_sessions.begin(); - const auto it_end = m_sessions.end(); - - for(; it != it_end ;) - { - auto it_next = it; - ++it_next; - - auto& session = it->second; - auto session_id = session.identifier(); - auto& document_server = session.document(); - const auto& ports = document_server.ports(); - - if(ports.find(&port) != ports.end()) - { - was_attached_flag = true; - document_server.port_factory_remove(port); - - // notify - onDisconnected(session, port.user()); - - if(ports.empty()) - { - writeSession(document_server, session_id); - - m_sessions.erase(it); - } - - break; - } - - it = it_next; - } - - if(!was_attached_flag) - { - port.impl_unbind(*this); - } - } - - void ServerBase::port_greet(flip::PortBase& from) - { - if(!authenticateUser(from.user(), from.session(), from.metadata())) - { - throw std::runtime_error("authentication failed"); - } - - auto session_id = from.session(); - auto it = m_sessions.find(session_id); - const bool is_new_session = (it == m_sessions.end()); - - if(is_new_session) - { - it = create_session(session_id); - } - - assert(it != m_sessions.end()); - - auto& session = it->second; - auto& document_server = session.document(); - - if(is_new_session) - { - sessionCreated(session); - } - - // rebind - from.impl_unbind(*this); - document_server.port_factory_add(from); - - // forward - document_server.port_greet(from); - - // notify - onConnected(session, from.user()); - } - - void ServerBase::port_commit(flip::PortBase& /* from */, const flip::Transaction& /* tx */) - { - // nothing - } - - void ServerBase::port_squash(flip::PortBase& /* from */, const flip::TxIdRange& /* range */, const flip::Transaction& /* tx */) - { - // nothing - } - - void ServerBase::port_push(flip::PortBase& /* from */, const flip::Transaction& /* tx */) - { - // port was rebound in greet - flip_FATAL; - } - - void ServerBase::port_signal(flip::PortBase& /* from */, const flip::SignalData& /* data */) - { - // port was rebound in greet - flip_FATAL; - } - - ServerBase::SessionMap::iterator ServerBase::create_session(uint64_t session_id) - { - auto validator_uptr = createValidator(session_id); - - auto document_uptr = std::make_unique(m_data_model, - *validator_uptr, - session_id); - - load_session(*document_uptr, session_id); - - auto && pair = std::make_pair(session_id, Session(*this, session_id, - std::move(document_uptr), - std::move(validator_uptr))); - - return m_sessions.insert(std::move(pair)).first; - } - - void ServerBase::load_session(flip::DocumentServer& server, uint64_t session_id) - { - flip::BackEndIR backend(readSessionBackend(session_id)); - - if(backend.empty()) - { - initEmptyDocument(session_id, server); - } - else - { - server.read(backend); - } - - server.commit(); - } - } -} diff --git a/Server/Source/KiwiServer_ServerBase.h b/Server/Source/KiwiServer_ServerBase.h deleted file mode 100644 index cb901887..00000000 --- a/Server/Source/KiwiServer_ServerBase.h +++ /dev/null @@ -1,187 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#pragma once - -#include "flip/config.h" -#include "flip/contrib/transport_tcp/PortTransportServerTcp.h" -#include "flip/DocumentServer.h" - -#include "flip/detail/DocumentValidatorBase.h" -#include "flip/detail/BackEndBase.h" -#include "flip/Signal.h" - -#include -#include - -namespace kiwi -{ - namespace server - { - // ================================================================================ // - // SERVER // - // ================================================================================ // - - class ServerBase : public flip::PortFactoryListener, public flip::PortListener - { - public: // methods - - class Session; - using SessionMap = std::map; - - //! @brief Constructor. - ServerBase(flip::DataModelBase const& data_model, uint16_t port); - - //! @brief Destructor. - virtual ~ServerBase(); - - //! @brief Server process - //! @details Must be called regularly. - void process(); - - //! @brief Get the number of sessions currently running. - size_t getNumberOfSessions() const; - - //! @brief Write the Session - void writeSession(flip::DocumentServer& server, uint64_t session_id); - - protected: // methods - - //! @brief Create a document validator. - virtual std::unique_ptr createValidator(uint64_t session_id) = 0; - - //! @brief Initialise a new empty document. - virtual void initEmptyDocument(uint64_t session_id, flip::DocumentBase & document) = 0; - - //! @brief read a session backend. - virtual flip::BackEndIR readSessionBackend(uint64_t session_id) = 0; - - //! @brief write a session backend. - virtual void writeSessionBackend(uint64_t session_id, flip::BackEndIR const& backend) = 0; - - //! @brief Authenticate a user. - virtual bool authenticateUser(uint64_t user_id, uint64_t session_id, std::string metadata) = 0; - - //! @brief Called when a new Session has been created. - virtual void sessionCreated(Session& session) {}; - - //! @brief Called when a user connects to a document. - virtual void onConnected(Session& session, uint64_t user_id) {}; - - //! @brief Called when a user has been disconnected from a document. - virtual void onDisconnected(Session& session, uint64_t user_id) {}; - - private: // methods - - SessionMap::iterator create_session(uint64_t session_id); - void load_session(flip::DocumentServer & server, uint64_t session_id); - - // PortFactoryListener - virtual void port_factory_add(flip::PortBase & port) override; - virtual void port_factory_remove(flip::PortBase & port) override; - - // PortListener - virtual void port_greet(flip::PortBase& from) override; - - virtual void port_commit(flip::PortBase& from, - flip::Transaction const & tx) override; - - virtual void port_squash(flip::PortBase& from, - flip::TxIdRange const& range, - flip::Transaction const& tx) override; - - virtual void port_push(flip::PortBase& from, - flip::Transaction const& tx) override; - - virtual void port_signal(flip::PortBase& from, - const flip::SignalData & data) override; - - private: // variables - - const flip::DataModelBase& m_data_model; - flip::PortTransportServerTcp m_port; - SessionMap m_sessions; - - private: // deleted methods - - ServerBase() = delete; - ServerBase(const ServerBase & rhs) = delete; - ServerBase(ServerBase && rhs) = delete; - ServerBase& operator =(const ServerBase & rhs) = delete; - ServerBase& operator =(ServerBase && rhs) = delete; - bool operator ==(const ServerBase & rhs) const = delete; - bool operator !=(const ServerBase & rhs) const = delete; - }; - - // ================================================================================ // - // SERVER SESSION // - // ================================================================================ // - - class ServerBase::Session - { - public: // methods - - //! @brief Constructor. - //! @details Create a Session by moving another Session. - Session(Session && rhs); - - //! @brief Constructor. - Session(ServerBase& parent, - uint64_t session_id, - std::unique_ptr && document_uptr, - std::unique_ptr && validator_uptr); - - //! @brief Destructor. - virtual ~Session() = default; - - //! @brief Get the Session identifier. - uint64_t identifier() const; - - //! @brief Get the document. - flip::DocumentServer& document(); - - //! @brief Write the session. - void write(); - - //! @brief Returns a list of connected users. - std::vector getConnectedUsers(); - - //! @brief Store the signal connection in the session. - void storeSignalConnection(flip::SignalConnection && cnx); - - private: // variables - - ServerBase& m_parent; - const uint64_t m_identifier; - std::unique_ptr m_validator_uptr; - std::unique_ptr m_document_uptr; - - std::vector m_signal_connections; - - private: // variables - - Session() = delete; - Session(const Session & rhs) = delete; - Session& operator = (const Session & rhs) = delete; - Session& operator = (Session && rhs) = delete; - }; - } -} diff --git a/Server/Source/Main.cpp b/Server/Source/Main.cpp index bcb0aef7..9c0d3d6e 100644 --- a/Server/Source/Main.cpp +++ b/Server/Source/Main.cpp @@ -20,7 +20,7 @@ */ #include -#include "KiwiServer_Server.h" +#include #include "KiwiServer_CommandLineParser.h" #include @@ -55,12 +55,16 @@ int main(int argc, char const* argv[]) } model::DataModel::init(); - std::unique_ptr server(nullptr); try { json config = json::parse(configuration_file.loadFileAsString().toStdString()); - server.reset(new server::Server(config["port"], config["backend_directory"])); + + std::unique_ptr server(new server::Server(config["port"], config["backend_directory"])); + + std::cout << "[server] - running on port " << config["port"] << std::endl; + + server->run(); } catch(nlohmann::detail::parse_error const& e) { @@ -78,10 +82,5 @@ int main(int argc, char const* argv[]) return 0; } - if(server) - { - server->run(); - } - return 0; } From 4ed68bb73b24bf3fe73f386d8c35bab867bc6155 Mon Sep 17 00:00:00 2001 From: jean-millot Date: Mon, 12 Jun 2017 18:22:33 +0200 Subject: [PATCH 002/148] Adding server tests. --- CMakeLists.txt | 19 +++- Test/Server/test_KiwiServer.cpp | 4 + Test/Server/test_Server.cpp | 188 ++++++++++++++++++++++++++++++++ 3 files changed, 207 insertions(+), 4 deletions(-) create mode 100755 Test/Server/test_Server.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 41aab38c..34ab95ce 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -297,7 +297,7 @@ set(FLIP_COMPILE_DEFINITIONS "flip_NOTHING=flip_NOTHING_FATAL") set(CMAKE_USE_OPENSSL OFF CACHE BOOL "Don't use openssl") set(BUILD_CPR_TESTS OFF CACHE BOOL "Don't build cpr tests") - + if(WIN32) if (CMAKE_CL_64) set(KIWI_CURL_LIB $ENV{KIWI_CURL_LIB_x64}) @@ -395,9 +395,6 @@ source_group_rec("${KIWI_SERVER_SRC}" ${ROOT_DIR}/Modules/KiwiServer) file(GLOB_RECURSE SERVER_SRC ${ROOT_DIR}/Server/Source/*.[c|h]pp ${ROOT_DIR}/Server/Source/*.h) add_executable(Server ${SERVER_SRC}) -target_include_directories(Server PUBLIC ${JSON_INCLUDE_DIRS}) -target_add_dependency(Server KiwiModel) -target_add_dependency(Server Juce) target_add_dependency(Server KiwiServer) source_group_rec("${SERVER_SRC}" ${ROOT_DIR}/Server/Source) @@ -470,6 +467,18 @@ endif() set_target_properties(test_engine PROPERTIES FOLDER Test) source_group_rec("${TEST_ENGINE_SRC}" ${ROOT_DIR}/Test/Engine) +# Test Server + +file(GLOB TEST_SERVER_SRC ${ROOT_DIR}/Test/Server/*.[c|h]pp + ${ROOT_DIR}/Test/Server/*.h) +add_executable(test_server ${TEST_SERVER_SRC}) +target_add_dependency(test_server KiwiServer) +set_target_properties(test_server PROPERTIES FOLDER Test) +if (LINUX) + target_link_libraries(test_engine PUBLIC ${PTHREAD}) +endif() +source_group_rec("${TEST_SERVER_SRC}" ${ROOT_DIR}/Test/Server) + # Coverage setting if(${GCOV_SUPPORT} STREQUAL "On" AND DEBUG) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage") @@ -478,6 +487,7 @@ if(${GCOV_SUPPORT} STREQUAL "On" AND DEBUG) target_link_libraries(test_dsp PUBLIC gcov) target_link_libraries(test_model PUBLIC gcov) target_link_libraries(test_engine PUBLIC gcov) + target_link_libraries(test_server PUBLIC gcov) endif() # Tests Target @@ -489,4 +499,5 @@ add_custom_command(TARGET Tests POST_BUILD COMMAND test_dsp COMMAND test_model COMMAND test_engine + COMMAND test_server USES_TERMINAL) diff --git a/Test/Server/test_KiwiServer.cpp b/Test/Server/test_KiwiServer.cpp index 779bf7c4..ca3e945e 100755 --- a/Test/Server/test_KiwiServer.cpp +++ b/Test/Server/test_KiwiServer.cpp @@ -23,10 +23,14 @@ #include "../catch.hpp" +#include + int main( int argc, char* const argv[] ) { std::cout << "running Unit-Tests - KiwiServer ..." << '\n' << '\n'; + kiwi::model::DataModel::init(); + int result = Catch::Session().run( argc, argv ); return result; diff --git a/Test/Server/test_Server.cpp b/Test/Server/test_Server.cpp new file mode 100755 index 00000000..a03f9b36 --- /dev/null +++ b/Test/Server/test_Server.cpp @@ -0,0 +1,188 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include "../catch.hpp" + +#include + +#include +#include + +#include +#include + +using namespace kiwi; + +// ==================================================================================== // +// SERVER // +// ==================================================================================== // + +TEST_CASE("Server - Server", "[Server, Server]") +{ + SECTION("Simple Connection - Deconnection") + { + kiwi::server::Server server(9090, "./server_backend"); + + std::thread server_thread([&server](){server.run();}); + + flip::Document document (kiwi::model::DataModel::use (), 123456789ULL, 'appl', 'gui '); + flip::CarrierTransportSocketTcp carrier (document, 987654ULL, "localhost", 9090); + + while(!carrier.is_connected()) + { + carrier.process(); + } + + CHECK(carrier.is_connected()); + + carrier.rebind("", 0); + + CHECK(!carrier.is_connected()); + + server.stop(); + server_thread.join(); + + juce::File backend ("./server_backend"); + + if (backend.exists()) + { + backend.deleteRecursively(); + } + } + + SECTION("Simple Connection - Server Killed") + { + std::unique_ptr server(new kiwi::server::Server(9090, "./server_backend")); + + std::thread server_thread([&server](){server->run();}); + + flip::Document document (kiwi::model::DataModel::use (), 123456789ULL, 'appl', 'gui '); + flip::CarrierTransportSocketTcp carrier (document, 987654ULL, "localhost", 9090); + + while(!carrier.is_connected()) + { + carrier.process(); + } + + CHECK(carrier.is_connected()); + + server->stop(); + server_thread.join(); + server.reset(nullptr); + + while(carrier.is_connected()) + { + carrier.process(); + } + + CHECK(!carrier.is_connected()); + + juce::File backend ("./server_backend"); + + if (backend.exists()) + { + backend.deleteRecursively(); + } + } + + SECTION("Multiple connections") + { + kiwi::server::Server server(9090, "./server_backend"); + + std::thread server_thread([&server](){server.run();}); + + // initializing user 1 + flip::Document document_1 (kiwi::model::DataModel::use (), 1UL, 'appl', 'gui '); + flip::CarrierTransportSocketTcp carrier_1 (document_1, 1234UL, "localhost", 9090); + + kiwi::model::Patcher& patcher_1 = document_1.root(); + + uint64_t other_connect_1 = 0; + + auto m_cnx_connect_1 = patcher_1.signal_user_connect.connect([&other_connect_1](uint64_t user_id) + { + other_connect_1 = user_id; + }); + + uint64_t other_disonnect_1 = 0; + + auto m_cnx_disconnect_1 = patcher_1.signal_user_disconnect.connect([&other_disonnect_1](uint64_t user_id) + { + other_disonnect_1 = user_id; + }); + + // initializing user 2 + flip::Document document_2 (kiwi::model::DataModel::use (), 2UL, 'appl', 'gui '); + flip::CarrierTransportSocketTcp carrier_2 (document_2, 1234ULL, "localhost", 9090); + + kiwi::model::Patcher& patcher_2 = document_2.root(); + + std::vector connected_users_2; + + auto m_cnx_2 = patcher_2.signal_receive_connected_users.connect([&connected_users_2](std::vector users) + { + connected_users_2 = users; + }); + + while(!carrier_1.is_connected()){carrier_1.process();} + + CHECK(carrier_1.is_connected()); + + while(connected_users_2.empty()) + { + carrier_2.process(); + document_2.pull(); + } + + auto it = std::find_if(connected_users_2.begin(), connected_users_2.end(), [](uint64_t id){return id == 1;}); + + CHECK(it != connected_users_2.end()); + + while(other_connect_1 == 0) {carrier_1.process(); document_1.pull();} + + CHECK(other_connect_1 == 2); + + carrier_2.rebind("", 0); + + while(carrier_2.is_connected()){carrier_2.process();} + while(other_disonnect_1 == 0){carrier_1.process(); document_1.pull();} + + CHECK(other_disonnect_1 == 2); + + carrier_1.rebind("", 0); + + while(carrier_1.is_connected()) + { + carrier_1.process(); + } + + server.stop(); + + server_thread.join(); + + juce::File backend ("./server_backend"); + + if (backend.exists()) + { + backend.deleteRecursively(); + } + } +} From 13ac18df41eb0c11d1b2a2507b18e85315353a9b Mon Sep 17 00:00:00 2001 From: jean-millot Date: Mon, 12 Jun 2017 11:09:04 +0200 Subject: [PATCH 003/148] Code review update documentation. --- CMakeLists.txt | 2 +- Modules/KiwiServer/KiwiServer_Server.cpp | 10 +++--- Modules/KiwiServer/KiwiServer_Server.h | 31 +++++++++------- Server/Source/Main.cpp | 19 ++++++---- Test/Server/test_Server.cpp | 46 +++++++++++++----------- 5 files changed, 61 insertions(+), 47 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 34ab95ce..dc0a35a9 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -475,7 +475,7 @@ add_executable(test_server ${TEST_SERVER_SRC}) target_add_dependency(test_server KiwiServer) set_target_properties(test_server PROPERTIES FOLDER Test) if (LINUX) - target_link_libraries(test_engine PUBLIC ${PTHREAD}) + target_link_libraries(test_server PUBLIC ${PTHREAD}) endif() source_group_rec("${TEST_SERVER_SRC}" ${ROOT_DIR}/Test/Server) diff --git a/Modules/KiwiServer/KiwiServer_Server.cpp b/Modules/KiwiServer/KiwiServer_Server.cpp index 86912e94..4eedfcc8 100644 --- a/Modules/KiwiServer/KiwiServer_Server.cpp +++ b/Modules/KiwiServer/KiwiServer_Server.cpp @@ -21,13 +21,13 @@ #include "KiwiServer_Server.h" +#include + #include #include #include #include -#include -#include namespace kiwi { @@ -101,7 +101,7 @@ namespace kiwi return m_running; } - juce::File Server::getSessionFile(uint64_t session_id) + juce::File Server::getSessionFile(uint64_t session_id) const { return m_backend_directory.getChildFile(juce::String(hexadecimal_convert(session_id))) .withFileExtension(kiwi_file_extension); @@ -111,7 +111,7 @@ namespace kiwi { const auto session_file = getSessionFile(session_id); - m_sessions.insert(std::move(std::make_pair(session_id, Session(session_id, session_file)))); + m_sessions.insert(std::make_pair(session_id, Session(session_id, session_file))); } void Server::onConnected(flip::PortBase & port) @@ -204,7 +204,7 @@ namespace kiwi , m_validator(std::move(other.m_validator)) , m_document(std::move(other.m_document)) , m_signal_connections(std::move(other.m_signal_connections)) - , m_backend_file(other.m_backend_file) + , m_backend_file(std::move(other.m_backend_file)) { ; } diff --git a/Modules/KiwiServer/KiwiServer_Server.h b/Modules/KiwiServer/KiwiServer_Server.h index 2bbe4690..16281b31 100644 --- a/Modules/KiwiServer/KiwiServer_Server.h +++ b/Modules/KiwiServer/KiwiServer_Server.h @@ -21,7 +21,6 @@ #pragma once -#include #include #include #include @@ -56,17 +55,18 @@ namespace kiwi public: // methods //! @brief Constructor. + //! @details Initializes socket and creates backend directory if not there. Server(uint16_t port, std::string const& backend_directory); //! @brief Destructor. - //! @details Disconnect all users and clean sessions. + //! @details Disconnect all users and clean sessions. onDisconnected will be called for all port. ~Server(); //! @brief Process the socket hence process all sessions. void process(); //! @brief Run the server. - //! @details This will run a loop that call ServerBase::process regularly. + //! @details This will run a loop that call process regularly. //! @see stop void run(); @@ -80,16 +80,17 @@ namespace kiwi private: // methods //! @brief Creates a new session for server. + //! @details Will load the document if there's a corresponding file in backend directory. void createSession(uint64_t session_id); - //! @brief Called when a user connects to a document + //! @brief Called when a user connects to a document. void onConnected(flip::PortBase & port); - //! @brief Called when a user has been disconnected from a document + //! @brief Called when a user has been disconnected from a document. void onDisconnected(flip::PortBase & port); //! @brief Get the path for a given session. - juce::File getSessionFile(uint64_t session_id); + juce::File getSessionFile(uint64_t session_id) const; private: // methods @@ -123,6 +124,7 @@ namespace kiwi private: // deleted methods + Server() = delete; Server(Server const& other) = delete; Server(Server &&other) = delete; Server &operator=(Server const& other) = delete; @@ -142,28 +144,31 @@ namespace kiwi Session(Session && rhs); //! @brief Constructor - //! @detailss Initialized with an empty document. + //! @details Constructor will load the document if file exists. backend_file is + //! the file in which the session will save and load document. Session(uint64_t identifier, juce::File const& backend_file); //! @brief Destructor. //! @details Unbinds all documents and ports. ~Session(); + //! @brief Returns the id of the session. uint64_t getId() const; - //! @brief Returns a backend holding full presentation of the document hold by this session. + //! @brief Saves the document into designated backend file. void save() const; - //! @brief Loads the session's document from the designated Backend entity. + //! @brief Loads the document from designated backend file. void load(); //! @brief Binds user to session. void bind(flip::PortBase & port); - //! @brief Unbind user to session. + //! @brief Unbinds user from session. + //! @details If user that disconnect is the last one, the session will be saved. void unbind(flip::PortBase & port); - //! @brief Returns wether a certain user is connected to session. + //! @brief Returns wether or not a certain user is connected to session. bool hasUser(uint64_t user_id) const; //! @brief Returns a list of connected users. @@ -177,7 +182,7 @@ namespace kiwi //! @brief Replies to a client with a list of connected users. void sendConnectedUsers() const; - private: // variables + private: // members const uint64_t m_identifier; std::unique_ptr m_validator; @@ -185,7 +190,7 @@ namespace kiwi std::vector m_signal_connections; juce::File m_backend_file; - private: // variables + private: // deleted methods Session() = delete; Session(const Session & rhs) = delete; diff --git a/Server/Source/Main.cpp b/Server/Source/Main.cpp index 9c0d3d6e..4d866a4b 100644 --- a/Server/Source/Main.cpp +++ b/Server/Source/Main.cpp @@ -56,15 +56,11 @@ int main(int argc, char const* argv[]) model::DataModel::init(); + json config; + try { - json config = json::parse(configuration_file.loadFileAsString().toStdString()); - - std::unique_ptr server(new server::Server(config["port"], config["backend_directory"])); - - std::cout << "[server] - running on port " << config["port"] << std::endl; - - server->run(); + config = json::parse(configuration_file.loadFileAsString().toStdString()); } catch(nlohmann::detail::parse_error const& e) { @@ -76,6 +72,15 @@ int main(int argc, char const* argv[]) std::cerr << "Accessing element json element failed : " << e.what() << "\n"; return 0; } + + try + { + server::Server server(config["port"], config["backend_directory"]); + + std::cout << "[server] - running on port " << config["port"] << std::endl; + + server.run(); + } catch(std::runtime_error const& e) { std::cerr << "Launching server failed: \nerr : " << e.what() << "\n"; diff --git a/Test/Server/test_Server.cpp b/Test/Server/test_Server.cpp index a03f9b36..9704e866 100755 --- a/Test/Server/test_Server.cpp +++ b/Test/Server/test_Server.cpp @@ -39,13 +39,15 @@ TEST_CASE("Server - Server", "[Server, Server]") { SECTION("Simple Connection - Deconnection") { - kiwi::server::Server server(9090, "./server_backend"); + kiwi::server::Server server(9191, "./server_backend_test"); std::thread server_thread([&server](){server.run();}); + // Initializing document flip::Document document (kiwi::model::DataModel::use (), 123456789ULL, 'appl', 'gui '); - flip::CarrierTransportSocketTcp carrier (document, 987654ULL, "localhost", 9090); + flip::CarrierTransportSocketTcp carrier (document, 987654ULL, "localhost", 9191); + // Client/Document connecting to server. while(!carrier.is_connected()) { carrier.process(); @@ -53,6 +55,7 @@ TEST_CASE("Server - Server", "[Server, Server]") CHECK(carrier.is_connected()); + // Client/Document disconnects from server. carrier.rebind("", 0); CHECK(!carrier.is_connected()); @@ -60,7 +63,7 @@ TEST_CASE("Server - Server", "[Server, Server]") server.stop(); server_thread.join(); - juce::File backend ("./server_backend"); + juce::File backend ("./server_backend_test"); if (backend.exists()) { @@ -70,13 +73,15 @@ TEST_CASE("Server - Server", "[Server, Server]") SECTION("Simple Connection - Server Killed") { - std::unique_ptr server(new kiwi::server::Server(9090, "./server_backend")); + std::unique_ptr server(new kiwi::server::Server(9191, "./server_backend_test")); std::thread server_thread([&server](){server->run();}); + // Initializing document. flip::Document document (kiwi::model::DataModel::use (), 123456789ULL, 'appl', 'gui '); - flip::CarrierTransportSocketTcp carrier (document, 987654ULL, "localhost", 9090); + flip::CarrierTransportSocketTcp carrier (document, 987654ULL, "localhost", 9191); + // Client/Document connecting to server. while(!carrier.is_connected()) { carrier.process(); @@ -84,10 +89,12 @@ TEST_CASE("Server - Server", "[Server, Server]") CHECK(carrier.is_connected()); + // Killing server before client is disconnected. server->stop(); server_thread.join(); server.reset(nullptr); + // Client automatically disconnected from server. while(carrier.is_connected()) { carrier.process(); @@ -95,7 +102,7 @@ TEST_CASE("Server - Server", "[Server, Server]") CHECK(!carrier.is_connected()); - juce::File backend ("./server_backend"); + juce::File backend ("./server_backend_test"); if (backend.exists()) { @@ -105,13 +112,13 @@ TEST_CASE("Server - Server", "[Server, Server]") SECTION("Multiple connections") { - kiwi::server::Server server(9090, "./server_backend"); + kiwi::server::Server server(9191, "./server_backend_test"); std::thread server_thread([&server](){server.run();}); - // initializing user 1 + // Initializing client 1 flip::Document document_1 (kiwi::model::DataModel::use (), 1UL, 'appl', 'gui '); - flip::CarrierTransportSocketTcp carrier_1 (document_1, 1234UL, "localhost", 9090); + flip::CarrierTransportSocketTcp carrier_1 (document_1, 1234UL, "localhost", 9191); kiwi::model::Patcher& patcher_1 = document_1.root(); @@ -129,9 +136,9 @@ TEST_CASE("Server - Server", "[Server, Server]") other_disonnect_1 = user_id; }); - // initializing user 2 + // Initializing client 2 flip::Document document_2 (kiwi::model::DataModel::use (), 2UL, 'appl', 'gui '); - flip::CarrierTransportSocketTcp carrier_2 (document_2, 1234ULL, "localhost", 9090); + flip::CarrierTransportSocketTcp carrier_2 (document_2, 1234ULL, "localhost", 9191); kiwi::model::Patcher& patcher_2 = document_2.root(); @@ -142,15 +149,13 @@ TEST_CASE("Server - Server", "[Server, Server]") connected_users_2 = users; }); + // Client 1 connects to server. while(!carrier_1.is_connected()){carrier_1.process();} CHECK(carrier_1.is_connected()); - while(connected_users_2.empty()) - { - carrier_2.process(); - document_2.pull(); - } + // Client 2 connects to server. Client 2 receives all connected users, client 1 is notified. + while(connected_users_2.empty()){carrier_2.process(); document_2.pull();} auto it = std::find_if(connected_users_2.begin(), connected_users_2.end(), [](uint64_t id){return id == 1;}); @@ -160,6 +165,7 @@ TEST_CASE("Server - Server", "[Server, Server]") CHECK(other_connect_1 == 2); + // Client 2 disconnects from server. Client 1 is notified. carrier_2.rebind("", 0); while(carrier_2.is_connected()){carrier_2.process();} @@ -167,18 +173,16 @@ TEST_CASE("Server - Server", "[Server, Server]") CHECK(other_disonnect_1 == 2); + // Client 1 disconnects from server. Client 1 is notified. carrier_1.rebind("", 0); - while(carrier_1.is_connected()) - { - carrier_1.process(); - } + while(carrier_1.is_connected()){carrier_1.process();} server.stop(); server_thread.join(); - juce::File backend ("./server_backend"); + juce::File backend ("./server_backend_test"); if (backend.exists()) { From 96bf6d83a9fa181892e082483990e5627284a6bc Mon Sep 17 00:00:00 2001 From: jmillot Date: Fri, 30 Jun 2017 16:58:42 +0200 Subject: [PATCH 004/148] Fix server's tests. --- Modules/KiwiServer/KiwiServer_Server.cpp | 34 ++++++++++-- Modules/KiwiServer/KiwiServer_Server.h | 9 +++- Test/Server/test_Server.cpp | 68 ++++++++++++++---------- 3 files changed, 77 insertions(+), 34 deletions(-) diff --git a/Modules/KiwiServer/KiwiServer_Server.cpp b/Modules/KiwiServer/KiwiServer_Server.cpp index 4eedfcc8..da7b0a32 100644 --- a/Modules/KiwiServer/KiwiServer_Server.cpp +++ b/Modules/KiwiServer/KiwiServer_Server.cpp @@ -101,6 +101,24 @@ namespace kiwi return m_running; } + std::set Server::getSessions() const + { + std::set sessions; + + for(auto & session : m_sessions) + { + sessions.insert(session.first); + } + + return sessions; + } + + std::set Server::getConnectedUsers(uint64_t session_id) const + { + auto session = m_sessions.find(session_id); + return session != m_sessions.end() ? session->second.getConnectedUsers() : std::set(); + } + juce::File Server::getSessionFile(uint64_t session_id) const { return m_backend_directory.getChildFile(juce::String(hexadecimal_convert(session_id))) @@ -297,8 +315,11 @@ namespace kiwi model::Patcher& patcher = m_document->root(); + std::set user_lit = getConnectedUsers(); + std::vector users(user_lit.begin(), user_lit.end()); + // send a list of connected users to the user that is connecting. - m_document->send_signal_if(patcher.signal_receive_connected_users.make(getConnectedUsers()), + m_document->send_signal_if(patcher.signal_receive_connected_users.make(users), [&port](flip::PortBase& current_port) { return port.user() == current_port.user(); @@ -357,15 +378,15 @@ namespace kiwi }) != ports.end(); } - std::vector Server::Session::getConnectedUsers() const + std::set Server::Session::getConnectedUsers() const { - std::vector users; + std::set users; auto const& ports = m_document->ports(); for(auto const& port : ports) { - users.emplace_back(port->user()); + users.emplace(port->user()); } return users; @@ -375,7 +396,10 @@ namespace kiwi { model::Patcher& patcher = m_document->root(); - m_document->reply_signal(patcher.signal_receive_connected_users.make(getConnectedUsers())); + std::set user_list = getConnectedUsers(); + std::vector users(user_list.begin(), user_list.end()); + + m_document->reply_signal(patcher.signal_receive_connected_users.make(users)); } } } diff --git a/Modules/KiwiServer/KiwiServer_Server.h b/Modules/KiwiServer/KiwiServer_Server.h index 16281b31..e1f52ed9 100644 --- a/Modules/KiwiServer/KiwiServer_Server.h +++ b/Modules/KiwiServer/KiwiServer_Server.h @@ -32,6 +32,7 @@ #include #include +#include namespace kiwi @@ -77,6 +78,12 @@ namespace kiwi //! @brief Returns true if the server is running. bool isRunning() const noexcept; + //! @brief Returns a list of sessions currenty opened. + std::set getSessions() const; + + //! @brief Returns a list of users connected to session + std::set getConnectedUsers(uint64_t session_id) const; + private: // methods //! @brief Creates a new session for server. @@ -172,7 +179,7 @@ namespace kiwi bool hasUser(uint64_t user_id) const; //! @brief Returns a list of connected users. - std::vector getConnectedUsers() const; + std::set getConnectedUsers() const; private: // methods diff --git a/Test/Server/test_Server.cpp b/Test/Server/test_Server.cpp index 9704e866..7faaf588 100755 --- a/Test/Server/test_Server.cpp +++ b/Test/Server/test_Server.cpp @@ -40,28 +40,34 @@ TEST_CASE("Server - Server", "[Server, Server]") SECTION("Simple Connection - Deconnection") { kiwi::server::Server server(9191, "./server_backend_test"); - - std::thread server_thread([&server](){server.run();}); // Initializing document - flip::Document document (kiwi::model::DataModel::use (), 123456789ULL, 'appl', 'gui '); - flip::CarrierTransportSocketTcp carrier (document, 987654ULL, "localhost", 9191); + flip::Document document (kiwi::model::DataModel::use (), 123456789, 'appl', 'gui '); + flip::CarrierTransportSocketTcp carrier (document, 987654, "localhost", 9191); // Client/Document connecting to server. - while(!carrier.is_connected()) + while(!carrier.is_connected() || server.getSessions().empty()) { carrier.process(); + server.process(); } CHECK(carrier.is_connected()); + CHECK(server.getSessions().count(987654)); + CHECK(server.getConnectedUsers(987654).count(123456789)); // Client/Document disconnects from server. carrier.rebind("", 0); - CHECK(!carrier.is_connected()); + // Client/Document connecting to server. + while(carrier.is_connected() || !server.getSessions().empty()) + { + carrier.process(); + server.process(); + } - server.stop(); - server_thread.join(); + CHECK(!carrier.is_connected()); + CHECK(server.getSessions().empty()); juce::File backend ("./server_backend_test"); @@ -75,23 +81,22 @@ TEST_CASE("Server - Server", "[Server, Server]") { std::unique_ptr server(new kiwi::server::Server(9191, "./server_backend_test")); - std::thread server_thread([&server](){server->run();}); - // Initializing document. - flip::Document document (kiwi::model::DataModel::use (), 123456789ULL, 'appl', 'gui '); - flip::CarrierTransportSocketTcp carrier (document, 987654ULL, "localhost", 9191); + flip::Document document (kiwi::model::DataModel::use (), 123456789, 'appl', 'gui '); + flip::CarrierTransportSocketTcp carrier (document, 987654, "localhost", 9191); // Client/Document connecting to server. - while(!carrier.is_connected()) + while(!carrier.is_connected() || server->getSessions().empty()) { carrier.process(); + server->process(); } CHECK(carrier.is_connected()); + CHECK(server->getSessions().count(987654)); // Killing server before client is disconnected. server->stop(); - server_thread.join(); server.reset(nullptr); // Client automatically disconnected from server. @@ -114,11 +119,9 @@ TEST_CASE("Server - Server", "[Server, Server]") { kiwi::server::Server server(9191, "./server_backend_test"); - std::thread server_thread([&server](){server.run();}); - // Initializing client 1 - flip::Document document_1 (kiwi::model::DataModel::use (), 1UL, 'appl', 'gui '); - flip::CarrierTransportSocketTcp carrier_1 (document_1, 1234UL, "localhost", 9191); + flip::Document document_1 (kiwi::model::DataModel::use (), 1, 'appl', 'gui '); + flip::CarrierTransportSocketTcp carrier_1 (document_1, 1234, "localhost", 9191); kiwi::model::Patcher& patcher_1 = document_1.root(); @@ -137,8 +140,8 @@ TEST_CASE("Server - Server", "[Server, Server]") }); // Initializing client 2 - flip::Document document_2 (kiwi::model::DataModel::use (), 2UL, 'appl', 'gui '); - flip::CarrierTransportSocketTcp carrier_2 (document_2, 1234ULL, "localhost", 9191); + flip::Document document_2 (kiwi::model::DataModel::use (), 2, 'appl', 'gui '); + flip::CarrierTransportSocketTcp carrier_2 (document_2, 1234, "localhost", 9191); kiwi::model::Patcher& patcher_2 = document_2.root(); @@ -150,38 +153,47 @@ TEST_CASE("Server - Server", "[Server, Server]") }); // Client 1 connects to server. - while(!carrier_1.is_connected()){carrier_1.process();} + while(!carrier_1.is_connected() || server.getSessions().empty()){carrier_1.process(); server.process();} CHECK(carrier_1.is_connected()); + CHECK(server.getConnectedUsers(1234).count(1)); // Client 2 connects to server. Client 2 receives all connected users, client 1 is notified. - while(connected_users_2.empty()){carrier_2.process(); document_2.pull();} + while(connected_users_2.empty() || !server.getConnectedUsers(1234).count(2)) + { + carrier_2.process(); + document_2.pull(); + server.process(); + } auto it = std::find_if(connected_users_2.begin(), connected_users_2.end(), [](uint64_t id){return id == 1;}); CHECK(it != connected_users_2.end()); - while(other_connect_1 == 0) {carrier_1.process(); document_1.pull();} + while(other_connect_1 == 0) + { + carrier_1.process(); + document_1.pull(); + server.process(); + } CHECK(other_connect_1 == 2); // Client 2 disconnects from server. Client 1 is notified. carrier_2.rebind("", 0); - while(carrier_2.is_connected()){carrier_2.process();} - while(other_disonnect_1 == 0){carrier_1.process(); document_1.pull();} + while(carrier_2.is_connected() || server.getConnectedUsers(1234).count(2)){carrier_2.process(); server.process();} + while(other_disonnect_1 == 0){carrier_1.process(); document_1.pull(); server.process();} CHECK(other_disonnect_1 == 2); // Client 1 disconnects from server. Client 1 is notified. carrier_1.rebind("", 0); - while(carrier_1.is_connected()){carrier_1.process();} + while(carrier_1.is_connected() || !server.getSessions().empty()){carrier_1.process(); server.process();} server.stop(); - server_thread.join(); - juce::File backend ("./server_backend_test"); if (backend.exists()) From 0fffafdf652e65f334e125d7cd52e0ad8b6f4b55 Mon Sep 17 00:00:00 2001 From: jmillot Date: Fri, 30 Jun 2017 17:14:38 +0200 Subject: [PATCH 005/148] Unbind port only on right sessions. --- Modules/KiwiServer/KiwiServer_Server.cpp | 36 ++++--------------- Modules/KiwiServer/KiwiServer_Server.h | 3 -- Test/Server/test_Server.cpp | 45 ++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 33 deletions(-) diff --git a/Modules/KiwiServer/KiwiServer_Server.cpp b/Modules/KiwiServer/KiwiServer_Server.cpp index da7b0a32..086675a7 100644 --- a/Modules/KiwiServer/KiwiServer_Server.cpp +++ b/Modules/KiwiServer/KiwiServer_Server.cpp @@ -146,27 +146,13 @@ namespace kiwi { port.impl_activate(false); - for(auto session_it = m_sessions.begin(); session_it != m_sessions.end();) + auto session = m_sessions.find(port.session()); + + session->second.unbind(port); + + if (session->second.getConnectedUsers().empty()) { - Session & session = session_it->second; - - if (session.hasUser(port.user())) - { - session.unbind(port); - - if (session.getConnectedUsers().empty()) - { - session_it = m_sessions.erase(session_it); - } - else - { - ++session_it; - } - } - else - { - ++session_it; - } + m_sessions.erase(session); } } @@ -368,16 +354,6 @@ namespace kiwi } } - bool Server::Session::hasUser(uint64_t user_id) const - { - auto const& ports = m_document->ports(); - - return std::find_if(ports.begin(), ports.end(), [user_id](flip::PortBase * port) - { - return port->user() == user_id; - }) != ports.end(); - } - std::set Server::Session::getConnectedUsers() const { std::set users; diff --git a/Modules/KiwiServer/KiwiServer_Server.h b/Modules/KiwiServer/KiwiServer_Server.h index e1f52ed9..b3b0bc89 100644 --- a/Modules/KiwiServer/KiwiServer_Server.h +++ b/Modules/KiwiServer/KiwiServer_Server.h @@ -175,9 +175,6 @@ namespace kiwi //! @details If user that disconnect is the last one, the session will be saved. void unbind(flip::PortBase & port); - //! @brief Returns wether or not a certain user is connected to session. - bool hasUser(uint64_t user_id) const; - //! @brief Returns a list of connected users. std::set getConnectedUsers() const; diff --git a/Test/Server/test_Server.cpp b/Test/Server/test_Server.cpp index 7faaf588..2d66f5ef 100755 --- a/Test/Server/test_Server.cpp +++ b/Test/Server/test_Server.cpp @@ -115,6 +115,51 @@ TEST_CASE("Server - Server", "[Server, Server]") } } + SECTION("One user connecting to multiple document") + { + kiwi::server::Server server(9191, "./server_backend_test"); + + // Initializing documents. + flip::Document document_1 (kiwi::model::DataModel::use (), 123456789, 'appl', 'gui '); + flip::CarrierTransportSocketTcp carrier_1 (document_1, 987654, "localhost", 9191); + + flip::Document document_2 (kiwi::model::DataModel::use (), 123456789, 'appl', 'gui '); + flip::CarrierTransportSocketTcp carrier_2 (document_2, 987655, "localhost", 9191); + + // Client/Document connecting to server. + while(!carrier_1.is_connected() || !carrier_2.is_connected() || server.getSessions().size() != 2) + { + carrier_1.process(); + carrier_2.process(); + server.process(); + } + + CHECK(carrier_1.is_connected()); + CHECK(carrier_2.is_connected()); + CHECK(server.getSessions().count(987654)); + CHECK(server.getSessions().count(987655)); + + carrier_1.rebind("", 0); + carrier_2.rebind("", 0); + + while(carrier_1.is_connected() || carrier_2.is_connected() || !server.getSessions().empty()) + { + carrier_1.process(); + carrier_2.process(); + server.process(); + } + + CHECK(!carrier_1.is_connected()); + CHECK(!carrier_2.is_connected()); + + juce::File backend ("./server_backend_test"); + + if (backend.exists()) + { + backend.deleteRecursively(); + } + } + SECTION("Multiple connections") { kiwi::server::Server server(9191, "./server_backend_test"); From 4903967c51951f03312fb9d85de3aac2a71b7694 Mon Sep 17 00:00:00 2001 From: jean-millot Date: Fri, 16 Jun 2017 12:31:02 +0200 Subject: [PATCH 006/148] Explicit ownership of task in scheduler. --- Modules/KiwiEngine/KiwiEngine_Objects.cpp | 28 ++- Modules/KiwiEngine/KiwiEngine_Objects.h | 8 +- Modules/KiwiEngine/KiwiEngine_Scheduler.h | 56 ++--- Modules/KiwiEngine/KiwiEngine_Scheduler.hpp | 98 +++++---- Test/Engine/test_Scheduler.cpp | 216 ++++---------------- 5 files changed, 149 insertions(+), 257 deletions(-) diff --git a/Modules/KiwiEngine/KiwiEngine_Objects.cpp b/Modules/KiwiEngine/KiwiEngine_Objects.cpp index 5f384912..8b17ce6a 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects.cpp @@ -195,7 +195,7 @@ namespace kiwi m_object.m_tasks.erase(std::find_if(m_object.m_tasks.begin(), m_object.m_tasks.end(), - [this](std::unique_ptr const& task) + [this](std::shared_ptr const& task) { return task.get() == this; })); @@ -223,6 +223,11 @@ namespace kiwi Receive::~Receive() { + for (std::shared_ptr const& task : m_tasks) + { + Scheduler<>::use().unschedule(task); + } + if(!m_name.empty()) { Beacon& beacon = getBeacon(m_name); @@ -239,9 +244,9 @@ namespace kiwi { if (!args.empty()) { - Task* task = new Task(*this, args); + std::shared_ptr task(new Task(*this, args)); Scheduler<>::use().schedule(task, std::chrono::milliseconds(0)); - m_tasks.insert(std::unique_ptr(task)); + m_tasks.insert(std::move(task)); } } @@ -283,7 +288,7 @@ namespace kiwi Delay::Delay(model::Object const& model, Patcher& patcher, std::vector const& args): Object(model, patcher), - m_task(*this), + m_task(new Task(*this)), m_delay(std::chrono::milliseconds(0)) { if (!args.empty()) @@ -294,6 +299,7 @@ namespace kiwi Delay::~Delay() { + Scheduler<>::use().unschedule(m_task); } void Delay::receive(size_t index, std::vector const& args) @@ -304,11 +310,11 @@ namespace kiwi { if(args[0].isString() && args[0].getString() == "bang") { - Scheduler<>::use().schedule(&m_task, m_delay); + Scheduler<>::use().schedule(m_task, m_delay); } else if(args[0].isString() && args[0].getString() == "stop") { - Scheduler<>::use().unschedule(&m_task); + Scheduler<>::use().unschedule(m_task); } } else if(index == 1) @@ -346,7 +352,7 @@ namespace kiwi m_object.m_tasks.erase(std::find_if(m_object.m_tasks.begin(), m_object.m_tasks.end(), - [this](std::unique_ptr const& task) + [this](std::shared_ptr const& task) { return task.get() == this; })); @@ -371,6 +377,10 @@ namespace kiwi Pipe::~Pipe() { + for (std::shared_ptr const& task : m_tasks) + { + Scheduler<>::use().unschedule(task); + } } void Pipe::receive(size_t index, std::vector const& args) @@ -379,9 +389,9 @@ namespace kiwi { if (index == 0) { - Task* task = new Task(*this, args); + std::shared_ptr task(new Task(*this, args)); Scheduler<>::use().schedule(task, m_delay); - m_tasks.insert(std::unique_ptr(task)); + m_tasks.insert(std::move(task)); } else if(index == 1 && args[0].isNumber()) { diff --git a/Modules/KiwiEngine/KiwiEngine_Objects.h b/Modules/KiwiEngine/KiwiEngine_Objects.h index 2c812658..5388e93a 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects.h @@ -138,7 +138,7 @@ namespace kiwi private: // members std::string m_name; - std::set> m_tasks; + std::set> m_tasks; }; // ================================================================================ // @@ -188,7 +188,7 @@ namespace kiwi Delay& m_object; }; - Task m_task; + std::shared_ptr m_task; Scheduler<>::clock_t::duration m_delay; }; @@ -212,7 +212,7 @@ namespace kiwi private: // members - std::set> m_tasks; + std::set> m_tasks; Scheduler<>::clock_t::duration m_delay; }; @@ -228,7 +228,7 @@ namespace kiwi ~Metro(); - void receive(size_t index, std::vector const& oargs) override; + void receive(size_t index, std::vector const& args) override; void timerCallBack() override; diff --git a/Modules/KiwiEngine/KiwiEngine_Scheduler.h b/Modules/KiwiEngine/KiwiEngine_Scheduler.h index 362a6940..607f978b 100644 --- a/Modules/KiwiEngine/KiwiEngine_Scheduler.h +++ b/Modules/KiwiEngine/KiwiEngine_Scheduler.h @@ -28,6 +28,7 @@ #include #include #include +#include #include "KiwiEngine_ConcurrentQueue.h" @@ -94,16 +95,16 @@ namespace kiwi //! during initialization before launching threads. void registerProducer(thread_token producer, thread_token consumer); - //! @brief Delays execution of a task. + //! @brief Delays execution of a task. Shared ownership. //! @details Calling twice this method with same task will cancel the previous scheduled execution - //! and add a new one at specified time. Ownership of task is not transfer to the scheduler. - //! One can either delete task at execution time or delete the task once done using it. - void schedule(Task * task, duration_t delay = std::chrono::milliseconds(0)); + //! and add a new one at specified time. If you move ownership of the task here the task will be + //! deleted at execution time. + void schedule(std::shared_ptr const& task, duration_t delay = std::chrono::milliseconds(0)); //! @brief Used to cancel the execution of a previously scheduled task. //! @details If the task is currently being processed by the scheduler, this method does't //! wait for the execution to finish but only guarantee that further execution will no occur. - void unschedule(Task * task); + void unschedule(std::shared_ptr const& task); //! @brief Processes events of the consumer that have reached exeuction time. void process(thread_token consumer); @@ -146,7 +147,7 @@ namespace kiwi struct Command { - std::shared_ptr m_event; + std::shared_ptr m_task; time_point_t m_time; }; @@ -158,11 +159,11 @@ namespace kiwi //! @brief Destructor ~Queue(); - //! @brief Delays the execution of a task. - void schedule(Task * task, duration_t delay); + //! @brief Delays the execution of a task. Shared ownership. + void schedule(std::shared_ptr const& task, duration_t delay); //! @brief Cancels the execution of a task. - void unschedule(Task * task); + void unschedule(std::shared_ptr const& task); //! @brief Processes all events that have reached execution time. void process(time_point_t process_time); @@ -170,16 +171,16 @@ namespace kiwi private: // methods //! @internal - void insert(std::shared_ptr event); + void emplace(Event && event); //! @internal - void remove(std::shared_ptr const& event); + void remove(Event const& event); private: // members - std::vector> m_events; - ConcurrentQueue m_commands; - mutable std::mutex m_mutex; + std::vector m_events; + ConcurrentQueue m_commands; + mutable std::mutex m_mutex; private: // friend classes @@ -224,8 +225,6 @@ namespace kiwi thread_token m_producer; thread_token m_consumer; - std::shared_ptr m_event; - private: // friends friend class Scheduler; @@ -281,7 +280,7 @@ namespace kiwi private: // members - std::unique_ptr m_task; + std::shared_ptr m_task; duration_t m_period; private: // deleted methods @@ -335,14 +334,23 @@ namespace kiwi public: // methods //! @brief Constructor. - Event(Task * task, time_point_t time); + Event(std::shared_ptr const& task, time_point_t time); + + //! @brief Copy Constructor. + Event(Event const& other); + + //! @brief Assignement operator + Event& operator=(Event const& other); + + //! @brief Moove constructor + Event(Event && other); + + //! @brief Moove assignment operator. + Event& operator=(Event && other); //! @brief Destructor. ~Event(); - //! @brief Equality operator. - bool operator==(Event const& other) const; - //! @brief Called by the scheduler to execute a the task. void execute(); @@ -352,16 +360,12 @@ namespace kiwi private: // members - Task * m_task; + std::shared_ptr m_task; time_point_t m_time; private: // deleted methods Event() = delete; - Event(Event const& other) = delete; - Event(Event && other) = delete;; - Event& operator=(Event && other); - Event& operator=(Event const& other) = delete; }; } } diff --git a/Modules/KiwiEngine/KiwiEngine_Scheduler.hpp b/Modules/KiwiEngine/KiwiEngine_Scheduler.hpp index 6c1ba74d..caca06f9 100644 --- a/Modules/KiwiEngine/KiwiEngine_Scheduler.hpp +++ b/Modules/KiwiEngine/KiwiEngine_Scheduler.hpp @@ -83,13 +83,14 @@ namespace kiwi } template - void Scheduler::schedule(Task * task, duration_t delay) + void Scheduler::schedule(std::shared_ptr const& task, duration_t delay) { + assert(task); m_queues[task->m_consumer][task->m_producer].schedule(task, delay); } template - void Scheduler::unschedule(Task * task) + void Scheduler::unschedule(std::shared_ptr const& task) { assert(task); m_queues[task->m_consumer][task->m_producer].unschedule(task); @@ -109,11 +110,12 @@ namespace kiwi } // ==================================================================================== // - // Queue // + // QUEUE // // ==================================================================================== // template Scheduler::Queue::Queue(): + m_events(), m_commands(1024) { } @@ -124,29 +126,31 @@ namespace kiwi } template - void Scheduler::Queue::schedule(Task * task, duration_t delay) + void Scheduler::Queue::schedule(std::shared_ptr const& task, duration_t delay) { - m_commands.push({task->m_event, clock_t::now() + delay }); + assert(task); + + m_commands.push({task, clock_t::now() + delay }); } template - void Scheduler::Queue::unschedule(Task * task) + void Scheduler::Queue::unschedule(std::shared_ptr const& task) { - m_commands.push({task->m_event, clock_t::time_point::max()}); + m_commands.push({task, clock_t::time_point::max()}); } template - void Scheduler::Queue::remove(std::shared_ptr const& event) + void Scheduler::Queue::remove(Event const& event) { - m_events.erase(std::remove_if(m_events.begin(), m_events.end(), [&event](auto& e) { + m_events.erase(std::remove_if(m_events.begin(), m_events.end(), [&event](Event const& e) { - return e == event; + return e.m_task == event.m_task; }), m_events.end()); } template - void Scheduler::Queue::insert(std::shared_ptr event) + void Scheduler::Queue::emplace(Event && event) { remove(event); @@ -154,9 +158,9 @@ namespace kiwi while(event_it != m_events.end()) { - if (event->m_time < (*event_it)->m_time) + if (event.m_time < event_it->m_time) { - m_events.insert(event_it, std::move(event)); + m_events.insert(event_it, event); break; } @@ -165,7 +169,7 @@ namespace kiwi if (event_it == m_events.end()) { - m_events.emplace_back(std::move(event)); + m_events.emplace_back(event); } } @@ -182,23 +186,24 @@ namespace kiwi if (m_commands.pop(command)) { - if (command.m_time != clock_t::time_point::max()) + Event event(std::move(command.m_task), command.m_time); + + if (event.m_time != clock_t::time_point::max()) { - command.m_event->m_time = command.m_time; - insert(std::move(command.m_event)); + emplace(std::move(event)); } else { - remove(command.m_event); + remove(event); } } } m_events.erase(std::remove_if(m_events.begin(), m_events.end(), [&process_time](auto& event) { - if (event->m_time <= process_time) + if (event.m_time <= process_time) { - event->execute(); + event.execute(); return true; } @@ -214,8 +219,7 @@ namespace kiwi template Scheduler::Task::Task(thread_token producer, thread_token consumer): m_producer(producer), - m_consumer(consumer), - m_event(new Event(this, time_point_t::max())) + m_consumer(consumer) { Scheduler& scheduler = Scheduler::use(); @@ -226,7 +230,6 @@ namespace kiwi template Scheduler::Task::~Task() { - m_event->m_task = nullptr; } // ==================================================================================== // @@ -278,7 +281,8 @@ namespace kiwi stopTimer(); m_period = period; - Scheduler::use().schedule(m_task.get(), m_period); + + Scheduler::use().schedule(m_task, m_period); } template @@ -286,13 +290,13 @@ namespace kiwi { timerCallBack(); - Scheduler::use().schedule(m_task.get(), m_period); + Scheduler::use().schedule(m_task, m_period); } template void Scheduler::Timer::stopTimer() { - Scheduler::use().unschedule(m_task.get()); + Scheduler::use().unschedule(m_task); } // ==================================================================================== // @@ -327,28 +331,48 @@ namespace kiwi // ==================================================================================== // template - Scheduler::Event::Event(Task * task, time_point_t time): + Scheduler::Event::Event(std::shared_ptr const& task, time_point_t time): m_task(task), m_time(time) { } template - Scheduler::Event::~Event() + Scheduler::Event::Event(Event const& other): + m_task(other.m_task), + m_time(other.m_time) { } template - bool Scheduler::Event::operator==(Event const& other) const + typename Scheduler::Event& Scheduler::Event::operator=(Event const& other) + { + m_task = other.m_task; + m_time = other.m_time; + + return *this; + } + + template + Scheduler::Event::Event(Event && other): + m_task(std::move(other.m_task)), + m_time(std::move(other.m_time)) + { + } + + template + typename Scheduler::Event& Scheduler::Event::operator=(Event && other) + { + m_task = std::move(other.m_task); + m_time = std::move(other.m_time); + + return *this; + } + + + template + Scheduler::Event::~Event() { - if (this != &other) - { - return m_task == other.m_task; - } - else - { - return true; - } } template diff --git a/Test/Engine/test_Scheduler.cpp b/Test/Engine/test_Scheduler.cpp index b411577a..17c4f8e0 100644 --- a/Test/Engine/test_Scheduler.cpp +++ b/Test/Engine/test_Scheduler.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include "../catch.hpp" @@ -38,28 +39,24 @@ class TTask final : public engine::Scheduler::Task TTask(engine::thread_token producer_token, engine::thread_token consumer_token, - std::function func, - bool process_delete = true): + std::function func): engine::Scheduler::Task(producer_token, consumer_token), - m_func(func), - m_process_delete(process_delete){}; + m_func(func) + { + } void execute() override { m_func.operator()(); - - if (m_process_delete) - { - delete this; - } } - ~TTask() = default; + ~TTask() + { + }; private: // members std::function m_func; - bool m_process_delete; }; using Scheduler = engine::Scheduler; @@ -118,7 +115,8 @@ TEST_CASE("Scheduler", "[Scheduler]") for(int i = 0 ; i < 10; ++i) { - sch.schedule(new Task(Thread::Engine, Thread::Engine, func), std::chrono::milliseconds(10 * i)); + sch.schedule(std::shared_ptr(new Task(Thread::Engine, Thread::Engine, func)), + std::chrono::milliseconds(10 * i)); } while(counter < 10){ sch.process(Thread::Engine);} @@ -136,16 +134,16 @@ TEST_CASE("Scheduler", "[Scheduler]") std::function func_cancel = [&i_cancel](){++i_cancel;}; std::function func_reschedule = [&i_reschedule](){++i_reschedule;}; - Scheduler::Task* standard = new Task(Thread::Engine, Thread::Engine, func_std); - Scheduler::Task* reschedule = new Task(Thread::Engine, Thread::Engine, func_reschedule); - Scheduler::Task* cancel = new Task(Thread::Engine, Thread::Engine, func_cancel, false); + std::shared_ptr standard(new Task(Thread::Engine, Thread::Engine, func_std)); + std::shared_ptr reschedule(new Task(Thread::Engine, Thread::Engine, func_reschedule)); + std::shared_ptr cancel(new Task(Thread::Engine, Thread::Engine, func_cancel)); - sch.schedule(standard); + sch.schedule(std::move(standard)); sch.schedule(reschedule); sch.schedule(cancel); sch.schedule(reschedule, std::chrono::milliseconds(1000 * 60 * 60)); - delete cancel; + sch.unschedule(cancel); while(i_standard < 1){sch.process(Thread::Engine);}; @@ -174,19 +172,29 @@ TEST_CASE("Scheduler", "[Scheduler]") std::function func = [&order](int number){order.push_back(number);}; - TTask * task_0 = new TTask(Thread::Engine, Thread::Engine, std::bind(func, 0), false); - TTask * task_1 = new TTask(Thread::Engine, Thread::Engine, std::bind(func, 1), false); + std::shared_ptr> task_0(new TTask(Thread::Engine, + Thread::Engine, + std::bind(func, 0))); + std::shared_ptr> task_1(new TTask(Thread::Engine, + Thread::Engine, + std::bind(func, 1))); tick_scheduler.schedule(task_0, std::chrono::milliseconds(1)); tick_scheduler.schedule(task_1, std::chrono::milliseconds(3)); - tick_scheduler.schedule(new TTask(Thread::Engine, Thread::Engine, std::bind(func, 2)), - std::chrono::milliseconds(2)); - tick_scheduler.schedule(new TTask(Thread::Engine, Thread::Engine, std::bind(func, 3)), - std::chrono::milliseconds(2)); + std::shared_ptr> task_2(new TTask(Thread::Engine, + Thread::Engine, + std::bind(func, 2))); + + std::shared_ptr> task_3(new TTask(Thread::Engine, + Thread::Engine, + std::bind(func, 3))); + + tick_scheduler.schedule(std::move(task_2), std::chrono::milliseconds(2)); + tick_scheduler.schedule(std::move(task_3), std::chrono::milliseconds(2)); tick_scheduler.schedule(task_0, std::chrono::milliseconds(3)); - delete task_1; + tick_scheduler.unschedule(task_1); while(order.size() < 3) { @@ -194,7 +202,7 @@ TEST_CASE("Scheduler", "[Scheduler]") tick_scheduler.process(Thread::Engine); } - delete task_0; + tick_scheduler.unschedule(task_0); CHECK(order[0] == 2); CHECK(order[1] == 3); @@ -222,7 +230,7 @@ TEST_CASE("Scheduler", "[Scheduler]") while(count_event < 30) { - sch.schedule(new Task(Thread::Gui, Thread::Engine, func_1)); + sch.schedule(std::shared_ptr(new Task(Thread::Gui, Thread::Engine, func_1))); ++count_event; } }); @@ -233,7 +241,7 @@ TEST_CASE("Scheduler", "[Scheduler]") while(count_event < 20) { - sch.schedule(new Task(Thread::Dsp, Thread::Engine, func_2)); + sch.schedule(std::shared_ptr(new Task(Thread::Dsp, Thread::Engine, func_2))); ++count_event; } }); @@ -251,157 +259,3 @@ TEST_CASE("Scheduler", "[Scheduler]") } } -// ==================================================================================== // -// SCHEDULER BENCHMARK // -// ==================================================================================== // - -void check_precision(std::vector * precision, Scheduler::time_point_t expected_time) -{ - precision->push_back(Scheduler::clock_t::now() - expected_time); -} - -size_t mean(std::vector &duration_list) -{ - size_t mean = 0; - - for (int i = 0; i < duration_list.size(); ++i) - { - mean = mean + std::chrono::duration_cast(duration_list[i]).count(); - } - - return mean / duration_list.size(); -} - -void construct_delay_list(std::vector &delay_list, size_t size) -{ - std::vector increment_list = {11, 56, 12, 70, 2, 92, 32, 66, 3, 102}; - - size_t cursor = 0; - size_t delay = 0; - - for (int i = 0; i < size; ++i) - { - delay_list.push_back(delay); - - delay = (delay + increment_list[cursor]) % 100; - - cursor = cursor = increment_list.size() ? 0 : cursor + 1; - } -} - -TEST_CASE("Scheduler Benchmark", "[Scheduler]") -{ - Scheduler& sch = Scheduler::use(); - - SECTION("Benchmark no delay MonoProducer") - { - // vector to check the mean of insertion time - std::vector insert; - insert.reserve(2048); - - // vector to check the execution precision of the callback - std::vector precision; - precision.reserve(2048); - - Scheduler::time_point_t before_launch = Scheduler::clock_t::now(); - - std::thread producer([&sch, &insert, &precision]() - { - size_t counter = 0; - - while(counter < 2048) - { - Scheduler::duration_t delay = std::chrono::milliseconds(0); - - Scheduler::Task* task = new Task(Thread::Gui, - Thread::Engine, - std::bind(check_precision, &precision, Scheduler::clock_t::now())); - - - Scheduler::time_point_t before = Scheduler::clock_t::now(); - - sch.schedule(task, delay); - - insert.push_back(Scheduler::clock_t::now() - before); - ++counter; - } - }); - - std::thread consumer([&sch, &precision]() - { - while(precision.size() < 2048) - { - sch.process(Thread::Engine); - } - }); - - producer.join(); - consumer.join(); - - size_t exec_time = std::chrono::duration_cast(Scheduler::clock_t::now() - before_launch).count(); - - std::cout << "Benchmark no delay results ------------" << std::endl; - std::cout << "Global Time : " << exec_time << " microseconds" << std::endl; - std::cout << "Mean insert time : " << mean(insert) << " nanoseconds" << std::endl; - std::cout << "Mean precision : " << mean(precision) << " nanoseconds" << std::endl << std::endl; - } - - SECTION("Benchmark random delay MonoProducer") - { - // vector to check the mean of insertion time - std::vector insert; - insert.reserve(2048); - - // vector to check the execution precision of the callback - std::vector precision; - precision.reserve(2048); - - // vector of pseudo random delay time between 0 and 100 - std::vector delay_list; - construct_delay_list(delay_list, 2048); - - Scheduler::time_point_t before_launch = Scheduler::clock_t::now(); - - std::thread producer([&sch, &insert, &precision, &delay_list]() - { - size_t counter = 0; - - while(counter < 2048) - { - Scheduler::duration_t delay = std::chrono::milliseconds(delay_list[counter]); - - std::function func = - std::bind(check_precision, &precision, Scheduler::clock_t::now() + delay); - - Task* task = new Task(Thread::Gui, Thread::Engine, func); - - Scheduler::time_point_t before = Scheduler::clock_t::now(); - - sch.schedule(task, delay); - - insert.push_back(Scheduler::clock_t::now() - before); - ++counter; - } - }); - - std::thread consumer([&sch, &precision]() - { - while(precision.size() < 2048) - { - sch.process(Thread::Engine); - } - }); - - consumer.join(); - producer.join(); - - size_t exec_time = - std::chrono::duration_cast(Scheduler::clock_t::now() - before_launch).count(); - - std::cout << "Benchmark delay results -------------------" << std::endl; - std::cout << "Global Time : " << exec_time << " microseconds" << std::endl; - std::cout << "Mean insert time : " << mean(insert) << " nanoseconds" << std::endl; - std::cout << "Mean precision nanoseconds: " << mean(precision) << " nanoseconds" << std::endl << std::endl; - } -} - From 818679e3956fcc7686c40900b8aa730b3c86b9b1 Mon Sep 17 00:00:00 2001 From: jean-millot Date: Mon, 19 Jun 2017 15:59:59 +0200 Subject: [PATCH 007/148] Enabling adding producers on the fly. --- .gitmodules | 6 +- CMakeLists.txt | 2 +- Client/Source/KiwiApp.cpp | 2 - .../KiwiEngine/KiwiEngine_ConcurrentQueue.h | 13 ++- Modules/KiwiEngine/KiwiEngine_Objects.cpp | 8 +- Modules/KiwiEngine/KiwiEngine_Scheduler.h | 21 ++-- Modules/KiwiEngine/KiwiEngine_Scheduler.hpp | 36 +++---- Test/Engine/test_Scheduler.cpp | 99 +++++++++++++++---- ThirdParty/concurrentqueue | 1 + ThirdParty/readerwriterqueue | 1 - 10 files changed, 117 insertions(+), 72 deletions(-) create mode 160000 ThirdParty/concurrentqueue delete mode 160000 ThirdParty/readerwriterqueue diff --git a/.gitmodules b/.gitmodules index 491d0b95..dac02834 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,6 +4,6 @@ [submodule "ThirdParty/cpr"] path = ThirdParty/cpr url = https://github.com/whoshuu/cpr.git -[submodule "ThirdParty/readerwriterqueue"] - path = ThirdParty/readerwriterqueue - url = https://github.com/cameron314/readerwriterqueue.git \ No newline at end of file +[submodule "ThirdParty/concurrentqueue"] + path = ThirdParty/concurrentqueue + url = https://github.com/cameron314/concurrentqueue.git diff --git a/CMakeLists.txt b/CMakeLists.txt index dc0a35a9..1814d74d 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -372,7 +372,7 @@ source_group_rec("${KIWI_DSP_SRC}" ${ROOT_DIR}/Modules/KiwiDsp) file(GLOB_RECURSE KIWI_ENGINE_SRC ${ROOT_DIR}/Modules/KiwiEngine/*.[c|h]pp ${ROOT_DIR}/Modules/KiwiEngine/*.h) add_library(KiwiEngine STATIC ${KIWI_ENGINE_SRC}) -target_include_directories(KiwiEngine PUBLIC ${ROOT_DIR}/ThirdParty/readerwriterqueue) +target_include_directories(KiwiEngine PUBLIC ${ROOT_DIR}/ThirdParty/concurrentqueue) target_include_directories(KiwiEngine PUBLIC ${ROOT_DIR}/Modules) target_add_dependency(KiwiEngine KiwiModel) target_add_dependency(KiwiEngine KiwiDsp) diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index 13ba6d46..77332135 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -107,8 +107,6 @@ namespace kiwi engine::Scheduler<>& scheduler = engine::Scheduler<>::createInstance(); scheduler.registerConsumer(Thread::Engine); - scheduler.registerProducer(Thread::Gui, Thread::Engine); - scheduler.registerProducer(Thread::Engine, Thread::Engine); m_quit_requested.store(false); m_engine_thread = std::thread(std::bind(&KiwiApp::processEngine, this)); diff --git a/Modules/KiwiEngine/KiwiEngine_ConcurrentQueue.h b/Modules/KiwiEngine/KiwiEngine_ConcurrentQueue.h index 0accd852..20f5f0b1 100644 --- a/Modules/KiwiEngine/KiwiEngine_ConcurrentQueue.h +++ b/Modules/KiwiEngine/KiwiEngine_ConcurrentQueue.h @@ -24,7 +24,7 @@ #include #include -#include +#include namespace kiwi { @@ -100,10 +100,17 @@ namespace kiwi return m_size.load(); } + private: // classes + + struct Trait : public moodycamel::ConcurrentQueueDefaultTraits + { + static const size_t BLOCK_SIZE = 1024; + }; + private: // members - mc::ReaderWriterQueue m_queue; - std::atomic m_size; + mc::ConcurrentQueue m_queue; + std::atomic m_size; private: // deleted methods diff --git a/Modules/KiwiEngine/KiwiEngine_Objects.cpp b/Modules/KiwiEngine/KiwiEngine_Objects.cpp index 8b17ce6a..48c985e4 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects.cpp @@ -179,7 +179,7 @@ namespace kiwi public: // methods Task(Receive& object, std::vector const& atoms): - Scheduler<>::Task(Thread::Gui, Thread::Engine), + Scheduler<>::Task(Thread::Engine), m_object(object), m_atoms(atoms) { @@ -276,7 +276,7 @@ namespace kiwi // ================================================================================ // Delay::Task::Task(Delay& object): - Scheduler<>::Task(Thread::Engine, Thread::Engine), + Scheduler<>::Task(Thread::Engine), m_object(object) { } @@ -336,7 +336,7 @@ namespace kiwi public: // methods Task(Pipe & object, std::vector const& atoms): - Scheduler<>::Task(Thread::Engine, Thread::Engine), + Scheduler<>::Task(Thread::Engine), m_object(object), m_atoms(atoms) { @@ -406,7 +406,7 @@ namespace kiwi Metro::Metro(model::Object const& model, Patcher& patcher, std::vector const& args): engine::Object(model, patcher), - Scheduler<>::Timer(Thread::Engine, Thread::Engine), + Scheduler<>::Timer(Thread::Engine), m_period(std::chrono::milliseconds(0)) { if(!args.empty()) diff --git a/Modules/KiwiEngine/KiwiEngine_Scheduler.h b/Modules/KiwiEngine/KiwiEngine_Scheduler.h index 607f978b..30a204b7 100644 --- a/Modules/KiwiEngine/KiwiEngine_Scheduler.h +++ b/Modules/KiwiEngine/KiwiEngine_Scheduler.h @@ -88,13 +88,6 @@ namespace kiwi //! is not thread safe and shall be done during initialization before launching threads. void registerConsumer(thread_token consumer); - //! @brief Adds a producer to the scheduler. - //! @details Does nothing if the pair consumer/producer already existed. Will register consumer - //! if not already registered. Creates a monoproducer, monoconsumer queue for the designated - //! pair of thread. Registering consumers is not thread safe and shall be done - //! during initialization before launching threads. - void registerProducer(thread_token producer, thread_token consumer); - //! @brief Delays execution of a task. Shared ownership. //! @details Calling twice this method with same task will cancel the previous scheduled execution //! and add a new one at specified time. If you move ownership of the task here the task will be @@ -119,7 +112,7 @@ namespace kiwi private: // members - std::map> m_queues; + std::map m_queues; private: // static members @@ -139,7 +132,7 @@ namespace kiwi //! @brief A class that holds a list of scheduled events. //! @details Implementation countains a list of events sorted by execution time that is updated - //! before processing using commands. A queue is created for each pair of producer/consumer. + //! before processing using commands. A queue is created for each consumer. template class Scheduler::Queue final { @@ -206,8 +199,8 @@ namespace kiwi public: // methods //! @brief Constructor. - //! @details A certain task is designed to be scheduled on only one pair of producer/consumer. - Task(thread_token producer, thread_token consumer); + //! @details A certain task is designed to be scheduled on only one consumer. + Task(thread_token consumer); //! @brief Destructor. //! @details It is not safe to destroy a task from another thread than the consumer because it can be @@ -223,8 +216,8 @@ namespace kiwi private: // methods - thread_token m_producer; thread_token m_consumer; + private: // friends friend class Scheduler; @@ -253,8 +246,8 @@ namespace kiwi public: // methods //! @brief Constructor. - //! @details A timer can only be created for a certain pair of producer/consumer. - Timer(thread_token producer_token, thread_token consumer_token); + //! @details A timer can only be created for a certain consumer. + Timer(thread_token consumer_token); //! @brief Destructor. //! @details It is not safe to destroy a timer in another thread than the consumer. If intended diff --git a/Modules/KiwiEngine/KiwiEngine_Scheduler.hpp b/Modules/KiwiEngine/KiwiEngine_Scheduler.hpp index caca06f9..c38171bc 100644 --- a/Modules/KiwiEngine/KiwiEngine_Scheduler.hpp +++ b/Modules/KiwiEngine/KiwiEngine_Scheduler.hpp @@ -75,25 +75,19 @@ namespace kiwi { m_queues[consumer]; } - - template - void Scheduler::registerProducer(thread_token producer, thread_token consumer) - { - m_queues[consumer][producer]; - } template void Scheduler::schedule(std::shared_ptr const& task, duration_t delay) { assert(task); - m_queues[task->m_consumer][task->m_producer].schedule(task, delay); + m_queues[task->m_consumer].schedule(task, delay); } template void Scheduler::unschedule(std::shared_ptr const& task) { assert(task); - m_queues[task->m_consumer][task->m_producer].unschedule(task); + m_queues[task->m_consumer].unschedule(task); } template @@ -103,7 +97,7 @@ namespace kiwi time_point_t process_time = clock_t::now(); - for(auto& queue : m_queues[consumer]) + for(auto& queue : m_queues) { queue.second.process(process_time); } @@ -217,14 +211,12 @@ namespace kiwi // ==================================================================================== // template - Scheduler::Task::Task(thread_token producer, thread_token consumer): - m_producer(producer), + Scheduler::Task::Task(thread_token consumer): m_consumer(consumer) { Scheduler& scheduler = Scheduler::use(); - assert(scheduler.m_queues.find(consumer) != scheduler.m_queues.end() && - scheduler.m_queues[consumer].find(producer) != scheduler.m_queues[consumer].end()); + assert(scheduler.m_queues.find(consumer) != scheduler.m_queues.end()); } template @@ -241,8 +233,8 @@ namespace kiwi { public: // methods - Task(Timer& timer, thread_token producer, thread_token consumer): - Scheduler::Task(producer, consumer), + Task(Timer& timer, thread_token consumer): + Scheduler::Task(consumer), m_timer(timer) { } @@ -264,8 +256,8 @@ namespace kiwi }; template - Scheduler::Timer::Timer(thread_token producer, thread_token consumer): - m_task(new Task(*this, producer, consumer)) + Scheduler::Timer::Timer(thread_token consumer): + m_task(new Task(*this, consumer)) { } @@ -309,10 +301,7 @@ namespace kiwi { Scheduler& scheduler = Scheduler::use(); - for (auto & queue : scheduler.m_queues[m_consumer]) - { - queue.second.m_mutex.lock(); - } + scheduler.m_queues[m_consumer].m_mutex.lock(); } template @@ -320,10 +309,7 @@ namespace kiwi { Scheduler& scheduler = Scheduler::use(); - for (auto & queue : scheduler.m_queues[m_consumer]) - { - queue.second.m_mutex.unlock(); - } + scheduler.m_queues[m_consumer].m_mutex.unlock(); } // ==================================================================================== // diff --git a/Test/Engine/test_Scheduler.cpp b/Test/Engine/test_Scheduler.cpp index 17c4f8e0..f1d1d175 100644 --- a/Test/Engine/test_Scheduler.cpp +++ b/Test/Engine/test_Scheduler.cpp @@ -37,10 +37,9 @@ class TTask final : public engine::Scheduler::Task { public: // methods - TTask(engine::thread_token producer_token, - engine::thread_token consumer_token, + TTask(engine::thread_token consumer_token, std::function func): - engine::Scheduler::Task(producer_token, consumer_token), + engine::Scheduler::Task(consumer_token), m_func(func) { } @@ -102,11 +101,6 @@ TEST_CASE("Scheduler", "[Scheduler]") sch.registerConsumer(Thread::Engine); - sch.registerProducer(Thread::Gui, Thread::Engine); - sch.registerProducer(Thread::Dsp, Thread::Engine); - sch.registerProducer(Thread::Engine, Thread::Engine); - - SECTION("Simple add and process") { int counter = 0; @@ -115,7 +109,7 @@ TEST_CASE("Scheduler", "[Scheduler]") for(int i = 0 ; i < 10; ++i) { - sch.schedule(std::shared_ptr(new Task(Thread::Engine, Thread::Engine, func)), + sch.schedule(std::shared_ptr(new Task(Thread::Engine, func)), std::chrono::milliseconds(10 * i)); } @@ -134,9 +128,9 @@ TEST_CASE("Scheduler", "[Scheduler]") std::function func_cancel = [&i_cancel](){++i_cancel;}; std::function func_reschedule = [&i_reschedule](){++i_reschedule;}; - std::shared_ptr standard(new Task(Thread::Engine, Thread::Engine, func_std)); - std::shared_ptr reschedule(new Task(Thread::Engine, Thread::Engine, func_reschedule)); - std::shared_ptr cancel(new Task(Thread::Engine, Thread::Engine, func_cancel)); + std::shared_ptr standard(new Task(Thread::Engine, func_std)); + std::shared_ptr reschedule(new Task(Thread::Engine, func_reschedule)); + std::shared_ptr cancel(new Task(Thread::Engine, func_cancel)); sch.schedule(std::move(standard)); sch.schedule(reschedule); @@ -166,28 +160,23 @@ TEST_CASE("Scheduler", "[Scheduler]") engine::Scheduler& tick_scheduler = engine::Scheduler::use(); tick_scheduler.registerConsumer(Thread::Engine); - tick_scheduler.registerProducer(Thread::Engine, Thread::Engine); std::vector order; std::function func = [&order](int number){order.push_back(number);}; std::shared_ptr> task_0(new TTask(Thread::Engine, - Thread::Engine, std::bind(func, 0))); std::shared_ptr> task_1(new TTask(Thread::Engine, - Thread::Engine, std::bind(func, 1))); tick_scheduler.schedule(task_0, std::chrono::milliseconds(1)); tick_scheduler.schedule(task_1, std::chrono::milliseconds(3)); std::shared_ptr> task_2(new TTask(Thread::Engine, - Thread::Engine, std::bind(func, 2))); std::shared_ptr> task_3(new TTask(Thread::Engine, - Thread::Engine, std::bind(func, 3))); tick_scheduler.schedule(std::move(task_2), std::chrono::milliseconds(2)); @@ -230,7 +219,7 @@ TEST_CASE("Scheduler", "[Scheduler]") while(count_event < 30) { - sch.schedule(std::shared_ptr(new Task(Thread::Gui, Thread::Engine, func_1))); + sch.schedule(std::shared_ptr(new Task(Thread::Engine, func_1))); ++count_event; } }); @@ -241,7 +230,7 @@ TEST_CASE("Scheduler", "[Scheduler]") while(count_event < 20) { - sch.schedule(std::shared_ptr(new Task(Thread::Dsp, Thread::Engine, func_2))); + sch.schedule(std::shared_ptr(new Task(Thread::Engine, func_2))); ++count_event; } }); @@ -257,5 +246,77 @@ TEST_CASE("Scheduler", "[Scheduler]") producer_1.join(); producer_2.join(); } + + SECTION("Multithreading execution order") + { + std::vector order; + + std::function func_1 = [&order]() + { + order.push_back(1); + }; + + std::function func_2 = [&order]() + { + order.push_back(2); + }; + + // Pushing producer 1 before producer 2 + + { + std::thread producer_1([&sch, &func_1]() + { + sch.schedule(std::make_shared(Thread::Engine, func_1)); + }); + + producer_1.join(); + + std::thread producer_2([&sch, &func_2]() + { + sch.schedule(std::make_shared(Thread::Engine, func_2)); + }); + + producer_2.join(); + + while(order.size() < 2) + { + sch.process(Thread::Engine); + } + + // Check that producer 1's task is executed first. + + CHECK(order[0] == 1); + CHECK(order[1] == 2); + + } + + // Pushgin producer 2 before producer 1 + + { + std::thread producer_2([&sch, &func_2]() + { + sch.schedule(std::make_shared(Thread::Engine, func_2)); + }); + + producer_2.join(); + + std::thread producer_1([&sch, &func_1]() + { + sch.schedule(std::make_shared(Thread::Engine, func_1)); + }); + + producer_1.join(); + + while(order.size() < 4) + { + sch.process(Thread::Engine); + } + + // Check that producer 2's task is executed first. + + CHECK(order[2] == 2); + CHECK(order[3] == 1); + } + } } diff --git a/ThirdParty/concurrentqueue b/ThirdParty/concurrentqueue new file mode 160000 index 00000000..5170da7f --- /dev/null +++ b/ThirdParty/concurrentqueue @@ -0,0 +1 @@ +Subproject commit 5170da7fd04335da6d4e1d2ed7209a539176e589 diff --git a/ThirdParty/readerwriterqueue b/ThirdParty/readerwriterqueue deleted file mode 160000 index 4c8fc3e6..00000000 --- a/ThirdParty/readerwriterqueue +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 4c8fc3e608d6e17c250df5db7da6bd0deaffa2a0 From 5f7f6c65b76e82b0a73554321f89fbb7f89561bc Mon Sep 17 00:00:00 2001 From: jean-millot Date: Mon, 19 Jun 2017 16:43:15 +0200 Subject: [PATCH 008/148] Fixup initializing with right submodule in CI --- .travis.yml | 4 ++-- appveyor.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index b9909d97..9ccd676e 100755 --- a/.travis.yml +++ b/.travis.yml @@ -35,7 +35,7 @@ matrix: install: # make sure CXX is correctly set - if [[ "${COMPILER}" != "" ]]; then export CXX=${COMPILER}; fi - - git submodule update --init --recursive ThirdParty/Juce ThirdParty/cpr ThirdParty/readerwriterqueue + - git submodule update --init --recursive ThirdParty/Juce ThirdParty/cpr ThirdParty/concurrentqueue - pip install --user cpp-coveralls - wget --no-check-certificate -O ../curl-7.52.1.tar.gz https://github.com/Musicoll/Kiwi/files/999838/curl-7.52.1-linux.tar.gz - wget --no-check-certificate -O ../flip-demo.tar.gz http://developer.irisate.com.s3-website-us-east-1.amazonaws.com/files/flip-demo-linux-c47e41da05.tar.gz @@ -74,7 +74,7 @@ matrix: env: COMPILER=clang++ install: - - git submodule update --init --recursive ThirdParty/Juce ThirdParty/cpr ThirdParty/readerwriterqueue + - git submodule update --init --recursive ThirdParty/Juce ThirdParty/cpr ThirdParty/concurrentqueue - curl -o ../curl-7.52.1.zip -L https://github.com/Musicoll/Kiwi/files/997532/curl-7.52.1-macos.zip - curl -o ../flip-demo.tar.gz -L http://developer.irisate.com.s3-website-us-east-1.amazonaws.com/files/flip-demo-macos-c47e41da05.tar.gz - cd .. diff --git a/appveyor.yml b/appveyor.yml index 9107cdfe..8fa16df5 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -15,7 +15,7 @@ environment: install: - git submodule update --init --recursive "ThirdParty/Juce" - git submodule update --init --recursive "ThirdParty/cpr" - - git submodule update --init --recursive "ThirdParty/readerwriterqueue" + - git submodule update --init --recursive "ThirdParty/concurrentqueue" - set PATH=C:\Python27;%PATH% - curl -o ..\curl-7.52.1-win32.zip -L -k https://github.com/Musicoll/Kiwi/files/998123/curl-7.52.1-win32.zip - curl -o ..\curl-7.52.1-x64.zip -L -k https://github.com/Musicoll/Kiwi/files/997546/curl-7.52.1-x64.zip From a05f8d640f8f2027e28c070715bedd358eaf3f78 Mon Sep 17 00:00:00 2001 From: jean-millot Date: Mon, 19 Jun 2017 19:42:50 +0200 Subject: [PATCH 009/148] Stop using scheduler as a singleton. One scheduler per consumer. --- Client/Source/KiwiApp.cpp | 23 ---- Client/Source/KiwiApp.h | 9 -- .../KiwiApp_PatcherManager.cpp | 9 +- Modules/KiwiEngine/KiwiEngine_Def.h | 7 -- Modules/KiwiEngine/KiwiEngine_Instance.cpp | 27 ++++- Modules/KiwiEngine/KiwiEngine_Instance.h | 16 +++ Modules/KiwiEngine/KiwiEngine_Object.cpp | 5 + Modules/KiwiEngine/KiwiEngine_Object.h | 8 ++ Modules/KiwiEngine/KiwiEngine_Objects.cpp | 22 ++-- Modules/KiwiEngine/KiwiEngine_Patcher.cpp | 9 ++ Modules/KiwiEngine/KiwiEngine_Patcher.h | 7 ++ Modules/KiwiEngine/KiwiEngine_Scheduler.h | 83 +++----------- Modules/KiwiEngine/KiwiEngine_Scheduler.hpp | 103 ++++-------------- Test/Engine/test_Scheduler.cpp | 91 ++++++---------- 14 files changed, 154 insertions(+), 265 deletions(-) diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index 77332135..07a72d19 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -98,18 +98,9 @@ namespace kiwi m_command_manager = std::make_unique(); - engine::Scheduler<>::createInstance(); - m_settings = std::make_unique(); m_menu_model.reset(new MainMenuModel()); - - engine::Scheduler<>& scheduler = engine::Scheduler<>::createInstance(); - - scheduler.registerConsumer(Thread::Engine); - - m_quit_requested.store(false); - m_engine_thread = std::thread(std::bind(&KiwiApp::processEngine, this)); m_instance = std::make_unique(); m_command_manager->registerAllCommandsForTarget(this); @@ -150,13 +141,8 @@ namespace kiwi { if(m_instance->closeAllPatcherWindows()) { - m_quit_requested.store(true); - m_engine_thread.join(); - m_instance.reset(); - engine::Scheduler<>::deleteInstance(); - quit(); } } @@ -194,15 +180,6 @@ namespace kiwi & juce::SystemStats::Windows) != 0; } - void KiwiApp::processEngine() - { - while(!m_quit_requested.load()) - { - engine::Scheduler<>::use().process(Thread::Engine); - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - } - } - // ================================================================================ // // STATIC QUERY // // ================================================================================ // diff --git a/Client/Source/KiwiApp.h b/Client/Source/KiwiApp.h index 08af5f8f..f2f8e922 100644 --- a/Client/Source/KiwiApp.h +++ b/Client/Source/KiwiApp.h @@ -21,12 +21,8 @@ #pragma once -#include - #include -#include - #include "KiwiApp_Application/KiwiApp_Instance.h" #include "KiwiApp_General/KiwiApp_StoredSettings.h" #include "KiwiApp_General/KiwiApp_LookAndFeel.h" @@ -84,9 +80,6 @@ namespace kiwi //! @brief Returns true if the app is running in a Windows operating system. static bool isWindows(); - //! @brief Run the engine scheduler executed queued events. - void processEngine(); - //============================================================================== //! @brief Get the current running application instance. @@ -214,8 +207,6 @@ namespace kiwi std::unique_ptr m_instance; std::unique_ptr m_command_manager; std::unique_ptr m_menu_model; - std::thread m_engine_thread; - std::atomic m_quit_requested; LookAndFeel m_looknfeel; TooltipWindow m_tooltip_window; diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.cpp index 391cccfd..4fdceb99 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.cpp @@ -399,13 +399,15 @@ namespace kiwi { if(patcher.added()) { - engine::Scheduler<>::Lock lock(Thread::Engine); + std::unique_lock lock(m_instance.useEngineInstance().getScheduler().lock()); + patcher.entity().emplace(patcher.document()); patcher.entity().emplace(m_instance.useEngineInstance()); } { - engine::Scheduler<>::Lock lock(Thread::Engine); + std::unique_lock lock(m_instance.useEngineInstance().getScheduler().lock()); + patcher.entity().use().modelChanged(patcher); } @@ -413,7 +415,8 @@ namespace kiwi if(patcher.removed()) { - engine::Scheduler<>::Lock lock(Thread::Engine); + std::unique_lock lock(m_instance.useEngineInstance().getScheduler().lock()); + patcher.entity().erase(); patcher.entity().erase(); } diff --git a/Modules/KiwiEngine/KiwiEngine_Def.h b/Modules/KiwiEngine/KiwiEngine_Def.h index 55cc4e93..0a9ee524 100644 --- a/Modules/KiwiEngine/KiwiEngine_Def.h +++ b/Modules/KiwiEngine/KiwiEngine_Def.h @@ -50,11 +50,4 @@ namespace kiwi class Patcher; class Instance; } - - enum Thread : engine::thread_token - { - Gui = 0, - Engine = 1, - Dsp = 2, - }; } diff --git a/Modules/KiwiEngine/KiwiEngine_Instance.cpp b/Modules/KiwiEngine/KiwiEngine_Instance.cpp index a18f7034..fd93c602 100644 --- a/Modules/KiwiEngine/KiwiEngine_Instance.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Instance.cpp @@ -32,14 +32,18 @@ namespace kiwi // ================================================================================ // Instance::Instance(std::unique_ptr audio_controler): - m_audio_controler(std::move(audio_controler)) + m_audio_controler(std::move(audio_controler)), + m_scheduler(), + m_quit(false), + m_engine_thread(std::bind(&Instance::processScheduler, this)) { addObjectsToFactory(); } Instance::~Instance() { - ; + m_quit.store(true); + m_engine_thread.join(); } // ================================================================================ // @@ -105,5 +109,24 @@ namespace kiwi { return *m_audio_controler.get(); } + + // ================================================================================ // + // SCHEDULER // + // ================================================================================ // + + Scheduler<> & Instance::getScheduler() + { + return m_scheduler; + } + + void Instance::processScheduler() + { + while(!m_quit.load()) + { + m_scheduler.process(); + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + + } + } } } diff --git a/Modules/KiwiEngine/KiwiEngine_Instance.h b/Modules/KiwiEngine/KiwiEngine_Instance.h index dace0722..e8fd4ffd 100644 --- a/Modules/KiwiEngine/KiwiEngine_Instance.h +++ b/Modules/KiwiEngine/KiwiEngine_Instance.h @@ -21,6 +21,9 @@ #pragma once +#include +#include + #include "flip/Document.h" #include "KiwiEngine_Console.h" @@ -77,16 +80,29 @@ namespace kiwi AudioControler& getAudioControler() const; + // ================================================================================ // + // SCHEDULER // + // ================================================================================ // + + //! @brief Returns the engine's scheduler. + Scheduler<> & getScheduler(); + private: // methods //! @internal Adds the engine objects to the engine::Factory void addObjectsToFactory(); + //! @internal Processes the scheduler to check if new messages have been added. + void processScheduler(); + private: // members Console m_console; std::unique_ptr m_audio_controler; + Scheduler<> m_scheduler; + std::atomic m_quit; + std::thread m_engine_thread; private: // deleted methods diff --git a/Modules/KiwiEngine/KiwiEngine_Object.cpp b/Modules/KiwiEngine/KiwiEngine_Object.cpp index cbaed1cc..be117f66 100644 --- a/Modules/KiwiEngine/KiwiEngine_Object.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Object.cpp @@ -81,6 +81,11 @@ namespace kiwi m_patcher.error(text); } + Scheduler<> & Object::getScheduler() const + { + return m_patcher.getScheduler(); + } + // ================================================================================ // // BEACON // // ================================================================================ // diff --git a/Modules/KiwiEngine/KiwiEngine_Object.h b/Modules/KiwiEngine/KiwiEngine_Object.h index db942f9f..82355346 100644 --- a/Modules/KiwiEngine/KiwiEngine_Object.h +++ b/Modules/KiwiEngine/KiwiEngine_Object.h @@ -22,6 +22,7 @@ #pragma once #include "KiwiEngine_Def.h" +#include "KiwiEngine_Scheduler.h" #include @@ -76,6 +77,13 @@ namespace kiwi //! @brief post an error message in the Console. void error(std::string const& text) const; + // ================================================================================ // + // SCHEDULER // + // ================================================================================ // + + //! @biref Returns the engine's scheduler. + Scheduler<> & getScheduler() const; + // ================================================================================ // // BEACON // // ================================================================================ // diff --git a/Modules/KiwiEngine/KiwiEngine_Objects.cpp b/Modules/KiwiEngine/KiwiEngine_Objects.cpp index 48c985e4..07fe13f5 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects.cpp @@ -179,7 +179,7 @@ namespace kiwi public: // methods Task(Receive& object, std::vector const& atoms): - Scheduler<>::Task(Thread::Engine), + Scheduler<>::Task(), m_object(object), m_atoms(atoms) { @@ -225,7 +225,7 @@ namespace kiwi { for (std::shared_ptr const& task : m_tasks) { - Scheduler<>::use().unschedule(task); + getScheduler().unschedule(task); } if(!m_name.empty()) @@ -245,7 +245,7 @@ namespace kiwi if (!args.empty()) { std::shared_ptr task(new Task(*this, args)); - Scheduler<>::use().schedule(task, std::chrono::milliseconds(0)); + getScheduler().schedule(task, std::chrono::milliseconds(0)); m_tasks.insert(std::move(task)); } } @@ -276,7 +276,7 @@ namespace kiwi // ================================================================================ // Delay::Task::Task(Delay& object): - Scheduler<>::Task(Thread::Engine), + Scheduler<>::Task(), m_object(object) { } @@ -299,7 +299,7 @@ namespace kiwi Delay::~Delay() { - Scheduler<>::use().unschedule(m_task); + getScheduler().unschedule(m_task); } void Delay::receive(size_t index, std::vector const& args) @@ -310,11 +310,11 @@ namespace kiwi { if(args[0].isString() && args[0].getString() == "bang") { - Scheduler<>::use().schedule(m_task, m_delay); + getScheduler().schedule(m_task, m_delay); } else if(args[0].isString() && args[0].getString() == "stop") { - Scheduler<>::use().unschedule(m_task); + getScheduler().unschedule(m_task); } } else if(index == 1) @@ -336,7 +336,7 @@ namespace kiwi public: // methods Task(Pipe & object, std::vector const& atoms): - Scheduler<>::Task(Thread::Engine), + Scheduler<>::Task(), m_object(object), m_atoms(atoms) { @@ -379,7 +379,7 @@ namespace kiwi { for (std::shared_ptr const& task : m_tasks) { - Scheduler<>::use().unschedule(task); + getScheduler().unschedule(task); } } @@ -390,7 +390,7 @@ namespace kiwi if (index == 0) { std::shared_ptr task(new Task(*this, args)); - Scheduler<>::use().schedule(task, m_delay); + getScheduler().schedule(task, m_delay); m_tasks.insert(std::move(task)); } else if(index == 1 && args[0].isNumber()) @@ -406,7 +406,7 @@ namespace kiwi Metro::Metro(model::Object const& model, Patcher& patcher, std::vector const& args): engine::Object(model, patcher), - Scheduler<>::Timer(Thread::Engine), + Scheduler<>::Timer(patcher.getScheduler()), m_period(std::chrono::milliseconds(0)) { if(!args.empty()) diff --git a/Modules/KiwiEngine/KiwiEngine_Patcher.cpp b/Modules/KiwiEngine/KiwiEngine_Patcher.cpp index 84d088e6..69edfd25 100644 --- a/Modules/KiwiEngine/KiwiEngine_Patcher.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Patcher.cpp @@ -187,6 +187,15 @@ namespace kiwi m_instance.error(text); } + // ================================================================================ // + // SCHEDULER // + // ================================================================================ // + + Scheduler<> & Patcher::getScheduler() const + { + return m_instance.getScheduler(); + } + // ================================================================================ // // BEACON // // ================================================================================ // diff --git a/Modules/KiwiEngine/KiwiEngine_Patcher.h b/Modules/KiwiEngine/KiwiEngine_Patcher.h index 3712f420..5bca9176 100644 --- a/Modules/KiwiEngine/KiwiEngine_Patcher.h +++ b/Modules/KiwiEngine/KiwiEngine_Patcher.h @@ -107,6 +107,13 @@ namespace kiwi //! @brief post an error message in the Console. void error(std::string const& text) const; + // ================================================================================ // + // SCHEDULER // + // ================================================================================ // + + //! @brief Returns the engine's scheduler. + Scheduler<> & getScheduler() const; + // ================================================================================ // // BEACON // // ================================================================================ // diff --git a/Modules/KiwiEngine/KiwiEngine_Scheduler.h b/Modules/KiwiEngine/KiwiEngine_Scheduler.h index 30a204b7..285f4ed2 100644 --- a/Modules/KiwiEngine/KiwiEngine_Scheduler.h +++ b/Modules/KiwiEngine/KiwiEngine_Scheduler.h @@ -29,6 +29,7 @@ #include #include #include +#include #include "KiwiEngine_ConcurrentQueue.h" @@ -40,8 +41,6 @@ namespace kiwi // SCHEDULER // // ==================================================================================== // - using thread_token = uint64_t; - //! @brief A class designed to delay tasks' execution between threads that where previously declared. //! @details The scheduler is designed as a singleton that uses multiple event lists. //! Before processing the scheduler one should create an instance and register all threads that will @@ -61,8 +60,6 @@ namespace kiwi class Timer; - class Lock; - private: // classes class Queue; @@ -71,22 +68,11 @@ namespace kiwi public: // methods - //! @brief Creates the instance of scheduler. - //! @details Shall be called before launching threads and processing the scheduler. - static Scheduler& createInstance(); - - //! @brief Retrieves the instance created with createInstance. - //! @details Fails if createInstance was not called previously. - static Scheduler& use(); - - //! @brief Destroys the instance previously created. - //! @details Call this method once caller is done using the scheduler. - static void deleteInstance(); + //! @brief Constructor + Scheduler(); - //! @brief Adds a consumer thread to the scheduler. - //! @details Does nothing if the consumer was already registered. Dynamicaly registering consumers - //! is not thread safe and shall be done during initialization before launching threads. - void registerConsumer(thread_token consumer); + //! @brief Desctructor. + ~Scheduler(); //! @brief Delays execution of a task. Shared ownership. //! @details Calling twice this method with same task will cancel the previous scheduled execution @@ -100,23 +86,15 @@ namespace kiwi void unschedule(std::shared_ptr const& task); //! @brief Processes events of the consumer that have reached exeuction time. - void process(thread_token consumer); - - private: // methods + void process(); - //! @brief Constructor - Scheduler(); - - //! @brief Desctructor. - ~Scheduler(); + //! @brief Lock the process until the returned lock is out of scope. + std::unique_lock lock() const; private: // members - std::map m_queues; - - private: // static members - - static Scheduler* m_instance; + Queue m_queue; + mutable std::mutex m_mutex; private: // deleted methods @@ -173,7 +151,6 @@ namespace kiwi std::vector m_events; ConcurrentQueue m_commands; - mutable std::mutex m_mutex; private: // friend classes @@ -200,7 +177,7 @@ namespace kiwi //! @brief Constructor. //! @details A certain task is designed to be scheduled on only one consumer. - Task(thread_token consumer); + Task(); //! @brief Destructor. //! @details It is not safe to destroy a task from another thread than the consumer because it can be @@ -214,10 +191,6 @@ namespace kiwi //! is reached. virtual void execute() = 0; - private: // methods - - thread_token m_consumer; - private: // friends friend class Scheduler; @@ -247,7 +220,7 @@ namespace kiwi //! @brief Constructor. //! @details A timer can only be created for a certain consumer. - Timer(thread_token consumer_token); + Timer(Scheduler & scheduler); //! @brief Destructor. //! @details It is not safe to destroy a timer in another thread than the consumer. If intended @@ -273,6 +246,7 @@ namespace kiwi private: // members + Scheduler & m_scheduler; std::shared_ptr m_task; duration_t m_period; @@ -285,37 +259,6 @@ namespace kiwi Timer& operator=(Timer && other) = delete; }; - // ==================================================================================== // - // LOCK // - // ==================================================================================== // - - //! @brief This class is intended to lock the execution of a certain consumer. - //! @details Beware that critical sections shall not take long since it blocks a certain thread - //! from processing events. - template - class Scheduler::Lock final - { - public: // methods - - //! @brief Constructor. - Lock(thread_token consumer); - - //! @brief Destructor. - ~Lock(); - - private: // members - - thread_token m_consumer; - - private: // deleted methods - - Lock() = delete; - Lock(Lock const& other) = delete; - Lock(Lock && other) = delete; - Lock& operator=(Lock const& other) = delete; - Lock& operator=(Lock && other) = delete; - }; - // ==================================================================================== // // EVENT // // ==================================================================================== // diff --git a/Modules/KiwiEngine/KiwiEngine_Scheduler.hpp b/Modules/KiwiEngine/KiwiEngine_Scheduler.hpp index c38171bc..06bbbdcd 100644 --- a/Modules/KiwiEngine/KiwiEngine_Scheduler.hpp +++ b/Modules/KiwiEngine/KiwiEngine_Scheduler.hpp @@ -31,12 +31,9 @@ namespace kiwi // SCHEDULER // // ==================================================================================== // - template - Scheduler* Scheduler::m_instance = nullptr; - template Scheduler::Scheduler(): - m_queues() + m_queue() { } @@ -44,63 +41,34 @@ namespace kiwi Scheduler::~Scheduler() { } - - template - Scheduler& Scheduler::createInstance() - { - if (m_instance == nullptr) - { - m_instance = new Scheduler(); - } - - return *m_instance; - } - - template - Scheduler& Scheduler::use() - { - assert(m_instance != nullptr); - return *m_instance; - } - - template - void Scheduler::deleteInstance() - { - assert(m_instance != nullptr); - delete m_instance; - } - - template - void Scheduler::registerConsumer(thread_token consumer) - { - m_queues[consumer]; - } template void Scheduler::schedule(std::shared_ptr const& task, duration_t delay) { assert(task); - m_queues[task->m_consumer].schedule(task, delay); + m_queue.schedule(task, delay); } template void Scheduler::unschedule(std::shared_ptr const& task) { assert(task); - m_queues[task->m_consumer].unschedule(task); + m_queue.unschedule(task); } template - void Scheduler::process(thread_token consumer) + void Scheduler::process() { - assert(m_queues.find(consumer) != m_queues.end()); - time_point_t process_time = clock_t::now(); - for(auto& queue : m_queues) - { - queue.second.process(process_time); - } + m_queue.process(process_time); + } + + template + std::unique_lock Scheduler::lock() const + { + std::unique_lock head_lock(m_mutex); + return std::move(head_lock); } // ==================================================================================== // @@ -170,8 +138,6 @@ namespace kiwi template void Scheduler::Queue::process(time_point_t process_time) { - std::lock_guard lock(m_mutex); - size_t command_size = m_commands.load_size(); for (size_t i = 0; i < command_size; ++i) @@ -211,12 +177,8 @@ namespace kiwi // ==================================================================================== // template - Scheduler::Task::Task(thread_token consumer): - m_consumer(consumer) + Scheduler::Task::Task() { - Scheduler& scheduler = Scheduler::use(); - - assert(scheduler.m_queues.find(consumer) != scheduler.m_queues.end()); } template @@ -233,9 +195,9 @@ namespace kiwi { public: // methods - Task(Timer& timer, thread_token consumer): - Scheduler::Task(consumer), - m_timer(timer) + Task(Timer& timer): + m_timer(timer), + m_period() { } @@ -256,8 +218,10 @@ namespace kiwi }; template - Scheduler::Timer::Timer(thread_token consumer): - m_task(new Task(*this, consumer)) + Scheduler::Timer::Timer(Scheduler & scheduler): + m_scheduler(scheduler), + m_task(new Task(*this)), + m_period() { } @@ -274,7 +238,7 @@ namespace kiwi m_period = period; - Scheduler::use().schedule(m_task, m_period); + m_scheduler.schedule(m_task, m_period); } template @@ -282,34 +246,13 @@ namespace kiwi { timerCallBack(); - Scheduler::use().schedule(m_task, m_period); + m_scheduler.schedule(m_task, m_period); } template void Scheduler::Timer::stopTimer() { - Scheduler::use().unschedule(m_task); - } - - // ==================================================================================== // - // LOCK // - // ==================================================================================== // - - template - Scheduler::Lock::Lock(thread_token consumer): - m_consumer(consumer) - { - Scheduler& scheduler = Scheduler::use(); - - scheduler.m_queues[m_consumer].m_mutex.lock(); - } - - template - Scheduler::Lock::~Lock() - { - Scheduler& scheduler = Scheduler::use(); - - scheduler.m_queues[m_consumer].m_mutex.unlock(); + m_scheduler.unschedule(m_task); } // ==================================================================================== // diff --git a/Test/Engine/test_Scheduler.cpp b/Test/Engine/test_Scheduler.cpp index f1d1d175..30d6df53 100644 --- a/Test/Engine/test_Scheduler.cpp +++ b/Test/Engine/test_Scheduler.cpp @@ -37,9 +37,8 @@ class TTask final : public engine::Scheduler::Task { public: // methods - TTask(engine::thread_token consumer_token, - std::function func): - engine::Scheduler::Task(consumer_token), + TTask(std::function func): + engine::Scheduler::Task(), m_func(func) { } @@ -79,15 +78,6 @@ struct TickClock static time_point now(){return current_time;}; }; -enum Thread : engine::thread_token -{ - Gui = 0, - Engine = 1, - Dsp = 2, - Network = 3 -}; - - // ==================================================================================== // // SCHEDULER // @@ -95,11 +85,7 @@ enum Thread : engine::thread_token TEST_CASE("Scheduler", "[Scheduler]") { - Scheduler::createInstance(); - - Scheduler& sch = Scheduler::use(); - - sch.registerConsumer(Thread::Engine); + Scheduler sch; SECTION("Simple add and process") { @@ -109,11 +95,11 @@ TEST_CASE("Scheduler", "[Scheduler]") for(int i = 0 ; i < 10; ++i) { - sch.schedule(std::shared_ptr(new Task(Thread::Engine, func)), + sch.schedule(std::shared_ptr(new Task(func)), std::chrono::milliseconds(10 * i)); } - while(counter < 10){ sch.process(Thread::Engine);} + while(counter < 10){ sch.process();} CHECK(counter == 10); } @@ -128,9 +114,9 @@ TEST_CASE("Scheduler", "[Scheduler]") std::function func_cancel = [&i_cancel](){++i_cancel;}; std::function func_reschedule = [&i_reschedule](){++i_reschedule;}; - std::shared_ptr standard(new Task(Thread::Engine, func_std)); - std::shared_ptr reschedule(new Task(Thread::Engine, func_reschedule)); - std::shared_ptr cancel(new Task(Thread::Engine, func_cancel)); + std::shared_ptr standard(new Task(func_std)); + std::shared_ptr reschedule(new Task(func_reschedule)); + std::shared_ptr cancel(new Task(func_cancel)); sch.schedule(std::move(standard)); sch.schedule(reschedule); @@ -139,7 +125,7 @@ TEST_CASE("Scheduler", "[Scheduler]") sch.schedule(reschedule, std::chrono::milliseconds(1000 * 60 * 60)); sch.unschedule(cancel); - while(i_standard < 1){sch.process(Thread::Engine);}; + while(i_standard < 1){sch.process();}; CHECK(i_standard == 1); CHECK(i_reschedule == 0); @@ -147,7 +133,7 @@ TEST_CASE("Scheduler", "[Scheduler]") sch.schedule(reschedule); - while(i_reschedule < 1){sch.process(Thread::Engine);}; + while(i_reschedule < 1){sch.process();}; CHECK(i_reschedule == 1); } @@ -156,28 +142,21 @@ TEST_CASE("Scheduler", "[Scheduler]") { TickClock::start(); - engine::Scheduler::createInstance(); - engine::Scheduler& tick_scheduler = engine::Scheduler::use(); - - tick_scheduler.registerConsumer(Thread::Engine); + engine::Scheduler tick_scheduler; std::vector order; std::function func = [&order](int number){order.push_back(number);}; - std::shared_ptr> task_0(new TTask(Thread::Engine, - std::bind(func, 0))); - std::shared_ptr> task_1(new TTask(Thread::Engine, - std::bind(func, 1))); + std::shared_ptr> task_0(new TTask(std::bind(func, 0))); + std::shared_ptr> task_1(new TTask(std::bind(func, 1))); tick_scheduler.schedule(task_0, std::chrono::milliseconds(1)); tick_scheduler.schedule(task_1, std::chrono::milliseconds(3)); - std::shared_ptr> task_2(new TTask(Thread::Engine, - std::bind(func, 2))); + std::shared_ptr> task_2(new TTask(std::bind(func, 2))); - std::shared_ptr> task_3(new TTask(Thread::Engine, - std::bind(func, 3))); + std::shared_ptr> task_3(new TTask(std::bind(func, 3))); tick_scheduler.schedule(std::move(task_2), std::chrono::milliseconds(2)); tick_scheduler.schedule(std::move(task_3), std::chrono::milliseconds(2)); @@ -188,7 +167,7 @@ TEST_CASE("Scheduler", "[Scheduler]") while(order.size() < 3) { TickClock::tick(); - tick_scheduler.process(Thread::Engine); + tick_scheduler.process(); } tick_scheduler.unschedule(task_0); @@ -198,7 +177,7 @@ TEST_CASE("Scheduler", "[Scheduler]") CHECK(order[2] == 0); } - SECTION("Multithreading multiproducern multiconsumer") + SECTION("Multithreading multiproducer multiconsumer") { std::atomic count_producer_1(0); std::atomic count_producer_2(0); @@ -219,7 +198,7 @@ TEST_CASE("Scheduler", "[Scheduler]") while(count_event < 30) { - sch.schedule(std::shared_ptr(new Task(Thread::Engine, func_1))); + sch.schedule(std::shared_ptr(new Task(func_1))); ++count_event; } }); @@ -230,14 +209,14 @@ TEST_CASE("Scheduler", "[Scheduler]") while(count_event < 20) { - sch.schedule(std::shared_ptr(new Task(Thread::Engine, func_2))); + sch.schedule(std::shared_ptr(new Task(func_2))); ++count_event; } }); while(count_producer_1 < 30 || count_producer_2 < 20) { - sch.process(Thread::Engine); + sch.process(); } CHECK(count_producer_1 == 30); @@ -251,36 +230,28 @@ TEST_CASE("Scheduler", "[Scheduler]") { std::vector order; - std::function func_1 = [&order]() - { - order.push_back(1); - }; - - std::function func_2 = [&order]() - { - order.push_back(2); - }; + std::function func = [&order](int stamp){order.push_back(stamp);}; // Pushing producer 1 before producer 2 { - std::thread producer_1([&sch, &func_1]() + std::thread producer_1([&sch, &func]() { - sch.schedule(std::make_shared(Thread::Engine, func_1)); + sch.schedule(std::make_shared(std::bind(func, 1))); }); producer_1.join(); - std::thread producer_2([&sch, &func_2]() + std::thread producer_2([&sch, &func]() { - sch.schedule(std::make_shared(Thread::Engine, func_2)); + sch.schedule(std::make_shared(std::bind(func, 2))); }); producer_2.join(); while(order.size() < 2) { - sch.process(Thread::Engine); + sch.process(); } // Check that producer 1's task is executed first. @@ -293,23 +264,23 @@ TEST_CASE("Scheduler", "[Scheduler]") // Pushgin producer 2 before producer 1 { - std::thread producer_2([&sch, &func_2]() + std::thread producer_2([&sch, &func]() { - sch.schedule(std::make_shared(Thread::Engine, func_2)); + sch.schedule(std::make_shared(std::bind(func, 2))); }); producer_2.join(); - std::thread producer_1([&sch, &func_1]() + std::thread producer_1([&sch, &func]() { - sch.schedule(std::make_shared(Thread::Engine, func_1)); + sch.schedule(std::make_shared(std::bind(func, 1))); }); producer_1.join(); while(order.size() < 4) { - sch.process(Thread::Engine); + sch.process(); } // Check that producer 2's task is executed first. From bc21e1b45120d921fc4f4f6cfd17072e27682aa0 Mon Sep 17 00:00:00 2001 From: jean-millot Date: Tue, 20 Jun 2017 14:41:50 +0200 Subject: [PATCH 010/148] Add thread id to the scheduler. --- Modules/KiwiEngine/KiwiEngine_Instance.cpp | 2 ++ Modules/KiwiEngine/KiwiEngine_Object.cpp | 2 ++ Modules/KiwiEngine/KiwiEngine_Objects.cpp | 13 +++++++++--- Modules/KiwiEngine/KiwiEngine_Scheduler.h | 13 ++++++++++++ Modules/KiwiEngine/KiwiEngine_Scheduler.hpp | 18 ++++++++++++++++- Test/Engine/test_Scheduler.cpp | 22 +++++++++++++++++++++ 6 files changed, 66 insertions(+), 4 deletions(-) diff --git a/Modules/KiwiEngine/KiwiEngine_Instance.cpp b/Modules/KiwiEngine/KiwiEngine_Instance.cpp index fd93c602..3e872e29 100644 --- a/Modules/KiwiEngine/KiwiEngine_Instance.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Instance.cpp @@ -121,6 +121,8 @@ namespace kiwi void Instance::processScheduler() { + m_scheduler.setThreadAsConsumer(); + while(!m_quit.load()) { m_scheduler.process(); diff --git a/Modules/KiwiEngine/KiwiEngine_Object.cpp b/Modules/KiwiEngine/KiwiEngine_Object.cpp index be117f66..a11a94ba 100644 --- a/Modules/KiwiEngine/KiwiEngine_Object.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Object.cpp @@ -99,6 +99,8 @@ namespace kiwi void Object::send(const size_t index, std::vector const& args) { + assert(getScheduler().isThisConsumerThread()); + const auto idx = static_cast::size_type>(index); if(idx < m_outlets.size()) diff --git a/Modules/KiwiEngine/KiwiEngine_Objects.cpp b/Modules/KiwiEngine/KiwiEngine_Objects.cpp index 07fe13f5..b83e0ee2 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects.cpp @@ -244,9 +244,16 @@ namespace kiwi { if (!args.empty()) { - std::shared_ptr task(new Task(*this, args)); - getScheduler().schedule(task, std::chrono::milliseconds(0)); - m_tasks.insert(std::move(task)); + if (!getScheduler().isThisConsumerThread()) + { + std::shared_ptr task(new Task(*this, args)); + getScheduler().schedule(task, std::chrono::milliseconds(0)); + m_tasks.insert(std::move(task)); + } + else + { + send(0, args); + } } } diff --git a/Modules/KiwiEngine/KiwiEngine_Scheduler.h b/Modules/KiwiEngine/KiwiEngine_Scheduler.h index 285f4ed2..7f3733c8 100644 --- a/Modules/KiwiEngine/KiwiEngine_Scheduler.h +++ b/Modules/KiwiEngine/KiwiEngine_Scheduler.h @@ -30,6 +30,7 @@ #include #include #include +#include #include "KiwiEngine_ConcurrentQueue.h" @@ -69,11 +70,22 @@ namespace kiwi public: // methods //! @brief Constructor + //! @details Sets current thread as the consumer thread. Scheduler(); //! @brief Desctructor. ~Scheduler(); + //! @brief Sets the current thread as the consumer thread. + //! @details This method can be called for instance if the scheduler's constructor + //! is called on another thread than desired consumer. + void setThreadAsConsumer(); + + //! @brief Check wehter or not this thread is the consumer. + //! @details This method can be usefull to help decide if a direct call can be made + //! or if the scheduler shall be used. + bool isThisConsumerThread(); + //! @brief Delays execution of a task. Shared ownership. //! @details Calling twice this method with same task will cancel the previous scheduled execution //! and add a new one at specified time. If you move ownership of the task here the task will be @@ -95,6 +107,7 @@ namespace kiwi Queue m_queue; mutable std::mutex m_mutex; + std::thread::id m_consumer_id; private: // deleted methods diff --git a/Modules/KiwiEngine/KiwiEngine_Scheduler.hpp b/Modules/KiwiEngine/KiwiEngine_Scheduler.hpp index 06bbbdcd..fd14618d 100644 --- a/Modules/KiwiEngine/KiwiEngine_Scheduler.hpp +++ b/Modules/KiwiEngine/KiwiEngine_Scheduler.hpp @@ -33,7 +33,9 @@ namespace kiwi template Scheduler::Scheduler(): - m_queue() + m_queue(), + m_mutex(), + m_consumer_id(std::this_thread::get_id()) { } @@ -41,6 +43,18 @@ namespace kiwi Scheduler::~Scheduler() { } + + template + void Scheduler::setThreadAsConsumer() + { + m_consumer_id = std::this_thread::get_id(); + } + + template + bool Scheduler::isThisConsumerThread() + { + return m_consumer_id == std::this_thread::get_id(); + } template void Scheduler::schedule(std::shared_ptr const& task, duration_t delay) @@ -59,6 +73,8 @@ namespace kiwi template void Scheduler::process() { + assert(std::this_thread::get_id() == m_consumer_id); + time_point_t process_time = clock_t::now(); m_queue.process(process_time); diff --git a/Test/Engine/test_Scheduler.cpp b/Test/Engine/test_Scheduler.cpp index 30d6df53..acb6cc5a 100644 --- a/Test/Engine/test_Scheduler.cpp +++ b/Test/Engine/test_Scheduler.cpp @@ -288,6 +288,28 @@ TEST_CASE("Scheduler", "[Scheduler]") CHECK(order[2] == 2); CHECK(order[3] == 1); } + + SECTION("Thread ids") + { + CHECK(sch.isThisConsumerThread()); + + // Transfer consumer ownership. + + std::thread consumer_thread([&sch]() + { + sch.setThreadAsConsumer(); + CHECK(sch.isThisConsumerThread()); + }); + + consumer_thread.join(); + + CHECK(!sch.isThisConsumerThread()); + + // Transfer back the ownership, to enable further test execution. + + sch.setThreadAsConsumer(); + + } } } From 7f0491037105e12d34cd69e0f7518b0d438aed5f Mon Sep 17 00:00:00 2001 From: jean-millot Date: Tue, 20 Jun 2017 15:13:08 +0200 Subject: [PATCH 011/148] Add scheduler's lock test. --- Modules/KiwiEngine/KiwiEngine_Scheduler.hpp | 3 ++ Test/Engine/test_Scheduler.cpp | 35 +++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/Modules/KiwiEngine/KiwiEngine_Scheduler.hpp b/Modules/KiwiEngine/KiwiEngine_Scheduler.hpp index fd14618d..a285e461 100644 --- a/Modules/KiwiEngine/KiwiEngine_Scheduler.hpp +++ b/Modules/KiwiEngine/KiwiEngine_Scheduler.hpp @@ -75,6 +75,8 @@ namespace kiwi { assert(std::this_thread::get_id() == m_consumer_id); + std::lock_guard lock(m_mutex); + time_point_t process_time = clock_t::now(); m_queue.process(process_time); @@ -84,6 +86,7 @@ namespace kiwi std::unique_lock Scheduler::lock() const { std::unique_lock head_lock(m_mutex); + return std::move(head_lock); } diff --git a/Test/Engine/test_Scheduler.cpp b/Test/Engine/test_Scheduler.cpp index acb6cc5a..e206c849 100644 --- a/Test/Engine/test_Scheduler.cpp +++ b/Test/Engine/test_Scheduler.cpp @@ -308,7 +308,42 @@ TEST_CASE("Scheduler", "[Scheduler]") // Transfer back the ownership, to enable further test execution. sch.setThreadAsConsumer(); + } + + SECTION("Scheduler lock") + { + std::atomic quit_requested(false); + + std::thread consumer([&sch, &quit_requested]() + { + sch.setThreadAsConsumer(); + + while(!quit_requested.load()) + { + sch.process(); + } + }); + { + std::unique_lock lock(sch.lock()); + + std::function func = [&quit_requested]() + { + quit_requested.store(true); + }; + + sch.schedule(std::shared_ptr(new Task(func))); + + std::this_thread::sleep_for(std::chrono::seconds(1)); + + CHECK(!quit_requested); + } + + consumer.join(); + + CHECK(quit_requested); + + sch.setThreadAsConsumer(); } } } From 7afa0d3876d20a53b175f6fc6cac1c16af4e1a57 Mon Sep 17 00:00:00 2001 From: jean-millot Date: Wed, 21 Jun 2017 11:26:14 +0200 Subject: [PATCH 012/148] Creating CallBack class that hold a function in scheduler. --- Modules/KiwiEngine/KiwiEngine_Scheduler.h | 36 ++++++++++++ Modules/KiwiEngine/KiwiEngine_Scheduler.hpp | 22 +++++++ Test/Engine/test_Scheduler.cpp | 64 ++++++++------------- 3 files changed, 81 insertions(+), 41 deletions(-) diff --git a/Modules/KiwiEngine/KiwiEngine_Scheduler.h b/Modules/KiwiEngine/KiwiEngine_Scheduler.h index 7f3733c8..eaecf3ce 100644 --- a/Modules/KiwiEngine/KiwiEngine_Scheduler.h +++ b/Modules/KiwiEngine/KiwiEngine_Scheduler.h @@ -59,6 +59,8 @@ namespace kiwi class Task; + class CallBack; + class Timer; private: // classes @@ -216,6 +218,40 @@ namespace kiwi Task& operator=(Task && other) = delete; }; + // ==================================================================================== // + // CALLBACK // + // ==================================================================================== // + + //! @brief The scheduler's callback is a task that uses an std::function for + //! conveniency. + template + class Scheduler::CallBack : public Scheduler::Task + { + public: // methods + + //! @brief Constructor, initializes function. + CallBack(std::function func); + + //! @brief Destructor. + ~CallBack(); + + //! @brief Executes the given functions. + void execute() override final; + + private: // members + + std::function m_func; + + private: // deleted methods + + CallBack() = delete; + CallBack(CallBack const& other) = delete; + CallBack(CallBack && other) = delete; + CallBack& operator=(CallBack const& other) = delete; + CallBack& operator=(CallBack && other) = delete; + }; + + // ==================================================================================== // // TIMER // // ==================================================================================== // diff --git a/Modules/KiwiEngine/KiwiEngine_Scheduler.hpp b/Modules/KiwiEngine/KiwiEngine_Scheduler.hpp index a285e461..db9a671b 100644 --- a/Modules/KiwiEngine/KiwiEngine_Scheduler.hpp +++ b/Modules/KiwiEngine/KiwiEngine_Scheduler.hpp @@ -205,6 +205,28 @@ namespace kiwi { } + // ==================================================================================== // + // CALLBACK // + // ==================================================================================== // + + template + Scheduler::CallBack::CallBack(std::function func): + Task(), + m_func(func) + { + } + + template + Scheduler::CallBack::~CallBack() + { + } + + template + void Scheduler::CallBack::execute() + { + m_func(); + } + // ==================================================================================== // // TIMER // // ==================================================================================== // diff --git a/Test/Engine/test_Scheduler.cpp b/Test/Engine/test_Scheduler.cpp index e206c849..52d4629e 100644 --- a/Test/Engine/test_Scheduler.cpp +++ b/Test/Engine/test_Scheduler.cpp @@ -32,34 +32,11 @@ using namespace kiwi; -template -class TTask final : public engine::Scheduler::Task -{ -public: // methods - - TTask(std::function func): - engine::Scheduler::Task(), - m_func(func) - { - } - - void execute() override - { - m_func.operator()(); - } - - ~TTask() - { - }; - -private: // members - - std::function m_func; -}; - using Scheduler = engine::Scheduler; -using Task = TTask; +using Task = engine::Scheduler<>::Task; + +using CallBack = engine::Scheduler<>::CallBack; static std::chrono::high_resolution_clock::time_point current_time = std::chrono::high_resolution_clock::now(); @@ -95,7 +72,7 @@ TEST_CASE("Scheduler", "[Scheduler]") for(int i = 0 ; i < 10; ++i) { - sch.schedule(std::shared_ptr(new Task(func)), + sch.schedule(std::shared_ptr(new CallBack(func)), std::chrono::milliseconds(10 * i)); } @@ -114,9 +91,9 @@ TEST_CASE("Scheduler", "[Scheduler]") std::function func_cancel = [&i_cancel](){++i_cancel;}; std::function func_reschedule = [&i_reschedule](){++i_reschedule;}; - std::shared_ptr standard(new Task(func_std)); - std::shared_ptr reschedule(new Task(func_reschedule)); - std::shared_ptr cancel(new Task(func_cancel)); + std::shared_ptr standard(new CallBack(func_std)); + std::shared_ptr reschedule(new CallBack(func_reschedule)); + std::shared_ptr cancel(new CallBack(func_cancel)); sch.schedule(std::move(standard)); sch.schedule(reschedule); @@ -148,15 +125,20 @@ TEST_CASE("Scheduler", "[Scheduler]") std::function func = [&order](int number){order.push_back(number);}; - std::shared_ptr> task_0(new TTask(std::bind(func, 0))); - std::shared_ptr> task_1(new TTask(std::bind(func, 1))); + std::shared_ptr::Task> + task_0(new engine::Scheduler::CallBack(std::bind(func, 0))); + + std::shared_ptr::Task> + task_1(new engine::Scheduler::CallBack(std::bind(func, 1))); tick_scheduler.schedule(task_0, std::chrono::milliseconds(1)); tick_scheduler.schedule(task_1, std::chrono::milliseconds(3)); - std::shared_ptr> task_2(new TTask(std::bind(func, 2))); + std::shared_ptr::Task> + task_2(new engine::Scheduler::CallBack(std::bind(func, 2))); - std::shared_ptr> task_3(new TTask(std::bind(func, 3))); + std::shared_ptr::Task> + task_3(new engine::Scheduler::CallBack(std::bind(func, 3))); tick_scheduler.schedule(std::move(task_2), std::chrono::milliseconds(2)); tick_scheduler.schedule(std::move(task_3), std::chrono::milliseconds(2)); @@ -198,7 +180,7 @@ TEST_CASE("Scheduler", "[Scheduler]") while(count_event < 30) { - sch.schedule(std::shared_ptr(new Task(func_1))); + sch.schedule(std::shared_ptr(new CallBack(func_1))); ++count_event; } }); @@ -209,7 +191,7 @@ TEST_CASE("Scheduler", "[Scheduler]") while(count_event < 20) { - sch.schedule(std::shared_ptr(new Task(func_2))); + sch.schedule(std::shared_ptr(new CallBack(func_2))); ++count_event; } }); @@ -237,14 +219,14 @@ TEST_CASE("Scheduler", "[Scheduler]") { std::thread producer_1([&sch, &func]() { - sch.schedule(std::make_shared(std::bind(func, 1))); + sch.schedule(std::make_shared(std::bind(func, 1))); }); producer_1.join(); std::thread producer_2([&sch, &func]() { - sch.schedule(std::make_shared(std::bind(func, 2))); + sch.schedule(std::make_shared(std::bind(func, 2))); }); producer_2.join(); @@ -266,14 +248,14 @@ TEST_CASE("Scheduler", "[Scheduler]") { std::thread producer_2([&sch, &func]() { - sch.schedule(std::make_shared(std::bind(func, 2))); + sch.schedule(std::make_shared(std::bind(func, 2))); }); producer_2.join(); std::thread producer_1([&sch, &func]() { - sch.schedule(std::make_shared(std::bind(func, 1))); + sch.schedule(std::make_shared(std::bind(func, 1))); }); producer_1.join(); @@ -332,7 +314,7 @@ TEST_CASE("Scheduler", "[Scheduler]") quit_requested.store(true); }; - sch.schedule(std::shared_ptr(new Task(func))); + sch.schedule(std::shared_ptr(new CallBack(func))); std::this_thread::sleep_for(std::chrono::seconds(1)); From 9921e1ef8460f735add7f863534a13098ac0460b Mon Sep 17 00:00:00 2001 From: jean-millot Date: Wed, 28 Jun 2017 17:13:10 +0200 Subject: [PATCH 013/148] Using scheduler for posting in console. --- .../KiwiApp_Application/KiwiApp_Console.cpp | 18 ++++++++++++++---- .../KiwiApp_Application/KiwiApp_Instance.cpp | 13 +++++++++++++ .../KiwiApp_Application/KiwiApp_Instance.h | 13 ++++++++++++- 3 files changed, 39 insertions(+), 5 deletions(-) diff --git a/Client/Source/KiwiApp_Application/KiwiApp_Console.cpp b/Client/Source/KiwiApp_Application/KiwiApp_Console.cpp index 7263ec2d..4c404654 100644 --- a/Client/Source/KiwiApp_Application/KiwiApp_Console.cpp +++ b/Client/Source/KiwiApp_Application/KiwiApp_Console.cpp @@ -140,12 +140,22 @@ namespace kiwi void ConsoleContent::consoleHistoryChanged(ConsoleHistory const&) { - juce::MessageManager::callAsync([this]() { - + engine::Scheduler<> &scheduler = KiwiApp::useInstance().useScheduler(); + + if (scheduler.isThisConsumerThread()) + { m_table.updateContent(); m_table.repaint(); - - }); + } + else + { + std::shared_ptr::Task> task(new engine::Scheduler<>::CallBack([this]() + { + m_table.updateContent(); + m_table.repaint(); + })); + scheduler.schedule(std::move(task)); + } } // ================================================================================ // diff --git a/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp b/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp index d5cab45b..e06a1e29 100644 --- a/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp +++ b/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp @@ -42,11 +42,13 @@ namespace kiwi size_t Instance::m_untitled_patcher_index(0); Instance::Instance() : + m_scheduler(), m_instance(std::make_unique()), m_browser(), m_console_history(std::make_shared(m_instance)), m_last_opened_file(juce::File::getSpecialLocation(juce::File::userHomeDirectory)) { + startTimer(10); std::srand(std::time(0)); m_user_id = std::rand(); @@ -62,6 +64,12 @@ namespace kiwi Instance::~Instance() { closeAllPatcherWindows(); + stopTimer(); + } + + void Instance::timerCallback() + { + m_scheduler.process(); } uint64_t Instance::getUserId() const noexcept @@ -79,6 +87,11 @@ namespace kiwi return m_instance; } + engine::Scheduler<> & Instance::useScheduler() + { + return m_scheduler; + } + void Instance::newPatcher() { auto manager_it = m_patcher_managers.emplace(m_patcher_managers.end(), new PatcherManager(*this)); diff --git a/Client/Source/KiwiApp_Application/KiwiApp_Instance.h b/Client/Source/KiwiApp_Application/KiwiApp_Instance.h index 27f4e77b..9b4cf78b 100644 --- a/Client/Source/KiwiApp_Application/KiwiApp_Instance.h +++ b/Client/Source/KiwiApp_Application/KiwiApp_Instance.h @@ -22,6 +22,9 @@ #pragma once #include +#include + +#include #include "flip/Document.h" @@ -43,7 +46,7 @@ namespace kiwi // ================================================================================ // //! @brief The Application Instance - class Instance + class Instance : public juce::Timer { public: @@ -53,6 +56,9 @@ namespace kiwi //! @brief Destructor ~Instance(); + //! @brief Timer call back, processes the scheduler events list. + void timerCallback() override final; + //! @brief Get the user ID of the Instance. uint64_t getUserId() const noexcept; @@ -65,6 +71,9 @@ namespace kiwi //! @brief Returns the engine::Instance engine::Instance const& getEngineInstance() const; + //! @brief Returns the instance's scheduler + engine::Scheduler<> & useScheduler(); + //! @brief Open a File. bool openFile(juce::File const& file); @@ -127,6 +136,8 @@ namespace kiwi private: // variables + engine::Scheduler<> m_scheduler; + engine::Instance m_instance; uint64_t m_user_id; From 5ea933cc717bf9df98d0b2df6c8b6dc69d142a06 Mon Sep 17 00:00:00 2001 From: jean-millot Date: Thu, 22 Jun 2017 15:33:01 +0200 Subject: [PATCH 014/148] Create schedule override with an std::function in scheduler. --- Client/Source/KiwiApp_Application/KiwiApp_Console.cpp | 5 ++--- Modules/KiwiEngine/KiwiEngine_Scheduler.h | 4 ++++ Modules/KiwiEngine/KiwiEngine_Scheduler.hpp | 6 ++++++ 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Client/Source/KiwiApp_Application/KiwiApp_Console.cpp b/Client/Source/KiwiApp_Application/KiwiApp_Console.cpp index 4c404654..87cc4f8b 100644 --- a/Client/Source/KiwiApp_Application/KiwiApp_Console.cpp +++ b/Client/Source/KiwiApp_Application/KiwiApp_Console.cpp @@ -149,12 +149,11 @@ namespace kiwi } else { - std::shared_ptr::Task> task(new engine::Scheduler<>::CallBack([this]() + scheduler.schedule([this]() { m_table.updateContent(); m_table.repaint(); - })); - scheduler.schedule(std::move(task)); + }); } } diff --git a/Modules/KiwiEngine/KiwiEngine_Scheduler.h b/Modules/KiwiEngine/KiwiEngine_Scheduler.h index eaecf3ce..b1dcbeec 100644 --- a/Modules/KiwiEngine/KiwiEngine_Scheduler.h +++ b/Modules/KiwiEngine/KiwiEngine_Scheduler.h @@ -94,6 +94,10 @@ namespace kiwi //! deleted at execution time. void schedule(std::shared_ptr const& task, duration_t delay = std::chrono::milliseconds(0)); + //! @brief Delays execution of a function by the sceduler. + //! @details Internally create a callback that will be executed and destroyed by the scheduler. + void schedule(std::function && func, duration_t delay = std::chrono::milliseconds(0)); + //! @brief Used to cancel the execution of a previously scheduled task. //! @details If the task is currently being processed by the scheduler, this method does't //! wait for the execution to finish but only guarantee that further execution will no occur. diff --git a/Modules/KiwiEngine/KiwiEngine_Scheduler.hpp b/Modules/KiwiEngine/KiwiEngine_Scheduler.hpp index db9a671b..414f6ec4 100644 --- a/Modules/KiwiEngine/KiwiEngine_Scheduler.hpp +++ b/Modules/KiwiEngine/KiwiEngine_Scheduler.hpp @@ -62,6 +62,12 @@ namespace kiwi assert(task); m_queue.schedule(task, delay); } + + template + void Scheduler::schedule(std::function && func, duration_t delay) + { + schedule(std::shared_ptr(new CallBack(func))); + } template void Scheduler::unschedule(std::shared_ptr const& task) From 143fc7d022c17adef397aa31b07efaf5ffc0c3e2 Mon Sep 17 00:00:00 2001 From: jean-millot Date: Wed, 28 Jun 2017 17:17:11 +0200 Subject: [PATCH 015/148] Use scheduler when handling node server response. --- .../KiwiApp_Network/KiwiApp_DocumentBrowser.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp b/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp index 98081851..8763a9fe 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp +++ b/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp @@ -315,16 +315,15 @@ namespace kiwi if(res.error) { - juce::MessageManager::callAsync([message = res.error.message](){ - KiwiApp::error("Kiwi API error: can't get documents => " + message); + KiwiApp::error("Kiwi API error: can't get documents => " + res.error.message); + } + else + { + KiwiApp::useInstance().useScheduler().schedule([this, docs]() + { + updateDocumentList(docs); }); - - return; } - - juce::MessageManager::callAsync([this, docs](){ - updateDocumentList(docs); - }); }); } From 64fc8c5eb749231cf465a0d846f6691a2b8c022e Mon Sep 17 00:00:00 2001 From: jean-millot Date: Wed, 28 Jun 2017 14:54:27 +0200 Subject: [PATCH 016/148] Correcting ownership transfer to scheduler. --- Modules/KiwiEngine/KiwiEngine_Scheduler.h | 23 +++++++----- Modules/KiwiEngine/KiwiEngine_Scheduler.hpp | 41 ++++++++++----------- Test/Engine/test_Scheduler.cpp | 31 ++++++++++++++++ 3 files changed, 63 insertions(+), 32 deletions(-) diff --git a/Modules/KiwiEngine/KiwiEngine_Scheduler.h b/Modules/KiwiEngine/KiwiEngine_Scheduler.h index b1dcbeec..c009922b 100644 --- a/Modules/KiwiEngine/KiwiEngine_Scheduler.h +++ b/Modules/KiwiEngine/KiwiEngine_Scheduler.h @@ -86,14 +86,18 @@ namespace kiwi //! @brief Check wehter or not this thread is the consumer. //! @details This method can be usefull to help decide if a direct call can be made //! or if the scheduler shall be used. - bool isThisConsumerThread(); + bool isThisConsumerThread() const; //! @brief Delays execution of a task. Shared ownership. //! @details Calling twice this method with same task will cancel the previous scheduled execution - //! and add a new one at specified time. If you move ownership of the task here the task will be - //! deleted at execution time. + //! and add a new one at specified time. void schedule(std::shared_ptr const& task, duration_t delay = std::chrono::milliseconds(0)); + //! @brief Delays execution of a task. Transfer ownership. + //! @details Calling twice this method with same task will cancel the previous scheduled execution + //! and add a new one at specified time. + void schedule(std::shared_ptr && task, duration_t delay = std::chrono::milliseconds(0)); + //! @brief Delays execution of a function by the sceduler. //! @details Internally create a callback that will be executed and destroyed by the scheduler. void schedule(std::function && func, duration_t delay = std::chrono::milliseconds(0)); @@ -152,6 +156,9 @@ namespace kiwi //! @brief Delays the execution of a task. Shared ownership. void schedule(std::shared_ptr const& task, duration_t delay); + //! @brief Delays the execution of a task. Transfer ownership. + void schedule(std::shared_ptr && task, duration_t delay); + //! @brief Cancels the execution of a task. void unschedule(std::shared_ptr const& task); @@ -323,13 +330,7 @@ namespace kiwi public: // methods //! @brief Constructor. - Event(std::shared_ptr const& task, time_point_t time); - - //! @brief Copy Constructor. - Event(Event const& other); - - //! @brief Assignement operator - Event& operator=(Event const& other); + Event(std::shared_ptr && task, time_point_t time); //! @brief Moove constructor Event(Event && other); @@ -355,6 +356,8 @@ namespace kiwi private: // deleted methods Event() = delete; + Event(Event const& other) = delete; + Event& operator=(Event const& other) = delete; }; } } diff --git a/Modules/KiwiEngine/KiwiEngine_Scheduler.hpp b/Modules/KiwiEngine/KiwiEngine_Scheduler.hpp index 414f6ec4..304d9609 100644 --- a/Modules/KiwiEngine/KiwiEngine_Scheduler.hpp +++ b/Modules/KiwiEngine/KiwiEngine_Scheduler.hpp @@ -51,7 +51,7 @@ namespace kiwi } template - bool Scheduler::isThisConsumerThread() + bool Scheduler::isThisConsumerThread() const { return m_consumer_id == std::this_thread::get_id(); } @@ -63,6 +63,13 @@ namespace kiwi m_queue.schedule(task, delay); } + template + void Scheduler::schedule(std::shared_ptr && task, duration_t delay) + { + assert(task); + m_queue.schedule(std::move(task), delay); + } + template void Scheduler::schedule(std::function && func, duration_t delay) { @@ -116,10 +123,16 @@ namespace kiwi void Scheduler::Queue::schedule(std::shared_ptr const& task, duration_t delay) { assert(task); - m_commands.push({task, clock_t::now() + delay }); } + template + void Scheduler::Queue::schedule(std::shared_ptr && task, duration_t delay) + { + assert(task); + m_commands.push({std::move(task), clock_t::now() + delay}); + } + template void Scheduler::Queue::unschedule(std::shared_ptr const& task) { @@ -147,7 +160,7 @@ namespace kiwi { if (event.m_time < event_it->m_time) { - m_events.insert(event_it, event); + m_events.insert(event_it, std::move(event)); break; } @@ -156,7 +169,7 @@ namespace kiwi if (event_it == m_events.end()) { - m_events.emplace_back(event); + m_events.emplace_back(std::move(event)); } } @@ -307,28 +320,12 @@ namespace kiwi // ==================================================================================== // template - Scheduler::Event::Event(std::shared_ptr const& task, time_point_t time): - m_task(task), + Scheduler::Event::Event(std::shared_ptr && task, time_point_t time): + m_task(std::move(task)), m_time(time) { } - template - Scheduler::Event::Event(Event const& other): - m_task(other.m_task), - m_time(other.m_time) - { - } - - template - typename Scheduler::Event& Scheduler::Event::operator=(Event const& other) - { - m_task = other.m_task; - m_time = other.m_time; - - return *this; - } - template Scheduler::Event::Event(Event && other): m_task(std::move(other.m_task)), diff --git a/Test/Engine/test_Scheduler.cpp b/Test/Engine/test_Scheduler.cpp index 52d4629e..c24de6ed 100644 --- a/Test/Engine/test_Scheduler.cpp +++ b/Test/Engine/test_Scheduler.cpp @@ -81,6 +81,37 @@ TEST_CASE("Scheduler", "[Scheduler]") CHECK(counter == 10); } + SECTION("Ownership") + { + struct TestDestructor : public Task + { + TestDestructor(int &counter):m_counter(counter){}; + + ~TestDestructor(){++m_counter;}; + + void execute() override final{}; + + int& m_counter; + }; + + int shared_count = 0; + int transfered_count = 0; + + std::shared_ptr shared(new TestDestructor(shared_count)); + std::shared_ptr transfered(new TestDestructor(transfered_count)); + + sch.schedule(shared); + CHECK(shared.use_count() == 2); + + sch.schedule(std::move(transfered)); + CHECK(transfered.use_count() == 0); + + sch.process(); + + CHECK(transfered_count == 1); // Check that transfered was destroyed. + CHECK(shared_count == 0); // Check that shared was not destroyed. + } + SECTION("Cancel/Reschedule mono thread") { int i_standard = 0; From b90f7e05715f9f298b48825014a1e02b2ca846a9 Mon Sep 17 00:00:00 2001 From: jmillot Date: Fri, 30 Jun 2017 17:43:22 +0200 Subject: [PATCH 017/148] Remove unused period into Timer::Task --- Modules/KiwiEngine/KiwiEngine_Scheduler.hpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Modules/KiwiEngine/KiwiEngine_Scheduler.hpp b/Modules/KiwiEngine/KiwiEngine_Scheduler.hpp index 304d9609..1be7cdc5 100644 --- a/Modules/KiwiEngine/KiwiEngine_Scheduler.hpp +++ b/Modules/KiwiEngine/KiwiEngine_Scheduler.hpp @@ -256,8 +256,7 @@ namespace kiwi public: // methods Task(Timer& timer): - m_timer(timer), - m_period() + m_timer(timer) { } @@ -273,7 +272,6 @@ namespace kiwi private: // members Timer& m_timer; - duration_t m_period; }; From bb8ae0e6dcbc5533085a7d18101cf64fec332bdc Mon Sep 17 00:00:00 2001 From: jean-millot Date: Wed, 5 Jul 2017 19:10:24 +0200 Subject: [PATCH 018/148] Adding a simple synchronous http request function using beast library. --- .gitmodules | 3 + .travis.yml | 20 ++++++- CMakeLists.txt | 67 +++++++++++++++++++++- Modules/KiwiNetwork/KiwiNetwork_Http.cpp | 29 ++++++++++ Modules/KiwiNetwork/KiwiNetwork_Http.h | 73 ++++++++++++++++++++++++ Test/Network/test_Http.cpp | 53 +++++++++++++++++ Test/Network/test_KiwiNetwork.cpp | 33 +++++++++++ ThirdParty/Beast | 1 + appveyor.yml | 4 ++ 9 files changed, 279 insertions(+), 4 deletions(-) create mode 100644 Modules/KiwiNetwork/KiwiNetwork_Http.cpp create mode 100644 Modules/KiwiNetwork/KiwiNetwork_Http.h create mode 100755 Test/Network/test_Http.cpp create mode 100755 Test/Network/test_KiwiNetwork.cpp create mode 160000 ThirdParty/Beast diff --git a/.gitmodules b/.gitmodules index dac02834..359fc1a3 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "ThirdParty/concurrentqueue"] path = ThirdParty/concurrentqueue url = https://github.com/cameron314/concurrentqueue.git +[submodule "ThirdParty/Beast"] + path = ThirdParty/Beast + url = https://github.com/vinniefalco/Beast.git diff --git a/.travis.yml b/.travis.yml index 9ccd676e..1c462912 100755 --- a/.travis.yml +++ b/.travis.yml @@ -35,7 +35,7 @@ matrix: install: # make sure CXX is correctly set - if [[ "${COMPILER}" != "" ]]; then export CXX=${COMPILER}; fi - - git submodule update --init --recursive ThirdParty/Juce ThirdParty/cpr ThirdParty/concurrentqueue + - git submodule update --init --recursive ThirdParty/Juce ThirdParty/cpr ThirdParty/concurrentqueue ThirdParty/Beast - pip install --user cpp-coveralls - wget --no-check-certificate -O ../curl-7.52.1.tar.gz https://github.com/Musicoll/Kiwi/files/999838/curl-7.52.1-linux.tar.gz - wget --no-check-certificate -O ../flip-demo.tar.gz http://developer.irisate.com.s3-website-us-east-1.amazonaws.com/files/flip-demo-linux-c47e41da05.tar.gz @@ -44,6 +44,14 @@ matrix: - tar xvzf flip-demo.tar.gz &> /dev/null - export KIWI_CURL_LIB=$(pwd)/curl-7.52.1/lib && export KIWI_CURL_INCLUDE=$(pwd)/curl-7.52.1/include - export KIWI_FLIP_LIB=$(pwd)/flip-demo/lib/gcc && export KIWI_FLIP_INCLUDE=$(pwd)/flip-demo/include + - cd ${HOME} + - wget --no-check-certificate -O ./boost_1_63_0.tar.gz https://sourceforge.net/projects/boost/files/boost/1.63.0/boost_1_63_0.tar.gz + - tar xvzf ./boost_1_63_0.tar.gz &> /dev/null + - cd ./boost_1_63_0 + - ./bootstrap.sh toolset=gcc link=static + - ./b2 --with-system stage + - export KIWI_BOOST_INCLUDE=${HOME}/boost_1_63_0 + - export KIWI_BOOST_LIB={HOME}/boost_1_63_0/stage/lib - cd ${TRAVIS_BUILD_DIR} script: @@ -74,7 +82,7 @@ matrix: env: COMPILER=clang++ install: - - git submodule update --init --recursive ThirdParty/Juce ThirdParty/cpr ThirdParty/concurrentqueue + - git submodule update --init --recursive ThirdParty/Juce ThirdParty/cpr ThirdParty/concurrentqueue ThirdParty/Beast - curl -o ../curl-7.52.1.zip -L https://github.com/Musicoll/Kiwi/files/997532/curl-7.52.1-macos.zip - curl -o ../flip-demo.tar.gz -L http://developer.irisate.com.s3-website-us-east-1.amazonaws.com/files/flip-demo-macos-c47e41da05.tar.gz - cd .. @@ -82,6 +90,14 @@ matrix: - tar xvzf flip-demo.tar.gz &> /dev/null - export KIWI_CURL_LIB=$(pwd)/curl-7.52.1/lib && export KIWI_CURL_INCLUDE=$(pwd)/curl-7.52.1/include - export KIWI_FLIP_LIB=$(pwd)/flip-demo/lib && export KIWI_FLIP_INCLUDE=$(pwd)/flip-demo/include + - cd ${HOME} + - curl -o ./boost_1_63_0.tar.gz -L https://sourceforge.net/projects/boost/files/boost/1.63.0/boost_1_63_0.tar.gz + - tar xvzf ./boost_1_63_0.tar.gz &> /dev/null + - cd ./boost_1_63_0 + - ./bootstrap.sh toolset=clang macosx-version-min=10.8 architecture=combined link=static + - ./b2 address-model=32_64 --with-system stage + - export KIWI_BOOST_INCLUDE=${HOME}/boost_1_63_0 + - export KIWI_BOOST_LIB={HOME}/boost_1_63_0/stage/lib - cd ${TRAVIS_BUILD_DIR} script: diff --git a/CMakeLists.txt b/CMakeLists.txt index 1814d74d..98d386f3 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -105,7 +105,8 @@ if (WIN32) elseif(APPLE) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-unknown-warning-option -Wno-pessimizing-move -Wno-overloaded-virtual -Wnounused-function") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-unknown-warning-option -Wno-pessimizing-move + -Wno-overloaded-virtual -Wnounused-function -Wno-unused-local-typedefs") if (DEBUG) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0") @@ -289,6 +290,35 @@ endif() set(FLIP_COMPILE_DEFINITIONS "flip_NOTHING=flip_NOTHING_FATAL") +#---------------------------------- +# Beast +#---------------------------------- + +set(Boost_INCLUDE_DIR $ENV{KIWI_BOOST_INCLUDE}) + +if (WIN32) + if (CMAKE_CL_64) + set(Boost_LIBRARY_DIR $ENV{KIWI_BOOST_LIB_x64}) + else() + set(Boost_LIBRARY_DIR $ENV{KIWI_BOOST_LIB_WIN32}) + endif() +else() + set(Boost_LIBRARY_DIR $ENV{KIWI_BOOST_LIB}) + set(Boost_NO_BOOST_CMAKE true) + set(Boost_NO_SYSTEM_PATHS true) +endif() + +option (Boost_USE_STATIC_LIBS "Use static libraries for boost" ON) +find_package (Boost 1.63.0 REQUIRED COMPONENTS system) + +if (Boost_FOUND) + message(STATUS "Boost found on system") + message(STATUS "Boost_LIBRARIES : " ${Boost_LIBRARIES}) + message(STATUS "BOOST_INCLUDE_DIRECTORES : " ${Boost_INCLUDE_DIRS}) +else() + message(FATAL_ERROR "Boost not found on system") +endif() + #---------------------------------- # Cpr #---------------------------------- @@ -365,6 +395,28 @@ target_include_directories(KiwiDsp PUBLIC ${ROOT_DIR}/Modules) set_target_properties(KiwiDsp PROPERTIES FOLDER Modules) source_group_rec("${KIWI_DSP_SRC}" ${ROOT_DIR}/Modules/KiwiDsp) +#---------------------------------- +# Network +#---------------------------------- + +file(GLOB_RECURSE KIWI_NETWORK_SRC ${ROOT_DIR}/Modules/KiwiNetwork/*.[c|h]pp + ${ROOT_DIR}/Modules/KiwiNetwork/*.h) +add_library(KiwiNetwork STATIC ${KIWI_NETWORK_SRC}) +target_include_directories(KiwiNetwork PUBLIC ${ROOT_DIR}/Modules + ${ROOT_DIR}/ThirdParty/Beast/include + ${Boost_INCLUDE_DIRS}) +target_compile_definitions(KiwiNetwork PUBLIC "-DBOOST_ALL_NO_LIB=1") +set(NETWORK_DEP ${Boost_LIBRARIES}) +if (WIN32) + set(NETWORK_DEP ${NETWORK_DEP} ${WS2_32}) +elseif(LINUX) + set(NETWORK_DEP ${NETWORK_DEP} ${PTHREAD}) +endif() +target_link_libraries(KiwiNetwork PUBLIC ${NETWORK_DEP}) +set_target_properties(KiwiNetwork PROPERTIES FOLDER Modules) +source_group_rec("${KIWI_NETWORK_SRC}" ${ROOT_DIR}/Modules/KiwiNetwork) + + #---------------------------------- # Engine #---------------------------------- @@ -455,6 +507,15 @@ target_add_dependency(test_model KiwiModel) set_target_properties(test_model PROPERTIES FOLDER Test) source_group_rec("${TEST_MODEL_SRC}" ${ROOT_DIR}/Test/Model) +# Test Network + +file(GLOB TEST_NETWORK_SRC ${ROOT_DIR}/Test/Network/*.[c|h]pp + ${ROOT_DIR}/Test/Network/*.h) +add_executable(test_network ${TEST_NETWORK_SRC}) +target_add_dependency(test_network KiwiNetwork) +set_target_properties(test_network PROPERTIES FOLDER Test) +source_group_rec("${TEST_NETWORK_SRC}" ${ROOT_DIR}/Test/Network) + # Test Engine file(GLOB TEST_ENGINE_SRC ${ROOT_DIR}/Test/Engine/*.[c|h]pp @@ -488,11 +549,12 @@ if(${GCOV_SUPPORT} STREQUAL "On" AND DEBUG) target_link_libraries(test_model PUBLIC gcov) target_link_libraries(test_engine PUBLIC gcov) target_link_libraries(test_server PUBLIC gcov) + target_link_libraries(test_network PUBLIC gcov) endif() # Tests Target -add_custom_target(Tests ALL DEPENDS test_dsp test_model test_engine) +add_custom_target(Tests ALL DEPENDS test_dsp test_model test_engine test_network) set_target_properties(Tests PROPERTIES FOLDER Test) add_custom_command(TARGET Tests @@ -500,4 +562,5 @@ add_custom_command(TARGET Tests COMMAND test_model COMMAND test_engine COMMAND test_server + COMMAND test_network USES_TERMINAL) diff --git a/Modules/KiwiNetwork/KiwiNetwork_Http.cpp b/Modules/KiwiNetwork/KiwiNetwork_Http.cpp new file mode 100644 index 00000000..41d47582 --- /dev/null +++ b/Modules/KiwiNetwork/KiwiNetwork_Http.cpp @@ -0,0 +1,29 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include "KiwiNetwork_Http.h" + +namespace kiwi +{ + namespace network + { + } +} diff --git a/Modules/KiwiNetwork/KiwiNetwork_Http.h b/Modules/KiwiNetwork/KiwiNetwork_Http.h new file mode 100644 index 00000000..83b6e839 --- /dev/null +++ b/Modules/KiwiNetwork/KiwiNetwork_Http.h @@ -0,0 +1,73 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +#include + +#include +#include + +using tcp = boost::asio::ip::tcp; + +namespace kiwi +{ + namespace network + { + //! @brief Sends an http request. + //! @details Returns the response generated by the server. The function blocks until response + //! is handed over. + //! @todo Handle errorcode message. Maybe add a timeout parameter. + template + void httpWrite(beast::http::request& request, + beast::http::response& response) + { + beast::error_code ec; + + // Set up an asio socket. + boost::asio::io_service ios; + tcp::resolver resolver(ios); + tcp::socket socket(ios); + + // Look up the domain name. + std::string host = request[beast::http::field::host].to_string(); + auto const lookup = resolver.resolve({host, "http"}, ec); + + // Establish connection to server. + boost::asio::connect(socket, lookup, ec); + + // Prepare the request. + request.prepare_payload(); + + // Sends the request. + beast::http::write(socket, request, ec); + + // Reads the response. + beast::flat_buffer buffer; + beast::http::read(socket, buffer, response, ec); + + // Close connection to server. + socket.shutdown(tcp::socket::shutdown_both, ec); + } + } +} diff --git a/Test/Network/test_Http.cpp b/Test/Network/test_Http.cpp new file mode 100755 index 00000000..1aca1287 --- /dev/null +++ b/Test/Network/test_Http.cpp @@ -0,0 +1,53 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +// ==================================================================================== // +// NETWORK // +// ==================================================================================== // + +#include + +#include "../catch.hpp" + +#include + +#include + +TEST_CASE("Network - Http", "[Network, Http]") +{ + SECTION("Client get request to echo server") + { + // Construct request and response. + beast::http::request request; + request.method(beast::http::verb::get); + request.target("/get"); + request.version = 11; + request.set(beast::http::field::host, "httpbin.org"); + request.set(beast::http::field::user_agent, "test"); + + beast::http::response response; + + // Send request and waits for response. + kiwi::network::httpWrite(request, response); + + CHECK(response.result() == beast::http::status::ok); + } +} diff --git a/Test/Network/test_KiwiNetwork.cpp b/Test/Network/test_KiwiNetwork.cpp new file mode 100755 index 00000000..4265ac35 --- /dev/null +++ b/Test/Network/test_KiwiNetwork.cpp @@ -0,0 +1,33 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v2 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#define CATCH_CONFIG_RUNNER + +#include "../catch.hpp" + +int main( int argc, char* const argv[] ) +{ + std::cout << "running Unit-Tests - KiwiNetwork ..." << '\n' << '\n'; + + int result = Catch::Session().run( argc, argv ); + + return result; +} diff --git a/ThirdParty/Beast b/ThirdParty/Beast new file mode 160000 index 00000000..78a065ba --- /dev/null +++ b/ThirdParty/Beast @@ -0,0 +1 @@ +Subproject commit 78a065ba39836d91d7e70d93de7f9140f518083b diff --git a/appveyor.yml b/appveyor.yml index 8fa16df5..f4337753 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -16,6 +16,7 @@ install: - git submodule update --init --recursive "ThirdParty/Juce" - git submodule update --init --recursive "ThirdParty/cpr" - git submodule update --init --recursive "ThirdParty/concurrentqueue" + - git submodule update --init --recursive "ThirdParty/Beast" - set PATH=C:\Python27;%PATH% - curl -o ..\curl-7.52.1-win32.zip -L -k https://github.com/Musicoll/Kiwi/files/998123/curl-7.52.1-win32.zip - curl -o ..\curl-7.52.1-x64.zip -L -k https://github.com/Musicoll/Kiwi/files/997546/curl-7.52.1-x64.zip @@ -32,6 +33,9 @@ install: - set KIWI_FLIP_INCLUDE_x64=%cd%/flip-demo/include - set KIWI_FLIP_LIB_WIN32=%cd%/flip-demo/lib/VS2015/Win32/Release - set KIWI_FLIP_INCLUDE_WIN32=%cd%/flip-demo/include + - set KIWI_BOOST_INCLUDE=C:\Libraries\boost_1_63_0 + - set KIWI_BOOST_LIB_x64=C:\Libraries\boost_1_63_0\lib64-msvc-14.0 + - set KIWI_BOOST_LIB_WIN3=C:\Libraries\boost_1_63_0\lib32-msvc-14.0 - cd %APPVEYOR_BUILD_FOLDER% build_script: From 9342d972131c34ff7400eab331360403e72eb9ca Mon Sep 17 00:00:00 2001 From: jean-millot Date: Fri, 7 Jul 2017 23:29:46 +0200 Subject: [PATCH 019/148] Integrating beast code --- .gitmodules | 3 - .travis.yml | 14 +- CMakeLists.txt | 47 +--- Client/Source/KiwiApp_Network/KiwiApp_Api.cpp | 102 ++++----- Client/Source/KiwiApp_Network/KiwiApp_Api.h | 20 +- .../KiwiApp_DocumentBrowser.cpp | 18 +- Modules/KiwiNetwork/KiwiNetwork_Http.h | 207 +++++++++++++++--- Test/Network/test_Http.cpp | 31 ++- ThirdParty/cpr | 1 - appveyor.yml | 11 +- 10 files changed, 279 insertions(+), 175 deletions(-) delete mode 160000 ThirdParty/cpr diff --git a/.gitmodules b/.gitmodules index 359fc1a3..077b9dd3 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,9 +1,6 @@ [submodule "ThirdParty/Juce"] path = ThirdParty/Juce url = https://github.com/julianstorer/JUCE.git -[submodule "ThirdParty/cpr"] - path = ThirdParty/cpr - url = https://github.com/whoshuu/cpr.git [submodule "ThirdParty/concurrentqueue"] path = ThirdParty/concurrentqueue url = https://github.com/cameron314/concurrentqueue.git diff --git a/.travis.yml b/.travis.yml index 1c462912..c75c1fc8 100755 --- a/.travis.yml +++ b/.travis.yml @@ -35,14 +35,11 @@ matrix: install: # make sure CXX is correctly set - if [[ "${COMPILER}" != "" ]]; then export CXX=${COMPILER}; fi - - git submodule update --init --recursive ThirdParty/Juce ThirdParty/cpr ThirdParty/concurrentqueue ThirdParty/Beast + - git submodule update --init --recursive ThirdParty/Juce ThirdParty/concurrentqueue ThirdParty/Beast - pip install --user cpp-coveralls - - wget --no-check-certificate -O ../curl-7.52.1.tar.gz https://github.com/Musicoll/Kiwi/files/999838/curl-7.52.1-linux.tar.gz - wget --no-check-certificate -O ../flip-demo.tar.gz http://developer.irisate.com.s3-website-us-east-1.amazonaws.com/files/flip-demo-linux-c47e41da05.tar.gz - cd .. - - tar xvzf curl-7.52.1.tar.gz - tar xvzf flip-demo.tar.gz &> /dev/null - - export KIWI_CURL_LIB=$(pwd)/curl-7.52.1/lib && export KIWI_CURL_INCLUDE=$(pwd)/curl-7.52.1/include - export KIWI_FLIP_LIB=$(pwd)/flip-demo/lib/gcc && export KIWI_FLIP_INCLUDE=$(pwd)/flip-demo/include - cd ${HOME} - wget --no-check-certificate -O ./boost_1_63_0.tar.gz https://sourceforge.net/projects/boost/files/boost/1.63.0/boost_1_63_0.tar.gz @@ -51,7 +48,7 @@ matrix: - ./bootstrap.sh toolset=gcc link=static - ./b2 --with-system stage - export KIWI_BOOST_INCLUDE=${HOME}/boost_1_63_0 - - export KIWI_BOOST_LIB={HOME}/boost_1_63_0/stage/lib + - export KIWI_BOOST_LIB=${HOME}/boost_1_63_0/stage/lib - cd ${TRAVIS_BUILD_DIR} script: @@ -82,13 +79,10 @@ matrix: env: COMPILER=clang++ install: - - git submodule update --init --recursive ThirdParty/Juce ThirdParty/cpr ThirdParty/concurrentqueue ThirdParty/Beast - - curl -o ../curl-7.52.1.zip -L https://github.com/Musicoll/Kiwi/files/997532/curl-7.52.1-macos.zip + - git submodule update --init --recursive ThirdParty/Juce ThirdParty/concurrentqueue ThirdParty/Beast - curl -o ../flip-demo.tar.gz -L http://developer.irisate.com.s3-website-us-east-1.amazonaws.com/files/flip-demo-macos-c47e41da05.tar.gz - cd .. - - unzip curl-7.52.1.zip - tar xvzf flip-demo.tar.gz &> /dev/null - - export KIWI_CURL_LIB=$(pwd)/curl-7.52.1/lib && export KIWI_CURL_INCLUDE=$(pwd)/curl-7.52.1/include - export KIWI_FLIP_LIB=$(pwd)/flip-demo/lib && export KIWI_FLIP_INCLUDE=$(pwd)/flip-demo/include - cd ${HOME} - curl -o ./boost_1_63_0.tar.gz -L https://sourceforge.net/projects/boost/files/boost/1.63.0/boost_1_63_0.tar.gz @@ -97,7 +91,7 @@ matrix: - ./bootstrap.sh toolset=clang macosx-version-min=10.8 architecture=combined link=static - ./b2 address-model=32_64 --with-system stage - export KIWI_BOOST_INCLUDE=${HOME}/boost_1_63_0 - - export KIWI_BOOST_LIB={HOME}/boost_1_63_0/stage/lib + - export KIWI_BOOST_LIB=${HOME}/boost_1_63_0/stage/lib - cd ${TRAVIS_BUILD_DIR} script: diff --git a/CMakeLists.txt b/CMakeLists.txt index 98d386f3..089c5aa9 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -319,51 +319,6 @@ else() message(FATAL_ERROR "Boost not found on system") endif() -#---------------------------------- -# Cpr -#---------------------------------- - -# Cpr settings - -set(CMAKE_USE_OPENSSL OFF CACHE BOOL "Don't use openssl") -set(BUILD_CPR_TESTS OFF CACHE BOOL "Don't build cpr tests") - -if(WIN32) - if (CMAKE_CL_64) - set(KIWI_CURL_LIB $ENV{KIWI_CURL_LIB_x64}) - set(KIWI_CURL_INCLUDE $ENV{KIWI_CURL_INCLUDE_x64}) - else() - set(KIWI_CURL_LIB $ENV{KIWI_CURL_LIB_WIN32}) - set(KIWI_CURL_INCLUDE $ENV{KIWI_CURL_INCLUDE_WIN32}) - endif() -else() - set(KIWI_CURL_LIB $ENV{KIWI_CURL_LIB}) - set(KIWI_CURL_INCLUDE $ENV{KIWI_CURL_INCLUDE}) -endif() - -message(STATUS "Searching curl library") -message(STATUS "Library search path is : " ${KIWI_CURL_LIB}) -message(STATUS "Include search path is : " ${KIWI_CURL_INCLUDE}) - -find_library(CURL_LIBRARIES NAMES curl PATHS ${KIWI_CURL_LIB} NO_DEFAULT_PATH) -find_path(CURL_INCLUDE_DIRS NAMES curl PATHS ${KIWI_CURL_INCLUDE} NO_DEFAULT_PATH) - -if (CURL_LIBRARIES AND CURL_INCLUDE_DIRS) - set(USE_SYSTEM_CURL ON CACHE BOOL "Use system curl") - set(CURL_FOUND TRUE CACHE BOOL "Curl found") - set(CMAKE_DISABLE_FIND_PACKAGE_CURL TRUE CACHE BOOL "Disactivate find package curl") - message(STATUS "Libcurl found on system") - message(STATUS "CURL_LIBRARIES : " ${CURL_LIBRARIES}) - message(STATUS "CURL_INCLUDE_DIRS : " ${CURL_INCLUDE_DIRS}) -else() - message(FATAL_ERROR "Curl was not found on system, check Readme.md for instructions on how to set searh path") -endif() - -add_subdirectory(ThirdParty/cpr) -set_target_properties(${CPR_LIBRARIES} PROPERTIES FOLDER ThirdParty) -set_target_properties(${CPR_LIBRARIES} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) -target_compile_definitions(${CPR_LIBRARIES} PUBLIC -DCURL_STATICLIB=1) - #---------------------------------- # Json #---------------------------------- @@ -457,11 +412,11 @@ source_group_rec("${SERVER_SRC}" ${ROOT_DIR}/Server/Source) file(GLOB_RECURSE KIWI_CLIENT_SRC ${ROOT_DIR}/Client/Source/*.[c|h]pp ${ROOT_DIR}/Client/Source/*.h) add_executable(Kiwi ${KIWI_CLIENT_SRC} "${KIWI_CLIENT_RESSOURCES}") +target_add_dependency(Kiwi KiwiNetwork) target_add_dependency(Kiwi KiwiEngine) target_add_dependency(Kiwi KiwiModel) target_add_dependency(Kiwi KiwiDsp) target_add_dependency(Kiwi Juce) -target_add_dependency(Kiwi ${CPR_LIBRARIES}) target_include_directories(Kiwi PUBLIC ${JSON_INCLUDE_DIRS} ${CPR_INCLUDE_DIRS}) if (APPLE) diff --git a/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp b/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp index 1e8017ff..6817efe8 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp +++ b/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp @@ -21,6 +21,8 @@ #include "KiwiApp_Api.h" +#include + namespace kiwi { void to_json(json& j, Api::Document const& doc) @@ -91,105 +93,91 @@ namespace kiwi return m_port; } - std::string Api::getProtocolStr() const + void Api::getDocuments(std::function callback) { - return (m_protocol == Protocol::HTTP) ? "http" : "https"; - } - - std::string Api::getApiRootUrl() const - { - std::string url{getProtocolStr() + "://" + m_host}; - - if(m_port != 80) + std::function res_callback = + [callback = std::move(callback)](Api::Response const& res, Api::Error const& error) { - url += ':' + std::to_string(m_port); - } - - url += "/api"; - - return url; - } - - void Api::getDocuments(std::function callback) - { - auto res_callback = [callback = std::move(callback)](Api::Response res) { - - if(res.status_code == 200) + if (res.result() == beast::http::status::ok) { if(hasJsonHeader(res)) { - auto j = json::parse(res.text); + auto j = json::parse(res.body); if(j.is_array()) { // parse each json objects as document and store them in a vector. - callback(std::move(res), j); + callback(res, error, j); return; } } - - res.error.code = cpr::ErrorCode::UNKNOWN_ERROR; - res.error.message = "Unable to parse response"; } - callback(std::move(res), {}); + callback(res, error, {}); }; + Api::Request request; + request.set(beast::http::field::host, m_host); + request.method(beast::http::verb::get); + request.target("/api/documents"); + request.version = 11; + + Api::Response response; + Api::Error error; - storeRequest(cpr::GetCallback(std::move(res_callback), - getApiRootUrl() + "/documents", - cpr::Timeout{3000})); + storeRequest(network::httpWriteAsync(request, std::to_string(m_port), res_callback, std::chrono::milliseconds(3000))); } - void Api::createDocument(std::function callback, + void Api::createDocument(std::function callback, std::string const& document_name) { + Api::Request request; + request.set(beast::http::field::host, m_host); + request.set(beast::http::field::content_type, "application/x-www-form-urlencoded"); + request.method(beast::http::verb::post); + request.target("/api/documents"); + request.version = 11; - cpr::Payload payload{{}}; + request.body = "name=" + document_name; - if(!document_name.empty()) + std::function res_callback = + [callback = std::move(callback)](Api::Response const& res, Api::Error const& error) { - payload.AddPair({"name", document_name}); - } - - auto res_callback = [callback = std::move(callback)](cpr::Response res) { - - if(res.status_code == 200) + if (res.result() == beast::http::status::ok) { if(hasJsonHeader(res)) { - auto j = json::parse(res.text); + auto j = json::parse(res.body); if(j.is_object()) { // parse object as a document - callback(std::move(res), j); - return; + callback(std::move(res), error, j); } } - - res.error.code = cpr::ErrorCode::UNKNOWN_ERROR; - res.error.message = "Unable to parse response"; } - callback(std::move(res), {}); + callback(std::move(res), error, {}); }; - storeRequest(cpr::PostCallback(std::move(res_callback), - getApiRootUrl() + "/documents", - std::move(payload), - cpr::Timeout{3000})); + storeRequest(network::httpWriteAsync(request, std::to_string(m_port), res_callback, std::chrono::milliseconds(3000))); } - void Api::renameDocument(std::function callback, + void Api::renameDocument(std::function callback, std::string document_id, std::string const& new_name) { assert(!new_name.empty() && "name should not be empty!"); - storeRequest(cpr::PutCallback(callback, - getApiRootUrl() + "/documents/" + document_id, - cpr::Payload{{"name", new_name}}, - cpr::Timeout{3000})); + Api::Request request; + request.set(beast::http::field::host, m_host); + request.set(beast::http::field::content_type, "application/x-www-form-urlencoded"); + request.method(beast::http::verb::put); + request.target("/api/documents/" + document_id); + request.version = 11; + + request.body = "name=" + new_name; + + storeRequest(network::httpWriteAsync(request, std::to_string(m_port), callback, std::chrono::milliseconds(3000))); } void Api::storeRequest(std::future && future) @@ -208,6 +196,6 @@ namespace kiwi bool Api::hasJsonHeader(Api::Response const& res) { - return (res.header.at("content-type") == "application/json; charset=utf-8"); + return (res[beast::http::field::content_type] == "application/json; charset=utf-8"); } } diff --git a/Client/Source/KiwiApp_Network/KiwiApp_Api.h b/Client/Source/KiwiApp_Network/KiwiApp_Api.h index fe89599a..69453633 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_Api.h +++ b/Client/Source/KiwiApp_Network/KiwiApp_Api.h @@ -21,7 +21,7 @@ #pragma once -#include +#include #include using nlohmann::json; @@ -53,7 +53,11 @@ namespace kiwi class User; - using Response = cpr::Response; + using Response = beast::http::response; + + using Request = beast::http::request; + + using Error = beast::error_code; //! @brief Constructor Api(std::string const& host, uint16_t port = 80, Protocol protocol = Api::Protocol::HTTP); @@ -61,12 +65,6 @@ namespace kiwi //! @brief Destructor ~Api(); - //! @brief Get the API protocol as a string. - std::string getProtocolStr() const; - - //! @brief Get the API root URL - std::string getApiRootUrl() const; - //! @brief Set the API host. void setHost(std::string const& host); @@ -80,16 +78,16 @@ namespace kiwi uint16_t getPort() const noexcept; //! @brief Make an async API request to get a list of documents - void getDocuments(std::function callback); + void getDocuments(std::function callback); //! @brief Make an async API request to create a new document //! @param callback - void createDocument(std::function callback, + void createDocument(std::function callback, std::string const& document_name = ""); //! @brief Rename a document asynchronously. //! @param callback The callback method that will be called when the request is completed. - void renameDocument(std::function callback, + void renameDocument(std::function callback, std::string document_id, std::string const& new_name); private: // methods diff --git a/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp b/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp index 8763a9fe..44e91f8f 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp +++ b/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp @@ -197,11 +197,11 @@ namespace kiwi void DocumentBrowser::Drive::createNewDocument() { - m_api.createDocument([this](Api::Response res, Api::Document document) { + m_api.createDocument([this](Api::Response const& res, Api::Error const& error, Api::Document document) { - if(res.error) + if(error) { - juce::MessageManager::callAsync([message = res.error.message](){ + juce::MessageManager::callAsync([message = error.message()](){ KiwiApp::error("Error: can't create document"); KiwiApp::error("=> " + message); }); @@ -311,11 +311,11 @@ namespace kiwi void DocumentBrowser::Drive::refresh() { - m_api.getDocuments([this](Api::Response res, Api::Documents docs) { + m_api.getDocuments([this](Api::Response const& res, Api::Error const& error, Api::Documents docs) { - if(res.error) + if(error) { - KiwiApp::error("Kiwi API error: can't get documents => " + res.error.message); + KiwiApp::error("Kiwi API error: can't get documents => " + error.message()); } else { @@ -376,15 +376,15 @@ namespace kiwi return; } - m_drive.useApi().renameDocument([](Api::Response res) { + m_drive.useApi().renameDocument([](Api::Response const& res, Api::Error const& error) { - if(!res.error) + if(!error) { std::cout << "document successfully updated" << '\n'; } else { - std::cout << "document update failed, err: " + res.error.message << '\n'; + std::cout << "document update failed, err: " + error.message() << '\n'; } }, m_document._id, new_name); diff --git a/Modules/KiwiNetwork/KiwiNetwork_Http.h b/Modules/KiwiNetwork/KiwiNetwork_Http.h index 83b6e839..13d6562c 100644 --- a/Modules/KiwiNetwork/KiwiNetwork_Http.h +++ b/Modules/KiwiNetwork/KiwiNetwork_Http.h @@ -22,8 +22,13 @@ #pragma once #include +#include +#include +#include +#include #include +#include #include #include @@ -34,40 +39,190 @@ namespace kiwi { namespace network { - //! @brief Sends an http request. - //! @details Returns the response generated by the server. The function blocks until response - //! is handed over. - //! @todo Handle errorcode message. Maybe add a timeout parameter. template - void httpWrite(beast::http::request& request, - beast::http::response& response) + class HttpQuerry { - beast::error_code ec; + public: // methods - // Set up an asio socket. - boost::asio::io_service ios; - tcp::resolver resolver(ios); - tcp::socket socket(ios); + HttpQuerry(beast::http::request& request, + beast::http::response& response, + std::string port, + beast::error_code& error, + std::chrono::milliseconds time_out = std::chrono::milliseconds(0)): + m_request(request), + m_response(response), + m_port(port), + m_io_service(), + m_socket(m_io_service), + m_error(error), + m_time_out(time_out), + m_timer(m_io_service), + m_buffer() + { + } - // Look up the domain name. - std::string host = request[beast::http::field::host].to_string(); - auto const lookup = resolver.resolve({host, "http"}, ec); + ~HttpQuerry() + { + } - // Establish connection to server. - boost::asio::connect(socket, lookup, ec); - - // Prepare the request. - request.prepare_payload(); + void writeRequest() + { + if (m_time_out > std::chrono::milliseconds(0)) + { + m_timer.expires_from_now(m_time_out); + + m_timer.async_wait([this](boost::system::error_code const& error) + { + this->handle_time_out(error); + }); + } + + tcp::resolver resolver(m_io_service); + + std::string host = m_request[beast::http::field::host].to_string(); + + resolver.async_resolve({host, m_port}, [this](beast::error_code const& error, + tcp::resolver::iterator iterator) + { + this->handle_resolve(error, iterator); + }); + + m_io_service.reset(); + + while(!m_error && m_io_service.run_one()) + { + } + }; + + private: // methods + + void handle_time_out(boost::system::error_code const& error) + { + m_io_service.stop(); + + m_socket.shutdown(tcp::socket::shutdown_both, m_error); + m_error = boost::asio::error::basic_errors::timed_out; + } + + void handle_read(beast::error_code const& error) + { + m_io_service.stop(); + + if (error) + { + m_error = error; + } + else + { + m_socket.shutdown(tcp::socket::shutdown_both, m_error); + } + } + + void handle_write(beast::error_code const& error) + { + if (error) + { + m_error = error; + } + else + { + beast::http::async_read(m_socket, m_buffer, m_response, [this](beast::error_code const& error) + { + this->handle_read(error); + }); + } + } + + void handle_connect(beast::error_code const& error) + { + if (error) + { + m_error = error; + } + else + { + m_request.prepare_payload(); + + beast::http::async_write(m_socket, m_request, [this](beast::error_code const& error) + { + this->handle_write(error); + }); + + } + } + + void handle_resolve(beast::error_code const& error, + tcp::resolver::iterator iterator) + { + if (error) + { + m_error = error; + } + else + { + boost::asio::async_connect(m_socket, iterator, [this](beast::error_code const& error, + tcp::resolver::iterator i) + { + this->handle_connect(error); + }); + } + } - // Sends the request. - beast::http::write(socket, request, ec); + private: // members - // Reads the response. - beast::flat_buffer buffer; - beast::http::read(socket, buffer, response, ec); + beast::http::request& m_request; + beast::http::response& m_response; + std::string m_port; + boost::asio::io_service m_io_service; + tcp::socket m_socket; + beast::error_code& m_error; + std::chrono::milliseconds m_time_out; + boost::asio::steady_timer m_timer; + beast::flat_buffer m_buffer; - // Close connection to server. - socket.shutdown(tcp::socket::shutdown_both, ec); + + private: // deleted methods + + HttpQuerry() = delete; + HttpQuerry(HttpQuerry const& other) = delete; + HttpQuerry(HttpQuerry && other) = delete; + HttpQuerry& operator=(HttpQuerry const& other) = delete; + HttpQuerry& operator=(HttpQuerry && other) = delete; + }; + + //! @brief Sends an http request. + //! @details Returns the response generated by the server. The function blocks until response + //! is received or error occurs. + template + void httpWrite(beast::http::request& request, + beast::http::response& response, + std::string port, + beast::error_code& error, + std::chrono::milliseconds time_out = std::chrono::milliseconds(0)) + { + HttpQuerry(request, response, port, error).writeRequest(); + } + + //! @brief Sends an http request asynchronously. + //! @details Returns the response generated by the server. The function is non blocking. callback + //! is called on another thread once response is received or error occurs. + template + std::future httpWriteAsync(beast::http::request const& request, + std::string port, + std::function const& response, + beast::error_code const& error)> callback, + std::chrono::milliseconds time_out = std::chrono::milliseconds(0)) + { + return std::async(std::launch::async, [request, port, time_out, callback]() + { + beast::http::request req(request); + beast::http::response response; + beast::error_code error; + + HttpQuerry(req, response, port, error, time_out).writeRequest(); + + return callback(response, error); + }); } } } diff --git a/Test/Network/test_Http.cpp b/Test/Network/test_Http.cpp index 1aca1287..47800010 100755 --- a/Test/Network/test_Http.cpp +++ b/Test/Network/test_Http.cpp @@ -43,11 +43,38 @@ TEST_CASE("Network - Http", "[Network, Http]") request.set(beast::http::field::host, "httpbin.org"); request.set(beast::http::field::user_agent, "test"); - beast::http::response response; + beast::http::response response; + + beast::error_code error; // Send request and waits for response. - kiwi::network::httpWrite(request, response); + kiwi::network::httpWrite(request, response, "80", error); CHECK(response.result() == beast::http::status::ok); + CHECK(!error); + } + + SECTION("Client asynchronous get request to echo server") + { + // Construct request and response. + beast::http::request request; + request.method(beast::http::verb::get); + request.target("/get"); + request.version = 11; + request.set(beast::http::field::host, "httpbin.org"); + request.set(beast::http::field::user_agent, "test"); + + std::function const& response, + beast::error_code const& error)> + callback = [](beast::http::response const& response, + beast::error_code const& error) + { + CHECK(response.result() == beast::http::status::ok); + CHECK(!error); + }; + + std::future future = kiwi::network::httpWriteAsync(std::move(request), "80", callback); + + future.get(); } } diff --git a/ThirdParty/cpr b/ThirdParty/cpr deleted file mode 160000 index 52d49878..00000000 --- a/ThirdParty/cpr +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 52d498788be27828dc9c33740f728b6be775d83f diff --git a/appveyor.yml b/appveyor.yml index f4337753..04c2198c 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -14,28 +14,19 @@ environment: install: - git submodule update --init --recursive "ThirdParty/Juce" - - git submodule update --init --recursive "ThirdParty/cpr" - git submodule update --init --recursive "ThirdParty/concurrentqueue" - git submodule update --init --recursive "ThirdParty/Beast" - set PATH=C:\Python27;%PATH% - - curl -o ..\curl-7.52.1-win32.zip -L -k https://github.com/Musicoll/Kiwi/files/998123/curl-7.52.1-win32.zip - - curl -o ..\curl-7.52.1-x64.zip -L -k https://github.com/Musicoll/Kiwi/files/997546/curl-7.52.1-x64.zip - curl -o ..\flip-demo.zip -L -k http://developer.irisate.com.s3-website-us-east-1.amazonaws.com/files/flip-demo-windows-c47e41da05.zip - cd .. - - 7z x curl-7.52.1-x64.zip - - 7z x curl-7.52.1-win32.zip - 7z x flip-demo.zip -o./flip-demo - - set KIWI_CURL_LIB_x64=%cd%/curl-7.52.1-x64/lib/Release - - set KIWI_CURL_INCLUDE_x64=%cd%/curl-7.52.1-x64/include - - set KIWI_CURL_LIB_WIN32=%cd%/curl-7.52.1-win32/lib/Release - - set KIWI_CURL_INCLUDE_WIN32=%cd%/curl-7.52.1-win32/include - set KIWI_FLIP_LIB_x64=%cd%/flip-demo/lib/VS2015/x64/Release - set KIWI_FLIP_INCLUDE_x64=%cd%/flip-demo/include - set KIWI_FLIP_LIB_WIN32=%cd%/flip-demo/lib/VS2015/Win32/Release - set KIWI_FLIP_INCLUDE_WIN32=%cd%/flip-demo/include - set KIWI_BOOST_INCLUDE=C:\Libraries\boost_1_63_0 - set KIWI_BOOST_LIB_x64=C:\Libraries\boost_1_63_0\lib64-msvc-14.0 - - set KIWI_BOOST_LIB_WIN3=C:\Libraries\boost_1_63_0\lib32-msvc-14.0 + - set KIWI_BOOST_LIB_WIN32=C:\Libraries\boost_1_63_0\lib32-msvc-14.0 - cd %APPVEYOR_BUILD_FOLDER% build_script: From b0b0b61f81fdb162c30b3049bdd9cf1113c02760 Mon Sep 17 00:00:00 2001 From: jean-millot Date: Wed, 12 Jul 2017 16:10:47 +0200 Subject: [PATCH 020/148] Changing httpWrite signature. --- Client/Source/KiwiApp_Network/KiwiApp_Api.cpp | 60 +++++++++++------- Modules/KiwiNetwork/KiwiNetwork_Http.h | 63 +++++++++---------- Test/Network/test_Http.cpp | 34 +++++----- 3 files changed, 87 insertions(+), 70 deletions(-) diff --git a/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp b/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp index 6817efe8..35c5de80 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp +++ b/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp @@ -116,29 +116,33 @@ namespace kiwi callback(res, error, {}); }; - Api::Request request; - request.set(beast::http::field::host, m_host); - request.method(beast::http::verb::get); - request.target("/api/documents"); - request.version = 11; + std::unique_ptr request(new Api::Request()); + request->set(beast::http::field::host, m_host); + request->method(beast::http::verb::get); + request->target("/api/documents"); + request->version = 11; - Api::Response response; - Api::Error error; + request->prepare_payload(); - storeRequest(network::httpWriteAsync(request, std::to_string(m_port), res_callback, std::chrono::milliseconds(3000))); + storeRequest(network::httpWriteAsync(std::move(request), + std::to_string(m_port), + res_callback, + std::chrono::milliseconds(3000))); } void Api::createDocument(std::function callback, std::string const& document_name) { - Api::Request request; - request.set(beast::http::field::host, m_host); - request.set(beast::http::field::content_type, "application/x-www-form-urlencoded"); - request.method(beast::http::verb::post); - request.target("/api/documents"); - request.version = 11; + std::unique_ptr request(new Api::Request()); + request->set(beast::http::field::host, m_host); + request->set(beast::http::field::content_type, "application/x-www-form-urlencoded"); + request->method(beast::http::verb::post); + request->target("/api/documents"); + request->version = 11; - request.body = "name=" + document_name; + request->body = "name=" + document_name; + + request->prepare_payload(); std::function res_callback = [callback = std::move(callback)](Api::Response const& res, Api::Error const& error) @@ -160,7 +164,10 @@ namespace kiwi callback(std::move(res), error, {}); }; - storeRequest(network::httpWriteAsync(request, std::to_string(m_port), res_callback, std::chrono::milliseconds(3000))); + storeRequest(network::httpWriteAsync(std::move(request), + std::to_string(m_port), + res_callback, + std::chrono::milliseconds(3000))); } void Api::renameDocument(std::function callback, @@ -168,16 +175,21 @@ namespace kiwi { assert(!new_name.empty() && "name should not be empty!"); - Api::Request request; - request.set(beast::http::field::host, m_host); - request.set(beast::http::field::content_type, "application/x-www-form-urlencoded"); - request.method(beast::http::verb::put); - request.target("/api/documents/" + document_id); - request.version = 11; + std::unique_ptr request(new Api::Request()); + request->set(beast::http::field::host, m_host); + request->set(beast::http::field::content_type, "application/x-www-form-urlencoded"); + request->method(beast::http::verb::put); + request->target("/api/documents/" + document_id); + request->version = 11; + + request->body = "name=" + new_name; - request.body = "name=" + new_name; + request->prepare_payload(); - storeRequest(network::httpWriteAsync(request, std::to_string(m_port), callback, std::chrono::milliseconds(3000))); + storeRequest(network::httpWriteAsync(std::move(request), + std::to_string(m_port), + callback, + std::chrono::milliseconds(3000))); } void Api::storeRequest(std::future && future) diff --git a/Modules/KiwiNetwork/KiwiNetwork_Http.h b/Modules/KiwiNetwork/KiwiNetwork_Http.h index 13d6562c..7eb59556 100644 --- a/Modules/KiwiNetwork/KiwiNetwork_Http.h +++ b/Modules/KiwiNetwork/KiwiNetwork_Http.h @@ -44,17 +44,15 @@ namespace kiwi { public: // methods - HttpQuerry(beast::http::request& request, - beast::http::response& response, + HttpQuerry(std::unique_ptr> request, std::string port, - beast::error_code& error, std::chrono::milliseconds time_out = std::chrono::milliseconds(0)): - m_request(request), - m_response(response), + m_request(std::move(request)), + m_response(), m_port(port), m_io_service(), m_socket(m_io_service), - m_error(error), + m_error(), m_time_out(time_out), m_timer(m_io_service), m_buffer() @@ -65,7 +63,7 @@ namespace kiwi { } - void writeRequest() + beast::http::response writeRequest(beast::error_code& error) { if (m_time_out > std::chrono::milliseconds(0)) { @@ -79,7 +77,7 @@ namespace kiwi tcp::resolver resolver(m_io_service); - std::string host = m_request[beast::http::field::host].to_string(); + std::string host = (*m_request)[beast::http::field::host].to_string(); resolver.async_resolve({host, m_port}, [this](beast::error_code const& error, tcp::resolver::iterator iterator) @@ -92,6 +90,10 @@ namespace kiwi while(!m_error && m_io_service.run_one()) { } + + error = m_error; + + return m_response; }; private: // methods @@ -140,10 +142,8 @@ namespace kiwi m_error = error; } else - { - m_request.prepare_payload(); - - beast::http::async_write(m_socket, m_request, [this](beast::error_code const& error) + { + beast::http::async_write(m_socket, *m_request, [this](beast::error_code const& error) { this->handle_write(error); }); @@ -170,15 +170,15 @@ namespace kiwi private: // members - beast::http::request& m_request; - beast::http::response& m_response; - std::string m_port; - boost::asio::io_service m_io_service; - tcp::socket m_socket; - beast::error_code& m_error; - std::chrono::milliseconds m_time_out; - boost::asio::steady_timer m_timer; - beast::flat_buffer m_buffer; + std::unique_ptr> m_request; + beast::http::response m_response; + std::string m_port; + boost::asio::io_service m_io_service; + tcp::socket m_socket; + beast::error_code m_error; + std::chrono::milliseconds m_time_out; + boost::asio::steady_timer m_timer; + beast::flat_buffer m_buffer; private: // deleted methods @@ -194,32 +194,31 @@ namespace kiwi //! @details Returns the response generated by the server. The function blocks until response //! is received or error occurs. template - void httpWrite(beast::http::request& request, - beast::http::response& response, - std::string port, - beast::error_code& error, - std::chrono::milliseconds time_out = std::chrono::milliseconds(0)) + beast::http::response httpWrite(std::unique_ptr> request, + std::string port, + beast::error_code& error, + std::chrono::milliseconds time_out = std::chrono::milliseconds(0)) { - HttpQuerry(request, response, port, error).writeRequest(); + return HttpQuerry(std::move(request), port).writeRequest(error); } //! @brief Sends an http request asynchronously. //! @details Returns the response generated by the server. The function is non blocking. callback //! is called on another thread once response is received or error occurs. template - std::future httpWriteAsync(beast::http::request const& request, + std::future httpWriteAsync(std::unique_ptr> request, std::string port, std::function const& response, beast::error_code const& error)> callback, std::chrono::milliseconds time_out = std::chrono::milliseconds(0)) { - return std::async(std::launch::async, [request, port, time_out, callback]() + std::unique_ptr> querry(new HttpQuerry(std::move(request), port, time_out)); + + return std::async(std::launch::async, [querry = std::move(querry), callback]() { - beast::http::request req(request); - beast::http::response response; beast::error_code error; - HttpQuerry(req, response, port, error, time_out).writeRequest(); + beast::http::response response = querry->writeRequest(error); return callback(response, error); }); diff --git a/Test/Network/test_Http.cpp b/Test/Network/test_Http.cpp index 47800010..7492d66e 100755 --- a/Test/Network/test_Http.cpp +++ b/Test/Network/test_Http.cpp @@ -36,19 +36,21 @@ TEST_CASE("Network - Http", "[Network, Http]") SECTION("Client get request to echo server") { // Construct request and response. - beast::http::request request; - request.method(beast::http::verb::get); - request.target("/get"); - request.version = 11; - request.set(beast::http::field::host, "httpbin.org"); - request.set(beast::http::field::user_agent, "test"); + std::unique_ptr> + request(new beast::http::request()); + request->method(beast::http::verb::get); + request->target("/get"); + request->version = 11; + request->set(beast::http::field::host, "httpbin.org"); + request->set(beast::http::field::user_agent, "test"); - beast::http::response response; + request->prepare_payload(); beast::error_code error; // Send request and waits for response. - kiwi::network::httpWrite(request, response, "80", error); + beast::http::response response = + kiwi::network::httpWrite(std::move(request), "80", error); CHECK(response.result() == beast::http::status::ok); CHECK(!error); @@ -57,12 +59,16 @@ TEST_CASE("Network - Http", "[Network, Http]") SECTION("Client asynchronous get request to echo server") { // Construct request and response. - beast::http::request request; - request.method(beast::http::verb::get); - request.target("/get"); - request.version = 11; - request.set(beast::http::field::host, "httpbin.org"); - request.set(beast::http::field::user_agent, "test"); + std::unique_ptr> + request(new beast::http::request()); + + request->method(beast::http::verb::get); + request->target("/get"); + request->version = 11; + request->set(beast::http::field::host, "httpbin.org"); + request->set(beast::http::field::user_agent, "test"); + + request->prepare_payload(); std::function const& response, beast::error_code const& error)> From 15d0789e1a935da3105577c7b3eaed8eb50e1b87 Mon Sep 17 00:00:00 2001 From: eliott PARIS Date: Thu, 13 Jul 2017 14:41:26 +0200 Subject: [PATCH 021/148] Fix CMakeList typos --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 089c5aa9..b8361bf9 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -285,7 +285,7 @@ if (FLIP_LIBRARIES AND FLIP_INCLUDE_DIRS) message(STATUS "FLIP_LIBRARIES : " ${FLIP_LIBRARIES}) message(STATUS "FLIP_INCLUDE_DIRS : " ${FLIP_INCLUDE_DIRS}) else() - message(FATAL_ERROR "Flip was not found on system, check Readme.md for instructions on how to set searh path") + message(FATAL_ERROR "Flip was not found on system, check Readme.md for instructions on how to set search path") endif() set(FLIP_COMPILE_DEFINITIONS "flip_NOTHING=flip_NOTHING_FATAL") @@ -314,7 +314,7 @@ find_package (Boost 1.63.0 REQUIRED COMPONENTS system) if (Boost_FOUND) message(STATUS "Boost found on system") message(STATUS "Boost_LIBRARIES : " ${Boost_LIBRARIES}) - message(STATUS "BOOST_INCLUDE_DIRECTORES : " ${Boost_INCLUDE_DIRS}) + message(STATUS "BOOST_INCLUDE_DIRECTORIES : " ${Boost_INCLUDE_DIRS}) else() message(FATAL_ERROR "Boost not found on system") endif() From 40632f2cd72336cac6d4b1ffab30e34bea9de243 Mon Sep 17 00:00:00 2001 From: eliott PARIS Date: Thu, 13 Jul 2017 14:42:04 +0200 Subject: [PATCH 022/148] update thirdparty links on the Readme --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d9d54865..313f3812 100644 --- a/README.md +++ b/README.md @@ -68,8 +68,9 @@ Kiwi uses the following ThirdParty libraries: - [Flip](http://developer.irisate.com/) - [Juce](https://github.com/WeAreROLI/JUCE) -- [cpr](https://github.com/whoshuu/cpr) -- [readerwriterqueue](https://github.com/cameron314/readerwriterqueue) +- [Beast](https://github.com/vinniefalco/Beast/) +- [concurrentqueue](https://github.com/cameron314/concurrentqueue) +- [json](https://github.com/nlohmann/json) > Most of the application icons are *designed by Freepik and distributed by Flaticon*. From e0c52da90cd4a55522d663d9bebeb6c4dc4e1bc2 Mon Sep 17 00:00:00 2001 From: eliott PARIS Date: Thu, 13 Jul 2017 15:03:14 +0200 Subject: [PATCH 023/148] Fix Query typo --- Modules/KiwiNetwork/KiwiNetwork_Http.h | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Modules/KiwiNetwork/KiwiNetwork_Http.h b/Modules/KiwiNetwork/KiwiNetwork_Http.h index 7eb59556..afa14071 100644 --- a/Modules/KiwiNetwork/KiwiNetwork_Http.h +++ b/Modules/KiwiNetwork/KiwiNetwork_Http.h @@ -40,11 +40,11 @@ namespace kiwi namespace network { template - class HttpQuerry + class HttpQuery { public: // methods - HttpQuerry(std::unique_ptr> request, + HttpQuery(std::unique_ptr> request, std::string port, std::chrono::milliseconds time_out = std::chrono::milliseconds(0)): m_request(std::move(request)), @@ -59,7 +59,7 @@ namespace kiwi { } - ~HttpQuerry() + ~HttpQuery() { } @@ -183,11 +183,11 @@ namespace kiwi private: // deleted methods - HttpQuerry() = delete; - HttpQuerry(HttpQuerry const& other) = delete; - HttpQuerry(HttpQuerry && other) = delete; - HttpQuerry& operator=(HttpQuerry const& other) = delete; - HttpQuerry& operator=(HttpQuerry && other) = delete; + HttpQuery() = delete; + HttpQuery(HttpQuery const& other) = delete; + HttpQuery(HttpQuery && other) = delete; + HttpQuery& operator=(HttpQuery const& other) = delete; + HttpQuery& operator=(HttpQuery && other) = delete; }; //! @brief Sends an http request. @@ -199,7 +199,7 @@ namespace kiwi beast::error_code& error, std::chrono::milliseconds time_out = std::chrono::milliseconds(0)) { - return HttpQuerry(std::move(request), port).writeRequest(error); + return HttpQuery(std::move(request), port).writeRequest(error); } //! @brief Sends an http request asynchronously. @@ -212,13 +212,13 @@ namespace kiwi beast::error_code const& error)> callback, std::chrono::milliseconds time_out = std::chrono::milliseconds(0)) { - std::unique_ptr> querry(new HttpQuerry(std::move(request), port, time_out)); + std::unique_ptr> query(new HttpQuery(std::move(request), port, time_out)); - return std::async(std::launch::async, [querry = std::move(querry), callback]() + return std::async(std::launch::async, [query = std::move(query), callback]() { beast::error_code error; - beast::http::response response = querry->writeRequest(error); + beast::http::response response = query->writeRequest(error); return callback(response, error); }); From 10ccfd03242a1c0c2e3b124362142bf9bcc7cf50 Mon Sep 17 00:00:00 2001 From: eliott PARIS Date: Thu, 13 Jul 2017 17:02:52 +0200 Subject: [PATCH 024/148] Put API class into the Network module --- CMakeLists.txt | 4 +- Client/Source/KiwiApp_Network/KiwiApp_Api.cpp | 213 ----------------- Client/Source/KiwiApp_Network/KiwiApp_Api.h | 115 ---------- .../KiwiApp_DocumentBrowser.cpp | 2 - .../KiwiApp_Network/KiwiApp_DocumentBrowser.h | 4 +- Modules/KiwiNetwork/KiwiNetwork_Api.cpp | 214 ++++++++++++++++++ Modules/KiwiNetwork/KiwiNetwork_Api.h | 114 ++++++++++ Test/Network/test_Http.cpp | 9 +- 8 files changed, 336 insertions(+), 339 deletions(-) delete mode 100644 Client/Source/KiwiApp_Network/KiwiApp_Api.cpp delete mode 100644 Client/Source/KiwiApp_Network/KiwiApp_Api.h create mode 100644 Modules/KiwiNetwork/KiwiNetwork_Api.cpp create mode 100644 Modules/KiwiNetwork/KiwiNetwork_Api.h diff --git a/CMakeLists.txt b/CMakeLists.txt index b8361bf9..1e36e603 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -359,7 +359,8 @@ file(GLOB_RECURSE KIWI_NETWORK_SRC ${ROOT_DIR}/Modules/KiwiNetwork/*.[c|h]pp add_library(KiwiNetwork STATIC ${KIWI_NETWORK_SRC}) target_include_directories(KiwiNetwork PUBLIC ${ROOT_DIR}/Modules ${ROOT_DIR}/ThirdParty/Beast/include - ${Boost_INCLUDE_DIRS}) + ${Boost_INCLUDE_DIRS} + ${JSON_INCLUDE_DIRS}) target_compile_definitions(KiwiNetwork PUBLIC "-DBOOST_ALL_NO_LIB=1") set(NETWORK_DEP ${Boost_LIBRARIES}) if (WIN32) @@ -417,7 +418,6 @@ target_add_dependency(Kiwi KiwiEngine) target_add_dependency(Kiwi KiwiModel) target_add_dependency(Kiwi KiwiDsp) target_add_dependency(Kiwi Juce) -target_include_directories(Kiwi PUBLIC ${JSON_INCLUDE_DIRS} ${CPR_INCLUDE_DIRS}) if (APPLE) set_target_properties(Kiwi PROPERTIES MACOSX_BUNDLE TRUE diff --git a/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp b/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp deleted file mode 100644 index 35c5de80..00000000 --- a/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp +++ /dev/null @@ -1,213 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#include "KiwiApp_Api.h" - -#include - -namespace kiwi -{ - void to_json(json& j, Api::Document const& doc) - { - std::stringstream session_id_converter; - session_id_converter << std::hex << doc.session_id; - - j = json{ - {"_id", doc._id}, - {"name", doc.name}, - {"session_id", session_id_converter.str()} - }; - } - - void from_json(json const& j, Api::Document& doc) - { - doc._id = j["_id"].get(); - doc.name = j["name"].get(); - doc.session_id = 0ul; - - if(j.count("session_id")) - { - std::stringstream converter(j["session_id"].get()); - converter >> std::hex >> doc.session_id; - } - } - - bool Api::Document::operator==(Api::Document const& other_doc) const - { - return (_id == other_doc._id); - } - - // ================================================================================ // - // API REQUEST // - // ================================================================================ // - - Api::Api(std::string const& host, uint16_t port, Protocol protocol) : - m_protocol(protocol), - m_host(host), - m_port(port) - { - ; - } - - //! @brief Destructor - Api::~Api() - { - - } - - void Api::setHost(std::string const& host) - { - m_host = host; - } - - std::string const& Api::getHost() const - { - return m_host; - } - - void Api::setPort(uint16_t port) noexcept - { - m_port = port; - } - - uint16_t Api::getPort() const noexcept - { - return m_port; - } - - void Api::getDocuments(std::function callback) - { - std::function res_callback = - [callback = std::move(callback)](Api::Response const& res, Api::Error const& error) - { - if (res.result() == beast::http::status::ok) - { - if(hasJsonHeader(res)) - { - auto j = json::parse(res.body); - - if(j.is_array()) - { - // parse each json objects as document and store them in a vector. - callback(res, error, j); - return; - } - } - } - - callback(res, error, {}); - }; - - std::unique_ptr request(new Api::Request()); - request->set(beast::http::field::host, m_host); - request->method(beast::http::verb::get); - request->target("/api/documents"); - request->version = 11; - - request->prepare_payload(); - - storeRequest(network::httpWriteAsync(std::move(request), - std::to_string(m_port), - res_callback, - std::chrono::milliseconds(3000))); - } - - void Api::createDocument(std::function callback, - std::string const& document_name) - { - std::unique_ptr request(new Api::Request()); - request->set(beast::http::field::host, m_host); - request->set(beast::http::field::content_type, "application/x-www-form-urlencoded"); - request->method(beast::http::verb::post); - request->target("/api/documents"); - request->version = 11; - - request->body = "name=" + document_name; - - request->prepare_payload(); - - std::function res_callback = - [callback = std::move(callback)](Api::Response const& res, Api::Error const& error) - { - if (res.result() == beast::http::status::ok) - { - if(hasJsonHeader(res)) - { - auto j = json::parse(res.body); - - if(j.is_object()) - { - // parse object as a document - callback(std::move(res), error, j); - } - } - } - - callback(std::move(res), error, {}); - }; - - storeRequest(network::httpWriteAsync(std::move(request), - std::to_string(m_port), - res_callback, - std::chrono::milliseconds(3000))); - } - - void Api::renameDocument(std::function callback, - std::string document_id, std::string const& new_name) - { - assert(!new_name.empty() && "name should not be empty!"); - - std::unique_ptr request(new Api::Request()); - request->set(beast::http::field::host, m_host); - request->set(beast::http::field::content_type, "application/x-www-form-urlencoded"); - request->method(beast::http::verb::put); - request->target("/api/documents/" + document_id); - request->version = 11; - - request->body = "name=" + new_name; - - request->prepare_payload(); - - storeRequest(network::httpWriteAsync(std::move(request), - std::to_string(m_port), - callback, - std::chrono::milliseconds(3000))); - } - - void Api::storeRequest(std::future && future) - { - for(std::future& f : m_pending_requests) - { - if(f.wait_for(std::chrono::seconds(0)) == std::future_status::ready) - { - f = std::move(future); - return; - } - } - - m_pending_requests.emplace_back(std::move(future)); - } - - bool Api::hasJsonHeader(Api::Response const& res) - { - return (res[beast::http::field::content_type] == "application/json; charset=utf-8"); - } -} diff --git a/Client/Source/KiwiApp_Network/KiwiApp_Api.h b/Client/Source/KiwiApp_Network/KiwiApp_Api.h deleted file mode 100644 index 69453633..00000000 --- a/Client/Source/KiwiApp_Network/KiwiApp_Api.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#pragma once - -#include - -#include -using nlohmann::json; - -namespace kiwi -{ - // ================================================================================ // - // API // - // ================================================================================ // - - //! @brief An API request handler class. - class Api - { - public: // methods - - enum class Protocol : uint8_t { HTTP = 0, HTTPS = 1 }; - - struct Document - { - std::string _id = "0"; - std::string name = ""; - uint64_t session_id = 0ul; - - //! @brief Returns true if the Document match another Document - bool operator==(Document const& other_doc) const; - }; - - using Documents = std::vector; - - class User; - - using Response = beast::http::response; - - using Request = beast::http::request; - - using Error = beast::error_code; - - //! @brief Constructor - Api(std::string const& host, uint16_t port = 80, Protocol protocol = Api::Protocol::HTTP); - - //! @brief Destructor - ~Api(); - - //! @brief Set the API host. - void setHost(std::string const& host); - - //! @brief Get the API host. - std::string const& getHost() const; - - //! @brief Set the API port. - void setPort(uint16_t port) noexcept; - - //! @brief Get the API port. - uint16_t getPort() const noexcept; - - //! @brief Make an async API request to get a list of documents - void getDocuments(std::function callback); - - //! @brief Make an async API request to create a new document - //! @param callback - void createDocument(std::function callback, - std::string const& document_name = ""); - - //! @brief Rename a document asynchronously. - //! @param callback The callback method that will be called when the request is completed. - void renameDocument(std::function callback, - std::string document_id, std::string const& new_name); - - private: // methods - - //! @internal Store the async future request in a vector - void storeRequest(std::future && future); - - //! @internal Check if the response header has a JSON content-type - static bool hasJsonHeader(Api::Response const& res); - - private: // variables - - Protocol m_protocol; - std::string m_host; - uint16_t m_port; - - std::vector> m_pending_requests; - }; - - //! @brief Helper function to convert an Api::Document into a json object - void to_json(json& j, Api::Document const& doc); - - //! @brief Helper function to convert a json object into an Api::Document - void from_json(json const& j, Api::Document& doc); -} diff --git a/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp b/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp index 44e91f8f..fb2766f8 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp +++ b/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp @@ -22,8 +22,6 @@ #include "KiwiApp_DocumentBrowser.h" #include "../KiwiApp.h" -#include "../KiwiApp_Network/KiwiApp_Api.h" - #include #include #include diff --git a/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.h b/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.h index 4dba3028..99c2bf44 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.h +++ b/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.h @@ -26,12 +26,14 @@ #include #include -#include "KiwiApp_Api.h" +#include #include "../KiwiApp_General/KiwiApp_StoredSettings.h" namespace kiwi { + using network::Api; + // ================================================================================ // // DOCUMENT BROWSER // // ================================================================================ // diff --git a/Modules/KiwiNetwork/KiwiNetwork_Api.cpp b/Modules/KiwiNetwork/KiwiNetwork_Api.cpp new file mode 100644 index 00000000..fe4d5b7f --- /dev/null +++ b/Modules/KiwiNetwork/KiwiNetwork_Api.cpp @@ -0,0 +1,214 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include "KiwiNetwork_Api.h" +#include "KiwiNetwork_Http.h" + +namespace kiwi +{ + namespace network + { + void to_json(json& j, Api::Document const& doc) + { + std::stringstream session_id_converter; + session_id_converter << std::hex << doc.session_id; + + j = json{ + {"_id", doc._id}, + {"name", doc.name}, + {"session_id", session_id_converter.str()} + }; + } + + void from_json(json const& j, Api::Document& doc) + { + doc._id = j["_id"].get(); + doc.name = j["name"].get(); + doc.session_id = 0ul; + + if(j.count("session_id")) + { + std::stringstream converter(j["session_id"].get()); + converter >> std::hex >> doc.session_id; + } + } + + bool Api::Document::operator==(Api::Document const& other_doc) const + { + return (_id == other_doc._id); + } + + // ================================================================================ // + // API REQUEST // + // ================================================================================ // + + Api::Api(std::string const& host, uint16_t port) : + m_host(host), + m_port(port) + { + ; + } + + //! @brief Destructor + Api::~Api() + { + + } + + void Api::setHost(std::string const& host) + { + m_host = host; + } + + std::string const& Api::getHost() const + { + return m_host; + } + + void Api::setPort(uint16_t port) noexcept + { + m_port = port; + } + + uint16_t Api::getPort() const noexcept + { + return m_port; + } + + void Api::getDocuments(std::function callback) + { + std::function res_callback = + [callback = std::move(callback)](Api::Response const& res, Api::Error const& error) + { + if (res.result() == beast::http::status::ok) + { + if(hasJsonHeader(res)) + { + auto j = json::parse(res.body); + + if(j.is_array()) + { + // parse each json objects as document and store them in a vector. + callback(res, error, j); + return; + } + } + } + + callback(res, error, {}); + }; + + auto request = std::make_unique(); + request->set(beast::http::field::host, m_host); + request->method(beast::http::verb::get); + request->target("/api/documents"); + request->version = 11; + + request->prepare_payload(); + + storeRequest(network::httpWriteAsync(std::move(request), + std::to_string(m_port), + res_callback, + std::chrono::milliseconds(3000))); + } + + void Api::createDocument(std::function callback, + std::string const& document_name) + { + auto request = std::make_unique(); + request->set(beast::http::field::host, m_host); + request->set(beast::http::field::content_type, "application/x-www-form-urlencoded"); + request->method(beast::http::verb::post); + request->target("/api/documents"); + request->version = 11; + + request->body = "name=" + document_name; + + request->prepare_payload(); + + std::function res_callback = + [callback = std::move(callback)](Api::Response const& res, Api::Error const& error) + { + if (res.result() == beast::http::status::ok) + { + if(hasJsonHeader(res)) + { + auto j = json::parse(res.body); + + if(j.is_object()) + { + // parse object as a document + callback(std::move(res), error, j); + } + } + } + + callback(std::move(res), error, {}); + }; + + storeRequest(network::httpWriteAsync(std::move(request), + std::to_string(m_port), + res_callback, + std::chrono::milliseconds(3000))); + } + + void Api::renameDocument(std::function callback, + std::string document_id, std::string const& new_name) + { + assert(!new_name.empty() && "name should not be empty!"); + + auto request = std::make_unique(); + request->set(beast::http::field::host, m_host); + request->set(beast::http::field::content_type, "application/x-www-form-urlencoded"); + request->method(beast::http::verb::put); + request->version = 11; + request->target("/api/documents/" + document_id); + + request->body = "name=" + new_name; + + request->prepare_payload(); + + storeRequest(network::httpWriteAsync(std::move(request), + std::to_string(m_port), + callback, + std::chrono::milliseconds(3000))); + } + + void Api::storeRequest(std::future && future) + { + for(std::future& f : m_pending_requests) + { + if(f.wait_for(std::chrono::seconds(0)) == std::future_status::ready) + { + f = std::move(future); + return; + } + } + + m_pending_requests.emplace_back(std::move(future)); + } + + bool Api::hasJsonHeader(Api::Response const& res) + { + return (res[beast::http::field::content_type] == "application/json; charset=utf-8"); + } + } +} diff --git a/Modules/KiwiNetwork/KiwiNetwork_Api.h b/Modules/KiwiNetwork/KiwiNetwork_Api.h new file mode 100644 index 00000000..a650b14b --- /dev/null +++ b/Modules/KiwiNetwork/KiwiNetwork_Api.h @@ -0,0 +1,114 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include "KiwiNetwork_Http.h" + +#include + +namespace kiwi +{ + using nlohmann::json; + + namespace network + { + // ================================================================================ // + // API // + // ================================================================================ // + + //! @brief An API request handler class. + class Api + { + public: // methods + + struct Document + { + std::string _id = "0"; + std::string name = ""; + uint64_t session_id = 0ul; + + //! @brief Returns true if the Document match another Document + bool operator==(Document const& other_doc) const; + }; + + using Documents = std::vector; + + using Response = beast::http::response; + + using Request = beast::http::request; + + using Error = beast::error_code; + + //! @brief Constructor + Api(std::string const& host, uint16_t port = 80); + + //! @brief Destructor + ~Api(); + + //! @brief Set the API host. + void setHost(std::string const& host); + + //! @brief Get the API host. + std::string const& getHost() const; + + //! @brief Set the API port. + void setPort(uint16_t port) noexcept; + + //! @brief Get the API port. + uint16_t getPort() const noexcept; + + //! @brief Make an async API request to get a list of documents + void getDocuments(std::function callback); + + //! @brief Make an async API request to create a new document + //! @param callback + void createDocument(std::function callback, + std::string const& document_name = ""); + + //! @brief Rename a document asynchronously. + //! @param callback The callback method that will be called when the request is completed. + void renameDocument(std::function callback, + std::string document_id, std::string const& new_name); + + private: // methods + + //! @internal Store the async future request in a vector + void storeRequest(std::future && future); + + //! @internal Check if the response header has a JSON content-type + static bool hasJsonHeader(Api::Response const& res); + + private: // variables + + std::string m_host; + uint16_t m_port; + + std::vector> m_pending_requests; + }; + + //! @brief Helper function to convert an Api::Document into a json object + void to_json(json& j, Api::Document const& doc); + + //! @brief Helper function to convert a json object into an Api::Document + void from_json(json const& j, Api::Document& doc); + } +} diff --git a/Test/Network/test_Http.cpp b/Test/Network/test_Http.cpp index 7492d66e..6e727dd6 100755 --- a/Test/Network/test_Http.cpp +++ b/Test/Network/test_Http.cpp @@ -36,8 +36,7 @@ TEST_CASE("Network - Http", "[Network, Http]") SECTION("Client get request to echo server") { // Construct request and response. - std::unique_ptr> - request(new beast::http::request()); + auto request = std::make_unique>(); request->method(beast::http::verb::get); request->target("/get"); request->version = 11; @@ -59,9 +58,7 @@ TEST_CASE("Network - Http", "[Network, Http]") SECTION("Client asynchronous get request to echo server") { // Construct request and response. - std::unique_ptr> - request(new beast::http::request()); - + auto request = std::make_unique>(); request->method(beast::http::verb::get); request->target("/get"); request->version = 11; @@ -73,7 +70,7 @@ TEST_CASE("Network - Http", "[Network, Http]") std::function const& response, beast::error_code const& error)> callback = [](beast::http::response const& response, - beast::error_code const& error) + beast::error_code const& error) { CHECK(response.result() == beast::http::status::ok); CHECK(!error); From 20ff8098c21ece1989a20971e227366c16f70625 Mon Sep 17 00:00:00 2001 From: eliott PARIS Date: Tue, 18 Jul 2017 18:24:46 +0200 Subject: [PATCH 025/148] Put API object into KiwiApp class and create a login form draft --- Client/Source/KiwiApp.cpp | 36 ++- Client/Source/KiwiApp.h | 3 + .../KiwiApp_Application/KiwiApp_Instance.cpp | 37 +++ .../KiwiApp_Application/KiwiApp_Instance.h | 12 +- .../Source/KiwiApp_Auth/KiwiApp_LoginForm.cpp | 224 ++++++++++++++++++ .../Source/KiwiApp_Auth/KiwiApp_LoginForm.h | 74 ++++++ .../KiwiApp_Components/KiwiApp_Window.h | 1 + .../KiwiApp_General/KiwiApp_CommandIDs.h | 7 +- .../KiwiApp_DocumentBrowser.cpp | 58 +---- .../KiwiApp_Network/KiwiApp_DocumentBrowser.h | 21 +- Modules/KiwiNetwork/KiwiNetwork_Api.h | 2 +- 11 files changed, 401 insertions(+), 74 deletions(-) create mode 100644 Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.cpp create mode 100644 Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.h diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index 07a72d19..25a03b9b 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -109,6 +109,9 @@ namespace kiwi juce::PopupMenu macMainMenuPopup; macMainMenuPopup.addCommandItem(&getCommandManager(), CommandIDs::showAboutAppWindow); macMainMenuPopup.addSeparator(); + macMainMenuPopup.addCommandItem(&getCommandManager(), CommandIDs::login); + macMainMenuPopup.addCommandItem(&getCommandManager(), CommandIDs::logout); + macMainMenuPopup.addSeparator(); macMainMenuPopup.addCommandItem(&getCommandManager(), CommandIDs::showAppSettingsWindow); juce::MenuBarModel::setMacMainMenu(m_menu_model.get(), &macMainMenuPopup, TRANS("Open Recent")); #endif @@ -206,6 +209,11 @@ namespace kiwi return *KiwiApp::use().m_instance.get(); } + Api& KiwiApp::useApi() + { + return KiwiApp::use().m_instance->useApi(); + } + uint64_t KiwiApp::userID() { return KiwiApp::use().m_instance->getUserId(); @@ -420,6 +428,7 @@ namespace kiwi { #if ! JUCE_MAC menu.addCommandItem(m_command_manager.get(), CommandIDs::showAboutAppWindow); + menu.addCommandItem(m_command_manager.get(), CommandIDs::login); #endif } @@ -446,7 +455,9 @@ namespace kiwi CommandIDs::showBeaconDispatcherWindow, CommandIDs::switchDsp, CommandIDs::startDsp, - CommandIDs::stopDsp + CommandIDs::stopDsp, + CommandIDs::login, + CommandIDs::logout, }; commands.addArray(ids, juce::numElementsInArray(ids)); @@ -480,6 +491,18 @@ namespace kiwi result.addDefaultKeypress('k', juce::ModifierKeys::commandModifier); break; } + case CommandIDs::login: + { + result.setInfo(TRANS("Login"), TRANS("Show the \"Login form\" Window"), + CommandCategories::windows, 0); + break; + } + case CommandIDs::logout: + { + result.setInfo(TRANS("Logout"), TRANS("Log out current user"), + CommandCategories::windows, 0); + break; + } case CommandIDs::showAboutAppWindow: { result.setInfo(TRANS("About Kiwi"), TRANS("Show the \"About Kiwi\" Window"), @@ -569,6 +592,17 @@ namespace kiwi m_instance->askUserToOpenPatcherDocument(); break; } + case CommandIDs::login: + { + m_instance->showLoginWindow(); + break; + } + case CommandIDs::logout: + { + //m_instance->showConsoleWindow(); + std::cout << "CommandIDs::logout: todo ! \n"; + break; + } case CommandIDs::showConsoleWindow : { m_instance->showConsoleWindow(); diff --git a/Client/Source/KiwiApp.h b/Client/Source/KiwiApp.h index f2f8e922..6405c955 100644 --- a/Client/Source/KiwiApp.h +++ b/Client/Source/KiwiApp.h @@ -91,6 +91,9 @@ namespace kiwi //! @brief Get the current running kiwi instance. static Instance& useInstance(); + //! @brief Get the Api object. + static Api& useApi(); + //! @brief Get the current running engine instance. static engine::Instance& useEngineInstance(); diff --git a/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp b/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp index e06a1e29..78bbbb85 100644 --- a/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp +++ b/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp @@ -29,6 +29,9 @@ #include "../KiwiApp_Components/KiwiApp_Window.h" #include "../KiwiApp_Patcher/KiwiApp_PatcherView.h" #include "../KiwiApp_Patcher/KiwiApp_PatcherComponent.h" +#include "../KiwiApp_General/KiwiApp_IDs.h" + +#include "../KiwiApp_Auth/KiwiApp_LoginForm.h" #include #include @@ -42,12 +45,17 @@ namespace kiwi size_t Instance::m_untitled_patcher_index(0); Instance::Instance() : + m_api(nullptr), m_scheduler(), m_instance(std::make_unique()), m_browser(), m_console_history(std::make_shared(m_instance)), m_last_opened_file(juce::File::getSpecialLocation(juce::File::userHomeDirectory)) { + auto& settings = getAppSettings().network(); + m_api.reset(new Api(settings.getHost(), settings.getApiPort())); + settings.addListener(*this); + startTimer(10); std::srand(std::time(0)); m_user_id = std::rand(); @@ -63,10 +71,29 @@ namespace kiwi Instance::~Instance() { + getAppSettings().network().removeListener(*this); closeAllPatcherWindows(); stopTimer(); } + void Instance::networkSettingsChanged(NetworkSettings const& settings, + const juce::Identifier& id) + { + if(id == Ids::host) + { + m_api->setHost(settings.getHost()); + } + else if(id == Ids::api_port) + { + m_api->setPort(settings.getApiPort()); + } + } + + Api& Instance::useApi() + { + return *m_api; + } + void Instance::timerCallback() { m_scheduler.process(); @@ -315,6 +342,16 @@ namespace kiwi }); } + void Instance::showLoginWindow() + { + showWindowWithId(WindowId::Login, []() { + + return std::make_unique("Log-in to Kiwi", + std::make_unique(), + true, false, "login_window"); + }); + } + void Instance::showAboutKiwiWindow() { showWindowWithId(WindowId::AboutKiwi, [](){ return std::make_unique(); }); diff --git a/Client/Source/KiwiApp_Application/KiwiApp_Instance.h b/Client/Source/KiwiApp_Application/KiwiApp_Instance.h index 9b4cf78b..7b2d4a50 100644 --- a/Client/Source/KiwiApp_Application/KiwiApp_Instance.h +++ b/Client/Source/KiwiApp_Application/KiwiApp_Instance.h @@ -46,7 +46,7 @@ namespace kiwi // ================================================================================ // //! @brief The Application Instance - class Instance : public juce::Timer + class Instance : public juce::Timer, public NetworkSettings::Listener { public: @@ -65,6 +65,9 @@ namespace kiwi //! @brief create a new patcher window. void newPatcher(); + //! @brief Returns the Api object. + Api& useApi(); + //! @brief Returns the engine::Instance engine::Instance& useEngineInstance(); @@ -105,6 +108,9 @@ namespace kiwi //! @brief Brings the Console to front. void showConsoleWindow(); + //! @brief Brings the Login form window to front. + void showLoginWindow(); + //! @brief Brings the "About Kiwi" window to front. void showAboutKiwiWindow(); @@ -121,6 +127,8 @@ namespace kiwi using PatcherManagers = std::vector>; + void networkSettingsChanged(NetworkSettings const&, const juce::Identifier& id) override; + //! @internal get the given patcher manager iterator. PatcherManagers::iterator getPatcherManager(PatcherManager const& manager); @@ -136,6 +144,8 @@ namespace kiwi private: // variables + std::unique_ptr m_api; + engine::Scheduler<> m_scheduler; engine::Instance m_instance; diff --git a/Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.cpp b/Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.cpp new file mode 100644 index 00000000..53d2b076 --- /dev/null +++ b/Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.cpp @@ -0,0 +1,224 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include "KiwiApp_LoginForm.h" +#include "../KiwiApp.h" + +namespace kiwi +{ + struct Spinner : public juce::Component, private juce::Timer + { + Spinner() { startTimer(1000 / 50); } + void timerCallback() override { repaint(); } + + void paint(juce::Graphics& g) override + { + getLookAndFeel().drawSpinningWaitAnimation(g, juce::Colours::whitesmoke, 0, 0, getWidth(), getHeight()); + } + }; + + struct LoginForm::OverlayComp : public juce::Component + { + OverlayComp() + { + addAndMakeVisible(spinner); + } + + ~OverlayComp() = default; + + void paint(juce::Graphics& g) override + { + auto& lf = KiwiApp::useLookAndFeel(); + const auto bgcolor = lf.getCurrentColourScheme().getUIColour(juce::LookAndFeel_V4::ColourScheme::UIColour::windowBackground); + + g.fillAll(bgcolor.withAlpha(0.97f)); + + g.setColour(juce::Colours::whitesmoke); + g.setFont(18.0f); + + g.drawFittedText(TRANS("login..."), getLocalBounds().reduced(20, 0).removeFromTop(proportionOfHeight(0.6f)), juce::Justification::centred, 5); + } + + void resized() override + { + const int spinnerSize = 40; + spinner.setBounds((getWidth() - spinnerSize) / 2, + proportionOfHeight(0.5f), + spinnerSize, spinnerSize); + } + + Spinner spinner; + + JUCE_LEAK_DETECTOR(LoginForm::OverlayComp) + }; + + static juce::juce_wchar getDefaultPasswordChar() noexcept + { + #if JUCE_LINUX + return 0x2022; + #else + return 0x25cf; + #endif + } + + LoginForm::LoginForm() + : message(juce::String(), "Enter an Email/username and password to log in") + , passwordBox(juce::String(), getDefaultPasswordChar()) + , registerButton(TRANS("Register")) + , cancelButton(TRANS("Cancel")) + { + setOpaque(true); + + //emailBox.setText(status.getUserEmail()); + emailBox.setText(""); + message.setJustificationType(juce::Justification::centred); + + addAndMakeVisible(message); + addAndMakeVisible(emailBox); + addAndMakeVisible(passwordBox); + + addAndMakeVisible(registerButton); + addAndMakeVisible(cancelButton); + + emailBox.setEscapeAndReturnKeysConsumed(false); + passwordBox.setEscapeAndReturnKeysConsumed(false); + + registerButton.addShortcut(juce::KeyPress(juce::KeyPress::returnKey)); + + registerButton.addListener(this); + cancelButton.addListener(this); + + lookAndFeelChanged(); + setSize(500, 250); + } + + LoginForm::~LoginForm() + { + m_overlay.deleteAndZero(); + } + + void LoginForm::paint(juce::Graphics& g) + { + auto& lf = KiwiApp::useLookAndFeel(); + const auto bgcolor = lf.getCurrentColourScheme().getUIColour(juce::LookAndFeel_V4::ColourScheme::UIColour::windowBackground); + + g.fillAll(bgcolor); + } + + void LoginForm::resized() + { + const int buttonHeight = 22; + + juce::Rectangle r(getLocalBounds().reduced(10, 20)); + + juce::Rectangle buttonArea(r.removeFromBottom(buttonHeight)); + registerButton.changeWidthToFitText(buttonHeight); + cancelButton.changeWidthToFitText(buttonHeight); + + const int gap = 20; + buttonArea = buttonArea.withSizeKeepingCentre(registerButton.getWidth() + +(cancelButton.isVisible() ? gap + cancelButton.getWidth() : 0), + buttonHeight); + registerButton.setBounds(buttonArea.removeFromLeft(registerButton.getWidth())); + buttonArea.removeFromLeft(gap); + cancelButton.setBounds(buttonArea); + + r.removeFromBottom(20); + + //(force use of a default system font to make sure it has the password blob character) + juce::Font font(juce::Font::getDefaultTypefaceForFont(juce::Font(juce::Font::getDefaultSansSerifFontName(), juce::Font::getDefaultStyle(), 5.0f))); + + const int boxHeight = 24; + passwordBox.setBounds(r.removeFromBottom(boxHeight)); + passwordBox.setInputRestrictions(64); + passwordBox.setFont(font); + + r.removeFromBottom(20); + emailBox.setBounds(r.removeFromBottom(boxHeight)); + emailBox.setInputRestrictions(512); + emailBox.setFont(font); + + r.removeFromBottom(20); + + message.setBounds(r); + + if(m_overlay != nullptr) + m_overlay->setBounds(getLocalBounds()); + } + + void LoginForm::lookAndFeelChanged() + { + juce::Colour labelCol(findColour(juce::TextEditor::backgroundColourId).contrasting(0.5f)); + + emailBox.setTextToShowWhenEmpty(TRANS("Email Address"), labelCol); + passwordBox.setTextToShowWhenEmpty(TRANS("Password"), labelCol); + } + + void LoginForm::showBubbleMessage(juce::String const& text, Component& target) + { + bubble = new juce::BubbleMessageComponent(500); + addChildComponent(bubble); + + juce::AttributedString attString; + attString.append(text, juce::Font(16.0f)); + + bubble->showAt(getLocalArea(&target, target.getLocalBounds()), + attString, 2000, // numMillisecondsBeforeRemoving + true, // removeWhenMouseClicked + false); // deleteSelfAfterUse + } + + void LoginForm::buttonClicked(juce::Button* b) + { + if(b == ®isterButton) + attemptRegistration(); + else if(b == &cancelButton) + dismiss(); + } + + void LoginForm::attemptRegistration() + { + if(m_overlay == nullptr) + { + if(emailBox.getText().trim().length() < 3) + { + showBubbleMessage(TRANS("Please enter a valid email address!"), emailBox); + return; + } + + if(passwordBox.getText().trim().length() < 3) + { + showBubbleMessage(TRANS("Please enter a valid password!"), passwordBox); + return; + } + + //status.setUserEmail(emailBox.getText()); + addAndMakeVisible(m_overlay = new OverlayComp()); + + resized(); + } + } + + void LoginForm::dismiss() + { + delete this; + } +} diff --git a/Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.h b/Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.h new file mode 100644 index 00000000..4027bb98 --- /dev/null +++ b/Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.h @@ -0,0 +1,74 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi +{ + class LoginForm : public juce::Component, private juce::ButtonListener + { + public: // methods + + //! @brief Constructor. + //! @details Creates a login form. + LoginForm(); + + //! @brief Destructor. + ~LoginForm(); + + /** This is called when the form is dismissed (either cancelled or when registration + succeeds). + By default it will delete this, but you can override it to do other things. + */ + virtual void dismiss(); + + private: // methods + + //! @internal paint method + void paint(juce::Graphics&) override; + + //! @internal resized method + void resized() override; + + //! @internal lookAndFeelChanged method + void lookAndFeelChanged() override; + + private: // variables + + juce::Label message; + juce::TextEditor emailBox, passwordBox; + juce::TextButton registerButton, cancelButton; + + juce::ScopedPointer bubble; + + struct OverlayComp; + friend struct OverlayComp; + Component::SafePointer m_overlay; + + void buttonClicked(juce::Button*) override; + void attemptRegistration(); + void showBubbleMessage(juce::String const&, juce::Component&); + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LoginForm) + }; +} diff --git a/Client/Source/KiwiApp_Components/KiwiApp_Window.h b/Client/Source/KiwiApp_Components/KiwiApp_Window.h index 0025420e..1d5c0fde 100644 --- a/Client/Source/KiwiApp_Components/KiwiApp_Window.h +++ b/Client/Source/KiwiApp_Components/KiwiApp_Window.h @@ -94,6 +94,7 @@ namespace kiwi enum class WindowId : std::size_t { Console = 0, + Login, AboutKiwi, DocumentBrowser, ApplicationSettings, diff --git a/Client/Source/KiwiApp_General/KiwiApp_CommandIDs.h b/Client/Source/KiwiApp_General/KiwiApp_CommandIDs.h index b021bd2c..9e7973ac 100644 --- a/Client/Source/KiwiApp_General/KiwiApp_CommandIDs.h +++ b/Client/Source/KiwiApp_General/KiwiApp_CommandIDs.h @@ -47,7 +47,7 @@ namespace kiwi showDocumentBrowserWindow = 0x202040, ///< Make visible the "document browser" window. showBeaconDispatcherWindow = 0x202050, ///< Make visible the "beacon dispatcher" window. addBeaconDispatcher = 0x202051, ///< Add a new "beacon dispatcher" element. - removeBeaconDispatcher = 0x202052, ///< Add a new "beacon dispatcher" element. + removeBeaconDispatcher = 0x202052, ///< Remove a "beacon dispatcher" element. undo = 0xf1000a, ///< Undo last action. redo = 0xf1000b, ///< Redo last action. @@ -86,7 +86,10 @@ namespace kiwi scrollToTop = 0xf30001, ///< Scroll to the top scrollToBottom = 0xf30002, ///< Scroll to the bottom - clearAll = 0xf40001 ///< Clear all content + clearAll = 0xf40001, ///< Clear all content + + login = 0xf50000, ///< Log-in the user. + logout = 0xf50010, ///< Log-out the user. }; // ================================================================================ // diff --git a/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp b/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp index fb2766f8..fe839a3f 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp +++ b/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp @@ -39,10 +39,7 @@ namespace kiwi { auto& settings = getAppSettings().network(); - m_distant_drive.reset(new Drive("Remote patchers", - settings.getHost(), - settings.getApiPort(), - settings.getSessionPort())); + m_distant_drive.reset(new Drive("Remote patchers", settings.getSessionPort())); int time = settings.getRefreshInterval(); if(time > 0) @@ -76,15 +73,7 @@ namespace kiwi void DocumentBrowser::networkSettingsChanged(NetworkSettings const& settings, const juce::Identifier& id) { - if(id == Ids::host) - { - m_distant_drive->setHost(settings.getHost()); - } - else if(id == Ids::api_port) - { - m_distant_drive->setApiPort(settings.getApiPort()); - } - else if(id == Ids::session_port) + if(id == Ids::session_port) { m_distant_drive->setSessionPort(settings.getSessionPort()); } @@ -128,10 +117,7 @@ namespace kiwi // ================================================================================ // DocumentBrowser::Drive::Drive(std::string const& name, - std::string const& host, - uint16_t api_port, uint16_t session_port) : - m_api(host, api_port), m_session_port(session_port), m_name(name) { @@ -148,21 +134,6 @@ namespace kiwi m_listeners.remove(listener); } - Api& DocumentBrowser::Drive::useApi() - { - return m_api; - } - - uint16_t DocumentBrowser::Drive::getApiPort() const - { - return m_api.getPort(); - } - - void DocumentBrowser::Drive::setApiPort(uint16_t port) - { - m_api.setPort(port); - } - void DocumentBrowser::Drive::setSessionPort(uint16_t port) { m_session_port = port; @@ -173,16 +144,6 @@ namespace kiwi return m_session_port; } - void DocumentBrowser::Drive::setHost(std::string const& host) - { - m_api.setHost(host); - } - - std::string const& DocumentBrowser::Drive::getHost() const - { - return m_api.getHost(); - } - void DocumentBrowser::Drive::setName(std::string const& name) { m_name = name; @@ -195,7 +156,9 @@ namespace kiwi void DocumentBrowser::Drive::createNewDocument() { - m_api.createDocument([this](Api::Response const& res, Api::Error const& error, Api::Document document) { + KiwiApp::useApi().createDocument([this](Api::Response const& res, + Api::Error const& error, + Api::Document document) { if(error) { @@ -233,10 +196,7 @@ namespace kiwi bool DocumentBrowser::Drive::operator==(Drive const& drive) const { - return (getHost() == drive.getHost()) - && (getApiPort() == drive.getApiPort()) - && (getSessionPort() == drive.getSessionPort()) - && (m_name == drive.getName()); + return (getSessionPort() == drive.getSessionPort()) && (m_name == drive.getName()); } void DocumentBrowser::Drive::updateDocumentList(Api::Documents docs) @@ -309,7 +269,7 @@ namespace kiwi void DocumentBrowser::Drive::refresh() { - m_api.getDocuments([this](Api::Response const& res, Api::Error const& error, Api::Documents docs) { + KiwiApp::useApi().getDocuments([this](Api::Response const& res, Api::Error const& error, Api::Documents docs) { if(error) { @@ -349,7 +309,7 @@ namespace kiwi std::string DocumentBrowser::Drive::DocumentSession::getHost() const { - return m_drive.getHost(); + return KiwiApp::useApi().getHost(); } uint64_t DocumentBrowser::Drive::DocumentSession::getSessionId() const @@ -374,7 +334,7 @@ namespace kiwi return; } - m_drive.useApi().renameDocument([](Api::Response const& res, Api::Error const& error) { + KiwiApp::useApi().renameDocument([](Api::Response const& res, Api::Error const& error) { if(!error) { diff --git a/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.h b/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.h index 99c2bf44..442c41d9 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.h +++ b/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.h @@ -120,10 +120,7 @@ namespace kiwi public: // methods - Drive(std::string const& name, - std::string const& host, - uint16_t api_port, - uint16_t session_port); + Drive(std::string const& name, uint16_t session_port); ~Drive() = default; @@ -133,27 +130,12 @@ namespace kiwi //! @brief remove a listener. void removeListener(Listener& listener); - //! @brief Returns the API object reference. - Api& useApi(); - - //! @brief Set the kiwi api port. - void setApiPort(uint16_t port); - - //! @brief Returns the kiwi api port. - uint16_t getApiPort() const; - //! @brief Set the kiwi document session port. void setSessionPort(uint16_t port); //! @brief Returns the kiwi document session port. uint16_t getSessionPort() const; - //! @brief Set both the api's and session's host. - void setHost(std::string const& host); - - //! @brief Returns the session host. - std::string const& getHost() const; - //! @brief Set the name of this drive. void setName(std::string const& host); @@ -181,7 +163,6 @@ namespace kiwi //! @internal Update the document list (need to be called in the juce Message thread) void updateDocumentList(Api::Documents docs); - Api m_api; uint16_t m_session_port = 9090; std::string m_name = "Drive"; DocumentSessions m_documents; diff --git a/Modules/KiwiNetwork/KiwiNetwork_Api.h b/Modules/KiwiNetwork/KiwiNetwork_Api.h index a650b14b..bac64902 100644 --- a/Modules/KiwiNetwork/KiwiNetwork_Api.h +++ b/Modules/KiwiNetwork/KiwiNetwork_Api.h @@ -59,7 +59,7 @@ namespace kiwi using Error = beast::error_code; //! @brief Constructor - Api(std::string const& host, uint16_t port = 80); + Api(std::string const& host = "127.0.0.1", uint16_t port = 80); //! @brief Destructor ~Api(); From 4db1d6e7a077a7fb6ed585c9f6040ad6cc043e29 Mon Sep 17 00:00:00 2001 From: eliott PARIS Date: Wed, 19 Jul 2017 13:39:42 +0200 Subject: [PATCH 026/148] Add a Http class and put definition in a hpp file --- Modules/KiwiNetwork/KiwiNetwork_Api.cpp | 28 +-- Modules/KiwiNetwork/KiwiNetwork_Http.cpp | 29 --- Modules/KiwiNetwork/KiwiNetwork_Http.h | 278 ++++++++--------------- Modules/KiwiNetwork/KiwiNetwork_Http.hpp | 198 ++++++++++++++++ Test/Network/test_Http.cpp | 4 +- 5 files changed, 312 insertions(+), 225 deletions(-) delete mode 100644 Modules/KiwiNetwork/KiwiNetwork_Http.cpp create mode 100644 Modules/KiwiNetwork/KiwiNetwork_Http.hpp diff --git a/Modules/KiwiNetwork/KiwiNetwork_Api.cpp b/Modules/KiwiNetwork/KiwiNetwork_Api.cpp index fe4d5b7f..395bac8e 100644 --- a/Modules/KiwiNetwork/KiwiNetwork_Api.cpp +++ b/Modules/KiwiNetwork/KiwiNetwork_Api.cpp @@ -93,7 +93,9 @@ namespace kiwi return m_port; } - void Api::getDocuments(std::function callback) + void Api::getDocuments(std::function callback) { std::function res_callback = [callback = std::move(callback)](Api::Response const& res, Api::Error const& error) @@ -124,10 +126,10 @@ namespace kiwi request->prepare_payload(); - storeRequest(network::httpWriteAsync(std::move(request), - std::to_string(m_port), - res_callback, - std::chrono::milliseconds(3000))); + storeRequest(Http::writeAsync(std::move(request), + std::to_string(m_port), + res_callback, + std::chrono::milliseconds(3000))); } void Api::createDocument(std::function callback, @@ -164,10 +166,10 @@ namespace kiwi callback(std::move(res), error, {}); }; - storeRequest(network::httpWriteAsync(std::move(request), - std::to_string(m_port), - res_callback, - std::chrono::milliseconds(3000))); + storeRequest(Http::writeAsync(std::move(request), + std::to_string(m_port), + res_callback, + std::chrono::milliseconds(3000))); } void Api::renameDocument(std::function callback, @@ -186,10 +188,10 @@ namespace kiwi request->prepare_payload(); - storeRequest(network::httpWriteAsync(std::move(request), - std::to_string(m_port), - callback, - std::chrono::milliseconds(3000))); + storeRequest(Http::writeAsync(std::move(request), + std::to_string(m_port), + callback, + std::chrono::milliseconds(3000))); } void Api::storeRequest(std::future && future) diff --git a/Modules/KiwiNetwork/KiwiNetwork_Http.cpp b/Modules/KiwiNetwork/KiwiNetwork_Http.cpp deleted file mode 100644 index 41d47582..00000000 --- a/Modules/KiwiNetwork/KiwiNetwork_Http.cpp +++ /dev/null @@ -1,29 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#include "KiwiNetwork_Http.h" - -namespace kiwi -{ - namespace network - { - } -} diff --git a/Modules/KiwiNetwork/KiwiNetwork_Http.h b/Modules/KiwiNetwork/KiwiNetwork_Http.h index afa14071..e1363210 100644 --- a/Modules/KiwiNetwork/KiwiNetwork_Http.h +++ b/Modules/KiwiNetwork/KiwiNetwork_Http.h @@ -33,195 +33,111 @@ #include #include -using tcp = boost::asio::ip::tcp; - -namespace kiwi -{ - namespace network +namespace kiwi { namespace network { + + using tcp = boost::asio::ip::tcp; + + // ================================================================================ // + // HTTP // + // ================================================================================ // + + class Http { - template - class HttpQuery - { - public: // methods - - HttpQuery(std::unique_ptr> request, - std::string port, - std::chrono::milliseconds time_out = std::chrono::milliseconds(0)): - m_request(std::move(request)), - m_response(), - m_port(port), - m_io_service(), - m_socket(m_io_service), - m_error(), - m_time_out(time_out), - m_timer(m_io_service), - m_buffer() - { - } - - ~HttpQuery() - { - } - - beast::http::response writeRequest(beast::error_code& error) - { - if (m_time_out > std::chrono::milliseconds(0)) - { - m_timer.expires_from_now(m_time_out); - - m_timer.async_wait([this](boost::system::error_code const& error) - { - this->handle_time_out(error); - }); - } - - tcp::resolver resolver(m_io_service); - - std::string host = (*m_request)[beast::http::field::host].to_string(); - - resolver.async_resolve({host, m_port}, [this](beast::error_code const& error, - tcp::resolver::iterator iterator) - { - this->handle_resolve(error, iterator); - }); - - m_io_service.reset(); - - while(!m_error && m_io_service.run_one()) - { - } - - error = m_error; - - return m_response; - }; - - private: // methods - - void handle_time_out(boost::system::error_code const& error) - { - m_io_service.stop(); - - m_socket.shutdown(tcp::socket::shutdown_both, m_error); - m_error = boost::asio::error::basic_errors::timed_out; - } - - void handle_read(beast::error_code const& error) - { - m_io_service.stop(); - - if (error) - { - m_error = error; - } - else - { - m_socket.shutdown(tcp::socket::shutdown_both, m_error); - } - } - - void handle_write(beast::error_code const& error) - { - if (error) - { - m_error = error; - } - else - { - beast::http::async_read(m_socket, m_buffer, m_response, [this](beast::error_code const& error) - { - this->handle_read(error); - }); - } - } - - void handle_connect(beast::error_code const& error) - { - if (error) - { - m_error = error; - } - else - { - beast::http::async_write(m_socket, *m_request, [this](beast::error_code const& error) - { - this->handle_write(error); - }); - - } - } - - void handle_resolve(beast::error_code const& error, - tcp::resolver::iterator iterator) - { - if (error) - { - m_error = error; - } - else - { - boost::asio::async_connect(m_socket, iterator, [this](beast::error_code const& error, - tcp::resolver::iterator i) - { - this->handle_connect(error); - }); - } - } - - private: // members - - std::unique_ptr> m_request; - beast::http::response m_response; - std::string m_port; - boost::asio::io_service m_io_service; - tcp::socket m_socket; - beast::error_code m_error; - std::chrono::milliseconds m_time_out; - boost::asio::steady_timer m_timer; - beast::flat_buffer m_buffer; - - - private: // deleted methods - - HttpQuery() = delete; - HttpQuery(HttpQuery const& other) = delete; - HttpQuery(HttpQuery && other) = delete; - HttpQuery& operator=(HttpQuery const& other) = delete; - HttpQuery& operator=(HttpQuery && other) = delete; - }; + public: // methods //! @brief Sends an http request. //! @details Returns the response generated by the server. The function blocks until response //! is received or error occurs. template - beast::http::response httpWrite(std::unique_ptr> request, - std::string port, - beast::error_code& error, - std::chrono::milliseconds time_out = std::chrono::milliseconds(0)) - { - return HttpQuery(std::move(request), port).writeRequest(error); - } + static beast::http::response + write(std::unique_ptr> request, + std::string port, + beast::error_code& error, + std::chrono::milliseconds timeout = std::chrono::milliseconds(0)); //! @brief Sends an http request asynchronously. //! @details Returns the response generated by the server. The function is non blocking. callback //! is called on another thread once response is received or error occurs. template - std::future httpWriteAsync(std::unique_ptr> request, - std::string port, - std::function const& response, - beast::error_code const& error)> callback, - std::chrono::milliseconds time_out = std::chrono::milliseconds(0)) - { - std::unique_ptr> query(new HttpQuery(std::move(request), port, time_out)); - - return std::async(std::launch::async, [query = std::move(query), callback]() - { - beast::error_code error; - - beast::http::response response = query->writeRequest(error); - - return callback(response, error); - }); - } - } -} + static std::future + writeAsync(std::unique_ptr> request, + std::string port, + std::function const& response, + beast::error_code const& error)> callback, + std::chrono::milliseconds timeout = std::chrono::milliseconds(0)); + + private: // nested classes + + template class Query; + + private: // deleted methods + + Http() = delete; + Http(Http const& other) = delete; + Http(Http && other) = delete; + Http& operator=(Http const& other) = delete; + Http& operator=(Http && other) = delete; + }; + + // ================================================================================ // + // HTTP QUERY // + // ================================================================================ // + + template + class Http::Query + { + public: // methods + + //! @brief Constructor. + Query(std::unique_ptr> request, + std::string port, + std::chrono::milliseconds timeout = std::chrono::milliseconds(0)); + + //! @brief Destructor. + ~Query(); + + //! @brief Write the request and get the response. + beast::http::response writeRequest(beast::error_code& error); + + private: // methods + + //! @internal + void handleTimeout(boost::system::error_code const& error); + + //! @internal + void handleRead(beast::error_code const& error); + + //! @internal + void handleWrite(beast::error_code const& error); + + //! @internal + void handleConnect(beast::error_code const& error); + + //! @internal + void handleResolve(beast::error_code const& error, + tcp::resolver::iterator iterator); + + private: // members + + std::unique_ptr> m_request; + beast::http::response m_response; + std::string m_port; + boost::asio::io_service m_io_service; + tcp::socket m_socket; + beast::error_code m_error; + std::chrono::milliseconds m_timeout; + boost::asio::steady_timer m_timer; + beast::flat_buffer m_buffer; + + private: // deleted methods + + Query() = delete; + Query(Query const& other) = delete; + Query(Query && other) = delete; + Query& operator=(Query const& other) = delete; + Query& operator=(Query && other) = delete; + }; + +}} // namespace kiwi::network + +#include "KiwiNetwork_Http.hpp" diff --git a/Modules/KiwiNetwork/KiwiNetwork_Http.hpp b/Modules/KiwiNetwork/KiwiNetwork_Http.hpp new file mode 100644 index 00000000..75f723c8 --- /dev/null +++ b/Modules/KiwiNetwork/KiwiNetwork_Http.hpp @@ -0,0 +1,198 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +namespace kiwi { namespace network { + + // ================================================================================ // + // HTTP // + // ================================================================================ // + + template + beast::http::response + Http::write(std::unique_ptr> request, + std::string port, + beast::error_code& error, + std::chrono::milliseconds timeout) + { + return Query(std::move(request), port, timeout).writeRequest(error); + } + + template + std::future + Http::writeAsync(std::unique_ptr> request, + std::string port, + std::function const& response, + beast::error_code const& error)> callback, + std::chrono::milliseconds timeout) + { + auto query = std::make_unique>(std::move(request), port, timeout); + + return std::async(std::launch::async, [query = std::move(query), cb = std::move(callback)]() { + + beast::error_code error; + beast::http::response response = query->writeRequest(error); + return cb(response, error); + + }); + } + + // ================================================================================ // + // HTTP QUERY // + // ================================================================================ // + + template + Http::Query::Query(std::unique_ptr> request, + std::string port, + std::chrono::milliseconds timeout) + : m_request(std::move(request)) + , m_response() + , m_port(port) + , m_io_service() + , m_socket(m_io_service) + , m_error() + , m_timeout(timeout) + , m_timer(m_io_service) + , m_buffer() + { + ; + } + + template + Http::Query::~Query() + { + ; + } + + template + beast::http::response + Http::Query::writeRequest(beast::error_code& error) + { + if (m_timeout > std::chrono::milliseconds(0)) + { + m_timer.expires_from_now(m_timeout); + + m_timer.async_wait([this](boost::system::error_code const& error) { + this->handleTimeout(error); + }); + } + + tcp::resolver resolver(m_io_service); + + const std::string host = m_request->at(beast::http::field::host).to_string(); + + resolver.async_resolve({host, m_port}, [this](beast::error_code const& error, + tcp::resolver::iterator iterator) { + handleResolve(error, iterator); + }); + + m_io_service.reset(); + + // block here until error or success + while(!m_error && m_io_service.run_one()) + { + ; + } + + error = m_error; + + return m_response; + }; + + template + void + Http::Query::handleTimeout(boost::system::error_code const& error) + { + m_io_service.stop(); + + m_socket.shutdown(tcp::socket::shutdown_both, m_error); + m_error = boost::asio::error::basic_errors::timed_out; + } + + template + void + Http::Query::handleRead(beast::error_code const& error) + { + m_io_service.stop(); + + if (error) + { + m_error = error; + } + else + { + m_socket.shutdown(tcp::socket::shutdown_both, m_error); + } + } + + template + void + Http::Query::handleWrite(beast::error_code const& error) + { + if (error) + { + m_error = error; + } + else + { + beast::http::async_read(m_socket, m_buffer, m_response, [this](beast::error_code const& error) { + handleRead(error); + }); + } + } + + template + void + Http::Query::handleConnect(beast::error_code const& error) + { + if (error) + { + m_error = error; + } + else + { + beast::http::async_write(m_socket, *m_request, [this](beast::error_code const& error) { + handleWrite(error); + }); + + } + } + + template + void + Http::Query::handleResolve(beast::error_code const& error, + tcp::resolver::iterator iterator) + { + if (error) + { + m_error = error; + } + else + { + boost::asio::async_connect(m_socket, iterator, [this](beast::error_code const& error, + tcp::resolver::iterator i) { + this->handleConnect(error); + }); + } + } + +}} // namespace kiwi::network diff --git a/Test/Network/test_Http.cpp b/Test/Network/test_Http.cpp index 6e727dd6..878ab29f 100755 --- a/Test/Network/test_Http.cpp +++ b/Test/Network/test_Http.cpp @@ -49,7 +49,7 @@ TEST_CASE("Network - Http", "[Network, Http]") // Send request and waits for response. beast::http::response response = - kiwi::network::httpWrite(std::move(request), "80", error); + kiwi::network::Http::write(std::move(request), "80", error); CHECK(response.result() == beast::http::status::ok); CHECK(!error); @@ -76,7 +76,7 @@ TEST_CASE("Network - Http", "[Network, Http]") CHECK(!error); }; - std::future future = kiwi::network::httpWriteAsync(std::move(request), "80", callback); + std::future future = kiwi::network::Http::writeAsync(std::move(request), "80", callback); future.get(); } From cf58bd35967ec23044c19c985fd6e4a3542a14ab Mon Sep 17 00:00:00 2001 From: eliott PARIS Date: Wed, 19 Jul 2017 16:52:11 +0200 Subject: [PATCH 027/148] Fix issue and add test for scheduling task with lambda --- CMakeLists.txt | 4 +- .../KiwiApp_Application/KiwiApp_Instance.cpp | 9 +- .../KiwiApp_Application/KiwiApp_Instance.h | 2 + .../KiwiApp_Auth/KiwiApp_IdentityManager.cpp | 0 .../KiwiApp_Auth/KiwiApp_IdentityManager.h | 51 ++++ .../Source/KiwiApp_Auth/KiwiApp_LoginForm.cpp | 274 +++++++++++++----- .../Source/KiwiApp_Auth/KiwiApp_LoginForm.h | 66 ++++- Client/Source/KiwiApp_Network/KiwiApp_Api.cpp | 256 ++++++++++++++++ Client/Source/KiwiApp_Network/KiwiApp_Api.h | 157 ++++++++++ .../KiwiApp_DocumentBrowser.cpp | 18 +- .../KiwiApp_Network/KiwiApp_DocumentBrowser.h | 4 +- Modules/KiwiEngine/KiwiEngine_Scheduler.h | 2 +- Modules/KiwiEngine/KiwiEngine_Scheduler.hpp | 2 +- Modules/KiwiNetwork/KiwiNetwork_Api.cpp | 216 -------------- Modules/KiwiNetwork/KiwiNetwork_Api.h | 114 -------- Modules/KiwiNetwork/KiwiNetwork_Http.cpp | 79 +++++ Modules/KiwiNetwork/KiwiNetwork_Http.h | 117 ++++++-- Modules/KiwiNetwork/KiwiNetwork_Http.hpp | 118 +++++--- Modules/KiwiNetwork/KiwiNetwork_Util.cpp | 52 ++++ Modules/KiwiNetwork/KiwiNetwork_Util.h | 30 ++ Test/Engine/test_Scheduler.cpp | 36 +++ Test/Network/test_Http.cpp | 38 ++- 22 files changed, 1154 insertions(+), 491 deletions(-) create mode 100644 Client/Source/KiwiApp_Auth/KiwiApp_IdentityManager.cpp create mode 100644 Client/Source/KiwiApp_Auth/KiwiApp_IdentityManager.h create mode 100644 Client/Source/KiwiApp_Network/KiwiApp_Api.cpp create mode 100644 Client/Source/KiwiApp_Network/KiwiApp_Api.h delete mode 100644 Modules/KiwiNetwork/KiwiNetwork_Api.cpp delete mode 100644 Modules/KiwiNetwork/KiwiNetwork_Api.h create mode 100644 Modules/KiwiNetwork/KiwiNetwork_Http.cpp create mode 100644 Modules/KiwiNetwork/KiwiNetwork_Util.cpp create mode 100644 Modules/KiwiNetwork/KiwiNetwork_Util.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 1e36e603..705c24c2 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -359,8 +359,7 @@ file(GLOB_RECURSE KIWI_NETWORK_SRC ${ROOT_DIR}/Modules/KiwiNetwork/*.[c|h]pp add_library(KiwiNetwork STATIC ${KIWI_NETWORK_SRC}) target_include_directories(KiwiNetwork PUBLIC ${ROOT_DIR}/Modules ${ROOT_DIR}/ThirdParty/Beast/include - ${Boost_INCLUDE_DIRS} - ${JSON_INCLUDE_DIRS}) + ${Boost_INCLUDE_DIRS}) target_compile_definitions(KiwiNetwork PUBLIC "-DBOOST_ALL_NO_LIB=1") set(NETWORK_DEP ${Boost_LIBRARIES}) if (WIN32) @@ -418,6 +417,7 @@ target_add_dependency(Kiwi KiwiEngine) target_add_dependency(Kiwi KiwiModel) target_add_dependency(Kiwi KiwiDsp) target_add_dependency(Kiwi Juce) +target_include_directories(Kiwi PUBLIC ${JSON_INCLUDE_DIRS}) if (APPLE) set_target_properties(Kiwi PROPERTIES MACOSX_BUNDLE TRUE diff --git a/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp b/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp index 78bbbb85..9d1d4c0a 100644 --- a/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp +++ b/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp @@ -346,9 +346,14 @@ namespace kiwi { showWindowWithId(WindowId::Login, []() { - return std::make_unique("Log-in to Kiwi", + auto login_window = std::make_unique("Log-in to Kiwi", std::make_unique(), - true, false, "login_window"); + false, false); + + login_window->centreWithSize(400, 300); + login_window->enterModalState(true); + + return login_window; }); } diff --git a/Client/Source/KiwiApp_Application/KiwiApp_Instance.h b/Client/Source/KiwiApp_Application/KiwiApp_Instance.h index 7b2d4a50..eeb5249f 100644 --- a/Client/Source/KiwiApp_Application/KiwiApp_Instance.h +++ b/Client/Source/KiwiApp_Application/KiwiApp_Instance.h @@ -37,6 +37,8 @@ #include "../KiwiApp_General/KiwiApp_StoredSettings.h" #include "../KiwiApp_Audio/KiwiApp_DspDeviceManager.h" +#include "../KiwiApp_Network/KiwiApp_Api.h" + namespace kiwi { class PatcherViewWindow; diff --git a/Client/Source/KiwiApp_Auth/KiwiApp_IdentityManager.cpp b/Client/Source/KiwiApp_Auth/KiwiApp_IdentityManager.cpp new file mode 100644 index 00000000..e69de29b diff --git a/Client/Source/KiwiApp_Auth/KiwiApp_IdentityManager.h b/Client/Source/KiwiApp_Auth/KiwiApp_IdentityManager.h new file mode 100644 index 00000000..1e1cfba6 --- /dev/null +++ b/Client/Source/KiwiApp_Auth/KiwiApp_IdentityManager.h @@ -0,0 +1,51 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +namespace kiwi +{ + class IdentityManager + { + public: // methods + + class User; + + IdentityManager(); + ~IdentityManager(); + + void login(); + + private: // variables + }; + + class IdentityManager::User + { + public: // methods + + User(uint64_t user_id); + ~User(); + + private: // variables + + uint64_t m_id; + } +} diff --git a/Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.cpp b/Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.cpp index 53d2b076..8072dfc0 100644 --- a/Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.cpp +++ b/Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.cpp @@ -22,8 +22,79 @@ #include "KiwiApp_LoginForm.h" #include "../KiwiApp.h" +#include "../KiwiApp_Ressources/KiwiApp_BinaryData.h" + namespace kiwi { + AlertBox::AlertBox(std::string const& message, + AlertBox::Type type, + bool can_cancel, + std::function on_close) + : m_message(message) + , m_type(type) + , m_close_fn(on_close) + { + if(can_cancel) + { + m_close_btn.reset(new juce::TextButton("X", "Close")); + m_close_btn->setColour(juce::TextButton::buttonColourId, juce::Colours::transparentBlack); + addAndMakeVisible(*m_close_btn); + m_close_btn->addListener(this); + } + } + + AlertBox::~AlertBox() + { + if(m_close_btn) + { + m_close_btn->removeListener(this); + } + } + + void AlertBox::paint(juce::Graphics& g) + { + const auto bgcolor = [](Type const& type) { + switch (type) { + case Type::Success: return juce::Colour::fromRGB(72, 175, 95); + case Type::Error: return juce::Colour::fromRGB(252, 99, 93); + default: return juce::Colours::grey; + } + }(m_type).withAlpha(1.f); + + g.setColour(bgcolor); + g.fillRoundedRectangle(getLocalBounds().reduced(1).toFloat(), 0.f); + + g.setFont(16.f); + g.setColour(bgcolor.contrasting(0.9)); + g.drawText(m_message, getLocalBounds().reduced(10), juce::Justification::verticallyCentred); + } + + void AlertBox::resized() + { + if(m_close_btn) + { + const int margin = 5; + const auto bounds = getLocalBounds(); + m_close_btn->setSize(20, 20); + m_close_btn->setTopRightPosition(bounds.getWidth() - margin, margin); + } + } + + void AlertBox::buttonClicked(juce::Button* b) + { + if(b == m_close_btn.get()) + { + if(m_close_fn) + { + m_close_fn(); + } + else + { + // close alert box + } + } + } + struct Spinner : public juce::Component, private juce::Timer { Spinner() { startTimer(1000 / 50); } @@ -52,7 +123,7 @@ namespace kiwi g.fillAll(bgcolor.withAlpha(0.97f)); g.setColour(juce::Colours::whitesmoke); - g.setFont(18.0f); + g.setFont(22.0f); g.drawFittedText(TRANS("login..."), getLocalBounds().reduced(20, 0).removeFromTop(proportionOfHeight(0.6f)), juce::Justification::centred, 5); } @@ -67,7 +138,7 @@ namespace kiwi Spinner spinner; - JUCE_LEAK_DETECTOR(LoginForm::OverlayComp) + JUCE_LEAK_DETECTOR(LoginForm::OverlayComp); }; static juce::juce_wchar getDefaultPasswordChar() noexcept @@ -80,34 +151,27 @@ namespace kiwi } LoginForm::LoginForm() - : message(juce::String(), "Enter an Email/username and password to log in") - , passwordBox(juce::String(), getDefaultPasswordChar()) - , registerButton(TRANS("Register")) - , cancelButton(TRANS("Cancel")) + : m_password_box(juce::String(), getDefaultPasswordChar()) + , m_submit_btn(TRANS("Login")) + , m_cancel_btn(TRANS("Cancel")) + , m_kiwi_app_image(juce::ImageCache::getFromMemory(binary_data::images::kiwi_icon_png, + binary_data::images::kiwi_icon_png_size)) { - setOpaque(true); - - //emailBox.setText(status.getUserEmail()); - emailBox.setText(""); - message.setJustificationType(juce::Justification::centred); + addAndMakeVisible(m_email_box); + addAndMakeVisible(m_password_box); + addAndMakeVisible(m_submit_btn); + addAndMakeVisible(m_cancel_btn); - addAndMakeVisible(message); - addAndMakeVisible(emailBox); - addAndMakeVisible(passwordBox); + m_email_box.setEscapeAndReturnKeysConsumed(false); + m_password_box.setEscapeAndReturnKeysConsumed(false); - addAndMakeVisible(registerButton); - addAndMakeVisible(cancelButton); + m_submit_btn.addShortcut(juce::KeyPress(juce::KeyPress::returnKey)); - emailBox.setEscapeAndReturnKeysConsumed(false); - passwordBox.setEscapeAndReturnKeysConsumed(false); - - registerButton.addShortcut(juce::KeyPress(juce::KeyPress::returnKey)); - - registerButton.addListener(this); - cancelButton.addListener(this); + m_submit_btn.addListener(this); + m_cancel_btn.addListener(this); lookAndFeelChanged(); - setSize(500, 250); + setSize(400, 300); } LoginForm::~LoginForm() @@ -121,76 +185,106 @@ namespace kiwi const auto bgcolor = lf.getCurrentColourScheme().getUIColour(juce::LookAndFeel_V4::ColourScheme::UIColour::windowBackground); g.fillAll(bgcolor); + + float img_size = 100; + int padding = 15; + + auto bounds = getLocalBounds(); + bounds.removeFromTop((m_alert_box != nullptr) ? m_alert_box->getHeight() : 0); + + g.drawImage(m_kiwi_app_image, + bounds.reduced(padding) + .removeFromTop(img_size).toFloat(), + juce::RectanglePlacement::xMid, false); } void LoginForm::resized() { - const int buttonHeight = 22; + const int alert_height = 50; + const int button_height = 35; - juce::Rectangle r(getLocalBounds().reduced(10, 20)); + juce::Rectangle r(getLocalBounds()); - juce::Rectangle buttonArea(r.removeFromBottom(buttonHeight)); - registerButton.changeWidthToFitText(buttonHeight); - cancelButton.changeWidthToFitText(buttonHeight); + if(m_alert_box) + { + m_alert_box->setBounds(r.removeFromTop(alert_height)); + } - const int gap = 20; - buttonArea = buttonArea.withSizeKeepingCentre(registerButton.getWidth() - +(cancelButton.isVisible() ? gap + cancelButton.getWidth() : 0), - buttonHeight); - registerButton.setBounds(buttonArea.removeFromLeft(registerButton.getWidth())); - buttonArea.removeFromLeft(gap); - cancelButton.setBounds(buttonArea); + r.removeFromTop(120); - r.removeFromBottom(20); + r.reduce(10, 10); //(force use of a default system font to make sure it has the password blob character) juce::Font font(juce::Font::getDefaultTypefaceForFont(juce::Font(juce::Font::getDefaultSansSerifFontName(), juce::Font::getDefaultStyle(), 5.0f))); - const int boxHeight = 24; - passwordBox.setBounds(r.removeFromBottom(boxHeight)); - passwordBox.setInputRestrictions(64); - passwordBox.setFont(font); + font.setHeight(22); + + const int boxHeight = 32; - r.removeFromBottom(20); - emailBox.setBounds(r.removeFromBottom(boxHeight)); - emailBox.setInputRestrictions(512); - emailBox.setFont(font); + m_email_box.setBounds(r.removeFromTop(boxHeight)); + m_email_box.setInputRestrictions(512); + m_email_box.setFont(font); - r.removeFromBottom(20); + r.removeFromTop(20); + m_password_box.setBounds(r.removeFromTop(boxHeight)); + m_password_box.setInputRestrictions(64); + m_password_box.setFont(font); - message.setBounds(r); + r.removeFromTop(20); + juce::Rectangle buttonArea(r.removeFromTop(button_height)); + m_submit_btn.changeWidthToFitText(button_height); + m_cancel_btn.changeWidthToFitText(button_height); + + const int gap = 20; + buttonArea = buttonArea.withSizeKeepingCentre(m_submit_btn.getWidth() + +(m_cancel_btn.isVisible() ? gap + m_cancel_btn.getWidth() : 0), + button_height); + + m_submit_btn.setBounds(buttonArea.removeFromLeft(m_submit_btn.getWidth())); + buttonArea.removeFromLeft(gap); + m_cancel_btn.setBounds(buttonArea); if(m_overlay != nullptr) + { m_overlay->setBounds(getLocalBounds()); + } } void LoginForm::lookAndFeelChanged() { juce::Colour labelCol(findColour(juce::TextEditor::backgroundColourId).contrasting(0.5f)); - emailBox.setTextToShowWhenEmpty(TRANS("Email Address"), labelCol); - passwordBox.setTextToShowWhenEmpty(TRANS("Password"), labelCol); + m_email_box.setTextToShowWhenEmpty(TRANS("Username or Email"), labelCol); + m_password_box.setTextToShowWhenEmpty(TRANS("Password"), labelCol); } - void LoginForm::showBubbleMessage(juce::String const& text, Component& target) + void LoginForm::showAlert(std::string const& message, AlertBox::Type type) { - bubble = new juce::BubbleMessageComponent(500); - addChildComponent(bubble); + const bool was_showing = (m_alert_box != nullptr); + if(was_showing) + { + removeChildComponent(m_alert_box.get()); + } + + m_alert_box.reset(new AlertBox(message, type, true, [this](){ + removeChildComponent(m_alert_box.get()); + m_alert_box.reset(); + setBounds(getBounds().withHeight(getHeight() - 50)); + })); - juce::AttributedString attString; - attString.append(text, juce::Font(16.0f)); + addAndMakeVisible(*m_alert_box); - bubble->showAt(getLocalArea(&target, target.getLocalBounds()), - attString, 2000, // numMillisecondsBeforeRemoving - true, // removeWhenMouseClicked - false); // deleteSelfAfterUse + if(!was_showing) + setBounds(getBounds().withHeight(getHeight() + 50)); + else + resized(); } void LoginForm::buttonClicked(juce::Button* b) { - if(b == ®isterButton) + if(b == &m_submit_btn) attemptRegistration(); - else if(b == &cancelButton) + else if(b == &m_cancel_btn) dismiss(); } @@ -198,22 +292,70 @@ namespace kiwi { if(m_overlay == nullptr) { - if(emailBox.getText().trim().length() < 3) + if(m_email_box.getText().trim().length() < 3) { - showBubbleMessage(TRANS("Please enter a valid email address!"), emailBox); + showAlert("Please enter a valid email address or username!", AlertBox::Type::Error); return; } - if(passwordBox.getText().trim().length() < 3) + if(m_password_box.getText().trim().length() < 3) { - showBubbleMessage(TRANS("Please enter a valid password!"), passwordBox); + showAlert("Please enter a valid password!", AlertBox::Type::Error); return; } - //status.setUserEmail(emailBox.getText()); addAndMakeVisible(m_overlay = new OverlayComp()); - resized(); + + auto callback = [this](Api::Response res, Api::Error err) + { + KiwiApp::useInstance().useScheduler().schedule([this, + res=std::move(res), + err=std::move(err)]() + { + removeChildComponent(m_overlay); + m_overlay.deleteAndZero(); + + if(err) + { + std::string message = "Error:" + err.message(); + std::cout << message << "\n"; + showAlert(message, AlertBox::Type::Error); + return; + } + else + { + auto j = json::parse(res.body); + + if(j.is_object()) + { + if(res.result() == beast::http::status::ok) + { + std::cout << "Authenticated !\n"; + std::cout << "token: " << j["token"] << "\n"; + showAlert("Login success!", AlertBox::Type::Success); + } + else + { + std::cout << "Failed...\n"; + std::string message = "Unknown Error !"; + if(j.count("message")) + { + message = j["message"]; + } + + std::cout << "Error: " << message << "\n"; + showAlert(message, AlertBox::Type::Error); + } + } + } + + }, std::chrono::milliseconds(500)); + }; + + KiwiApp::useApi().getAuthToken(m_email_box.getText().toStdString(), + m_password_box.getText().toStdString(), + callback); } } diff --git a/Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.h b/Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.h index 4027bb98..37d3ec3d 100644 --- a/Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.h +++ b/Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.h @@ -25,6 +25,45 @@ namespace kiwi { + class AlertBox : public juce::Component, private juce::ButtonListener + { + public: // methods + + enum class Type : uint8_t + { + Info = 0, + Success = 1, + Error = 2 + }; + + //! @brief Constructor. + AlertBox(std::string const& message, + Type type = Type::Info, + bool can_cancel = true, + std::function on_close = nullptr); + + //! @brief Destructor. + ~AlertBox(); + + private: // methods + + //! @internal paint method + void paint(juce::Graphics&) override; + + //! @internal resized method + void resized() override; + + //! @internal juce::ButtonListener + void buttonClicked(juce::Button*) override; + + private: // variables + + std::string m_message; + Type m_type = Type::Info; + std::unique_ptr m_close_btn; + std::function m_close_fn; + }; + class LoginForm : public juce::Component, private juce::ButtonListener { public: // methods @@ -36,11 +75,10 @@ namespace kiwi //! @brief Destructor. ~LoginForm(); - /** This is called when the form is dismissed (either cancelled or when registration - succeeds). - By default it will delete this, but you can override it to do other things. - */ - virtual void dismiss(); + //! @brief This is called when the form is dismissed (either cancelled or when registration + // succeeds). + //! @details By default it will delete this, but you can override it to do other things. + void dismiss(); private: // methods @@ -53,22 +91,24 @@ namespace kiwi //! @internal lookAndFeelChanged method void lookAndFeelChanged() override; + void showAlert(std::string const& message, AlertBox::Type type = AlertBox::Type::Error); + + void buttonClicked(juce::Button*) override; + void attemptRegistration(); + private: // variables - juce::Label message; - juce::TextEditor emailBox, passwordBox; - juce::TextButton registerButton, cancelButton; + juce::TextEditor m_email_box, m_password_box; + juce::TextButton m_submit_btn, m_cancel_btn; + + std::unique_ptr m_alert_box; - juce::ScopedPointer bubble; + juce::Image m_kiwi_app_image; struct OverlayComp; friend struct OverlayComp; Component::SafePointer m_overlay; - void buttonClicked(juce::Button*) override; - void attemptRegistration(); - void showBubbleMessage(juce::String const&, juce::Component&); - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LoginForm) }; } diff --git a/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp b/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp new file mode 100644 index 00000000..0cf40611 --- /dev/null +++ b/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp @@ -0,0 +1,256 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include "KiwiApp_Api.h" + +namespace kiwi +{ + // ================================================================================ // + // API // + // ================================================================================ // + + void Api::getAuthToken(std::string const& username, + std::string const& password, + Callback callback) + { + Post("/api/login", { + {"username", username}, + {"password", password} + }, std::move(callback), Timeout(3000)); + } + + void Api::getDocuments(std::function callback) + + { + auto cb = [callback = std::move(callback)](Response res, Error error) + { + if (res.result() == beast::http::status::ok) + { + if(hasJsonHeader(res)) + { + auto j = json::parse(res.body); + + if(j.is_array()) + { + // parse each json objects as document and store them in a vector. + callback(res, error, j); + return; + } + } + } + + callback(res, error, {}); + }; + + Get("/api/documents", cb, Timeout(3000)); + } + + void Api::createDocument(std::string const& document_name, + std::function callback) + { + auto cb = [callback = std::move(callback)](Response res, Error error) + { + if (res.result() == beast::http::status::ok) + { + if(hasJsonHeader(res)) + { + auto j = json::parse(res.body); + + if(j.is_object()) + { + // parse object as a document + callback(std::move(res), error, j); + } + } + } + + callback(std::move(res), error, {}); + }; + + Post("/api/documents", { + {"name", document_name} + }, std::move(cb), Timeout(3000)); + + } + + void Api::renameDocument(std::string document_id, std::string const& new_name, + Callback callback) + { + assert(!new_name.empty() && "name should not be empty!"); + + Put("/api/documents/" + document_id, { + {"name", new_name} + }, std::move(callback), Timeout(3000)); + } + + bool Api::hasJsonHeader(Response const& res) + { + return (res[beast::http::field::content_type] == "application/json; charset=utf-8"); + } + + // ================================================================================ // + // SESSION // + // ================================================================================ // + + Api::Api(std::string const& host, uint16_t port) : + m_host(host), + m_port(port) + { + ; + } + + Api::~Api() + { + + } + + void Api::setHost(std::string const& host) + { + m_host = host; + } + + std::string const& Api::getHost() const + { + return m_host; + } + + void Api::setPort(uint16_t port) noexcept + { + m_port = port; + } + + uint16_t Api::getPort() const noexcept + { + return m_port; + } + + void Api::storeRequest(std::future && future) + { + for(std::future& f : m_pending_requests) + { + if(f.wait_for(std::chrono::seconds(0)) == std::future_status::ready) + { + f = std::move(future); + return; + } + } + + m_pending_requests.emplace_back(std::move(future)); + } + + void Api::Get(std::string const& endpoint, + Callback callback, + Timeout timeout) + { + auto request = std::make_unique(); + request->version = 11; + + request->set(beast::http::field::host, getHost()); + request->method(beast::http::verb::get); + request->target(endpoint); + request->prepare_payload(); + + storeRequest(Http::writeAsync(std::move(request), + std::to_string(m_port), + std::move(callback), + timeout)); + } + + void Api::Post(std::string const& endpoint, + Payload payload, + Callback callback, + Timeout timeout) + { + auto request = std::make_unique(); + request->version = 11; + + request->set(beast::http::field::host, getHost()); + request->set(beast::http::field::content_type, "application/x-www-form-urlencoded"); + request->method(beast::http::verb::post); + request->target(endpoint); + + request->body = payload.content; + request->prepare_payload(); + + storeRequest(Http::writeAsync(std::move(request), + std::to_string(m_port), + std::move(callback), + timeout)); + } + + void Api::Put(std::string const& endpoint, + Payload payload, + Callback callback, + Timeout timeout) + { + auto request = std::make_unique(); + request->version = 11; + + request->set(beast::http::field::host, getHost()); + request->set(beast::http::field::content_type, "application/x-www-form-urlencoded"); + request->method(beast::http::verb::put); + request->target(endpoint); + + request->body = payload.content; + request->prepare_payload(); + + storeRequest(Http::writeAsync(std::move(request), + std::to_string(m_port), + std::move(callback), + timeout)); + } + + // ================================================================================ // + // API DOCUMENT // + // ================================================================================ // + + void to_json(json& j, Api::Document const& doc) + { + std::stringstream session_id_converter; + session_id_converter << std::hex << doc.session_id; + + j = json{ + {"_id", doc._id}, + {"name", doc.name}, + {"session_id", session_id_converter.str()} + }; + } + + void from_json(json const& j, Api::Document& doc) + { + doc._id = j["_id"].get(); + doc.name = j["name"].get(); + doc.session_id = 0ul; + + if(j.count("session_id")) + { + std::stringstream converter(j["session_id"].get()); + converter >> std::hex >> doc.session_id; + } + } + + bool Api::Document::operator==(Api::Document const& other_doc) const + { + return (_id == other_doc._id); + } +} diff --git a/Client/Source/KiwiApp_Network/KiwiApp_Api.h b/Client/Source/KiwiApp_Network/KiwiApp_Api.h new file mode 100644 index 00000000..82094a1a --- /dev/null +++ b/Client/Source/KiwiApp_Network/KiwiApp_Api.h @@ -0,0 +1,157 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +#include + +namespace kiwi +{ + using nlohmann::json; + using network::Http; + + // ================================================================================ // + // API // + // ================================================================================ // + + //! @brief An API request handler class. + class Api + { + public: // methods + + using BodyType = beast::http::string_body; + using Response = Http::Response; + using Request = beast::http::request; + using Error = Http::Error; + using Callback = std::function; + using Timeout = Http::Timeout; + + class Document; + class User; + + using Documents = std::vector; + + using Payload = Http::Payload; + + //! @brief Constructor + Api(std::string const& host = "127.0.0.1", uint16_t port = 80); + + //! @brief Destructor + ~Api(); + + //! @brief Set the host. + void setHost(std::string const& host); + + //! @brief Get the host. + std::string const& getHost() const; + + //! @brief Set the port. + void setPort(uint16_t port) noexcept; + + //! @brief Get the port. + uint16_t getPort() const noexcept; + + //! @brief Get the authentication token + //! @param username_or_email user name or email adress + //! @param password password + void getAuthToken(std::string const& username_or_email, + std::string const& password, + Callback callback); + + //! @brief Make an async API request to get a list of documents + void getDocuments(std::function callback); + + //! @brief Make an async API request to create a new document + //! @param callback + void createDocument(std::string const& document_name, + std::function callback); + + //! @brief Rename a document asynchronously. + //! @param callback The callback method that will be called when the request is completed. + void renameDocument(std::string document_id, std::string const& new_name, + Callback callback); + + private: // methods + + //! @brief Make a Post request. + void Post(std::string const& endpoint, + Payload payload, + Callback callback, + Timeout timeout = Timeout(0)); + + //! @brief Make a Get request. + void Get(std::string const& endpoint, + Callback callback, + Timeout timeout = Timeout(0)); + + //! @brief Make a Put request. + void Put(std::string const& endpoint, + Payload payload, + Callback callback, + Timeout timeout = Timeout(0)); + + //! @internal Store the async future request in a vector + void storeRequest(std::future && future); + + //! @internal Check if the response header has a JSON content-type + static bool hasJsonHeader(Response const& res); + + private: // variables + + std::string m_host; + uint16_t m_port; + std::string m_auth_token; + + std::vector> m_pending_requests; + + private: // deleted methods + + Api() = delete; + Api(Api const&) = delete; + Api(Api &&) = delete; + Api& operator=(Api const&) = delete; + Api& operator=(Api &&) = delete; + }; + + // ================================================================================ // + // API DOCUMENT // + // ================================================================================ // + + class Api::Document + { + public: + + std::string _id = "0"; + std::string name = ""; + uint64_t session_id = 0ul; + + //! @brief Returns true if the Document match another Document + bool operator==(Document const& other_doc) const; + }; + + //! @brief Helper function to convert an Api::Document into a json object + void to_json(json& j, Api::Document const& doc); + + //! @brief Helper function to convert a json object into an Api::Document + void from_json(json const& j, Api::Document& doc); +} diff --git a/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp b/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp index fe839a3f..9f34a402 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp +++ b/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp @@ -156,9 +156,9 @@ namespace kiwi void DocumentBrowser::Drive::createNewDocument() { - KiwiApp::useApi().createDocument([this](Api::Response const& res, - Api::Error const& error, - Api::Document document) { + KiwiApp::useApi().createDocument("", [this](Api::Response res, + Api::Error error, + Api::Document document) { if(error) { @@ -269,16 +269,15 @@ namespace kiwi void DocumentBrowser::Drive::refresh() { - KiwiApp::useApi().getDocuments([this](Api::Response const& res, Api::Error const& error, Api::Documents docs) { + KiwiApp::useApi().getDocuments([this](Api::Response res, Api::Error error, Api::Documents docs) { if(error) { - KiwiApp::error("Kiwi API error: can't get documents => " + error.message()); + KiwiApp::error("Kiwi API error: can't get documents => " + error.message()); } else { - KiwiApp::useInstance().useScheduler().schedule([this, docs]() - { + KiwiApp::useInstance().useScheduler().schedule([this, docs]() { updateDocumentList(docs); }); } @@ -334,7 +333,8 @@ namespace kiwi return; } - KiwiApp::useApi().renameDocument([](Api::Response const& res, Api::Error const& error) { + KiwiApp::useApi().renameDocument(m_document._id, new_name, + [](Api::Response res, Api::Error error) { if(!error) { @@ -345,7 +345,7 @@ namespace kiwi std::cout << "document update failed, err: " + error.message() << '\n'; } - }, m_document._id, new_name); + }); } bool DocumentBrowser::Drive::DocumentSession::operator==(DocumentSession const& other_doc) const diff --git a/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.h b/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.h index 442c41d9..511a8bed 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.h +++ b/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.h @@ -26,14 +26,12 @@ #include #include -#include +#include "../KiwiApp_Network/KiwiApp_Api.h" #include "../KiwiApp_General/KiwiApp_StoredSettings.h" namespace kiwi { - using network::Api; - // ================================================================================ // // DOCUMENT BROWSER // // ================================================================================ // diff --git a/Modules/KiwiEngine/KiwiEngine_Scheduler.h b/Modules/KiwiEngine/KiwiEngine_Scheduler.h index c009922b..db7fcc25 100644 --- a/Modules/KiwiEngine/KiwiEngine_Scheduler.h +++ b/Modules/KiwiEngine/KiwiEngine_Scheduler.h @@ -98,7 +98,7 @@ namespace kiwi //! and add a new one at specified time. void schedule(std::shared_ptr && task, duration_t delay = std::chrono::milliseconds(0)); - //! @brief Delays execution of a function by the sceduler. + //! @brief Delays execution of a function by the scheduler. //! @details Internally create a callback that will be executed and destroyed by the scheduler. void schedule(std::function && func, duration_t delay = std::chrono::milliseconds(0)); diff --git a/Modules/KiwiEngine/KiwiEngine_Scheduler.hpp b/Modules/KiwiEngine/KiwiEngine_Scheduler.hpp index 1be7cdc5..03c9ca0a 100644 --- a/Modules/KiwiEngine/KiwiEngine_Scheduler.hpp +++ b/Modules/KiwiEngine/KiwiEngine_Scheduler.hpp @@ -73,7 +73,7 @@ namespace kiwi template void Scheduler::schedule(std::function && func, duration_t delay) { - schedule(std::shared_ptr(new CallBack(func))); + schedule(std::make_shared(func), delay); } template diff --git a/Modules/KiwiNetwork/KiwiNetwork_Api.cpp b/Modules/KiwiNetwork/KiwiNetwork_Api.cpp deleted file mode 100644 index 395bac8e..00000000 --- a/Modules/KiwiNetwork/KiwiNetwork_Api.cpp +++ /dev/null @@ -1,216 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#include "KiwiNetwork_Api.h" -#include "KiwiNetwork_Http.h" - -namespace kiwi -{ - namespace network - { - void to_json(json& j, Api::Document const& doc) - { - std::stringstream session_id_converter; - session_id_converter << std::hex << doc.session_id; - - j = json{ - {"_id", doc._id}, - {"name", doc.name}, - {"session_id", session_id_converter.str()} - }; - } - - void from_json(json const& j, Api::Document& doc) - { - doc._id = j["_id"].get(); - doc.name = j["name"].get(); - doc.session_id = 0ul; - - if(j.count("session_id")) - { - std::stringstream converter(j["session_id"].get()); - converter >> std::hex >> doc.session_id; - } - } - - bool Api::Document::operator==(Api::Document const& other_doc) const - { - return (_id == other_doc._id); - } - - // ================================================================================ // - // API REQUEST // - // ================================================================================ // - - Api::Api(std::string const& host, uint16_t port) : - m_host(host), - m_port(port) - { - ; - } - - //! @brief Destructor - Api::~Api() - { - - } - - void Api::setHost(std::string const& host) - { - m_host = host; - } - - std::string const& Api::getHost() const - { - return m_host; - } - - void Api::setPort(uint16_t port) noexcept - { - m_port = port; - } - - uint16_t Api::getPort() const noexcept - { - return m_port; - } - - void Api::getDocuments(std::function callback) - { - std::function res_callback = - [callback = std::move(callback)](Api::Response const& res, Api::Error const& error) - { - if (res.result() == beast::http::status::ok) - { - if(hasJsonHeader(res)) - { - auto j = json::parse(res.body); - - if(j.is_array()) - { - // parse each json objects as document and store them in a vector. - callback(res, error, j); - return; - } - } - } - - callback(res, error, {}); - }; - - auto request = std::make_unique(); - request->set(beast::http::field::host, m_host); - request->method(beast::http::verb::get); - request->target("/api/documents"); - request->version = 11; - - request->prepare_payload(); - - storeRequest(Http::writeAsync(std::move(request), - std::to_string(m_port), - res_callback, - std::chrono::milliseconds(3000))); - } - - void Api::createDocument(std::function callback, - std::string const& document_name) - { - auto request = std::make_unique(); - request->set(beast::http::field::host, m_host); - request->set(beast::http::field::content_type, "application/x-www-form-urlencoded"); - request->method(beast::http::verb::post); - request->target("/api/documents"); - request->version = 11; - - request->body = "name=" + document_name; - - request->prepare_payload(); - - std::function res_callback = - [callback = std::move(callback)](Api::Response const& res, Api::Error const& error) - { - if (res.result() == beast::http::status::ok) - { - if(hasJsonHeader(res)) - { - auto j = json::parse(res.body); - - if(j.is_object()) - { - // parse object as a document - callback(std::move(res), error, j); - } - } - } - - callback(std::move(res), error, {}); - }; - - storeRequest(Http::writeAsync(std::move(request), - std::to_string(m_port), - res_callback, - std::chrono::milliseconds(3000))); - } - - void Api::renameDocument(std::function callback, - std::string document_id, std::string const& new_name) - { - assert(!new_name.empty() && "name should not be empty!"); - - auto request = std::make_unique(); - request->set(beast::http::field::host, m_host); - request->set(beast::http::field::content_type, "application/x-www-form-urlencoded"); - request->method(beast::http::verb::put); - request->version = 11; - request->target("/api/documents/" + document_id); - - request->body = "name=" + new_name; - - request->prepare_payload(); - - storeRequest(Http::writeAsync(std::move(request), - std::to_string(m_port), - callback, - std::chrono::milliseconds(3000))); - } - - void Api::storeRequest(std::future && future) - { - for(std::future& f : m_pending_requests) - { - if(f.wait_for(std::chrono::seconds(0)) == std::future_status::ready) - { - f = std::move(future); - return; - } - } - - m_pending_requests.emplace_back(std::move(future)); - } - - bool Api::hasJsonHeader(Api::Response const& res) - { - return (res[beast::http::field::content_type] == "application/json; charset=utf-8"); - } - } -} diff --git a/Modules/KiwiNetwork/KiwiNetwork_Api.h b/Modules/KiwiNetwork/KiwiNetwork_Api.h deleted file mode 100644 index bac64902..00000000 --- a/Modules/KiwiNetwork/KiwiNetwork_Api.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#pragma once - -#include "KiwiNetwork_Http.h" - -#include - -namespace kiwi -{ - using nlohmann::json; - - namespace network - { - // ================================================================================ // - // API // - // ================================================================================ // - - //! @brief An API request handler class. - class Api - { - public: // methods - - struct Document - { - std::string _id = "0"; - std::string name = ""; - uint64_t session_id = 0ul; - - //! @brief Returns true if the Document match another Document - bool operator==(Document const& other_doc) const; - }; - - using Documents = std::vector; - - using Response = beast::http::response; - - using Request = beast::http::request; - - using Error = beast::error_code; - - //! @brief Constructor - Api(std::string const& host = "127.0.0.1", uint16_t port = 80); - - //! @brief Destructor - ~Api(); - - //! @brief Set the API host. - void setHost(std::string const& host); - - //! @brief Get the API host. - std::string const& getHost() const; - - //! @brief Set the API port. - void setPort(uint16_t port) noexcept; - - //! @brief Get the API port. - uint16_t getPort() const noexcept; - - //! @brief Make an async API request to get a list of documents - void getDocuments(std::function callback); - - //! @brief Make an async API request to create a new document - //! @param callback - void createDocument(std::function callback, - std::string const& document_name = ""); - - //! @brief Rename a document asynchronously. - //! @param callback The callback method that will be called when the request is completed. - void renameDocument(std::function callback, - std::string document_id, std::string const& new_name); - - private: // methods - - //! @internal Store the async future request in a vector - void storeRequest(std::future && future); - - //! @internal Check if the response header has a JSON content-type - static bool hasJsonHeader(Api::Response const& res); - - private: // variables - - std::string m_host; - uint16_t m_port; - - std::vector> m_pending_requests; - }; - - //! @brief Helper function to convert an Api::Document into a json object - void to_json(json& j, Api::Document const& doc); - - //! @brief Helper function to convert a json object into an Api::Document - void from_json(json const& j, Api::Document& doc); - } -} diff --git a/Modules/KiwiNetwork/KiwiNetwork_Http.cpp b/Modules/KiwiNetwork/KiwiNetwork_Http.cpp new file mode 100644 index 00000000..1823b659 --- /dev/null +++ b/Modules/KiwiNetwork/KiwiNetwork_Http.cpp @@ -0,0 +1,79 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include "KiwiNetwork_Http.h" +#include "KiwiNetwork_Util.h" + +namespace kiwi { namespace network { + + // ================================================================================ // + // HTTP PAYLOAD // + // ================================================================================ // + + Http::Payload::Payload(const std::initializer_list& pairs) + : Payload(begin(pairs), end(pairs)) + { + ; + } + + void Http::Payload::AddPair(const Pair& pair) + { + if(!content.empty()) + { + content += "&"; + } + + auto escaped = util::urlEncode(pair.value); + content += pair.key + "=" + escaped; + } + + // ================================================================================ // + // HTTP PARAMETERS // + // ================================================================================ // + + Http::Parameters::Parameters(std::initializer_list const& parameters) + { + for(auto const& parameter : parameters) + { + AddParameter(parameter); + } + } + + void Http::Parameters::AddParameter(Parameter const& parameter) + { + if (!content.empty()) + { + content += "&"; + } + + auto escapedKey = util::urlEncode(parameter.key); + if (parameter.value.empty()) + { + content += escapedKey; + } + else + { + auto escapedValue = util::urlEncode(parameter.value); + content += escapedKey + "=" + escapedValue; + } + } + +}} diff --git a/Modules/KiwiNetwork/KiwiNetwork_Http.h b/Modules/KiwiNetwork/KiwiNetwork_Http.h index e1363210..f969590c 100644 --- a/Modules/KiwiNetwork/KiwiNetwork_Http.h +++ b/Modules/KiwiNetwork/KiwiNetwork_Http.h @@ -30,8 +30,8 @@ #include #include -#include #include +#include namespace kiwi { namespace network { @@ -45,26 +45,41 @@ namespace kiwi { namespace network { { public: // methods + //template + //using Response = beast::http::response; + + template + class Response; + + template + using Request = beast::http::request; + + using Timeout = std::chrono::milliseconds; + + using Error = beast::error_code; + + class Payload; + class Parameters; + //! @brief Sends an http request. //! @details Returns the response generated by the server. The function blocks until response //! is received or error occurs. template - static beast::http::response - write(std::unique_ptr> request, + static Response + write(std::unique_ptr> request, std::string port, - beast::error_code& error, - std::chrono::milliseconds timeout = std::chrono::milliseconds(0)); + Error& error, + Timeout timeout = Timeout(0)); //! @brief Sends an http request asynchronously. //! @details Returns the response generated by the server. The function is non blocking. callback //! is called on another thread once response is received or error occurs. template static std::future - writeAsync(std::unique_ptr> request, + writeAsync(std::unique_ptr> request, std::string port, - std::function const& response, - beast::error_code const& error)> callback, - std::chrono::milliseconds timeout = std::chrono::milliseconds(0)); + std::function, Error)> callback, + Timeout timeout = Timeout(0)); private: // nested classes @@ -79,6 +94,63 @@ namespace kiwi { namespace network { Http& operator=(Http && other) = delete; }; + // ================================================================================ // + // HTTP PAYLOAD // + // ================================================================================ // + + class Http::Payload + { + public: + + struct Pair; + + template + Payload(const It begin, const It end); + + Payload(std::initializer_list const& pairs); + + void AddPair(Pair const& pair); + + std::string content; + }; + + // ================================================================================ // + // HTTP PARAMETERS // + // ================================================================================ // + + class Http::Parameters + { + public: + + struct Parameter; + + Parameters() = default; + Parameters(const std::initializer_list& parameters); + + void AddParameter(Parameter const& parameter); + + std::string content; + }; + + struct Http::Parameters::Parameter + { + template + Parameter(KeyType&& key, ValueType&& value); + + std::string key; + std::string value; + }; + + // ================================================================================ // + // HTTP RESPONSE // + // ================================================================================ // + + template + class Http::Response : public beast::http::response + { + public: + }; + // ================================================================================ // // HTTP QUERY // // ================================================================================ // @@ -89,43 +161,44 @@ namespace kiwi { namespace network { public: // methods //! @brief Constructor. - Query(std::unique_ptr> request, + Query(std::unique_ptr> request, std::string port, - std::chrono::milliseconds timeout = std::chrono::milliseconds(0)); + Http::Timeout timeout = Http::Timeout(0)); //! @brief Destructor. ~Query(); //! @brief Write the request and get the response. - beast::http::response writeRequest(beast::error_code& error); + Http::Response writeRequest(Http::Error& error); private: // methods //! @internal - void handleTimeout(boost::system::error_code const& error); + void handleTimeout(beast::error_code const& error); //! @internal - void handleRead(beast::error_code const& error); + void connect(beast::error_code const& error, + tcp::resolver::iterator iterator); //! @internal - void handleWrite(beast::error_code const& error); + void write(beast::error_code const& error); //! @internal - void handleConnect(beast::error_code const& error); + void read(beast::error_code const& error); //! @internal - void handleResolve(beast::error_code const& error, - tcp::resolver::iterator iterator); + void shutdown(beast::error_code const& error); private: // members - std::unique_ptr> m_request; - beast::http::response m_response; + std::unique_ptr> m_request; + Http::Response m_response; + Http::Error m_error; + Http::Timeout m_timeout; + std::string m_port; boost::asio::io_service m_io_service; tcp::socket m_socket; - beast::error_code m_error; - std::chrono::milliseconds m_timeout; boost::asio::steady_timer m_timer; beast::flat_buffer m_buffer; diff --git a/Modules/KiwiNetwork/KiwiNetwork_Http.hpp b/Modules/KiwiNetwork/KiwiNetwork_Http.hpp index 75f723c8..39f36958 100644 --- a/Modules/KiwiNetwork/KiwiNetwork_Http.hpp +++ b/Modules/KiwiNetwork/KiwiNetwork_Http.hpp @@ -28,34 +28,82 @@ namespace kiwi { namespace network { // ================================================================================ // template - beast::http::response - Http::write(std::unique_ptr> request, + Http::Response + Http::write(std::unique_ptr> request, std::string port, beast::error_code& error, - std::chrono::milliseconds timeout) + Timeout timeout) { return Query(std::move(request), port, timeout).writeRequest(error); } template std::future - Http::writeAsync(std::unique_ptr> request, + Http::writeAsync(std::unique_ptr> request, std::string port, - std::function const& response, - beast::error_code const& error)> callback, - std::chrono::milliseconds timeout) + std::function response, + Error error)> callback, + Timeout timeout) { auto query = std::make_unique>(std::move(request), port, timeout); return std::async(std::launch::async, [query = std::move(query), cb = std::move(callback)]() { beast::error_code error; - beast::http::response response = query->writeRequest(error); - return cb(response, error); + Response response(query->writeRequest(error)); + return cb(std::move(response), error); }); } + // ================================================================================ // + // HTTP PAYLOAD // + // ================================================================================ // + + template + Http::Payload::Payload(const It begin, const It end) + { + for (It pair = begin; pair != end; ++pair) + { + AddPair(*pair); + } + } + + struct Http::Payload::Pair + { + template ::value, bool>::type = true> + Pair(KeyType&& p_key, ValueType&& p_value) + : key{std::forward(p_key)} + , value{std::forward(p_value)} + { + ; + } + + template + Pair(KeyType&& p_key, const std::int32_t& p_value) + : key{std::forward(p_key)} + , value{std::to_string(p_value)} + { + ; + } + + std::string key; + std::string value; + }; + + // ================================================================================ // + // HTTP PARAMETERS // + // ================================================================================ // + + template + Http::Parameters::Parameter::Parameter(KeyType&& key, ValueType&& value) + : key{std::forward(key)} + , value{std::forward(value)} + { + ; + } + // ================================================================================ // // HTTP QUERY // // ================================================================================ // @@ -63,14 +111,14 @@ namespace kiwi { namespace network { template Http::Query::Query(std::unique_ptr> request, std::string port, - std::chrono::milliseconds timeout) + Http::Timeout timeout) : m_request(std::move(request)) , m_response() + , m_error() + , m_timeout(timeout) , m_port(port) , m_io_service() , m_socket(m_io_service) - , m_error() - , m_timeout(timeout) , m_timer(m_io_service) , m_buffer() { @@ -84,15 +132,15 @@ namespace kiwi { namespace network { } template - beast::http::response - Http::Query::writeRequest(beast::error_code& error) + Http::Response + Http::Query::writeRequest(Http::Error& error) { - if (m_timeout > std::chrono::milliseconds(0)) + if (m_timeout > Http::Timeout(0)) { m_timer.expires_from_now(m_timeout); m_timer.async_wait([this](boost::system::error_code const& error) { - this->handleTimeout(error); + handleTimeout(error); }); } @@ -102,7 +150,7 @@ namespace kiwi { namespace network { resolver.async_resolve({host, m_port}, [this](beast::error_code const& error, tcp::resolver::iterator iterator) { - handleResolve(error, iterator); + connect(error, iterator); }); m_io_service.reset(); @@ -120,7 +168,7 @@ namespace kiwi { namespace network { template void - Http::Query::handleTimeout(boost::system::error_code const& error) + Http::Query::handleTimeout(beast::error_code const& error) { m_io_service.stop(); @@ -130,23 +178,25 @@ namespace kiwi { namespace network { template void - Http::Query::handleRead(beast::error_code const& error) + Http::Query::connect(beast::error_code const& error, + tcp::resolver::iterator iterator) { - m_io_service.stop(); - if (error) { m_error = error; } else { - m_socket.shutdown(tcp::socket::shutdown_both, m_error); + boost::asio::async_connect(m_socket, iterator, [this](beast::error_code const& error, + tcp::resolver::iterator i) { + this->write(error); + }); } } template void - Http::Query::handleWrite(beast::error_code const& error) + Http::Query::write(beast::error_code const& error) { if (error) { @@ -154,15 +204,16 @@ namespace kiwi { namespace network { } else { - beast::http::async_read(m_socket, m_buffer, m_response, [this](beast::error_code const& error) { - handleRead(error); + beast::http::async_write(m_socket, *m_request, [this](beast::error_code const& error) { + read(error); }); + } } template void - Http::Query::handleConnect(beast::error_code const& error) + Http::Query::read(beast::error_code const& error) { if (error) { @@ -170,28 +221,25 @@ namespace kiwi { namespace network { } else { - beast::http::async_write(m_socket, *m_request, [this](beast::error_code const& error) { - handleWrite(error); + beast::http::async_read(m_socket, m_buffer, m_response, [this](beast::error_code const& error) { + shutdown(error); }); - } } template void - Http::Query::handleResolve(beast::error_code const& error, - tcp::resolver::iterator iterator) + Http::Query::shutdown(beast::error_code const& error) { + m_io_service.stop(); + if (error) { m_error = error; } else { - boost::asio::async_connect(m_socket, iterator, [this](beast::error_code const& error, - tcp::resolver::iterator i) { - this->handleConnect(error); - }); + m_socket.shutdown(tcp::socket::shutdown_both, m_error); } } diff --git a/Modules/KiwiNetwork/KiwiNetwork_Util.cpp b/Modules/KiwiNetwork/KiwiNetwork_Util.cpp new file mode 100644 index 00000000..44d7e5ed --- /dev/null +++ b/Modules/KiwiNetwork/KiwiNetwork_Util.cpp @@ -0,0 +1,52 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include "KiwiNetwork_Util.h" + +#include +#include +#include +#include +#include + +namespace kiwi { namespace network { namespace util { + + std::string urlEncode(const std::string& value) { + std::ostringstream escaped; + escaped.fill('0'); + escaped << std::hex; + + for (auto i = value.cbegin(), n = value.cend(); i != n; ++i) { + std::string::value_type c = (*i); + // Keep alphanumeric and other accepted characters intact + if (std::isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') { + escaped << c; + continue; + } + // Any other characters are percent-encoded + escaped << '%' << std::setw(2) << std::int32_t((unsigned char) c); + } + + return escaped.str(); + } + + +}}} // namespace kiwi::network::util diff --git a/Modules/KiwiNetwork/KiwiNetwork_Util.h b/Modules/KiwiNetwork/KiwiNetwork_Util.h new file mode 100644 index 00000000..52ef7acc --- /dev/null +++ b/Modules/KiwiNetwork/KiwiNetwork_Util.h @@ -0,0 +1,30 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace network { namespace util { + + std::string urlEncode(std::string const& response); + +}}} // namespace kiwi::network::util diff --git a/Test/Engine/test_Scheduler.cpp b/Test/Engine/test_Scheduler.cpp index c24de6ed..d50c26bb 100644 --- a/Test/Engine/test_Scheduler.cpp +++ b/Test/Engine/test_Scheduler.cpp @@ -81,6 +81,42 @@ TEST_CASE("Scheduler", "[Scheduler]") CHECK(counter == 10); } + SECTION("Schedule lambda") + { + bool success = false; + + sch.schedule([&success]() { + success = true; + }, std::chrono::milliseconds(0)); + + REQUIRE_FALSE(success); + sch.process(); + REQUIRE(success); + } + + SECTION("Schedule lambda with delay") + { + bool success = false; + + sch.schedule([&success]() { + success = true; + }, std::chrono::milliseconds(1000)); + + REQUIRE_FALSE(success); + sch.process(); + REQUIRE_FALSE(success); + + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + sch.process(); + REQUIRE_FALSE(success); + + // check with 5ms precision. + std::this_thread::sleep_for(std::chrono::milliseconds(505)); + sch.process(); + + REQUIRE(success); + } + SECTION("Ownership") { struct TestDestructor : public Task diff --git a/Test/Network/test_Http.cpp b/Test/Network/test_Http.cpp index 878ab29f..3820e4e6 100755 --- a/Test/Network/test_Http.cpp +++ b/Test/Network/test_Http.cpp @@ -33,6 +33,8 @@ TEST_CASE("Network - Http", "[Network, Http]") { + using namespace kiwi::network; + SECTION("Client get request to echo server") { // Construct request and response. @@ -49,7 +51,7 @@ TEST_CASE("Network - Http", "[Network, Http]") // Send request and waits for response. beast::http::response response = - kiwi::network::Http::write(std::move(request), "80", error); + Http::write(std::move(request), "80", error); CHECK(response.result() == beast::http::status::ok); CHECK(!error); @@ -58,7 +60,7 @@ TEST_CASE("Network - Http", "[Network, Http]") SECTION("Client asynchronous get request to echo server") { // Construct request and response. - auto request = std::make_unique>(); + auto request = std::make_unique>(); request->method(beast::http::verb::get); request->target("/get"); request->version = 11; @@ -67,16 +69,38 @@ TEST_CASE("Network - Http", "[Network, Http]") request->prepare_payload(); - std::function const& response, - beast::error_code const& error)> - callback = [](beast::http::response const& response, - beast::error_code const& error) + std::function, Http::Error)> + callback = [](Http::Response response, Http::Error error) { CHECK(response.result() == beast::http::status::ok); CHECK(!error); }; - std::future future = kiwi::network::Http::writeAsync(std::move(request), "80", callback); + auto future = Http::writeAsync(std::move(request), "80", callback); + + future.get(); + } + + SECTION("Deferred request body") + { + beast::http::header header; + + header.version = 11; + header.method(beast::http::verb::get); + header.set(beast::http::field::host, "httpbin.org"); + header.target("/get"); + header.set(beast::http::field::user_agent, "KiwiApp - Tests"); + + std::function, Http::Error)> + callback = [](Http::Response response, Http::Error error) + { + REQUIRE_FALSE(error); + CHECK(response.result() == beast::http::status::ok); + }; + + auto future = Http::writeAsync(std::make_unique>(std::move(header)), + "80", + callback); future.get(); } From 98d288bcf94c8ca36af17d0f51af0614b35c2091 Mon Sep 17 00:00:00 2001 From: eliott PARIS Date: Wed, 26 Jul 2017 14:11:38 +0200 Subject: [PATCH 028/148] Add an http::Session class --- .../Source/KiwiApp_Auth/KiwiApp_LoginForm.cpp | 10 +- Client/Source/KiwiApp_Network/KiwiApp_Api.cpp | 193 ++++++-------- Client/Source/KiwiApp_Network/KiwiApp_Api.h | 37 +-- .../KiwiApp_DocumentBrowser.cpp | 51 ++-- Modules/KiwiNetwork/KiwiHttp/KiwiHttp.h | 144 ++++++++++ Modules/KiwiNetwork/KiwiHttp/KiwiHttp.hpp | 201 ++++++++++++++ .../KiwiNetwork/KiwiHttp/KiwiHttp_Session.cpp | 230 ++++++++++++++++ .../KiwiNetwork/KiwiHttp/KiwiHttp_Session.h | 145 +++++++++++ .../KiwiHttp_Session.hpp} | 73 +++--- .../KiwiHttp_Util.cpp} | 8 +- .../KiwiHttp_Util.h} | 4 +- Modules/KiwiNetwork/KiwiNetwork_Http.h | 195 +------------- Modules/KiwiNetwork/KiwiNetwork_Http.hpp | 246 ------------------ Test/Network/test_Http.cpp | 62 +++-- 14 files changed, 910 insertions(+), 689 deletions(-) create mode 100644 Modules/KiwiNetwork/KiwiHttp/KiwiHttp.h create mode 100644 Modules/KiwiNetwork/KiwiHttp/KiwiHttp.hpp create mode 100644 Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Session.cpp create mode 100644 Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Session.h rename Modules/KiwiNetwork/{KiwiNetwork_Http.cpp => KiwiHttp/KiwiHttp_Session.hpp} (54%) rename Modules/KiwiNetwork/{KiwiNetwork_Util.cpp => KiwiHttp/KiwiHttp_Util.cpp} (91%) rename Modules/KiwiNetwork/{KiwiNetwork_Util.h => KiwiHttp/KiwiHttp_Util.h} (89%) delete mode 100644 Modules/KiwiNetwork/KiwiNetwork_Http.hpp diff --git a/Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.cpp b/Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.cpp index 8072dfc0..a11406c6 100644 --- a/Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.cpp +++ b/Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.cpp @@ -307,18 +307,16 @@ namespace kiwi addAndMakeVisible(m_overlay = new OverlayComp()); resized(); - auto callback = [this](Api::Response res, Api::Error err) + auto callback = [this](Api::Response res) { - KiwiApp::useInstance().useScheduler().schedule([this, - res=std::move(res), - err=std::move(err)]() + KiwiApp::useInstance().useScheduler().schedule([this, res = std::move(res)]() { removeChildComponent(m_overlay); m_overlay.deleteAndZero(); - if(err) + if(res.error) { - std::string message = "Error:" + err.message(); + std::string message = "Error:" + res.error.message(); std::cout << message << "\n"; showAlert(message, AlertBox::Type::Error); return; diff --git a/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp b/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp index 0cf40611..6edcef90 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp +++ b/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp @@ -24,25 +24,63 @@ namespace kiwi { // ================================================================================ // - // API // + // API // + // ================================================================================ // + + Api::Api(std::string const& host, uint16_t port) : + m_host(host), + m_port(port) + { + ; + } + + Api::~Api() + { + + } + + void Api::setHost(std::string const& host) + { + m_host = host; + } + + std::string const& Api::getHost() const + { + return m_host; + } + + void Api::setPort(uint16_t port) noexcept + { + m_port = port; + } + + uint16_t Api::getPort() const noexcept + { + return m_port; + } + + // ================================================================================ // + // API REQUESTS // // ================================================================================ // void Api::getAuthToken(std::string const& username, std::string const& password, Callback callback) { - Post("/api/login", { + auto session = makeSession("/api/login"); + session->setPayload({ {"username", username}, {"password", password} - }, std::move(callback), Timeout(3000)); + }); + + storeFuture(session->GetAsync(std::move(callback))); } - void Api::getDocuments(std::function callback) - + void Api::getDocuments(std::function callback) { - auto cb = [callback = std::move(callback)](Response res, Error error) + auto cb = [callback = std::move(callback)](Response res) { - if (res.result() == beast::http::status::ok) + if (!res.error && res.result() == beast::http::status::ok) { if(hasJsonHeader(res)) { @@ -51,26 +89,25 @@ namespace kiwi if(j.is_array()) { // parse each json objects as document and store them in a vector. - callback(res, error, j); + callback(std::move(res), j); return; } } } - callback(res, error, {}); + callback(std::move(res), {}); }; - Get("/api/documents", cb, Timeout(3000)); + auto session = makeSession("/api/documents"); + storeFuture(session->GetAsync(std::move(cb))); } void Api::createDocument(std::string const& document_name, - std::function callback) + std::function callback) { - auto cb = [callback = std::move(callback)](Response res, Error error) + auto cb = [callback = std::move(callback)](Response res) { - if (res.result() == beast::http::status::ok) + if (!res.error && res.result() == beast::http::status::ok) { if(hasJsonHeader(res)) { @@ -79,18 +116,23 @@ namespace kiwi if(j.is_object()) { // parse object as a document - callback(std::move(res), error, j); + callback(std::move(res), j); } } } - callback(std::move(res), error, {}); + callback(std::move(res), {}); }; - Post("/api/documents", { - {"name", document_name} - }, std::move(cb), Timeout(3000)); + auto session = makeSession("/api/documents"); + if(!document_name.empty()) + { + session->setPayload({ + {"name", document_name} + }); + } + storeFuture(session->PostAsync(std::move(cb))); } void Api::renameDocument(std::string document_id, std::string const& new_name, @@ -98,9 +140,12 @@ namespace kiwi { assert(!new_name.empty() && "name should not be empty!"); - Put("/api/documents/" + document_id, { + auto session = makeSession("/api/documents" + document_id); + session->setPayload({ {"name", new_name} - }, std::move(callback), Timeout(3000)); + }); + + storeFuture(session->PutAsync(std::move(callback))); } bool Api::hasJsonHeader(Response const& res) @@ -108,43 +153,17 @@ namespace kiwi return (res[beast::http::field::content_type] == "application/json; charset=utf-8"); } - // ================================================================================ // - // SESSION // - // ================================================================================ // - - Api::Api(std::string const& host, uint16_t port) : - m_host(host), - m_port(port) - { - ; - } - - Api::~Api() - { - - } - - void Api::setHost(std::string const& host) - { - m_host = host; - } - - std::string const& Api::getHost() const - { - return m_host; - } - - void Api::setPort(uint16_t port) noexcept - { - m_port = port; - } - - uint16_t Api::getPort() const noexcept + std::unique_ptr Api::makeSession(std::string const& endpoint) { - return m_port; + auto session = std::make_unique(); + session->setHost(m_host); + session->setPort(std::to_string(m_port)); + session->setTarget(endpoint); + session->setTimeout(http::Timeout(3000)); + return std::move(session); } - void Api::storeRequest(std::future && future) + void Api::storeFuture(std::future && future) { for(std::future& f : m_pending_requests) { @@ -158,68 +177,6 @@ namespace kiwi m_pending_requests.emplace_back(std::move(future)); } - void Api::Get(std::string const& endpoint, - Callback callback, - Timeout timeout) - { - auto request = std::make_unique(); - request->version = 11; - - request->set(beast::http::field::host, getHost()); - request->method(beast::http::verb::get); - request->target(endpoint); - request->prepare_payload(); - - storeRequest(Http::writeAsync(std::move(request), - std::to_string(m_port), - std::move(callback), - timeout)); - } - - void Api::Post(std::string const& endpoint, - Payload payload, - Callback callback, - Timeout timeout) - { - auto request = std::make_unique(); - request->version = 11; - - request->set(beast::http::field::host, getHost()); - request->set(beast::http::field::content_type, "application/x-www-form-urlencoded"); - request->method(beast::http::verb::post); - request->target(endpoint); - - request->body = payload.content; - request->prepare_payload(); - - storeRequest(Http::writeAsync(std::move(request), - std::to_string(m_port), - std::move(callback), - timeout)); - } - - void Api::Put(std::string const& endpoint, - Payload payload, - Callback callback, - Timeout timeout) - { - auto request = std::make_unique(); - request->version = 11; - - request->set(beast::http::field::host, getHost()); - request->set(beast::http::field::content_type, "application/x-www-form-urlencoded"); - request->method(beast::http::verb::put); - request->target(endpoint); - - request->body = payload.content; - request->prepare_payload(); - - storeRequest(Http::writeAsync(std::move(request), - std::to_string(m_port), - std::move(callback), - timeout)); - } - // ================================================================================ // // API DOCUMENT // // ================================================================================ // diff --git a/Client/Source/KiwiApp_Network/KiwiApp_Api.h b/Client/Source/KiwiApp_Network/KiwiApp_Api.h index 82094a1a..10e8aedc 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_Api.h +++ b/Client/Source/KiwiApp_Network/KiwiApp_Api.h @@ -28,7 +28,7 @@ namespace kiwi { using nlohmann::json; - using network::Http; + using namespace network; // ================================================================================ // // API // @@ -39,20 +39,15 @@ namespace kiwi { public: // methods - using BodyType = beast::http::string_body; - using Response = Http::Response; - using Request = beast::http::request; - using Error = Http::Error; - using Callback = std::function; - using Timeout = Http::Timeout; + using Session = network::http::Session; + using Response = Session::Response; + using Callback = Session::Callback; class Document; class User; using Documents = std::vector; - using Payload = Http::Payload; - //! @brief Constructor Api(std::string const& host = "127.0.0.1", uint16_t port = 80); @@ -79,12 +74,12 @@ namespace kiwi Callback callback); //! @brief Make an async API request to get a list of documents - void getDocuments(std::function callback); + void getDocuments(std::function callback); //! @brief Make an async API request to create a new document //! @param callback void createDocument(std::string const& document_name, - std::function callback); + std::function callback); //! @brief Rename a document asynchronously. //! @param callback The callback method that will be called when the request is completed. @@ -93,25 +88,11 @@ namespace kiwi private: // methods - //! @brief Make a Post request. - void Post(std::string const& endpoint, - Payload payload, - Callback callback, - Timeout timeout = Timeout(0)); - - //! @brief Make a Get request. - void Get(std::string const& endpoint, - Callback callback, - Timeout timeout = Timeout(0)); - - //! @brief Make a Put request. - void Put(std::string const& endpoint, - Payload payload, - Callback callback, - Timeout timeout = Timeout(0)); + //! @internal Make a new session with pre-filled data. + std::unique_ptr makeSession(std::string const& endpoint); //! @internal Store the async future request in a vector - void storeRequest(std::future && future); + void storeFuture(std::future && future); //! @internal Check if the response header has a JSON content-type static bool hasJsonHeader(Response const& res); diff --git a/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp b/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp index 9f34a402..86d6f2a0 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp +++ b/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp @@ -156,32 +156,30 @@ namespace kiwi void DocumentBrowser::Drive::createNewDocument() { - KiwiApp::useApi().createDocument("", [this](Api::Response res, - Api::Error error, - Api::Document document) { + KiwiApp::useApi().createDocument("", [this](Api::Response res, Api::Document document) { - if(error) + if(res.error) { - juce::MessageManager::callAsync([message = error.message()](){ + juce::MessageManager::callAsync([message = res.error.message()](){ KiwiApp::error("Error: can't create document"); KiwiApp::error("=> " + message); }); - - return; } - - juce::MessageManager::callAsync([this, document]() { - - auto it = m_documents.emplace(m_documents.end(), std::make_unique(*this, std::move(document))); - - m_listeners.call(&Listener::documentAdded, *(it->get())); - m_listeners.call(&Listener::driveChanged); - - (*it)->open(); - }); - + else + { + juce::MessageManager::callAsync([this, document]() { + + auto it = m_documents.emplace(m_documents.end(), + std::make_unique(*this, + std::move(document))); + + m_listeners.call(&Listener::documentAdded, *(it->get())); + m_listeners.call(&Listener::driveChanged); + + (*it)->open(); + }); + } }); - } DocumentBrowser::Drive::DocumentSessions const& DocumentBrowser::Drive::getDocuments() const @@ -269,11 +267,11 @@ namespace kiwi void DocumentBrowser::Drive::refresh() { - KiwiApp::useApi().getDocuments([this](Api::Response res, Api::Error error, Api::Documents docs) { + KiwiApp::useApi().getDocuments([this](Api::Response res, Api::Documents docs) { - if(error) + if(res.error) { - KiwiApp::error("Kiwi API error: can't get documents => " + error.message()); + KiwiApp::error("Kiwi API error: can't get documents => " + res.error.message()); } else { @@ -333,16 +331,15 @@ namespace kiwi return; } - KiwiApp::useApi().renameDocument(m_document._id, new_name, - [](Api::Response res, Api::Error error) { + KiwiApp::useApi().renameDocument(m_document._id, new_name, [](Api::Response res) { - if(!error) + if(!res.error) { - std::cout << "document successfully updated" << '\n'; + std::cout << "document update failed, err: " + res.error.message() << '\n'; } else { - std::cout << "document update failed, err: " + error.message() << '\n'; + std::cout << "document successfully updated\n"; } }); diff --git a/Modules/KiwiNetwork/KiwiHttp/KiwiHttp.h b/Modules/KiwiNetwork/KiwiHttp/KiwiHttp.h new file mode 100644 index 00000000..402b0fb7 --- /dev/null +++ b/Modules/KiwiNetwork/KiwiHttp/KiwiHttp.h @@ -0,0 +1,144 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +namespace kiwi { namespace network { namespace http { + + using Timeout = std::chrono::milliseconds; + using Error = beast::error_code; + + // ================================================================================ // + // RESPONSE // + // ================================================================================ // + + template + class Response : public beast::http::response + { + public: + Error error; + }; + + template + using Request = beast::http::request; + + //! @brief Sends an http request. + //! @details Returns the response generated by the server. The function blocks until response + //! is received or error occurs. + template + static Response + write(std::unique_ptr> request, + std::string port, + Timeout timeout = Timeout(0)); + + //! @brief Sends an http request asynchronously. + //! @details Returns the response generated by the server. The function is non blocking. callback + //! is called on another thread once response is received or error occurs. + template + static std::future + writeAsync(std::unique_ptr> request, + std::string port, + std::function)> callback, + Timeout timeout = Timeout(0)); + + // ================================================================================ // + // QUERY // + // ================================================================================ // + + template + class Query + { + public: // methods + + //! @brief Constructor. + Query(std::unique_ptr> request, + std::string port, + Timeout timeout = Timeout(0)); + + //! @brief Destructor. + ~Query(); + + //! @brief Write the request and get the response. + template + Response writeRequest(); + + private: // methods + + using tcp = boost::asio::ip::tcp; + + //! @internal + void handleTimeout(beast::error_code const& error); + + //! @internal + template + void connect(Response& response, + beast::error_code const& error, + tcp::resolver::iterator iterator); + + //! @internal + template + void write(Response& response, + beast::error_code const& error); + + //! @internal + template + void read(Response& response, + beast::error_code const& error); + + //! @internal + void shutdown(beast::error_code const& error); + + private: // members + + std::unique_ptr> m_request; + Error m_error; + Timeout m_timeout; + + std::string m_port; + boost::asio::io_service m_io_service; + tcp::socket m_socket; + boost::asio::steady_timer m_timer; + beast::flat_buffer m_buffer; + + private: // deleted methods + + Query() = delete; + Query(Query const& other) = delete; + Query(Query && other) = delete; + Query& operator=(Query const& other) = delete; + Query& operator=(Query && other) = delete; + }; + +}}} // namespace kiwi::network::http + +#include "KiwiHttp.hpp" diff --git a/Modules/KiwiNetwork/KiwiHttp/KiwiHttp.hpp b/Modules/KiwiNetwork/KiwiHttp/KiwiHttp.hpp new file mode 100644 index 00000000..870a8d1d --- /dev/null +++ b/Modules/KiwiNetwork/KiwiHttp/KiwiHttp.hpp @@ -0,0 +1,201 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +namespace kiwi { namespace network { namespace http { + + // ================================================================================ // + // HTTP // + // ================================================================================ // + + template + Response + write(std::unique_ptr> request, + std::string port, + Timeout timeout) + { + return Query(std::move(request), port, timeout).template writeRequest(); + } + + template + std::future + writeAsync(std::unique_ptr> request, + std::string port, + std::function)> callback, + Timeout timeout) + { + auto query = std::make_unique>(std::move(request), port, timeout); + + return std::async(std::launch::async, [query = std::move(query), cb = std::move(callback)]() { + + return cb(query->template writeRequest()); + + }); + } + + // ================================================================================ // + // HTTP QUERY // + // ================================================================================ // + + template + Query::Query(std::unique_ptr> request, + std::string port, + Timeout timeout) + : m_request(std::move(request)) + , m_error() + , m_timeout(timeout) + , m_port(port) + , m_io_service() + , m_socket(m_io_service) + , m_timer(m_io_service) + , m_buffer() + { + ; + } + + template + Query::~Query() + { + ; + } + + template + template + Response + Query::writeRequest() + { + if (m_timeout > Timeout(0)) + { + m_timer.expires_from_now(m_timeout); + + m_timer.async_wait([this](boost::system::error_code const& error) { + handleTimeout(error); + }); + } + + tcp::resolver resolver(m_io_service); + + const std::string host = m_request->at(beast::http::field::host).to_string(); + + Response response; + + resolver.async_resolve({host, m_port}, [this, &response](Error const& error, + tcp::resolver::iterator iterator) { + connect(response, error, iterator); + }); + + m_io_service.reset(); + + // block here until error or success + while(!m_error && m_io_service.run_one()) + { + ; + } + + response.error = m_error; + + return std::move(response); + }; + + template + void + Query::handleTimeout(Error const& error) + { + m_io_service.stop(); + + m_socket.shutdown(tcp::socket::shutdown_both, m_error); + m_error = boost::asio::error::basic_errors::timed_out; + } + + template + template + void + Query::connect(Response& response, + Error const& error, + tcp::resolver::iterator iterator) + { + if (error) + { + m_error = error; + } + else + { + boost::asio::async_connect(m_socket, iterator, [this, &response](Error const& error, + tcp::resolver::iterator i) { + this->write(response, error); + }); + } + } + + template + template + void + Query::write(Response& response, + beast::error_code const& error) + { + if (error) + { + m_error = error; + } + else + { + beast::http::async_write(m_socket, *m_request, [this, &response](Error const& error) { + read(response, error); + }); + } + } + + template + template + void + Query::read(Response& response, + Error const& error) + { + if (error) + { + m_error = error; + } + else + { + beast::http::async_read(m_socket, m_buffer, response, [this](Error const& error) { + shutdown(error); + }); + } + } + + template + void + Query::shutdown(Error const& error) + { + m_io_service.stop(); + + if (error) + { + m_error = error; + } + else + { + m_socket.shutdown(tcp::socket::shutdown_both, m_error); + } + } + +}}} // namespace kiwi::network::http diff --git a/Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Session.cpp b/Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Session.cpp new file mode 100644 index 00000000..4eab4cfe --- /dev/null +++ b/Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Session.cpp @@ -0,0 +1,230 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include "KiwiHttp_Session.h" +#include "KiwiHttp_Util.h" + +namespace kiwi { namespace network { namespace http { + + // ================================================================================ // + // HTTP PAYLOAD // + // ================================================================================ // + + Payload::Payload(const std::initializer_list& pairs) + : Payload(begin(pairs), end(pairs)) + { + ; + } + + void Payload::AddPair(const Pair& pair) + { + if(!content.empty()) + { + content += "&"; + } + + auto escaped = util::urlEncode(pair.value); + content += pair.key + "=" + escaped; + } + + // ================================================================================ // + // HTTP PARAMETERS // + // ================================================================================ // + + Parameters::Parameters(std::initializer_list const& parameters) + { + for(auto const& parameter : parameters) + { + AddParameter(parameter); + } + } + + void Parameters::AddParameter(Parameter const& parameter) + { + if (!content.empty()) + { + content += "&"; + } + + auto escapedKey = util::urlEncode(parameter.key); + if (parameter.value.empty()) + { + content += escapedKey; + } + else + { + auto escapedValue = util::urlEncode(parameter.value); + content += escapedKey + "=" + escapedValue; + } + } + + // ================================================================================ // + // BODY // + // ================================================================================ // + + Body::Body(std::string body) + : content(std::move(body)) + { + + } + + // ================================================================================ // + // SESSION // + // ================================================================================ // + + Session::Session() + : m_port("80") + , m_target() + , m_parameters() + , m_payload() + , m_body() + , m_timeout(0) + , m_req_header() + { + ; + } + + void Session::setHost(std::string const& host) + { + m_req_header.set(beast::http::field::host, host); + } + + void Session::setPort(std::string const& port) + { + m_port = port; + } + + void Session::setTarget(std::string const& endpoint) + { + m_target = endpoint; + } + + void Session::setTimeout(Timeout timeout) + { + m_timeout = timeout; + } + + void Session::setParameters(Parameters && parameters) + { + m_parameters = std::move(parameters); + } + + void Session::setPayload(Payload && payload) + { + m_payload = std::move(payload); + } + + Session::Response Session::Get() + { + return makeResponse(beast::http::verb::get); + } + + Session::AsyncResponse Session::GetAsync(Callback callback) + { + return makeResponse(beast::http::verb::get, std::move(callback)); + } + + Session::Response Session::Post() + { + return makeResponse(beast::http::verb::post); + } + + Session::AsyncResponse Session::PostAsync(Callback callback) + { + return makeResponse(beast::http::verb::post, std::move(callback)); + } + + Session::Response Session::Put() + { + return makeResponse(beast::http::verb::put); + } + + Session::AsyncResponse Session::PutAsync(Callback callback) + { + return makeResponse(beast::http::verb::put, std::move(callback)); + } + + Session::Response Session::Delete() + { + return makeResponse(beast::http::verb::delete_); + } + + Session::AsyncResponse Session::DeleteAsync(Callback callback) + { + return makeResponse(beast::http::verb::delete_, std::move(callback)); + } + + std::unique_ptr> Session::makeQuery() + { + const auto makeTarget = [this]() { + + if(!m_parameters.content.empty()) + { + return m_target + "?" + m_parameters.content; + } + + return m_target; + }; + + auto request = std::make_unique>(std::move(m_req_header)); + request->target(makeTarget()); + + if(!(m_req_header.method() == beast::http::verb::get) && + (!m_payload.content.empty() + || !m_body.content.empty())) + { + if(!m_payload.content.empty()) + { + request->set(beast::http::field::content_type, "application/x-www-form-urlencoded"); + request->body = std::move(m_payload.content); + } + else if(!m_body.content.empty()) + { + auto& req = *request; + const auto content_type = req[beast::http::field::content_type]; + if(content_type.empty()) + { + request->set(beast::http::field::content_type, "text/plain"); + } + + request->body = std::move(m_body.content); + } + } + + request->prepare_payload(); + return std::make_unique>(std::move(request), m_port, m_timeout); + } + + Session::Response Session::makeResponse(beast::http::verb verb) + { + m_req_header.method(verb); + return std::move(makeQuery()->writeRequest()); + } + + Session::AsyncResponse Session::makeResponse(beast::http::verb verb, Session::Callback && callback) + { + m_req_header.method(verb); + return std::async(std::launch::async, [query = makeQuery(), cb = std::move(callback)]() { + return cb(std::move(query->writeRequest())); + }); + } + +}}} // namespace kiwi::network::http diff --git a/Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Session.h b/Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Session.h new file mode 100644 index 00000000..a94b0282 --- /dev/null +++ b/Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Session.h @@ -0,0 +1,145 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include "KiwiHttp.h" + +namespace kiwi { namespace network { namespace http { + + // ================================================================================ // + // PAYLOAD // + // ================================================================================ // + + class Payload + { + public: + + struct Pair; + + Payload() = default; + + template + Payload(const It begin, const It end); + + Payload(std::initializer_list const& pairs); + + void AddPair(Pair const& pair); + + std::string content; + }; + + // ================================================================================ // + // PARAMETERS // + // ================================================================================ // + + class Parameters + { + public: + + struct Parameter; + + Parameters() = default; + Parameters(const std::initializer_list& parameters); + + void AddParameter(Parameter const& parameter); + + std::string content; + }; + + struct Parameters::Parameter + { + template + Parameter(KeyType&& key, ValueType&& value); + + std::string key; + std::string value; + }; + + // ================================================================================ // + // BODY // + // ================================================================================ // + + class Body + { + public: + + Body() = default; + Body(std::string body); + + std::string content; + }; + + // ================================================================================ // + // SESSION // + // ================================================================================ // + + class Session + { + public: // methods + + using Response = http::Response; + using AsyncResponse = std::future; + using Callback = std::function; + + Session(); + ~Session() = default; + + void setHost(std::string const& host); + void setPort(std::string const& port); + void setTarget(std::string const& endpoint); + void setTimeout(Timeout timeout); + void setParameters(Parameters && parameters); + void setPayload(Payload && payload); + void setBody(Body && body); + + Response Get(); + AsyncResponse GetAsync(Callback callback); + + Response Post(); + AsyncResponse PostAsync(Callback callback); + + Response Put(); + AsyncResponse PutAsync(Callback callback); + + Response Delete(); + AsyncResponse DeleteAsync(Callback callback); + + private: // variables + + std::unique_ptr> makeQuery(); + + Response makeResponse(beast::http::verb verb); + AsyncResponse makeResponse(beast::http::verb verb, Callback && callback); + + std::string m_port; + std::string m_target; + Parameters m_parameters; + Payload m_payload; + Body m_body; + Timeout m_timeout; + + beast::http::request_header<> m_req_header; + }; + +}}} // namespace kiwi::network::http + +#include "KiwiHttp_Session.hpp" diff --git a/Modules/KiwiNetwork/KiwiNetwork_Http.cpp b/Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Session.hpp similarity index 54% rename from Modules/KiwiNetwork/KiwiNetwork_Http.cpp rename to Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Session.hpp index 1823b659..5fe14030 100644 --- a/Modules/KiwiNetwork/KiwiNetwork_Http.cpp +++ b/Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Session.hpp @@ -19,61 +19,56 @@ ============================================================================== */ -#include "KiwiNetwork_Http.h" -#include "KiwiNetwork_Util.h" +#pragma once -namespace kiwi { namespace network { +namespace kiwi { namespace network { namespace http { // ================================================================================ // - // HTTP PAYLOAD // + // HTTP PAYLOAD // // ================================================================================ // - Http::Payload::Payload(const std::initializer_list& pairs) - : Payload(begin(pairs), end(pairs)) + template + Payload::Payload(const It begin, const It end) { - ; + for (It pair = begin; pair != end; ++pair) + { + AddPair(*pair); + } } - void Http::Payload::AddPair(const Pair& pair) + struct Payload::Pair { - if(!content.empty()) + template ::value, bool>::type = true> + Pair(KeyType&& p_key, ValueType&& p_value) + : key{std::forward(p_key)} + , value{std::forward(p_value)} { - content += "&"; + ; } - auto escaped = util::urlEncode(pair.value); - content += pair.key + "=" + escaped; - } + template + Pair(KeyType&& p_key, const std::int32_t& p_value) + : key{std::forward(p_key)} + , value{std::to_string(p_value)} + { + ; + } + + std::string key; + std::string value; + }; // ================================================================================ // - // HTTP PARAMETERS // + // HTTP PARAMETERS // // ================================================================================ // - Http::Parameters::Parameters(std::initializer_list const& parameters) - { - for(auto const& parameter : parameters) - { - AddParameter(parameter); - } - } - - void Http::Parameters::AddParameter(Parameter const& parameter) + template + Parameters::Parameter::Parameter(KeyType&& key, ValueType&& value) + : key{std::forward(key)} + , value{std::forward(value)} { - if (!content.empty()) - { - content += "&"; - } - - auto escapedKey = util::urlEncode(parameter.key); - if (parameter.value.empty()) - { - content += escapedKey; - } - else - { - auto escapedValue = util::urlEncode(parameter.value); - content += escapedKey + "=" + escapedValue; - } + ; } -}} +}}} // namespace kiwi::network::http diff --git a/Modules/KiwiNetwork/KiwiNetwork_Util.cpp b/Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Util.cpp similarity index 91% rename from Modules/KiwiNetwork/KiwiNetwork_Util.cpp rename to Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Util.cpp index 44d7e5ed..69ff499d 100644 --- a/Modules/KiwiNetwork/KiwiNetwork_Util.cpp +++ b/Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Util.cpp @@ -19,15 +19,15 @@ ============================================================================== */ -#include "KiwiNetwork_Util.h" +#include "KiwiHttp_Util.h" #include #include #include #include -#include +#include -namespace kiwi { namespace network { namespace util { +namespace kiwi { namespace network { namespace http { namespace util { std::string urlEncode(const std::string& value) { std::ostringstream escaped; @@ -49,4 +49,4 @@ namespace kiwi { namespace network { namespace util { } -}}} // namespace kiwi::network::util +}}}} // namespace kiwi::network::http::util diff --git a/Modules/KiwiNetwork/KiwiNetwork_Util.h b/Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Util.h similarity index 89% rename from Modules/KiwiNetwork/KiwiNetwork_Util.h rename to Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Util.h index 52ef7acc..948fbfa6 100644 --- a/Modules/KiwiNetwork/KiwiNetwork_Util.h +++ b/Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Util.h @@ -23,8 +23,8 @@ #include -namespace kiwi { namespace network { namespace util { +namespace kiwi { namespace network { namespace http { namespace util { std::string urlEncode(std::string const& response); -}}} // namespace kiwi::network::util +}}}} // namespace kiwi::network::http::util diff --git a/Modules/KiwiNetwork/KiwiNetwork_Http.h b/Modules/KiwiNetwork/KiwiNetwork_Http.h index f969590c..a577ad47 100644 --- a/Modules/KiwiNetwork/KiwiNetwork_Http.h +++ b/Modules/KiwiNetwork/KiwiNetwork_Http.h @@ -21,196 +21,5 @@ #pragma once -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -namespace kiwi { namespace network { - - using tcp = boost::asio::ip::tcp; - - // ================================================================================ // - // HTTP // - // ================================================================================ // - - class Http - { - public: // methods - - //template - //using Response = beast::http::response; - - template - class Response; - - template - using Request = beast::http::request; - - using Timeout = std::chrono::milliseconds; - - using Error = beast::error_code; - - class Payload; - class Parameters; - - //! @brief Sends an http request. - //! @details Returns the response generated by the server. The function blocks until response - //! is received or error occurs. - template - static Response - write(std::unique_ptr> request, - std::string port, - Error& error, - Timeout timeout = Timeout(0)); - - //! @brief Sends an http request asynchronously. - //! @details Returns the response generated by the server. The function is non blocking. callback - //! is called on another thread once response is received or error occurs. - template - static std::future - writeAsync(std::unique_ptr> request, - std::string port, - std::function, Error)> callback, - Timeout timeout = Timeout(0)); - - private: // nested classes - - template class Query; - - private: // deleted methods - - Http() = delete; - Http(Http const& other) = delete; - Http(Http && other) = delete; - Http& operator=(Http const& other) = delete; - Http& operator=(Http && other) = delete; - }; - - // ================================================================================ // - // HTTP PAYLOAD // - // ================================================================================ // - - class Http::Payload - { - public: - - struct Pair; - - template - Payload(const It begin, const It end); - - Payload(std::initializer_list const& pairs); - - void AddPair(Pair const& pair); - - std::string content; - }; - - // ================================================================================ // - // HTTP PARAMETERS // - // ================================================================================ // - - class Http::Parameters - { - public: - - struct Parameter; - - Parameters() = default; - Parameters(const std::initializer_list& parameters); - - void AddParameter(Parameter const& parameter); - - std::string content; - }; - - struct Http::Parameters::Parameter - { - template - Parameter(KeyType&& key, ValueType&& value); - - std::string key; - std::string value; - }; - - // ================================================================================ // - // HTTP RESPONSE // - // ================================================================================ // - - template - class Http::Response : public beast::http::response - { - public: - }; - - // ================================================================================ // - // HTTP QUERY // - // ================================================================================ // - - template - class Http::Query - { - public: // methods - - //! @brief Constructor. - Query(std::unique_ptr> request, - std::string port, - Http::Timeout timeout = Http::Timeout(0)); - - //! @brief Destructor. - ~Query(); - - //! @brief Write the request and get the response. - Http::Response writeRequest(Http::Error& error); - - private: // methods - - //! @internal - void handleTimeout(beast::error_code const& error); - - //! @internal - void connect(beast::error_code const& error, - tcp::resolver::iterator iterator); - - //! @internal - void write(beast::error_code const& error); - - //! @internal - void read(beast::error_code const& error); - - //! @internal - void shutdown(beast::error_code const& error); - - private: // members - - std::unique_ptr> m_request; - Http::Response m_response; - Http::Error m_error; - Http::Timeout m_timeout; - - std::string m_port; - boost::asio::io_service m_io_service; - tcp::socket m_socket; - boost::asio::steady_timer m_timer; - beast::flat_buffer m_buffer; - - private: // deleted methods - - Query() = delete; - Query(Query const& other) = delete; - Query(Query && other) = delete; - Query& operator=(Query const& other) = delete; - Query& operator=(Query && other) = delete; - }; - -}} // namespace kiwi::network - -#include "KiwiNetwork_Http.hpp" +#include "KiwiHttp/KiwiHttp.h" +#include "KiwiHttp/KiwiHttp_Session.h" diff --git a/Modules/KiwiNetwork/KiwiNetwork_Http.hpp b/Modules/KiwiNetwork/KiwiNetwork_Http.hpp deleted file mode 100644 index 39f36958..00000000 --- a/Modules/KiwiNetwork/KiwiNetwork_Http.hpp +++ /dev/null @@ -1,246 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#pragma once - -namespace kiwi { namespace network { - - // ================================================================================ // - // HTTP // - // ================================================================================ // - - template - Http::Response - Http::write(std::unique_ptr> request, - std::string port, - beast::error_code& error, - Timeout timeout) - { - return Query(std::move(request), port, timeout).writeRequest(error); - } - - template - std::future - Http::writeAsync(std::unique_ptr> request, - std::string port, - std::function response, - Error error)> callback, - Timeout timeout) - { - auto query = std::make_unique>(std::move(request), port, timeout); - - return std::async(std::launch::async, [query = std::move(query), cb = std::move(callback)]() { - - beast::error_code error; - Response response(query->writeRequest(error)); - return cb(std::move(response), error); - - }); - } - - // ================================================================================ // - // HTTP PAYLOAD // - // ================================================================================ // - - template - Http::Payload::Payload(const It begin, const It end) - { - for (It pair = begin; pair != end; ++pair) - { - AddPair(*pair); - } - } - - struct Http::Payload::Pair - { - template ::value, bool>::type = true> - Pair(KeyType&& p_key, ValueType&& p_value) - : key{std::forward(p_key)} - , value{std::forward(p_value)} - { - ; - } - - template - Pair(KeyType&& p_key, const std::int32_t& p_value) - : key{std::forward(p_key)} - , value{std::to_string(p_value)} - { - ; - } - - std::string key; - std::string value; - }; - - // ================================================================================ // - // HTTP PARAMETERS // - // ================================================================================ // - - template - Http::Parameters::Parameter::Parameter(KeyType&& key, ValueType&& value) - : key{std::forward(key)} - , value{std::forward(value)} - { - ; - } - - // ================================================================================ // - // HTTP QUERY // - // ================================================================================ // - - template - Http::Query::Query(std::unique_ptr> request, - std::string port, - Http::Timeout timeout) - : m_request(std::move(request)) - , m_response() - , m_error() - , m_timeout(timeout) - , m_port(port) - , m_io_service() - , m_socket(m_io_service) - , m_timer(m_io_service) - , m_buffer() - { - ; - } - - template - Http::Query::~Query() - { - ; - } - - template - Http::Response - Http::Query::writeRequest(Http::Error& error) - { - if (m_timeout > Http::Timeout(0)) - { - m_timer.expires_from_now(m_timeout); - - m_timer.async_wait([this](boost::system::error_code const& error) { - handleTimeout(error); - }); - } - - tcp::resolver resolver(m_io_service); - - const std::string host = m_request->at(beast::http::field::host).to_string(); - - resolver.async_resolve({host, m_port}, [this](beast::error_code const& error, - tcp::resolver::iterator iterator) { - connect(error, iterator); - }); - - m_io_service.reset(); - - // block here until error or success - while(!m_error && m_io_service.run_one()) - { - ; - } - - error = m_error; - - return m_response; - }; - - template - void - Http::Query::handleTimeout(beast::error_code const& error) - { - m_io_service.stop(); - - m_socket.shutdown(tcp::socket::shutdown_both, m_error); - m_error = boost::asio::error::basic_errors::timed_out; - } - - template - void - Http::Query::connect(beast::error_code const& error, - tcp::resolver::iterator iterator) - { - if (error) - { - m_error = error; - } - else - { - boost::asio::async_connect(m_socket, iterator, [this](beast::error_code const& error, - tcp::resolver::iterator i) { - this->write(error); - }); - } - } - - template - void - Http::Query::write(beast::error_code const& error) - { - if (error) - { - m_error = error; - } - else - { - beast::http::async_write(m_socket, *m_request, [this](beast::error_code const& error) { - read(error); - }); - - } - } - - template - void - Http::Query::read(beast::error_code const& error) - { - if (error) - { - m_error = error; - } - else - { - beast::http::async_read(m_socket, m_buffer, m_response, [this](beast::error_code const& error) { - shutdown(error); - }); - } - } - - template - void - Http::Query::shutdown(beast::error_code const& error) - { - m_io_service.stop(); - - if (error) - { - m_error = error; - } - else - { - m_socket.shutdown(tcp::socket::shutdown_both, m_error); - } - } - -}} // namespace kiwi::network diff --git a/Test/Network/test_Http.cpp b/Test/Network/test_Http.cpp index 3820e4e6..4eb9abd5 100755 --- a/Test/Network/test_Http.cpp +++ b/Test/Network/test_Http.cpp @@ -50,17 +50,17 @@ TEST_CASE("Network - Http", "[Network, Http]") beast::error_code error; // Send request and waits for response. - beast::http::response response = - Http::write(std::move(request), "80", error); + http::Response response = + http::write(std::move(request), "80"); + REQUIRE(!response.error); CHECK(response.result() == beast::http::status::ok); - CHECK(!error); } SECTION("Client asynchronous get request to echo server") { // Construct request and response. - auto request = std::make_unique>(); + auto request = std::make_unique>(); request->method(beast::http::verb::get); request->target("/get"); request->version = 11; @@ -69,39 +69,49 @@ TEST_CASE("Network - Http", "[Network, Http]") request->prepare_payload(); - std::function, Http::Error)> - callback = [](Http::Response response, Http::Error error) + std::function)> + callback = [](http::Response response) { + REQUIRE(!response.error); CHECK(response.result() == beast::http::status::ok); - CHECK(!error); }; - auto future = Http::writeAsync(std::move(request), "80", callback); - + auto future = http::writeAsync(std::move(request), "80", callback); future.get(); } +} + +TEST_CASE("Network - Http Session", "[Network, Http]") +{ + using namespace kiwi::network; - SECTION("Deferred request body") + SECTION("Session GetAsync") { - beast::http::header header; - - header.version = 11; - header.method(beast::http::verb::get); - header.set(beast::http::field::host, "httpbin.org"); - header.target("/get"); - header.set(beast::http::field::user_agent, "KiwiApp - Tests"); + http::Session session; + session.setHost("httpbin.org"); + session.setTarget("/get"); - std::function, Http::Error)> - callback = [](Http::Response response, Http::Error error) - { - REQUIRE_FALSE(error); + auto future = session.GetAsync([](http::Session::Response response) { + REQUIRE(!response.error); CHECK(response.result() == beast::http::status::ok); - }; - - auto future = Http::writeAsync(std::make_unique>(std::move(header)), - "80", - callback); + }); future.get(); } + + SECTION("Session GetAsync with Parameters") + { + http::Session session; + session.setHost("httpbin.org"); + session.setTarget("/get"); + session.setParameters({ + {"foo", "bar bar"}, + {"value", "42"} + }); + + session.GetAsync([](http::Session::Response response) { + REQUIRE(!response.error); + CHECK(response.result() == beast::http::status::ok); + }); + } } From 8bc556608a70f3bb1e9dbf17da4a19979940590d Mon Sep 17 00:00:00 2001 From: eliott PARIS Date: Tue, 22 Aug 2017 12:54:07 +0200 Subject: [PATCH 029/148] Add Authorization header field setting --- Modules/KiwiNetwork/KiwiHttp/KiwiHttp.hpp | 2 +- Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Session.cpp | 5 +++++ Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Session.h | 2 ++ Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Util.cpp | 11 ++++++++--- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/Modules/KiwiNetwork/KiwiHttp/KiwiHttp.hpp b/Modules/KiwiNetwork/KiwiHttp/KiwiHttp.hpp index 870a8d1d..fc1c46b1 100644 --- a/Modules/KiwiNetwork/KiwiHttp/KiwiHttp.hpp +++ b/Modules/KiwiNetwork/KiwiHttp/KiwiHttp.hpp @@ -87,7 +87,7 @@ namespace kiwi { namespace network { namespace http { { m_timer.expires_from_now(m_timeout); - m_timer.async_wait([this](boost::system::error_code const& error) { + m_timer.async_wait([this](Error const& error) { handleTimeout(error); }); } diff --git a/Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Session.cpp b/Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Session.cpp index 4eab4cfe..6105995c 100644 --- a/Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Session.cpp +++ b/Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Session.cpp @@ -122,6 +122,11 @@ namespace kiwi { namespace network { namespace http { m_timeout = timeout; } + void Session::setAuthorization(std::string const& auth) + { + m_req_header.set(beast::http::field::authorization, auth); + } + void Session::setParameters(Parameters && parameters) { m_parameters = std::move(parameters); diff --git a/Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Session.h b/Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Session.h index a94b0282..84b223c7 100644 --- a/Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Session.h +++ b/Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Session.h @@ -107,6 +107,8 @@ namespace kiwi { namespace network { namespace http { void setPort(std::string const& port); void setTarget(std::string const& endpoint); void setTimeout(Timeout timeout); + void setAuthorization(std::string const& auth); + void setParameters(Parameters && parameters); void setPayload(Payload && payload); void setBody(Body && body); diff --git a/Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Util.cpp b/Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Util.cpp index 69ff499d..2ca28735 100644 --- a/Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Util.cpp +++ b/Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Util.cpp @@ -29,18 +29,23 @@ namespace kiwi { namespace network { namespace http { namespace util { - std::string urlEncode(const std::string& value) { + std::string urlEncode(const std::string& value) + { std::ostringstream escaped; escaped.fill('0'); escaped << std::hex; - for (auto i = value.cbegin(), n = value.cend(); i != n; ++i) { + for (auto i = value.cbegin(), n = value.cend(); i != n; ++i) + { std::string::value_type c = (*i); + // Keep alphanumeric and other accepted characters intact - if (std::isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') { + if (std::isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') + { escaped << c; continue; } + // Any other characters are percent-encoded escaped << '%' << std::setw(2) << std::int32_t((unsigned char) c); } From 6e18f3b129aa6ee4804e764b4be8c41a530365b8 Mon Sep 17 00:00:00 2001 From: eliott PARIS Date: Tue, 22 Aug 2017 12:54:51 +0200 Subject: [PATCH 030/148] Add an Api controller --- Client/Source/KiwiApp.cpp | 14 +- Client/Source/KiwiApp.h | 8 + .../KiwiApp_Application/KiwiApp_Instance.cpp | 25 -- .../KiwiApp_Application/KiwiApp_Instance.h | 12 +- .../KiwiApp_Auth/KiwiApp_IdentityManager.cpp | 0 .../KiwiApp_Auth/KiwiApp_IdentityManager.h | 51 ---- .../Source/KiwiApp_Auth/KiwiApp_LoginForm.cpp | 102 ++++---- .../Source/KiwiApp_Auth/KiwiApp_LoginForm.h | 15 +- .../KiwiApp_General/KiwiApp_StoredSettings.h | 2 +- Client/Source/KiwiApp_Network/KiwiApp_Api.cpp | 235 +++++++++++++++--- Client/Source/KiwiApp_Network/KiwiApp_Api.h | 187 +++++++++++--- .../KiwiApp_Network/KiwiApp_ApiController.cpp | 96 +++++++ .../KiwiApp_Network/KiwiApp_ApiController.h | 87 +++++++ .../KiwiApp_DocumentBrowser.cpp | 2 +- 14 files changed, 630 insertions(+), 206 deletions(-) delete mode 100644 Client/Source/KiwiApp_Auth/KiwiApp_IdentityManager.cpp delete mode 100644 Client/Source/KiwiApp_Auth/KiwiApp_IdentityManager.h create mode 100644 Client/Source/KiwiApp_Network/KiwiApp_ApiController.cpp create mode 100644 Client/Source/KiwiApp_Network/KiwiApp_ApiController.h diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index 25a03b9b..ff31a087 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -102,6 +102,9 @@ namespace kiwi m_menu_model.reset(new MainMenuModel()); + m_api_controller.reset(new ApiController()); + m_api.reset(new Api(*m_api_controller)); + m_instance = std::make_unique(); m_command_manager->registerAllCommandsForTarget(this); @@ -131,6 +134,8 @@ namespace kiwi juce::MenuBarModel::setMacMainMenu(nullptr); #endif + m_api.reset(); + m_api_controller.reset(); m_settings.reset(); } @@ -206,12 +211,17 @@ namespace kiwi Instance& KiwiApp::useInstance() { - return *KiwiApp::use().m_instance.get(); + return *KiwiApp::use().m_instance; } Api& KiwiApp::useApi() { - return KiwiApp::use().m_instance->useApi(); + return *KiwiApp::use().m_api; + } + + ApiController& KiwiApp::useApiController() + { + return *KiwiApp::use().m_api_controller; } uint64_t KiwiApp::userID() diff --git a/Client/Source/KiwiApp.h b/Client/Source/KiwiApp.h index 6405c955..26f0f815 100644 --- a/Client/Source/KiwiApp.h +++ b/Client/Source/KiwiApp.h @@ -29,6 +29,8 @@ #include "KiwiApp_Components/KiwiApp_TooltipWindow.h" +#include "KiwiApp_Network/KiwiApp_ApiController.h" + namespace ProjectInfo { const char* const projectName = "Kiwi"; @@ -94,6 +96,9 @@ namespace kiwi //! @brief Get the Api object. static Api& useApi(); + //! @brief Get the Api controller. + static ApiController& useApiController(); + //! @brief Get the current running engine instance. static engine::Instance& useEngineInstance(); @@ -207,6 +212,9 @@ namespace kiwi private: // members + std::unique_ptr m_api_controller; + std::unique_ptr m_api; + std::unique_ptr m_instance; std::unique_ptr m_command_manager; std::unique_ptr m_menu_model; diff --git a/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp b/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp index 9d1d4c0a..81fa312f 100644 --- a/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp +++ b/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp @@ -29,7 +29,6 @@ #include "../KiwiApp_Components/KiwiApp_Window.h" #include "../KiwiApp_Patcher/KiwiApp_PatcherView.h" #include "../KiwiApp_Patcher/KiwiApp_PatcherComponent.h" -#include "../KiwiApp_General/KiwiApp_IDs.h" #include "../KiwiApp_Auth/KiwiApp_LoginForm.h" @@ -45,17 +44,12 @@ namespace kiwi size_t Instance::m_untitled_patcher_index(0); Instance::Instance() : - m_api(nullptr), m_scheduler(), m_instance(std::make_unique()), m_browser(), m_console_history(std::make_shared(m_instance)), m_last_opened_file(juce::File::getSpecialLocation(juce::File::userHomeDirectory)) { - auto& settings = getAppSettings().network(); - m_api.reset(new Api(settings.getHost(), settings.getApiPort())); - settings.addListener(*this); - startTimer(10); std::srand(std::time(0)); m_user_id = std::rand(); @@ -71,29 +65,10 @@ namespace kiwi Instance::~Instance() { - getAppSettings().network().removeListener(*this); closeAllPatcherWindows(); stopTimer(); } - void Instance::networkSettingsChanged(NetworkSettings const& settings, - const juce::Identifier& id) - { - if(id == Ids::host) - { - m_api->setHost(settings.getHost()); - } - else if(id == Ids::api_port) - { - m_api->setPort(settings.getApiPort()); - } - } - - Api& Instance::useApi() - { - return *m_api; - } - void Instance::timerCallback() { m_scheduler.process(); diff --git a/Client/Source/KiwiApp_Application/KiwiApp_Instance.h b/Client/Source/KiwiApp_Application/KiwiApp_Instance.h index eeb5249f..85b1b9af 100644 --- a/Client/Source/KiwiApp_Application/KiwiApp_Instance.h +++ b/Client/Source/KiwiApp_Application/KiwiApp_Instance.h @@ -34,11 +34,8 @@ #include "KiwiApp_BeaconDispatcher.h" #include "../KiwiApp_Patcher/KiwiApp_PatcherManager.h" -#include "../KiwiApp_General/KiwiApp_StoredSettings.h" #include "../KiwiApp_Audio/KiwiApp_DspDeviceManager.h" -#include "../KiwiApp_Network/KiwiApp_Api.h" - namespace kiwi { class PatcherViewWindow; @@ -48,7 +45,7 @@ namespace kiwi // ================================================================================ // //! @brief The Application Instance - class Instance : public juce::Timer, public NetworkSettings::Listener + class Instance : public juce::Timer { public: @@ -67,9 +64,6 @@ namespace kiwi //! @brief create a new patcher window. void newPatcher(); - //! @brief Returns the Api object. - Api& useApi(); - //! @brief Returns the engine::Instance engine::Instance& useEngineInstance(); @@ -129,8 +123,6 @@ namespace kiwi using PatcherManagers = std::vector>; - void networkSettingsChanged(NetworkSettings const&, const juce::Identifier& id) override; - //! @internal get the given patcher manager iterator. PatcherManagers::iterator getPatcherManager(PatcherManager const& manager); @@ -146,8 +138,6 @@ namespace kiwi private: // variables - std::unique_ptr m_api; - engine::Scheduler<> m_scheduler; engine::Instance m_instance; diff --git a/Client/Source/KiwiApp_Auth/KiwiApp_IdentityManager.cpp b/Client/Source/KiwiApp_Auth/KiwiApp_IdentityManager.cpp deleted file mode 100644 index e69de29b..00000000 diff --git a/Client/Source/KiwiApp_Auth/KiwiApp_IdentityManager.h b/Client/Source/KiwiApp_Auth/KiwiApp_IdentityManager.h deleted file mode 100644 index 1e1cfba6..00000000 --- a/Client/Source/KiwiApp_Auth/KiwiApp_IdentityManager.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#pragma once - -namespace kiwi -{ - class IdentityManager - { - public: // methods - - class User; - - IdentityManager(); - ~IdentityManager(); - - void login(); - - private: // variables - }; - - class IdentityManager::User - { - public: // methods - - User(uint64_t user_id); - ~User(); - - private: // variables - - uint64_t m_id; - } -} diff --git a/Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.cpp b/Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.cpp index a11406c6..aa71151c 100644 --- a/Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.cpp +++ b/Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.cpp @@ -106,9 +106,12 @@ namespace kiwi } }; - struct LoginForm::OverlayComp : public juce::Component + class LoginForm::OverlayComp : public juce::Component { - OverlayComp() + public: // methods + + OverlayComp(juce::String message) + : m_message(message) { addAndMakeVisible(spinner); } @@ -125,7 +128,7 @@ namespace kiwi g.setColour(juce::Colours::whitesmoke); g.setFont(22.0f); - g.drawFittedText(TRANS("login..."), getLocalBounds().reduced(20, 0).removeFromTop(proportionOfHeight(0.6f)), juce::Justification::centred, 5); + g.drawFittedText(m_message, getLocalBounds().reduced(20, 0).removeFromTop(proportionOfHeight(0.6f)), juce::Justification::centred, 5); } void resized() override @@ -136,7 +139,10 @@ namespace kiwi spinnerSize, spinnerSize); } + private: // variables + Spinner spinner; + juce::String m_message; JUCE_LEAK_DETECTOR(LoginForm::OverlayComp); }; @@ -258,6 +264,24 @@ namespace kiwi m_password_box.setTextToShowWhenEmpty(TRANS("Password"), labelCol); } + void LoginForm::showOverlay() + { + if(m_overlay == nullptr) + { + addAndMakeVisible(m_overlay = new OverlayComp("login...")); + resized(); + } + } + + void LoginForm::hideOverlay() + { + if(m_overlay) + { + removeChildComponent(m_overlay); + m_overlay.deleteAndZero(); + } + } + void LoginForm::showAlert(std::string const& message, AlertBox::Type type) { const bool was_showing = (m_alert_box != nullptr); @@ -288,6 +312,7 @@ namespace kiwi dismiss(); } + void LoginForm::attemptRegistration() { if(m_overlay == nullptr) @@ -304,56 +329,41 @@ namespace kiwi return; } - addAndMakeVisible(m_overlay = new OverlayComp()); - resized(); + showOverlay(); + + auto success_callback = [this](Api::AuthUser user) + { + KiwiApp::useInstance().useScheduler().schedule([this, user = std::move(user)]() { + + std::cout << "Authenticated !\n"; + std::cout << "User ID: " << user.api_id << "\n"; + + hideOverlay(); + showAlert("Login success, welcome " + user.name + "!", AlertBox::Type::Success); + + //auto& api_controller = KiwiApp::useApiController(); + //api_controller.setAuthUser(user); + + }, std::chrono::milliseconds(500)); + }; - auto callback = [this](Api::Response res) + auto error_callback = [this](Api::Error error) { - KiwiApp::useInstance().useScheduler().schedule([this, res = std::move(res)]() - { - removeChildComponent(m_overlay); - m_overlay.deleteAndZero(); + KiwiApp::useInstance().useScheduler().schedule([this, message = error.getMessage()]() { + + std::cout << "Error: " << message << "\n"; - if(res.error) - { - std::string message = "Error:" + res.error.message(); - std::cout << message << "\n"; - showAlert(message, AlertBox::Type::Error); - return; - } - else - { - auto j = json::parse(res.body); - - if(j.is_object()) - { - if(res.result() == beast::http::status::ok) - { - std::cout << "Authenticated !\n"; - std::cout << "token: " << j["token"] << "\n"; - showAlert("Login success!", AlertBox::Type::Success); - } - else - { - std::cout << "Failed...\n"; - std::string message = "Unknown Error !"; - if(j.count("message")) - { - message = j["message"]; - } - - std::cout << "Error: " << message << "\n"; - showAlert(message, AlertBox::Type::Error); - } - } - } + hideOverlay(); + showAlert(message, AlertBox::Type::Error); }, std::chrono::milliseconds(500)); }; - KiwiApp::useApi().getAuthToken(m_email_box.getText().toStdString(), - m_password_box.getText().toStdString(), - callback); + auto& api = KiwiApp::useApi(); + api.login(m_email_box.getText().toStdString(), + m_password_box.getText().toStdString(), + success_callback, + error_callback); } } diff --git a/Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.h b/Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.h index 37d3ec3d..03e6b738 100644 --- a/Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.h +++ b/Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.h @@ -75,9 +75,8 @@ namespace kiwi //! @brief Destructor. ~LoginForm(); - //! @brief This is called when the form is dismissed (either cancelled or when registration - // succeeds). - //! @details By default it will delete this, but you can override it to do other things. + //! @brief This is called when the form is dismissed + //! @details (either cancelled or when registration succeeds). void dismiss(); private: // methods @@ -91,6 +90,12 @@ namespace kiwi //! @internal lookAndFeelChanged method void lookAndFeelChanged() override; + //! @internal Show overlay + void showOverlay(); + + //! @internal Hide overlay + void hideOverlay(); + void showAlert(std::string const& message, AlertBox::Type type = AlertBox::Type::Error); void buttonClicked(juce::Button*) override; @@ -105,8 +110,8 @@ namespace kiwi juce::Image m_kiwi_app_image; - struct OverlayComp; - friend struct OverlayComp; + class OverlayComp; + friend class OverlayComp; Component::SafePointer m_overlay; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LoginForm) diff --git a/Client/Source/KiwiApp_General/KiwiApp_StoredSettings.h b/Client/Source/KiwiApp_General/KiwiApp_StoredSettings.h index 5bb3e3dc..9134e684 100644 --- a/Client/Source/KiwiApp_General/KiwiApp_StoredSettings.h +++ b/Client/Source/KiwiApp_General/KiwiApp_StoredSettings.h @@ -78,7 +78,7 @@ namespace kiwi //! @brief Destructor. virtual ~Listener() = default; - //! @brief Called when a document session has been added. + //! @brief Called when the network settings has changed. virtual void networkSettingsChanged(NetworkSettings const&, juce::Identifier const&) = 0; }; diff --git a/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp b/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp index 6edcef90..298eacab 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp +++ b/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp @@ -23,57 +23,75 @@ namespace kiwi { - // ================================================================================ // - // API // - // ================================================================================ // + const std::string Api::Endpoint::root = "/api"; + const std::string Api::Endpoint::login {Api::Endpoint::root + "/login"}; + const std::string Api::Endpoint::documents {Api::Endpoint::root + "/documents"}; + const std::string Api::Endpoint::users {Api::Endpoint::root + "/users"}; - Api::Api(std::string const& host, uint16_t port) : - m_host(host), - m_port(port) + std::string Api::Endpoint::document(std::string const& document_id) { - ; + return Api::Endpoint::documents + '/' + document_id; } - Api::~Api() + std::string Api::Endpoint::user(std::string const& user_id) { - + return Api::Endpoint::users + '/' + user_id; } - void Api::setHost(std::string const& host) - { - m_host = host; - } - - std::string const& Api::getHost() const - { - return m_host; - } + // ================================================================================ // + // API // + // ================================================================================ // - void Api::setPort(uint16_t port) noexcept + Api::Api(Api::Controller& controller) : + m_controller(controller) { - m_port = port; + ; } - uint16_t Api::getPort() const noexcept + Api::~Api() { - return m_port; + } // ================================================================================ // // API REQUESTS // // ================================================================================ // - void Api::getAuthToken(std::string const& username, - std::string const& password, - Callback callback) + void Api::login(std::string const& username_or_email, + std::string const& password, + CallbackFn success_cb, + ErrorCallback error_cb) { - auto session = makeSession("/api/login"); + assert(!username_or_email.empty()); + assert(!password.empty()); + + auto session = makeSession(Endpoint::login, false); + session->setPayload({ - {"username", username}, + {"username", username_or_email}, {"password", password} }); - storeFuture(session->GetAsync(std::move(callback))); + auto cb = [success = std::move(success_cb), + fail = std::move(error_cb)](Response res) + { + if (!res.error + && hasJsonHeader(res) + && res.result() == beast::http::status::ok) + { + const auto j = json::parse(res.body); + + if(j.is_object() && j.count("user") && j.count("token")) + { + success({j["user"], j["token"]}); + return; + } + } + + fail(res); + }; + + storeFuture(session->PostAsync(std::move(cb))); } void Api::getDocuments(std::function callback) @@ -98,7 +116,7 @@ namespace kiwi callback(std::move(res), {}); }; - auto session = makeSession("/api/documents"); + auto session = makeSession(Endpoint::documents); storeFuture(session->GetAsync(std::move(cb))); } @@ -124,7 +142,8 @@ namespace kiwi callback(std::move(res), {}); }; - auto session = makeSession("/api/documents"); + auto session = makeSession(Endpoint::documents); + if(!document_name.empty()) { session->setPayload({ @@ -140,7 +159,7 @@ namespace kiwi { assert(!new_name.empty() && "name should not be empty!"); - auto session = makeSession("/api/documents" + document_id); + auto session = makeSession(Endpoint::document(document_id)); session->setPayload({ {"name", new_name} }); @@ -153,13 +172,21 @@ namespace kiwi return (res[beast::http::field::content_type] == "application/json; charset=utf-8"); } - std::unique_ptr Api::makeSession(std::string const& endpoint) + std::unique_ptr Api::makeSession(std::string const& endpoint, bool add_auth) { auto session = std::make_unique(); - session->setHost(m_host); - session->setPort(std::to_string(m_port)); + session->setHost(m_controller.getHost()); + session->setPort(std::to_string(m_controller.getPort())); session->setTarget(endpoint); session->setTimeout(http::Timeout(3000)); + + const AuthUser& user = m_controller.getAuthUser(); + + if(add_auth && !user.token.empty()) + { + session->setAuthorization("JWT " + user.token); + } + return std::move(session); } @@ -177,6 +204,89 @@ namespace kiwi m_pending_requests.emplace_back(std::move(future)); } + // ================================================================================ // + // API ERROR // + // ================================================================================ // + + Api::Error::Error() + : m_status_code(0) + , m_message("Unknown Error") + { + + } + + Api::Error::Error(Api::Response const& response) + : m_status_code(response.result_int()) + , m_message(response.error ? response.error.message() : "Unknown Error") + { + if(!response.error && hasJsonHeader(response)) + { + const auto j = json::parse(response.body); + + if(j.count("message")) + { + m_message = j["message"]; + } + } + } + + unsigned Api::Error::getStatusCode() const + { + return m_status_code; + } + + std::string const& Api::Error::getMessage() const + { + return m_message; + } + + // ================================================================================ // + // API USER // + // ================================================================================ // + + void to_json(json& j, Api::User const& user) + { + std::stringstream converter; + converter << std::hex << user.flip_id; + + j = json{ + {"_id", user.api_id}, + {"flip_id", converter.str()}, + {"username", user.name}, + {"email", user.email} + }; + } + + void from_json(json const& j, Api::User& user) + { + user.api_id = j.count("_id") ? j["_id"].get() : ""; + user.name = j.count("username") ? j["username"].get() : ""; + user.email = j.count("email") ? j["email"].get() : ""; + user.flip_id = 0ul; + + if(j.count("flip_id")) + { + std::stringstream converter(j["flip_id"].get()); + converter >> std::hex >> user.flip_id; + } + } + + // ================================================================================ // + // API AUTH USER // + // ================================================================================ // + + Api::AuthUser::AuthUser(User const& user, std::string const& _token) + : Api::User(user) + , token(_token) + { + ; + } + + bool Api::AuthUser::isValid() const noexcept + { + return (!api_id.empty() && flip_id != 0 && !token.empty()); + } + // ================================================================================ // // API DOCUMENT // // ================================================================================ // @@ -195,8 +305,8 @@ namespace kiwi void from_json(json const& j, Api::Document& doc) { - doc._id = j["_id"].get(); - doc.name = j["name"].get(); + doc._id = j.count("_id") ? j["_id"].get() : ""; + doc.name = j.count("name") ? j["name"].get() : ""; doc.session_id = 0ul; if(j.count("session_id")) @@ -210,4 +320,57 @@ namespace kiwi { return (_id == other_doc._id); } + + // ================================================================================ // + // API CONTROLLER // + // ================================================================================ // + + Api::Controller::Controller() + : Api::Controller("127.0.0.1", 80) + { + ; + } + + Api::Controller::Controller(std::string const& host, uint16_t port) + : m_host(host) + , m_port(port) + , m_auth_user() + { + ; + } + + void Api::Controller::setHost(std::string const& host) + { + m_host = host; + } + + std::string const& Api::Controller::getHost() const + { + return m_host; + } + + void Api::Controller::setPort(uint16_t port) noexcept + { + m_port = port; + } + + uint16_t Api::Controller::getPort() const noexcept + { + return m_port; + } + + bool Api::Controller::isUserLoggedIn() + { + return m_auth_user.isValid(); + } + + Api::AuthUser const& Api::Controller::getAuthUser() const + { + return m_auth_user; + } + + void Api::Controller::logout() + { + m_auth_user.token.clear(); + } } diff --git a/Client/Source/KiwiApp_Network/KiwiApp_Api.h b/Client/Source/KiwiApp_Network/KiwiApp_Api.h index 10e8aedc..509cb444 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_Api.h +++ b/Client/Source/KiwiApp_Network/KiwiApp_Api.h @@ -34,44 +34,48 @@ namespace kiwi // API // // ================================================================================ // - //! @brief An API request handler class. + //! @brief A remote API request handler. + //! @details This class provide helper methods to work with the remote Kiwi REST API. + //! All operations are done asynchronously. class Api { public: // methods + class Controller; + using Session = network::http::Session; using Response = Session::Response; - using Callback = Session::Callback; + class Error; + + template + using CallbackFn = std::function; + + using Callback = CallbackFn; + using ErrorCallback = CallbackFn; - class Document; class User; + class AuthUser; + class Folder; + class Document; using Documents = std::vector; + using Users = std::vector; + + public: // requests //! @brief Constructor - Api(std::string const& host = "127.0.0.1", uint16_t port = 80); + Api(Api::Controller& controller); //! @brief Destructor ~Api(); - //! @brief Set the host. - void setHost(std::string const& host); - - //! @brief Get the host. - std::string const& getHost() const; - - //! @brief Set the port. - void setPort(uint16_t port) noexcept; - - //! @brief Get the port. - uint16_t getPort() const noexcept; - - //! @brief Get the authentication token - //! @param username_or_email user name or email adress + //! @brief Attempt to log the user in. + //! @param username_or_email user name or email address //! @param password password - void getAuthToken(std::string const& username_or_email, - std::string const& password, - Callback callback); + void login(std::string const& username_or_email, + std::string const& password, + CallbackFn success_cb, + ErrorCallback error_cb); //! @brief Make an async API request to get a list of documents void getDocuments(std::function callback); @@ -88,10 +92,22 @@ namespace kiwi private: // methods + //! @brief Kiwi API Endpoints + struct Endpoint + { + static const std::string root; + static const std::string login; + static const std::string documents; + static const std::string users; + + static std::string document(std::string const& document_id); + static std::string user(std::string const& user_id); + }; + //! @internal Make a new session with pre-filled data. - std::unique_ptr makeSession(std::string const& endpoint); + std::unique_ptr makeSession(std::string const& endpoint, bool add_auth = true); - //! @internal Store the async future request in a vector + //! @internal Store the async future response in a vector void storeFuture(std::future && future); //! @internal Check if the response header has a JSON content-type @@ -99,11 +115,8 @@ namespace kiwi private: // variables - std::string m_host; - uint16_t m_port; - std::string m_auth_token; - - std::vector> m_pending_requests; + Api::Controller& m_controller; + std::vector> m_pending_requests; private: // deleted methods @@ -114,6 +127,72 @@ namespace kiwi Api& operator=(Api &&) = delete; }; + // ================================================================================ // + // API ERROR // + // ================================================================================ // + + class Api::Error + { + public: // methods + + Error(); + + Error(Api::Response const& response); + + ~Error() = default; + + unsigned getStatusCode() const; + + std::string const& getMessage() const; + + private: // members + + unsigned m_status_code; + std::string m_message {}; + }; + + // ================================================================================ // + // API USER // + // ================================================================================ // + + class Api::User + { + public: // methods + + User() = default; + virtual ~User() = default; + + std::string api_id {}; + uint64_t flip_id = 0; + std::string name {}; + std::string email {}; + }; + + //! @brief Helper function to convert an Api::User into a json object + void to_json(json& j, Api::User const& user); + + //! @brief Helper function to convert a json object into an Api::User + void from_json(json const& j, Api::User& user); + + // ================================================================================ // + // API AUTH USER // + // ================================================================================ // + + class Api::AuthUser : public Api::User + { + public: // methods + + AuthUser() = default; + + AuthUser(User const& user, std::string const& token); + + ~AuthUser() = default; + + bool isValid() const noexcept; + + std::string token; + }; + // ================================================================================ // // API DOCUMENT // // ================================================================================ // @@ -122,6 +201,8 @@ namespace kiwi { public: + Document() = default; + std::string _id = "0"; std::string name = ""; uint64_t session_id = 0ul; @@ -135,4 +216,54 @@ namespace kiwi //! @brief Helper function to convert a json object into an Api::Document void from_json(json const& j, Api::Document& doc); + + // ================================================================================ // + // API CONTROLLER // + // ================================================================================ // + + class Api::Controller + { + public: // methods + + //! @brief Constructor + Controller(); + + //! @brief Constructor + //! @param remote_host The remote host to connect the client to. + //! @param remote_port The remote port to connect the client to. + Controller(std::string const& remote_host, uint16_t remote_port); + + virtual ~Controller() = default; + + //! @brief Set the host. + void setHost(std::string const& host); + + //! @brief Get the host. + std::string const& getHost() const; + + //! @brief Set the port. + void setPort(uint16_t port) noexcept; + + //! @brief Get the port. + uint16_t getPort() const noexcept; + + //! @brief Returns true if the current client api user is logged in. + //! @see logout + bool isUserLoggedIn(); + + //! @brief Returns the authenticated user + Api::AuthUser const& getAuthUser() const; + + //! @brief Log-out the authenticated user. + //! @details This will clear the stored token. + //! The client will need to login again after this function call to perform authenticated request. + //! @see login, isUserLoggedIn + virtual void logout(); + + private: // variables + + std::string m_host; + uint16_t m_port; + Api::AuthUser m_auth_user; + }; } diff --git a/Client/Source/KiwiApp_Network/KiwiApp_ApiController.cpp b/Client/Source/KiwiApp_Network/KiwiApp_ApiController.cpp new file mode 100644 index 00000000..bf08f382 --- /dev/null +++ b/Client/Source/KiwiApp_Network/KiwiApp_ApiController.cpp @@ -0,0 +1,96 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include "KiwiApp_ApiController.h" +#include "../KiwiApp_General/KiwiApp_IDs.h" + +namespace kiwi +{ + ApiController::ApiController() + { + auto& network_settings = getAppSettings().network(); + + setHost(network_settings.getHost()); + setPort(network_settings.getApiPort()); + + network_settings.addListener(*this); + } + + ApiController::~ApiController() + { + getAppSettings().network().removeListener(*this); + } + + void ApiController::networkSettingsChanged(NetworkSettings const& settings, + const juce::Identifier& id) + { + if(id == Ids::host) + { + setHost(settings.getHost()); + } + else if(id == Ids::api_port) + { + setPort(settings.getApiPort()); + } + } + + void ApiController::addListener(Listener& listener) + { + m_listeners.add(listener); + } + + void ApiController::removeListener(Listener& listener) + { + m_listeners.remove(listener); + } + + void ApiController::askUserToLogin(std::string const& message) + { + ; // todo + } + + void ApiController::closeLoginForm() + { + ; // todo + } + + void ApiController::login(std::string const& name_or_email, + std::string const& password) + { + m_listeners.call(&ApiController::Listener::AuthUserChanged, getAuthUser()); + } + + void ApiController::logout() + { + Api::Controller::logout(); + m_listeners.call(&ApiController::Listener::AuthUserChanged, getAuthUser()); + } + + void ApiController::restoreFromXml() + { + + } + + void ApiController::saveToXml() + { + + } +} diff --git a/Client/Source/KiwiApp_Network/KiwiApp_ApiController.h b/Client/Source/KiwiApp_Network/KiwiApp_ApiController.h new file mode 100644 index 00000000..cda2ee9e --- /dev/null +++ b/Client/Source/KiwiApp_Network/KiwiApp_ApiController.h @@ -0,0 +1,87 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +#include + +#include "../KiwiApp_Network/KiwiApp_Api.h" +#include "../KiwiApp_General/KiwiApp_StoredSettings.h" + +#include "../KiwiApp_Auth/KiwiApp_LoginForm.h" + +#include + +namespace kiwi +{ + class ApiController + : public Api::Controller + , private NetworkSettings::Listener + { + public: // nested classes + + struct Listener + { + virtual ~Listener() {} + virtual void AuthUserChanged(Api::AuthUser const&) = 0; + }; + + public: // methods + + //! @brief Constructor + ApiController(); + + //! @brief Destructor + ~ApiController(); + + void addListener(Listener& listener); + void removeListener(Listener& listener); + + void askUserToLogin(std::string const& message = ""); + + void closeLoginForm(); + + //! @brief Attempt to log the client api user in (Async). + //! @param name_or_email The name or email of the user. + //! @param password The user password. + //! @see logout, isUserLoggedIn + void login(std::string const& name_or_email, + std::string const& password); + + //! @brief Log the client api user out. + //! @see login, isUserLoggedIn + void logout() override; + + void restoreFromXml(); + void saveToXml(); + + private: // methods + + //! @brief Called when the network settings has changed. + void networkSettingsChanged(NetworkSettings const&, juce::Identifier const&) override; + + private: // variables + + engine::Listeners m_listeners; + }; +} diff --git a/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp b/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp index 86d6f2a0..de6a0b0d 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp +++ b/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp @@ -306,7 +306,7 @@ namespace kiwi std::string DocumentBrowser::Drive::DocumentSession::getHost() const { - return KiwiApp::useApi().getHost(); + return KiwiApp::useApiController().getHost(); } uint64_t DocumentBrowser::Drive::DocumentSession::getSessionId() const From 75364dbaf9216597b29abda56fa28673701940dc Mon Sep 17 00:00:00 2001 From: eliott PARIS Date: Wed, 23 Aug 2017 20:09:50 +0200 Subject: [PATCH 031/148] Add an Account menu --- Client/Source/KiwiApp.cpp | 70 +++++++++++++------ Client/Source/KiwiApp.h | 1 + .../KiwiApp_Application/KiwiApp_Instance.cpp | 11 ++- .../KiwiApp_Application/KiwiApp_Instance.h | 3 + .../KiwiApp_General/KiwiApp_CommandIDs.h | 3 +- 5 files changed, 65 insertions(+), 23 deletions(-) diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index ff31a087..86d1b44b 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -112,9 +112,6 @@ namespace kiwi juce::PopupMenu macMainMenuPopup; macMainMenuPopup.addCommandItem(&getCommandManager(), CommandIDs::showAboutAppWindow); macMainMenuPopup.addSeparator(); - macMainMenuPopup.addCommandItem(&getCommandManager(), CommandIDs::login); - macMainMenuPopup.addCommandItem(&getCommandManager(), CommandIDs::logout); - macMainMenuPopup.addSeparator(); macMainMenuPopup.addCommandItem(&getCommandManager(), CommandIDs::showAppSettingsWindow); juce::MenuBarModel::setMacMainMenu(m_menu_model.get(), &macMainMenuPopup, TRANS("Open Recent")); #endif @@ -338,7 +335,7 @@ namespace kiwi { const char* const names[] = { - "File", "Edit", "View", "Options", "Window", "Help", nullptr + "Account", "File", "Edit", "View", "Options", "Window", "Help", nullptr }; return juce::StringArray(names); @@ -346,12 +343,13 @@ namespace kiwi void KiwiApp::createMenu(juce::PopupMenu& menu, const juce::String& menuName) { - if (menuName == "File") createFileMenu (menu); - else if (menuName == "Edit") createEditMenu (menu); - else if (menuName == "View") createViewMenu (menu); - else if (menuName == "Options") createOptionsMenu (menu); - else if (menuName == "Window") createWindowMenu (menu); - else if (menuName == "Help") createHelpMenu (menu); + if (menuName == "Account") createAccountMenu (menu); + else if (menuName == "File") createFileMenu (menu); + else if (menuName == "Edit") createEditMenu (menu); + else if (menuName == "View") createViewMenu (menu); + else if (menuName == "Options") createOptionsMenu (menu); + else if (menuName == "Window") createWindowMenu (menu); + else if (menuName == "Help") createHelpMenu (menu); else assert(false); // names have changed? } @@ -361,6 +359,14 @@ namespace kiwi } + void KiwiApp::createAccountMenu(juce::PopupMenu& menu) + { + menu.addCommandItem(&getCommandManager(), CommandIDs::login); + menu.addCommandItem(&getCommandManager(), CommandIDs::signin); + menu.addSeparator(); + menu.addCommandItem(&getCommandManager(), CommandIDs::logout); + } + void KiwiApp::createFileMenu(juce::PopupMenu& menu) { menu.addCommandItem(m_command_manager.get(), CommandIDs::newPatcher); @@ -438,7 +444,6 @@ namespace kiwi { #if ! JUCE_MAC menu.addCommandItem(m_command_manager.get(), CommandIDs::showAboutAppWindow); - menu.addCommandItem(m_command_manager.get(), CommandIDs::login); #endif } @@ -467,6 +472,7 @@ namespace kiwi CommandIDs::startDsp, CommandIDs::stopDsp, CommandIDs::login, + CommandIDs::signin, CommandIDs::logout, }; @@ -503,14 +509,30 @@ namespace kiwi } case CommandIDs::login: { - result.setInfo(TRANS("Login"), TRANS("Show the \"Login form\" Window"), + const bool logged = m_api_controller->isUserLoggedIn(); + result.setInfo(logged + ? juce::String(TRANS("Logged-in as ") + m_api_controller->getAuthUser().name) + : TRANS("Login"), + TRANS("Show the \"Login form\" Window"), + CommandCategories::windows, 0); + + result.setActive(!logged); + break; + } + case CommandIDs::signin: + { + result.setInfo(TRANS("Register"), TRANS("Show the \"Register form\" Window"), CommandCategories::windows, 0); + + result.setActive(!m_api_controller->isUserLoggedIn()); break; } case CommandIDs::logout: { result.setInfo(TRANS("Logout"), TRANS("Log out current user"), CommandCategories::windows, 0); + + result.setActive(m_api_controller->isUserLoggedIn()); break; } case CommandIDs::showAboutAppWindow: @@ -575,15 +597,17 @@ namespace kiwi break; } + case juce::StandardApplicationCommandIDs::quit: + { + result.setInfo(TRANS("Quit Kiwi"), TRANS("Quits the application"), + CommandCategories::general, 0); + + result.addDefaultKeypress('q', juce::ModifierKeys::commandModifier); + break; + } default: { - if(commandID == juce::StandardApplicationCommandIDs::quit) - { - result.setInfo(TRANS("Quit Kiwi"), TRANS("Quits the application"), - CommandCategories::general, 0); - - result.addDefaultKeypress('q', juce::ModifierKeys::commandModifier); - } + break; } } } @@ -607,10 +631,14 @@ namespace kiwi m_instance->showLoginWindow(); break; } + case CommandIDs::signin: + { + m_instance->showLoginWindow(); + break; + } case CommandIDs::logout: { - //m_instance->showConsoleWindow(); - std::cout << "CommandIDs::logout: todo ! \n"; + m_api_controller->logout(); break; } case CommandIDs::showConsoleWindow : diff --git a/Client/Source/KiwiApp.h b/Client/Source/KiwiApp.h index 26f0f815..a0b666d9 100644 --- a/Client/Source/KiwiApp.h +++ b/Client/Source/KiwiApp.h @@ -159,6 +159,7 @@ namespace kiwi //! @brief Called by createMenu to create each menu void createOpenRecentPatchersMenu(juce::PopupMenu& menu); + void createAccountMenu(juce::PopupMenu& menu); void createFileMenu(juce::PopupMenu& menu); void createEditMenu(juce::PopupMenu& menu); void createViewMenu(juce::PopupMenu& menu); diff --git a/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp b/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp index 81fa312f..34cf0f8f 100644 --- a/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp +++ b/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp @@ -221,6 +221,15 @@ namespace kiwi #endif } + void Instance::closeWindowWithId(WindowId window_id) + { + auto& window_uptr = m_windows[std::size_t(window_id)]; + if(!window_uptr) + { + closeWindow(*window_uptr); + } + } + bool Instance::closeAllPatcherWindows() { bool success = true; @@ -319,7 +328,7 @@ namespace kiwi void Instance::showLoginWindow() { - showWindowWithId(WindowId::Login, []() { + showWindowWithId(WindowId::AuthForm, []() { auto login_window = std::make_unique("Log-in to Kiwi", std::make_unique(), diff --git a/Client/Source/KiwiApp_Application/KiwiApp_Instance.h b/Client/Source/KiwiApp_Application/KiwiApp_Instance.h index 85b1b9af..0d443aed 100644 --- a/Client/Source/KiwiApp_Application/KiwiApp_Instance.h +++ b/Client/Source/KiwiApp_Application/KiwiApp_Instance.h @@ -85,6 +85,9 @@ namespace kiwi //! @brief Attempt to close the given window asking user to save file if needed. void closeWindow(Window& window); + //! @brief Attempt to close the window with the given id, asking user to save file if needed. + void closeWindowWithId(WindowId window_id); + //! @brief Attempt to close all document, after asking user to save them if needed. //! @return True if all document have been closed, false if the user cancel the action. bool closeAllPatcherWindows(); diff --git a/Client/Source/KiwiApp_General/KiwiApp_CommandIDs.h b/Client/Source/KiwiApp_General/KiwiApp_CommandIDs.h index 9e7973ac..39c62210 100644 --- a/Client/Source/KiwiApp_General/KiwiApp_CommandIDs.h +++ b/Client/Source/KiwiApp_General/KiwiApp_CommandIDs.h @@ -89,7 +89,8 @@ namespace kiwi clearAll = 0xf40001, ///< Clear all content login = 0xf50000, ///< Log-in the user. - logout = 0xf50010, ///< Log-out the user. + signin = 0xf50010, ///< Sign-in the user. + logout = 0xf50020, ///< Log-out the user. }; // ================================================================================ // From 1c36fffe46b8ae8c1514dd87e840150e38ef00af Mon Sep 17 00:00:00 2001 From: eliott PARIS Date: Wed, 23 Aug 2017 20:16:04 +0200 Subject: [PATCH 032/148] Update API::User class and login process --- .../Source/KiwiApp_Auth/KiwiApp_LoginForm.cpp | 43 +++++++++++-------- .../KiwiApp_Components/KiwiApp_Window.cpp | 7 ++- .../KiwiApp_Components/KiwiApp_Window.h | 5 ++- Client/Source/KiwiApp_Network/KiwiApp_Api.cpp | 19 +++----- Client/Source/KiwiApp_Network/KiwiApp_Api.h | 13 +++--- .../KiwiApp_Network/KiwiApp_ApiController.cpp | 40 +++++++++++------ .../KiwiApp_Network/KiwiApp_ApiController.h | 21 ++++----- 7 files changed, 86 insertions(+), 62 deletions(-) diff --git a/Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.cpp b/Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.cpp index aa71151c..072bf01c 100644 --- a/Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.cpp +++ b/Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.cpp @@ -128,7 +128,10 @@ namespace kiwi g.setColour(juce::Colours::whitesmoke); g.setFont(22.0f); - g.drawFittedText(m_message, getLocalBounds().reduced(20, 0).removeFromTop(proportionOfHeight(0.6f)), juce::Justification::centred, 5); + g.drawFittedText(m_message, + getLocalBounds().reduced(20, 0) + .removeFromTop(proportionOfHeight(0.6f)), + juce::Justification::centred, 5); } void resized() override @@ -299,17 +302,25 @@ namespace kiwi addAndMakeVisible(*m_alert_box); if(!was_showing) + { setBounds(getBounds().withHeight(getHeight() + 50)); + } else + { resized(); + } } void LoginForm::buttonClicked(juce::Button* b) { if(b == &m_submit_btn) + { attemptRegistration(); + } else if(b == &m_cancel_btn) + { dismiss(); + } } @@ -331,19 +342,10 @@ namespace kiwi showOverlay(); - auto success_callback = [this](Api::AuthUser user) + auto success_callback = [this]() { - KiwiApp::useInstance().useScheduler().schedule([this, user = std::move(user)]() { - - std::cout << "Authenticated !\n"; - std::cout << "User ID: " << user.api_id << "\n"; - - hideOverlay(); - showAlert("Login success, welcome " + user.name + "!", AlertBox::Type::Success); - - //auto& api_controller = KiwiApp::useApiController(); - //api_controller.setAuthUser(user); - + KiwiApp::useInstance().useScheduler().schedule([this]() { + dismiss(); }, std::chrono::milliseconds(500)); }; @@ -359,16 +361,19 @@ namespace kiwi }, std::chrono::milliseconds(500)); }; - auto& api = KiwiApp::useApi(); - api.login(m_email_box.getText().toStdString(), - m_password_box.getText().toStdString(), - success_callback, - error_callback); + auto& api_controller = KiwiApp::useApiController(); + api_controller.login(m_email_box.getText().toStdString(), + m_password_box.getText().toStdString(), + success_callback, + error_callback); } } void LoginForm::dismiss() { - delete this; + if(Window* parent_window = findParentComponentOfClass()) + { + parent_window->close(); + } } } diff --git a/Client/Source/KiwiApp_Components/KiwiApp_Window.cpp b/Client/Source/KiwiApp_Components/KiwiApp_Window.cpp index a232b401..aad7dd61 100644 --- a/Client/Source/KiwiApp_Components/KiwiApp_Window.cpp +++ b/Client/Source/KiwiApp_Components/KiwiApp_Window.cpp @@ -112,11 +112,16 @@ namespace kiwi return m_is_main_window; } - void Window::closeButtonPressed() + void Window::close() { KiwiApp::use().closeWindow(*this); } + void Window::closeButtonPressed() + { + close(); + } + // ================================================================================ // // APPLICATION COMMAND TARGET // // ================================================================================ // diff --git a/Client/Source/KiwiApp_Components/KiwiApp_Window.h b/Client/Source/KiwiApp_Components/KiwiApp_Window.h index 1d5c0fde..616f543d 100644 --- a/Client/Source/KiwiApp_Components/KiwiApp_Window.h +++ b/Client/Source/KiwiApp_Components/KiwiApp_Window.h @@ -69,6 +69,9 @@ namespace kiwi //! @see restoreWindowState void saveWindowState(); + //! @brief Close the window. + void close(); + // ================================================================================ // // APPLICATION COMMAND TARGET // // ================================================================================ // @@ -94,7 +97,7 @@ namespace kiwi enum class WindowId : std::size_t { Console = 0, - Login, + AuthForm, AboutKiwi, DocumentBrowser, ApplicationSettings, diff --git a/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp b/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp index 298eacab..9adbd82d 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp +++ b/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp @@ -246,12 +246,9 @@ namespace kiwi void to_json(json& j, Api::User const& user) { - std::stringstream converter; - converter << std::hex << user.flip_id; - j = json{ - {"_id", user.api_id}, - {"flip_id", converter.str()}, + {"__v", user.api_version}, + {"_id", user._id}, {"username", user.name}, {"email", user.email} }; @@ -259,16 +256,10 @@ namespace kiwi void from_json(json const& j, Api::User& user) { - user.api_id = j.count("_id") ? j["_id"].get() : ""; + user.api_version = j.count("__v") ? j["__v"].get() : 0; + user._id = j.count("_id") ? j["_id"].get() : ""; user.name = j.count("username") ? j["username"].get() : ""; user.email = j.count("email") ? j["email"].get() : ""; - user.flip_id = 0ul; - - if(j.count("flip_id")) - { - std::stringstream converter(j["flip_id"].get()); - converter >> std::hex >> user.flip_id; - } } // ================================================================================ // @@ -284,7 +275,7 @@ namespace kiwi bool Api::AuthUser::isValid() const noexcept { - return (!api_id.empty() && flip_id != 0 && !token.empty()); + return (!_id.empty() && !token.empty()); } // ================================================================================ // diff --git a/Client/Source/KiwiApp_Network/KiwiApp_Api.h b/Client/Source/KiwiApp_Network/KiwiApp_Api.h index 509cb444..bc27e851 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_Api.h +++ b/Client/Source/KiwiApp_Network/KiwiApp_Api.h @@ -61,7 +61,7 @@ namespace kiwi using Documents = std::vector; using Users = std::vector; - public: // requests + public: // methods //! @brief Constructor Api(Api::Controller& controller); @@ -69,6 +69,8 @@ namespace kiwi //! @brief Destructor ~Api(); + public: // requests + //! @brief Attempt to log the user in. //! @param username_or_email user name or email address //! @param password password @@ -87,7 +89,8 @@ namespace kiwi //! @brief Rename a document asynchronously. //! @param callback The callback method that will be called when the request is completed. - void renameDocument(std::string document_id, std::string const& new_name, + void renameDocument(std::string document_id, + std::string const& new_name, Callback callback); private: // methods @@ -162,8 +165,8 @@ namespace kiwi User() = default; virtual ~User() = default; - std::string api_id {}; - uint64_t flip_id = 0; + int api_version = 0; + std::string _id {}; std::string name {}; std::string email {}; }; @@ -260,7 +263,7 @@ namespace kiwi //! @see login, isUserLoggedIn virtual void logout(); - private: // variables + protected: // variables std::string m_host; uint16_t m_port; diff --git a/Client/Source/KiwiApp_Network/KiwiApp_ApiController.cpp b/Client/Source/KiwiApp_Network/KiwiApp_ApiController.cpp index bf08f382..43cc11be 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_ApiController.cpp +++ b/Client/Source/KiwiApp_Network/KiwiApp_ApiController.cpp @@ -20,8 +20,11 @@ */ #include "KiwiApp_ApiController.h" + #include "../KiwiApp_General/KiwiApp_IDs.h" +#include "../KiwiApp.h" + namespace kiwi { ApiController::ApiController() @@ -62,20 +65,33 @@ namespace kiwi m_listeners.remove(listener); } - void ApiController::askUserToLogin(std::string const& message) - { - ; // todo - } - - void ApiController::closeLoginForm() - { - ; // todo - } - void ApiController::login(std::string const& name_or_email, - std::string const& password) + std::string const& password, + std::function success_cb, + Api::ErrorCallback error_callback) { - m_listeners.call(&ApiController::Listener::AuthUserChanged, getAuthUser()); + auto success_callback = [this, success_cb = std::move(success_cb)](Api::AuthUser user) + { + std::cout << "User " << user._id << " Authenticated !\n"; + + KiwiApp::useInstance().useScheduler().schedule([this, success_cb = std::move(success_cb), user = std::move(user)]() { + + m_auth_user = std::move(user); + m_listeners.call(&ApiController::Listener::AuthUserChanged, getAuthUser()); + + std::cout << "is logged in : " << m_auth_user.isValid() << std::endl; + + KiwiApp::commandStatusChanged(); + + success_cb(); + + }); + }; + + auto& api = KiwiApp::useApi(); + api.login(name_or_email, password, + success_callback, + std::move(error_callback)); } void ApiController::logout() diff --git a/Client/Source/KiwiApp_Network/KiwiApp_ApiController.h b/Client/Source/KiwiApp_Network/KiwiApp_ApiController.h index cda2ee9e..385879f1 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_ApiController.h +++ b/Client/Source/KiwiApp_Network/KiwiApp_ApiController.h @@ -21,17 +21,14 @@ #pragma once -#include +#include -#include +#include #include "../KiwiApp_Network/KiwiApp_Api.h" #include "../KiwiApp_General/KiwiApp_StoredSettings.h" - #include "../KiwiApp_Auth/KiwiApp_LoginForm.h" -#include - namespace kiwi { class ApiController @@ -54,25 +51,29 @@ namespace kiwi //! @brief Destructor ~ApiController(); + //! @brief Adds a listener. void addListener(Listener& listener); - void removeListener(Listener& listener); - - void askUserToLogin(std::string const& message = ""); - void closeLoginForm(); + //! @brief Removes a listener. + void removeListener(Listener& listener); //! @brief Attempt to log the client api user in (Async). //! @param name_or_email The name or email of the user. //! @param password The user password. //! @see logout, isUserLoggedIn void login(std::string const& name_or_email, - std::string const& password); + std::string const& password, + std::function success_callback, + Api::ErrorCallback error_callback); //! @brief Log the client api user out. //! @see login, isUserLoggedIn void logout() override; + //! @brief Restore the controller state. void restoreFromXml(); + + //! @brief Save the controller state. void saveToXml(); private: // methods From 0ff4ff9a8fedf68337f0e8b2cfa62625fde53e43 Mon Sep 17 00:00:00 2001 From: eliott PARIS Date: Thu, 24 Aug 2017 13:25:32 +0200 Subject: [PATCH 033/148] Ask the user to confirm on logout and close all patchers relative to this user account --- CMakeLists.txt | 1 + Client/Source/KiwiApp.cpp | 30 +++++++++++--- Client/Source/KiwiApp.h | 16 +++++++- .../KiwiApp_Application/KiwiApp_Instance.cpp | 41 +++++++++++++++---- .../KiwiApp_Application/KiwiApp_Instance.h | 7 ++-- .../Source/KiwiApp_Auth/KiwiApp_LoginForm.cpp | 11 +++-- Client/Source/KiwiApp_Network/KiwiApp_Api.cpp | 24 ++++++++--- Client/Source/KiwiApp_Network/KiwiApp_Api.h | 16 +++++--- .../KiwiApp_Network/KiwiApp_ApiController.cpp | 23 +++++------ .../KiwiApp_Network/KiwiApp_ApiController.h | 5 ++- .../KiwiApp_DocumentBrowser.cpp | 10 ----- .../KiwiApp_Network/KiwiApp_DocumentBrowser.h | 6 --- .../KiwiApp_PatcherManager.cpp | 29 ++++--------- 13 files changed, 135 insertions(+), 84 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 705c24c2..6e9856ac 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -131,6 +131,7 @@ endif() if (WIN32) add_definitions("-D_CPPUNWIND") + add_definitions("-D_WIN32_WINNT=0x0501") if (DEBUG) add_definitions("-D_CONSOLE=1") diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index 86d1b44b..d953bc03 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -216,13 +216,31 @@ namespace kiwi return *KiwiApp::use().m_api; } - ApiController& KiwiApp::useApiController() + void KiwiApp::login(std::string const& name_or_email, + std::string const& password, + std::function success_callback, + Api::ErrorCallback error_callback) { - return *KiwiApp::use().m_api_controller; + auto& api_controller = *KiwiApp::use().m_api_controller; + api_controller.login(name_or_email, password, std::move(success_callback), std::move(error_callback)); + } + + Api::AuthUser const& KiwiApp::getCurrentUser() + { + return KiwiApp::use().m_api_controller->getAuthUser(); + } + + void KiwiApp::logout() + { + if(useInstance().logout()) + { + KiwiApp::use().m_api_controller->logout(); + } } uint64_t KiwiApp::userID() { + // refactor this (maybe a useless method) return KiwiApp::use().m_instance->getUserId(); } @@ -575,7 +593,7 @@ namespace kiwi result.setInfo(TRANS("Switch global DSP state"), TRANS("Switch global DSP state"), CommandCategories::general, 0); - result.setTicked(m_instance->getEngineInstance().getAudioControler().isAudioOn()); + result.setTicked(m_instance->useEngineInstance().getAudioControler().isAudioOn()); break; } @@ -584,7 +602,7 @@ namespace kiwi result.setInfo(TRANS("Start dsp"), TRANS("Start dsp"), CommandCategories::general, 0); - result.setActive(!m_instance->getEngineInstance().getAudioControler().isAudioOn()); + result.setActive(!m_instance->useEngineInstance().getAudioControler().isAudioOn()); break; } @@ -593,7 +611,7 @@ namespace kiwi result.setInfo(TRANS("Stop dsp"), TRANS("Stop dsp"), CommandCategories::general, 0); - result.setActive(m_instance->getEngineInstance().getAudioControler().isAudioOn()); + result.setActive(m_instance->useEngineInstance().getAudioControler().isAudioOn()); break; } @@ -638,7 +656,7 @@ namespace kiwi } case CommandIDs::logout: { - m_api_controller->logout(); + logout(); break; } case CommandIDs::showConsoleWindow : diff --git a/Client/Source/KiwiApp.h b/Client/Source/KiwiApp.h index a0b666d9..2a996648 100644 --- a/Client/Source/KiwiApp.h +++ b/Client/Source/KiwiApp.h @@ -96,8 +96,20 @@ namespace kiwi //! @brief Get the Api object. static Api& useApi(); - //! @brief Get the Api controller. - static ApiController& useApiController(); + //! @brief Attempt to log the client api user in (Async). + //! @param name_or_email The name or email of the user. + //! @param password The user password. + //! @see logout, getCurrentUser + static void login(std::string const& name_or_email, + std::string const& password, + std::function success_callback, + Api::ErrorCallback error_callback); + + //! @brief Returns the current user + static Api::AuthUser const& getCurrentUser(); + + //! @brief Log-out the user + static void logout(); //! @brief Get the current running engine instance. static engine::Instance& useEngineInstance(); diff --git a/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp b/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp index 34cf0f8f..c26f0b7a 100644 --- a/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp +++ b/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp @@ -32,9 +32,6 @@ #include "../KiwiApp_Auth/KiwiApp_LoginForm.h" -#include -#include - namespace kiwi { // ================================================================================ // @@ -51,8 +48,6 @@ namespace kiwi m_last_opened_file(juce::File::getSpecialLocation(juce::File::userHomeDirectory)) { startTimer(10); - std::srand(std::time(0)); - m_user_id = std::rand(); // reserve space for singleton windows. m_windows.resize(std::size_t(WindowId::count)); @@ -76,7 +71,39 @@ namespace kiwi uint64_t Instance::getUserId() const noexcept { - return m_user_id; + const auto& user = KiwiApp::getCurrentUser(); + return user.isLoggedIn() ? user.getIdAsInt() : flip::Ref::User::Offline; + } + + bool Instance::logout() + { + bool user_agreed = false; + + for(auto it = m_patcher_managers.begin(); it != m_patcher_managers.end();) + { + auto& manager = *it->get(); + if(manager.isRemote()) + { + if(!user_agreed) + { + user_agreed = juce::AlertWindow::showOkCancelBox(juce::AlertWindow::WarningIcon, + TRANS("Are you about to logout."), + TRANS("All patchers connected to this account will be closed...")); + + if(!user_agreed) + return false; + } + + manager.forceCloseAllWindows(); + it = m_patcher_managers.erase(it); + } + else + { + it++; + } + } + + return true; } engine::Instance& Instance::useEngineInstance() @@ -84,7 +111,7 @@ namespace kiwi return m_instance; } - engine::Instance const& Instance::getEngineInstance() const + engine::Instance const& Instance::useEngineInstance() const { return m_instance; } diff --git a/Client/Source/KiwiApp_Application/KiwiApp_Instance.h b/Client/Source/KiwiApp_Application/KiwiApp_Instance.h index 0d443aed..643ecbb8 100644 --- a/Client/Source/KiwiApp_Application/KiwiApp_Instance.h +++ b/Client/Source/KiwiApp_Application/KiwiApp_Instance.h @@ -61,6 +61,9 @@ namespace kiwi //! @brief Get the user ID of the Instance. uint64_t getUserId() const noexcept; + //! @brief Close all remote patchers. + bool logout(); + //! @brief create a new patcher window. void newPatcher(); @@ -68,7 +71,7 @@ namespace kiwi engine::Instance& useEngineInstance(); //! @brief Returns the engine::Instance - engine::Instance const& getEngineInstance() const; + engine::Instance const& useEngineInstance() const; //! @brief Returns the instance's scheduler engine::Scheduler<> & useScheduler(); @@ -145,8 +148,6 @@ namespace kiwi engine::Instance m_instance; - uint64_t m_user_id; - DocumentBrowser m_browser; PatcherManagers m_patcher_managers; diff --git a/Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.cpp b/Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.cpp index 072bf01c..82eb297c 100644 --- a/Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.cpp +++ b/Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.cpp @@ -351,7 +351,7 @@ namespace kiwi auto error_callback = [this](Api::Error error) { - KiwiApp::useInstance().useScheduler().schedule([this, message = error.getMessage()]() { + KiwiApp::useInstance().useScheduler().schedule([this, message = error.getMessage()](){ std::cout << "Error: " << message << "\n"; @@ -361,11 +361,10 @@ namespace kiwi }, std::chrono::milliseconds(500)); }; - auto& api_controller = KiwiApp::useApiController(); - api_controller.login(m_email_box.getText().toStdString(), - m_password_box.getText().toStdString(), - success_callback, - error_callback); + KiwiApp::login(m_email_box.getText().toStdString(), + m_password_box.getText().toStdString(), + std::move(success_callback), + std::move(error_callback)); } } diff --git a/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp b/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp index 9adbd82d..5afcafda 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp +++ b/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp @@ -244,6 +244,15 @@ namespace kiwi // API USER // // ================================================================================ // + uint64_t Api::User::getIdAsInt() const + { + uint64_t result = 0ull; + std::stringstream converter(_id); + converter >> std::hex >> result; + + return result; + } + void to_json(json& j, Api::User const& user) { j = json{ @@ -266,13 +275,18 @@ namespace kiwi // API AUTH USER // // ================================================================================ // - Api::AuthUser::AuthUser(User const& user, std::string const& _token) - : Api::User(user) - , token(_token) + Api::AuthUser::AuthUser(User user, std::string _token) + : Api::User(std::move(user)) + , token(std::move(_token)) { ; } + bool Api::AuthUser::isLoggedIn() const + { + return !token.empty(); + } + bool Api::AuthUser::isValid() const noexcept { return (!_id.empty() && !token.empty()); @@ -350,7 +364,7 @@ namespace kiwi return m_port; } - bool Api::Controller::isUserLoggedIn() + bool Api::Controller::isUserLoggedIn() const { return m_auth_user.isValid(); } @@ -360,7 +374,7 @@ namespace kiwi return m_auth_user; } - void Api::Controller::logout() + void Api::Controller::clearToken() { m_auth_user.token.clear(); } diff --git a/Client/Source/KiwiApp_Network/KiwiApp_Api.h b/Client/Source/KiwiApp_Network/KiwiApp_Api.h index bc27e851..b640bbf7 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_Api.h +++ b/Client/Source/KiwiApp_Network/KiwiApp_Api.h @@ -165,6 +165,8 @@ namespace kiwi User() = default; virtual ~User() = default; + uint64_t getIdAsInt() const; + int api_version = 0; std::string _id {}; std::string name {}; @@ -187,13 +189,15 @@ namespace kiwi AuthUser() = default; - AuthUser(User const& user, std::string const& token); + AuthUser(User user, std::string token); ~AuthUser() = default; + bool isLoggedIn() const; + bool isValid() const noexcept; - std::string token; + std::string token {}; }; // ================================================================================ // @@ -252,16 +256,18 @@ namespace kiwi //! @brief Returns true if the current client api user is logged in. //! @see logout - bool isUserLoggedIn(); + bool isUserLoggedIn() const; //! @brief Returns the authenticated user Api::AuthUser const& getAuthUser() const; - //! @brief Log-out the authenticated user. + protected: // methods + + //! @brief Clears the token. //! @details This will clear the stored token. //! The client will need to login again after this function call to perform authenticated request. //! @see login, isUserLoggedIn - virtual void logout(); + virtual void clearToken(); protected: // variables diff --git a/Client/Source/KiwiApp_Network/KiwiApp_ApiController.cpp b/Client/Source/KiwiApp_Network/KiwiApp_ApiController.cpp index 43cc11be..3de3a1ea 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_ApiController.cpp +++ b/Client/Source/KiwiApp_Network/KiwiApp_ApiController.cpp @@ -67,36 +67,35 @@ namespace kiwi void ApiController::login(std::string const& name_or_email, std::string const& password, - std::function success_cb, + std::function success_callback, Api::ErrorCallback error_callback) { - auto success_callback = [this, success_cb = std::move(success_cb)](Api::AuthUser user) - { - std::cout << "User " << user._id << " Authenticated !\n"; + auto success_cb = [this, success_callback = std::move(success_callback)](Api::AuthUser user){ - KiwiApp::useInstance().useScheduler().schedule([this, success_cb = std::move(success_cb), user = std::move(user)]() { + auto& scheduler = KiwiApp::useInstance().useScheduler(); + //scheduler.schedule([this, success_callback = std::move(success_callback), user = std::move(user)](){ + scheduler.schedule([this, success_callback, user](){ - m_auth_user = std::move(user); - m_listeners.call(&ApiController::Listener::AuthUserChanged, getAuthUser()); + std::cout << "User " << user._id << " Authenticated !\n"; - std::cout << "is logged in : " << m_auth_user.isValid() << std::endl; + m_auth_user = std::move(user); + m_listeners.call(&ApiController::Listener::AuthUserChanged, m_auth_user); KiwiApp::commandStatusChanged(); - success_cb(); - + success_callback(); }); }; auto& api = KiwiApp::useApi(); api.login(name_or_email, password, - success_callback, + std::move(success_cb), std::move(error_callback)); } void ApiController::logout() { - Api::Controller::logout(); + Api::Controller::clearToken(); m_listeners.call(&ApiController::Listener::AuthUserChanged, getAuthUser()); } diff --git a/Client/Source/KiwiApp_Network/KiwiApp_ApiController.h b/Client/Source/KiwiApp_Network/KiwiApp_ApiController.h index 385879f1..8dc96498 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_ApiController.h +++ b/Client/Source/KiwiApp_Network/KiwiApp_ApiController.h @@ -40,6 +40,7 @@ namespace kiwi struct Listener { virtual ~Listener() {} + virtual void userConnectedCallback(Api::AuthUser const&) = 0; virtual void AuthUserChanged(Api::AuthUser const&) = 0; }; @@ -66,9 +67,9 @@ namespace kiwi std::function success_callback, Api::ErrorCallback error_callback); - //! @brief Log the client api user out. + //! @brief Log-out the user. //! @see login, isUserLoggedIn - void logout() override; + void logout(); //! @brief Restore the controller state. void restoreFromXml(); diff --git a/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp b/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp index de6a0b0d..e64bac29 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp +++ b/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp @@ -304,21 +304,11 @@ namespace kiwi return m_document.name; } - std::string DocumentBrowser::Drive::DocumentSession::getHost() const - { - return KiwiApp::useApiController().getHost(); - } - uint64_t DocumentBrowser::Drive::DocumentSession::getSessionId() const { return m_document.session_id; } - uint16_t DocumentBrowser::Drive::DocumentSession::getSessionPort() const - { - return m_drive.getSessionPort(); - } - DocumentBrowser::Drive const& DocumentBrowser::Drive::DocumentSession::useDrive() const { return m_drive; diff --git a/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.h b/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.h index 511a8bed..2363677d 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.h +++ b/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.h @@ -215,15 +215,9 @@ namespace kiwi //! @brief Returns the document name std::string getName() const; - //! @brief Returns the document session host - std::string getHost() const; - //! @brief Returns the session id of the document. uint64_t getSessionId() const; - //! @brief Returns the document session port. - uint16_t getSessionPort() const; - //! @brief Returns the drive that holds this document. DocumentBrowser::Drive const& useDrive() const; diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.cpp index 4fdceb99..c0c4c7c2 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.cpp @@ -108,9 +108,11 @@ namespace kiwi m_listeners.call(&Listener::connectedUserChanged, *this); }); + const auto& network_settings = getAppSettings().network(); + DocumentManager::connect(patcher, - session.getHost(), - session.getSessionPort(), + network_settings.getHost(), + network_settings.getSessionPort(), session.getSessionId()); patcher.useSelfUser(); @@ -265,18 +267,12 @@ namespace kiwi auto& user = patcher.useSelfUser(); auto& views = user.getViews(); - bool view_has_been_removed = false; - for(auto it = views.begin(); it != views.end();) { it = user.removeView(*it); - view_has_been_removed = view_has_been_removed || (it != views.end()); } - if(view_has_been_removed) - { - DocumentManager::commit(patcher); - } + DocumentManager::commit(patcher); } bool PatcherManager::askAllWindowsToClose() @@ -434,7 +430,7 @@ namespace kiwi { changed = (changed || user.added() || user.removed()); - if(user.getId() == m_instance.getUserId()) + if(user.getId() == m_document.user()) { for(auto& view : user.getViews()) { @@ -452,20 +448,13 @@ namespace kiwi } } } - - /* - if(!patcher.removed() && changed) - { - m_listeners.call(&Listener::connectedUserChanged, *this); - } - */ } void PatcherManager::createPatcherWindow(model::Patcher& patcher, model::Patcher::User const& user, model::Patcher::View& view) { - if(user.getId() == m_instance.getUserId()) + if(user.getId() == m_document.user()) { auto& patcherview = view.entity().emplace(*this, m_instance, patcher, view); view.entity().emplace(*this, patcherview); @@ -477,7 +466,7 @@ namespace kiwi model::Patcher::User const& user, model::Patcher::View& view) { - if(user.getId() == m_instance.getUserId()) + if(user.getId() == m_document.user()) { // Notify PatcherView auto& patcherview = view.entity().use(); @@ -489,7 +478,7 @@ namespace kiwi model::Patcher::User const& user, model::Patcher::View& view) { - if(user.getId() == m_instance.getUserId()) + if(user.getId() == m_document.user()) { view.entity().erase(); view.entity().erase(); From 075c2c6b9f1e27f57f58f3e0c94c07ae9eaa38f7 Mon Sep 17 00:00:00 2001 From: eliott PARIS Date: Thu, 24 Aug 2017 16:34:13 +0200 Subject: [PATCH 034/148] Update Beast submodule to version 108 --- .gitmodules | 2 +- Modules/KiwiNetwork/KiwiHttp/KiwiHttp.h | 6 ++++-- README.md | 2 +- Test/Network/test_Http.cpp | 4 +++- ThirdParty/Beast | 2 +- 5 files changed, 10 insertions(+), 6 deletions(-) diff --git a/.gitmodules b/.gitmodules index 077b9dd3..ba43d85c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -6,4 +6,4 @@ url = https://github.com/cameron314/concurrentqueue.git [submodule "ThirdParty/Beast"] path = ThirdParty/Beast - url = https://github.com/vinniefalco/Beast.git + url = https://github.com/boostorg/beast.git diff --git a/Modules/KiwiNetwork/KiwiHttp/KiwiHttp.h b/Modules/KiwiNetwork/KiwiHttp/KiwiHttp.h index 402b0fb7..42ccf663 100644 --- a/Modules/KiwiNetwork/KiwiHttp/KiwiHttp.h +++ b/Modules/KiwiNetwork/KiwiHttp/KiwiHttp.h @@ -30,8 +30,10 @@ #include #include -#include -#include +#include +#include + +namespace beast = boost::beast; namespace kiwi { namespace network { namespace http { diff --git a/README.md b/README.md index 313f3812..da9b6631 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,7 @@ Kiwi uses the following ThirdParty libraries: - [Flip](http://developer.irisate.com/) - [Juce](https://github.com/WeAreROLI/JUCE) -- [Beast](https://github.com/vinniefalco/Beast/) +- [Beast](https://github.com/boostorg/Beast/) - [concurrentqueue](https://github.com/cameron314/concurrentqueue) - [json](https://github.com/nlohmann/json) diff --git a/Test/Network/test_Http.cpp b/Test/Network/test_Http.cpp index 4eb9abd5..36b87092 100755 --- a/Test/Network/test_Http.cpp +++ b/Test/Network/test_Http.cpp @@ -27,7 +27,9 @@ #include "../catch.hpp" -#include +#include + +namespace beast = boost::beast; #include diff --git a/ThirdParty/Beast b/ThirdParty/Beast index 78a065ba..359cbb1c 160000 --- a/ThirdParty/Beast +++ b/ThirdParty/Beast @@ -1 +1 @@ -Subproject commit 78a065ba39836d91d7e70d93de7f9140f518083b +Subproject commit 359cbb1ce49cc9079371178645b9442e184942d0 From c39aac04a04bee71c73a034e5623a43e554eb669 Mon Sep 17 00:00:00 2001 From: eliott PARIS Date: Sat, 26 Aug 2017 00:02:38 +0200 Subject: [PATCH 035/148] Add a "remember me" option and save/restore user profile --- Client/Source/KiwiApp.cpp | 31 +++++- Client/Source/KiwiApp.h | 2 +- .../KiwiApp_Application/KiwiApp_Instance.cpp | 2 +- .../Source/KiwiApp_Auth/KiwiApp_LoginForm.cpp | 36 ++++-- .../Source/KiwiApp_Auth/KiwiApp_LoginForm.h | 2 + .../KiwiApp_General/KiwiApp_CommandIDs.h | 1 + Client/Source/KiwiApp_General/KiwiApp_IDs.h | 1 + .../KiwiApp_StoredSettings.cpp | 47 +++++++- .../KiwiApp_General/KiwiApp_StoredSettings.h | 12 ++ Client/Source/KiwiApp_Network/KiwiApp_Api.cpp | 105 ++++++++++++++---- Client/Source/KiwiApp_Network/KiwiApp_Api.h | 74 ++++++++++-- .../KiwiApp_Network/KiwiApp_ApiController.cpp | 49 ++++---- .../KiwiApp_Network/KiwiApp_ApiController.h | 11 +- .../KiwiApp_Ressources/KiwiApp_BinaryData.cpp | 3 +- .../KiwiApp_Ressources/KiwiApp_BinaryData.h | 2 +- .../BinaryRes/Settings/network.settings | 2 +- 16 files changed, 299 insertions(+), 81 deletions(-) diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index d953bc03..00417b90 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -235,6 +235,7 @@ namespace kiwi if(useInstance().logout()) { KiwiApp::use().m_api_controller->logout(); + KiwiApp::commandStatusChanged(); } } @@ -379,6 +380,8 @@ namespace kiwi void KiwiApp::createAccountMenu(juce::PopupMenu& menu) { + menu.addCommandItem(&getCommandManager(), CommandIDs::remember_me); + menu.addSeparator(); menu.addCommandItem(&getCommandManager(), CommandIDs::login); menu.addCommandItem(&getCommandManager(), CommandIDs::signin); menu.addSeparator(); @@ -492,6 +495,7 @@ namespace kiwi CommandIDs::login, CommandIDs::signin, CommandIDs::logout, + CommandIDs::remember_me, }; commands.addArray(ids, juce::numElementsInArray(ids)); @@ -527,9 +531,10 @@ namespace kiwi } case CommandIDs::login: { - const bool logged = m_api_controller->isUserLoggedIn(); + auto const& user = getCurrentUser(); + const bool logged = user.isLoggedIn(); result.setInfo(logged - ? juce::String(TRANS("Logged-in as ") + m_api_controller->getAuthUser().name) + ? juce::String(TRANS("Logged-in as ") + user.getName()) : TRANS("Login"), TRANS("Show the \"Login form\" Window"), CommandCategories::windows, 0); @@ -542,7 +547,7 @@ namespace kiwi result.setInfo(TRANS("Register"), TRANS("Show the \"Register form\" Window"), CommandCategories::windows, 0); - result.setActive(!m_api_controller->isUserLoggedIn()); + result.setActive(!getCurrentUser().isLoggedIn()); break; } case CommandIDs::logout: @@ -550,7 +555,18 @@ namespace kiwi result.setInfo(TRANS("Logout"), TRANS("Log out current user"), CommandCategories::windows, 0); - result.setActive(m_api_controller->isUserLoggedIn()); + result.setActive(getCurrentUser().isLoggedIn()); + break; + } + case CommandIDs::remember_me: + { + result.setInfo(TRANS("Remember me"), TRANS("Remember current user"), + CommandCategories::windows, 0); + + auto const& user = getCurrentUser(); + + result.setActive(user.isLoggedIn()); + result.setTicked(getAppSettings().network().getRememberUserFlag()); break; } case CommandIDs::showAboutAppWindow: @@ -659,6 +675,13 @@ namespace kiwi logout(); break; } + case CommandIDs::remember_me: + { + auto& settings = getAppSettings().network(); + settings.setRememberUserFlag(!settings.getRememberUserFlag()); + commandStatusChanged(); + break; + } case CommandIDs::showConsoleWindow : { m_instance->showConsoleWindow(); diff --git a/Client/Source/KiwiApp.h b/Client/Source/KiwiApp.h index 2a996648..7ee0206e 100644 --- a/Client/Source/KiwiApp.h +++ b/Client/Source/KiwiApp.h @@ -96,7 +96,7 @@ namespace kiwi //! @brief Get the Api object. static Api& useApi(); - //! @brief Attempt to log the client api user in (Async). + //! @brief Attempt to log-in the user (Async). //! @param name_or_email The name or email of the user. //! @param password The user password. //! @see logout, getCurrentUser diff --git a/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp b/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp index c26f0b7a..409982fb 100644 --- a/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp +++ b/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp @@ -361,7 +361,7 @@ namespace kiwi std::make_unique(), false, false); - login_window->centreWithSize(400, 300); + login_window->centreWithSize(400, 330); login_window->enterModalState(true); return login_window; diff --git a/Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.cpp b/Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.cpp index 82eb297c..2a4e860d 100644 --- a/Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.cpp +++ b/Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.cpp @@ -163,14 +163,32 @@ namespace kiwi : m_password_box(juce::String(), getDefaultPasswordChar()) , m_submit_btn(TRANS("Login")) , m_cancel_btn(TRANS("Cancel")) + , m_remember_me_checkbox("Remember me") , m_kiwi_app_image(juce::ImageCache::getFromMemory(binary_data::images::kiwi_icon_png, binary_data::images::kiwi_icon_png_size)) { + //(force use of a default system font to make sure it has the password blob character) + juce::Font font(juce::Font::getDefaultTypefaceForFont(juce::Font(juce::Font::getDefaultSansSerifFontName(), + juce::Font::getDefaultStyle(), 5.0f))); + + font.setHeight(22); + + m_email_box.setInputRestrictions(512); + m_email_box.setFont(font); + m_email_box.setText(KiwiApp::getCurrentUser().getName(), false); + + m_password_box.setInputRestrictions(64); + m_password_box.setFont(font); + addAndMakeVisible(m_email_box); addAndMakeVisible(m_password_box); + addAndMakeVisible(m_remember_me_checkbox); addAndMakeVisible(m_submit_btn); addAndMakeVisible(m_cancel_btn); + m_remember_me_checkbox.setToggleState(getAppSettings().network().getRememberUserFlag(), + juce::NotificationType::dontSendNotification); + m_email_box.setEscapeAndReturnKeysConsumed(false); m_password_box.setEscapeAndReturnKeysConsumed(false); @@ -180,7 +198,8 @@ namespace kiwi m_cancel_btn.addListener(this); lookAndFeelChanged(); - setSize(400, 300); + setSize(400, 330); + resized(); } LoginForm::~LoginForm() @@ -223,23 +242,17 @@ namespace kiwi r.reduce(10, 10); - //(force use of a default system font to make sure it has the password blob character) - juce::Font font(juce::Font::getDefaultTypefaceForFont(juce::Font(juce::Font::getDefaultSansSerifFontName(), juce::Font::getDefaultStyle(), 5.0f))); - - font.setHeight(22); - const int boxHeight = 32; m_email_box.setBounds(r.removeFromTop(boxHeight)); - m_email_box.setInputRestrictions(512); - m_email_box.setFont(font); r.removeFromTop(20); m_password_box.setBounds(r.removeFromTop(boxHeight)); - m_password_box.setInputRestrictions(64); - m_password_box.setFont(font); - r.removeFromTop(20); + r.removeFromTop(10); + m_remember_me_checkbox.setBounds(r.removeFromTop(boxHeight)); + + r.removeFromTop(10); juce::Rectangle buttonArea(r.removeFromTop(button_height)); m_submit_btn.changeWidthToFitText(button_height); m_cancel_btn.changeWidthToFitText(button_height); @@ -345,6 +358,7 @@ namespace kiwi auto success_callback = [this]() { KiwiApp::useInstance().useScheduler().schedule([this]() { + getAppSettings().network().setRememberUserFlag(m_remember_me_checkbox.getToggleState()); dismiss(); }, std::chrono::milliseconds(500)); }; diff --git a/Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.h b/Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.h index 03e6b738..cee53fc6 100644 --- a/Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.h +++ b/Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.h @@ -106,6 +106,8 @@ namespace kiwi juce::TextEditor m_email_box, m_password_box; juce::TextButton m_submit_btn, m_cancel_btn; + juce::ToggleButton m_remember_me_checkbox; + std::unique_ptr m_alert_box; juce::Image m_kiwi_app_image; diff --git a/Client/Source/KiwiApp_General/KiwiApp_CommandIDs.h b/Client/Source/KiwiApp_General/KiwiApp_CommandIDs.h index 39c62210..dc5ca39f 100644 --- a/Client/Source/KiwiApp_General/KiwiApp_CommandIDs.h +++ b/Client/Source/KiwiApp_General/KiwiApp_CommandIDs.h @@ -91,6 +91,7 @@ namespace kiwi login = 0xf50000, ///< Log-in the user. signin = 0xf50010, ///< Sign-in the user. logout = 0xf50020, ///< Log-out the user. + remember_me = 0xf50030, ///< Toggle the "remember me" option to save user profile. }; // ================================================================================ // diff --git a/Client/Source/KiwiApp_General/KiwiApp_IDs.h b/Client/Source/KiwiApp_General/KiwiApp_IDs.h index eb5fe879..3074b01f 100644 --- a/Client/Source/KiwiApp_General/KiwiApp_IDs.h +++ b/Client/Source/KiwiApp_General/KiwiApp_IDs.h @@ -38,6 +38,7 @@ namespace kiwi DECLARE_ID(api_port); DECLARE_ID(session_port); DECLARE_ID(refresh_interval); + DECLARE_ID(remember_me); DECLARE_ID(NETWORK_CONFIG); diff --git a/Client/Source/KiwiApp_General/KiwiApp_StoredSettings.cpp b/Client/Source/KiwiApp_General/KiwiApp_StoredSettings.cpp index 2910c926..0038cf23 100644 --- a/Client/Source/KiwiApp_General/KiwiApp_StoredSettings.cpp +++ b/Client/Source/KiwiApp_General/KiwiApp_StoredSettings.cpp @@ -40,11 +40,13 @@ namespace kiwi return getAppSettings().getGlobalProperties(); } - static juce::PropertiesFile::Options getPropertyFileOptionsFor(const juce::String& filename) + juce::PropertiesFile::Options getPropertyFileOptionsFor(juce::String const& filename, juce::String const& suffix) { + assert(suffix.isNotEmpty() && "need an extension"); + juce::PropertiesFile::Options options; options.applicationName = filename; - options.filenameSuffix = "settings"; + options.filenameSuffix = suffix; options.osxLibrarySubFolder = "Application Support"; #if JUCE_LINUX @@ -61,6 +63,36 @@ namespace kiwi return std::make_unique(getPropertyFileOptionsFor(filename)); } + bool saveJsonToFile(juce::String const& filename, json const& j) + { + juce::File file = getPropertyFileOptionsFor(filename, "json").getDefaultFile(); + juce::TemporaryFile tempFile(file); + + { + juce::FileOutputStream out(tempFile.getFile()); + + if (!out.openedOk()) + return false; + + std::string json_str = j.dump(4); + out.write(json_str.data(), json_str.size()); + + out.flush(); // (called explicitly to force an fsync on posix) + + if (out.getStatus().failed()) + return false; + } + + return tempFile.overwriteTargetFileWithTemporary(); + } + + json getJsonFromFile(juce::String const& filename) + { + juce::File file = getPropertyFileOptionsFor(filename, "json").getDefaultFile(); + std::string json_user_str = file.loadFileAsString().toStdString(); + return json::parse(json_user_str); + } + // ================================================================================ // // NETWORK SETTINGS // // ================================================================================ // @@ -162,6 +194,16 @@ namespace kiwi return m_settings.getPropertyAsValue(Ids::refresh_interval, nullptr); } + void NetworkSettings::setRememberUserFlag(bool remember_me) + { + m_settings.setProperty(Ids::remember_me, remember_me, nullptr); + } + + bool NetworkSettings::getRememberUserFlag() const + { + return m_settings.getProperty(Ids::remember_me); + } + void NetworkSettings::addListener(Listener& listener) { m_listeners.add(listener); @@ -209,6 +251,7 @@ namespace kiwi void StoredSettings::reload() { m_property_files.clear(); + m_property_files.emplace_back(createPropsFile("kiwi_settings")); // Try to reload User settings diff --git a/Client/Source/KiwiApp_General/KiwiApp_StoredSettings.h b/Client/Source/KiwiApp_General/KiwiApp_StoredSettings.h index 9134e684..fc22a5fc 100644 --- a/Client/Source/KiwiApp_General/KiwiApp_StoredSettings.h +++ b/Client/Source/KiwiApp_General/KiwiApp_StoredSettings.h @@ -23,9 +23,12 @@ #include #include +#include namespace kiwi { + using nlohmann::json; + // ================================================================================ // // NETWORK SETTINGS // // ================================================================================ // @@ -72,6 +75,10 @@ namespace kiwi //! @brief Returns the session port as a juce::Value juce::Value getRefreshIntervalValue(); + void setRememberUserFlag(bool remember_me); + + bool getRememberUserFlag() const; + //! @brief NetworkSettings Listener struct Listener { @@ -157,4 +164,9 @@ namespace kiwi StoredSettings& getAppSettings(); juce::PropertiesFile& getGlobalProperties(); + juce::PropertiesFile::Options getPropertyFileOptionsFor(juce::String const& filename, + juce::String const& suffix = "settings"); + + bool saveJsonToFile(juce::String const& filename, json const& j); + json getJsonFromFile(juce::String const& filename); }; diff --git a/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp b/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp index 5afcafda..5ce14af3 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp +++ b/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp @@ -81,9 +81,19 @@ namespace kiwi { const auto j = json::parse(res.body); - if(j.is_object() && j.count("user") && j.count("token")) + if(j.is_object() && j.count("user")) { - success({j["user"], j["token"]}); + AuthUser user(j["user"]); + + if(user.isLoggedIn()) + { + success(std::move(user)); + } + else + { + fail({res.result_int(), "Failed to parse result"}); + } + return; } } @@ -182,9 +192,9 @@ namespace kiwi const AuthUser& user = m_controller.getAuthUser(); - if(add_auth && !user.token.empty()) + if(add_auth && !user.isLoggedIn()) { - session->setAuthorization("JWT " + user.token); + session->setAuthorization("JWT " + user.getToken()); } return std::move(session); @@ -211,6 +221,13 @@ namespace kiwi Api::Error::Error() : m_status_code(0) , m_message("Unknown Error") + { + ; + } + + Api::Error::Error(unsigned status_code, std::string const& message) + : m_status_code(status_code) + , m_message(message) { } @@ -244,52 +261,92 @@ namespace kiwi // API USER // // ================================================================================ // + std::string const& Api::User::getName() const + { + return m_name; + } + + std::string const& Api::User::getEmail() const + { + return m_email; + } + + std::string const& Api::User::getIdAsString() const + { + return m_id; + } + uint64_t Api::User::getIdAsInt() const { uint64_t result = 0ull; - std::stringstream converter(_id); + std::stringstream converter(m_id); converter >> std::hex >> result; return result; } + bool Api::User::isValid() const noexcept + { + return (!m_id.empty() && !m_email.empty()); + } + + int Api::User::getApiVersion() const + { + return m_api_version; + } + void to_json(json& j, Api::User const& user) { j = json{ - {"__v", user.api_version}, - {"_id", user._id}, - {"username", user.name}, - {"email", user.email} + {"__v", user.getApiVersion()}, + {"_id", user.getIdAsString()}, + {"username", user.getName()}, + {"email", user.getEmail()} }; } void from_json(json const& j, Api::User& user) { - user.api_version = j.count("__v") ? j["__v"].get() : 0; - user._id = j.count("_id") ? j["_id"].get() : ""; - user.name = j.count("username") ? j["username"].get() : ""; - user.email = j.count("email") ? j["email"].get() : ""; + user.m_api_version = Api::getJsonValue(j, "__v"); + user.m_id = Api::getJsonValue(j, "_id"); + user.m_name = Api::getJsonValue(j, "username"); + user.m_email = Api::getJsonValue(j, "email"); } // ================================================================================ // // API AUTH USER // // ================================================================================ // - Api::AuthUser::AuthUser(User user, std::string _token) - : Api::User(std::move(user)) - , token(std::move(_token)) + /* + Api::AuthUser::AuthUser(AuthUser&& other) + : Api::User(other) + , m_token(std::move(other.m_token)) { - ; + } + */ bool Api::AuthUser::isLoggedIn() const { - return !token.empty(); + return isValid() && !m_token.empty(); + } + + std::string const& Api::AuthUser::getToken() const + { + return m_token; + } + + //! @brief Helper function to convert an Api::AuthUser into a json object + void to_json(json& j, Api::AuthUser const& user) + { + to_json(j, static_cast(user)); + j["token"] = user.getToken(); } - bool Api::AuthUser::isValid() const noexcept + void from_json(json const& j, Api::AuthUser& user) { - return (!_id.empty() && !token.empty()); + from_json(j, static_cast(user)); + user.m_token = Api::getJsonValue(j, "token"); } // ================================================================================ // @@ -310,8 +367,8 @@ namespace kiwi void from_json(json const& j, Api::Document& doc) { - doc._id = j.count("_id") ? j["_id"].get() : ""; - doc.name = j.count("name") ? j["name"].get() : ""; + doc._id = Api::getJsonValue(j, "_id"); + doc.name = Api::getJsonValue(j, "name"); doc.session_id = 0ul; if(j.count("session_id")) @@ -366,7 +423,7 @@ namespace kiwi bool Api::Controller::isUserLoggedIn() const { - return m_auth_user.isValid(); + return m_auth_user.isLoggedIn(); } Api::AuthUser const& Api::Controller::getAuthUser() const @@ -376,6 +433,6 @@ namespace kiwi void Api::Controller::clearToken() { - m_auth_user.token.clear(); + m_auth_user.m_token.clear(); } } diff --git a/Client/Source/KiwiApp_Network/KiwiApp_Api.h b/Client/Source/KiwiApp_Network/KiwiApp_Api.h index b640bbf7..6d283cd0 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_Api.h +++ b/Client/Source/KiwiApp_Network/KiwiApp_Api.h @@ -93,6 +93,14 @@ namespace kiwi std::string const& new_name, Callback callback); + public: // helper methods + + template + static Type getJsonValue(json const& json, std::string const& key, Type default_value = {}) + { + return json.count(key) ? json.at(key).get() : default_value; + } + private: // methods //! @brief Kiwi API Endpoints @@ -140,6 +148,8 @@ namespace kiwi Error(); + Error(unsigned status_code, std::string const& message); + Error(Api::Response const& response); ~Error() = default; @@ -162,15 +172,47 @@ namespace kiwi { public: // methods + //! @brief Constructor. User() = default; + virtual ~User() = default; + //! @brief Constructor. + //User& operator = (User && user); + + //! @brief Get the user name. + std::string const& getName() const; + + //! @brief Get the user email. + std::string const& getEmail() const; + + //! @brief Get the user id as a string. + std::string const& getIdAsString() const; + + //! @brief Get the user id as an integer. uint64_t getIdAsInt() const; - int api_version = 0; - std::string _id {}; - std::string name {}; - std::string email {}; + //! @brief Get the user api version. + int getApiVersion() const; + + //! @brief Returns true if the user has a valid id and email. + bool isValid() const noexcept; + + private: // deleted methods + + //User(User const&) = delete; + + private: // variables + + friend void from_json(json const&, Api::User&); + + int m_api_version = 0; + std::string m_id {}; + std::string m_name {}; + std::string m_email {}; + + //uint64_t m_int_id = 0ull; + //bool m_int_id_need_update_flag = true; }; //! @brief Helper function to convert an Api::User into a json object @@ -189,17 +231,35 @@ namespace kiwi AuthUser() = default; - AuthUser(User user, std::string token); + //AuthUser(AuthUser&& other); ~AuthUser() = default; + //! @brief Returns true if the user has a token. + //! @see getToken bool isLoggedIn() const; - bool isValid() const noexcept; + //! @brief Returns the user token. + //! @see isLoggedIn() + std::string const& getToken() const; - std::string token {}; + private: // variables + + //AuthUser(AuthUser&& other) = default; + + friend void from_json(json const&, Api::AuthUser&); + + friend Api::Controller; + + std::string m_token {}; }; + //! @brief Helper function to convert an Api::AuthUser into a json object + void to_json(json& j, Api::AuthUser const& user); + + //! @brief Helper function to convert a json object into an Api::AuthUser + void from_json(json const& j, Api::AuthUser& user); + // ================================================================================ // // API DOCUMENT // // ================================================================================ // diff --git a/Client/Source/KiwiApp_Network/KiwiApp_ApiController.cpp b/Client/Source/KiwiApp_Network/KiwiApp_ApiController.cpp index 3de3a1ea..1ce17bfa 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_ApiController.cpp +++ b/Client/Source/KiwiApp_Network/KiwiApp_ApiController.cpp @@ -29,17 +29,38 @@ namespace kiwi { ApiController::ApiController() { - auto& network_settings = getAppSettings().network(); + auto& settings = getAppSettings().network(); - setHost(network_settings.getHost()); - setPort(network_settings.getApiPort()); + setHost(settings.getHost()); + setPort(settings.getApiPort()); - network_settings.addListener(*this); + settings.addListener(*this); + + restoreAuthUserProfile(); } ApiController::~ApiController() { - getAppSettings().network().removeListener(*this); + auto& settings = getAppSettings().network(); + settings.removeListener(*this); + + if(!settings.getRememberUserFlag()) + { + clearToken(); + } + + saveAuthUserProfile(); + } + + bool ApiController::saveAuthUserProfile() + { + return saveJsonToFile("AuthUser", getAuthUser()); + } + + bool ApiController::restoreAuthUserProfile() + { + from_json(getJsonFromFile("AuthUser"), m_auth_user); + return true; } void ApiController::networkSettingsChanged(NetworkSettings const& settings, @@ -73,11 +94,8 @@ namespace kiwi auto success_cb = [this, success_callback = std::move(success_callback)](Api::AuthUser user){ auto& scheduler = KiwiApp::useInstance().useScheduler(); - //scheduler.schedule([this, success_callback = std::move(success_callback), user = std::move(user)](){ scheduler.schedule([this, success_callback, user](){ - std::cout << "User " << user._id << " Authenticated !\n"; - m_auth_user = std::move(user); m_listeners.call(&ApiController::Listener::AuthUserChanged, m_auth_user); @@ -87,10 +105,7 @@ namespace kiwi }); }; - auto& api = KiwiApp::useApi(); - api.login(name_or_email, password, - std::move(success_cb), - std::move(error_callback)); + KiwiApp::useApi().login(name_or_email, password, std::move(success_cb), std::move(error_callback)); } void ApiController::logout() @@ -98,14 +113,4 @@ namespace kiwi Api::Controller::clearToken(); m_listeners.call(&ApiController::Listener::AuthUserChanged, getAuthUser()); } - - void ApiController::restoreFromXml() - { - - } - - void ApiController::saveToXml() - { - - } } diff --git a/Client/Source/KiwiApp_Network/KiwiApp_ApiController.h b/Client/Source/KiwiApp_Network/KiwiApp_ApiController.h index 8dc96498..f11a2d53 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_ApiController.h +++ b/Client/Source/KiwiApp_Network/KiwiApp_ApiController.h @@ -50,6 +50,8 @@ namespace kiwi ApiController(); //! @brief Destructor + //! @details If the "remember me" flag is true, the user profile will be saved when the object is destroyed. + //! If false, the user profile will be saved whithout the token. ~ApiController(); //! @brief Adds a listener. @@ -71,14 +73,11 @@ namespace kiwi //! @see login, isUserLoggedIn void logout(); - //! @brief Restore the controller state. - void restoreFromXml(); - - //! @brief Save the controller state. - void saveToXml(); - private: // methods + bool saveAuthUserProfile(); + bool restoreAuthUserProfile(); + //! @brief Called when the network settings has changed. void networkSettingsChanged(NetworkSettings const&, juce::Identifier const&) override; diff --git a/Client/Source/KiwiApp_Ressources/KiwiApp_BinaryData.cpp b/Client/Source/KiwiApp_Ressources/KiwiApp_BinaryData.cpp index 3077607b..e0f2bb6e 100644 --- a/Client/Source/KiwiApp_Ressources/KiwiApp_BinaryData.cpp +++ b/Client/Source/KiwiApp_Ressources/KiwiApp_BinaryData.cpp @@ -147690,7 +147690,8 @@ namespace kiwi 0x6f, 0x72, 0x74, 0x3d, 0x22, 0x38, 0x30, 0x38, 0x30, 0x22, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x3d, 0x22, 0x39, 0x30, 0x39, 0x30, 0x22, 0x20, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x3d, -0x22, 0x30, 0x22, 0x2f, 0x3e, 0x0d, 0x0a +0x22, 0x30, 0x22, 0x20, 0x72, 0x65, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x6d, 0x65, 0x3d, +0x22, 0x31, 0x22, 0x2f, 0x3e, 0x0d, 0x0a }; const char* network_settings = (const char *) network_settings_array; diff --git a/Client/Source/KiwiApp_Ressources/KiwiApp_BinaryData.h b/Client/Source/KiwiApp_Ressources/KiwiApp_BinaryData.h index bca334c3..e82e9ad4 100644 --- a/Client/Source/KiwiApp_Ressources/KiwiApp_BinaryData.h +++ b/Client/Source/KiwiApp_Ressources/KiwiApp_BinaryData.h @@ -122,7 +122,7 @@ namespace kiwi namespace settings { extern char const* network_settings; - const int network_settings_size = 135; + const int network_settings_size = 151; } } diff --git a/Ressources/BinaryRes/Settings/network.settings b/Ressources/BinaryRes/Settings/network.settings index 6cd78617..afcba1d7 100644 --- a/Ressources/BinaryRes/Settings/network.settings +++ b/Ressources/BinaryRes/Settings/network.settings @@ -1,3 +1,3 @@ - + From 58a1d08419b8f34a0014be0d4c7afb6d8b3aa351 Mon Sep 17 00:00:00 2001 From: eliott PARIS Date: Sun, 27 Aug 2017 16:47:18 +0200 Subject: [PATCH 036/148] - Add a new FormComponent class to build forms easily - Refactor Login form - Add a signup form - update saved user data. --- Client/Source/KiwiApp.cpp | 24 +- Client/Source/KiwiApp.h | 10 + .../KiwiApp_Application/KiwiApp_Instance.cpp | 19 +- .../KiwiApp_Application/KiwiApp_Instance.h | 6 +- .../Source/KiwiApp_Auth/KiwiApp_AuthPanel.cpp | 251 +++++++++ .../Source/KiwiApp_Auth/KiwiApp_AuthPanel.h | 110 ++++ .../Source/KiwiApp_Auth/KiwiApp_LoginForm.cpp | 392 ------------- .../Source/KiwiApp_Auth/KiwiApp_LoginForm.h | 121 ---- .../KiwiApp_FormComponent.cpp | 523 ++++++++++++++++++ .../KiwiApp_FormComponent.h | 284 ++++++++++ .../KiwiApp_Components/KiwiApp_Window.h | 2 +- .../KiwiApp_General/KiwiApp_CommandIDs.h | 2 +- .../KiwiApp_StoredSettings.cpp | 12 +- Client/Source/KiwiApp_Network/KiwiApp_Api.cpp | 84 ++- Client/Source/KiwiApp_Network/KiwiApp_Api.h | 26 +- .../KiwiApp_Network/KiwiApp_ApiController.cpp | 38 +- .../KiwiApp_Network/KiwiApp_ApiController.h | 11 +- 17 files changed, 1362 insertions(+), 553 deletions(-) create mode 100644 Client/Source/KiwiApp_Auth/KiwiApp_AuthPanel.cpp create mode 100644 Client/Source/KiwiApp_Auth/KiwiApp_AuthPanel.h delete mode 100644 Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.cpp delete mode 100644 Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.h create mode 100644 Client/Source/KiwiApp_Components/KiwiApp_FormComponent.cpp create mode 100644 Client/Source/KiwiApp_Components/KiwiApp_FormComponent.h diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index 00417b90..e156aa8c 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -225,6 +225,16 @@ namespace kiwi api_controller.login(name_or_email, password, std::move(success_callback), std::move(error_callback)); } + void KiwiApp::signup(std::string const& username, + std::string const& email, + std::string const& password, + std::function success_callback, + Api::ErrorCallback error_callback) + { + auto& api_controller = *KiwiApp::use().m_api_controller; + api_controller.signup(username, email, password, std::move(success_callback), std::move(error_callback)); + } + Api::AuthUser const& KiwiApp::getCurrentUser() { return KiwiApp::use().m_api_controller->getAuthUser(); @@ -383,7 +393,7 @@ namespace kiwi menu.addCommandItem(&getCommandManager(), CommandIDs::remember_me); menu.addSeparator(); menu.addCommandItem(&getCommandManager(), CommandIDs::login); - menu.addCommandItem(&getCommandManager(), CommandIDs::signin); + menu.addCommandItem(&getCommandManager(), CommandIDs::signup); menu.addSeparator(); menu.addCommandItem(&getCommandManager(), CommandIDs::logout); } @@ -493,7 +503,7 @@ namespace kiwi CommandIDs::startDsp, CommandIDs::stopDsp, CommandIDs::login, - CommandIDs::signin, + CommandIDs::signup, CommandIDs::logout, CommandIDs::remember_me, }; @@ -542,7 +552,7 @@ namespace kiwi result.setActive(!logged); break; } - case CommandIDs::signin: + case CommandIDs::signup: { result.setInfo(TRANS("Register"), TRANS("Show the \"Register form\" Window"), CommandCategories::windows, 0); @@ -662,17 +672,17 @@ namespace kiwi } case CommandIDs::login: { - m_instance->showLoginWindow(); + m_instance->showAuthWindow(AuthPanel::FormType::Login); break; } - case CommandIDs::signin: + case CommandIDs::signup: { - m_instance->showLoginWindow(); + m_instance->showAuthWindow(AuthPanel::FormType::SignUp); break; } case CommandIDs::logout: { - logout(); + KiwiApp::logout(); break; } case CommandIDs::remember_me: diff --git a/Client/Source/KiwiApp.h b/Client/Source/KiwiApp.h index 7ee0206e..9c0f0dcc 100644 --- a/Client/Source/KiwiApp.h +++ b/Client/Source/KiwiApp.h @@ -105,6 +105,16 @@ namespace kiwi std::function success_callback, Api::ErrorCallback error_callback); + //! @brief Attempt to register/signup the user. + //! @param username user name + //! @param email email address + //! @param password password + static void signup(std::string const& username, + std::string const& email, + std::string const& password, + std::function success_callback, + Api::ErrorCallback error_callback); + //! @brief Returns the current user static Api::AuthUser const& getCurrentUser(); diff --git a/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp b/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp index 409982fb..1420a4c1 100644 --- a/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp +++ b/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp @@ -30,7 +30,7 @@ #include "../KiwiApp_Patcher/KiwiApp_PatcherView.h" #include "../KiwiApp_Patcher/KiwiApp_PatcherComponent.h" -#include "../KiwiApp_Auth/KiwiApp_LoginForm.h" +#include "../KiwiApp_General/KiwiApp_CommandIDs.h" namespace kiwi { @@ -353,18 +353,17 @@ namespace kiwi }); } - void Instance::showLoginWindow() + void Instance::showAuthWindow(AuthPanel::FormType type) { - showWindowWithId(WindowId::AuthForm, []() { + showWindowWithId(WindowId::FormComponent, [type]() { - auto login_window = std::make_unique("Log-in to Kiwi", - std::make_unique(), - false, false); + auto window = std::make_unique("Kiwi", + std::make_unique(type), + false, false); + window->centreWithSize(window->getWidth(), window->getHeight()); + window->enterModalState(true); - login_window->centreWithSize(400, 330); - login_window->enterModalState(true); - - return login_window; + return window; }); } diff --git a/Client/Source/KiwiApp_Application/KiwiApp_Instance.h b/Client/Source/KiwiApp_Application/KiwiApp_Instance.h index 643ecbb8..ba497ec9 100644 --- a/Client/Source/KiwiApp_Application/KiwiApp_Instance.h +++ b/Client/Source/KiwiApp_Application/KiwiApp_Instance.h @@ -36,6 +36,8 @@ #include "../KiwiApp_Patcher/KiwiApp_PatcherManager.h" #include "../KiwiApp_Audio/KiwiApp_DspDeviceManager.h" +#include "../KiwiApp_Auth/KiwiApp_AuthPanel.h" + namespace kiwi { class PatcherViewWindow; @@ -110,8 +112,8 @@ namespace kiwi //! @brief Brings the Console to front. void showConsoleWindow(); - //! @brief Brings the Login form window to front. - void showLoginWindow(); + //! @brief Brings the Auth form window to front. + void showAuthWindow(AuthPanel::FormType type); //! @brief Brings the "About Kiwi" window to front. void showAboutKiwiWindow(); diff --git a/Client/Source/KiwiApp_Auth/KiwiApp_AuthPanel.cpp b/Client/Source/KiwiApp_Auth/KiwiApp_AuthPanel.cpp new file mode 100644 index 00000000..1a790914 --- /dev/null +++ b/Client/Source/KiwiApp_Auth/KiwiApp_AuthPanel.cpp @@ -0,0 +1,251 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include "KiwiApp_AuthPanel.h" + +#include "../KiwiApp.h" +#include "../KiwiApp_General/KiwiApp_CommandIDs.h" + +namespace kiwi +{ + // ================================================================================ // + // LOGIN FORM // + // ================================================================================ // + + LoginForm::LoginForm() + : FormComponent("login", "login...") + { + addField(); + + addField("username", + KiwiApp::getCurrentUser().getName(), + "Username or Email"); + + addField("password", "", "Password"); + + addField("remember_me", + "Remember me", + getAppSettings().network().getRememberUserFlag()); + } + + void LoginForm::onUserSubmit() + { + const auto username = getFieldValue("username").toString(); + const auto password = getFieldValue("password").toString(); + const bool remember_me = getFieldValue("remember_me").getValue(); + + if(username.trim().length() < 3) + { + showAlert("Please enter a valid email address or username!", AlertBox::Type::Error); + return; + } + + if(password.trim().length() < 3) + { + showAlert("Please enter a valid password!", AlertBox::Type::Error); + return; + } + + showOverlay(); + + auto success_callback = [this, remember_me]() + { + KiwiApp::useInstance().useScheduler().schedule([this, remember_me]() { + + showSuccessOverlay("Login success !"); + + KiwiApp::useInstance().useScheduler().schedule([this, remember_me]() { + + getAppSettings().network().setRememberUserFlag(remember_me); + dismiss(); + + }, std::chrono::milliseconds(1000)); + + }, std::chrono::milliseconds(500)); + }; + + auto error_callback = [this](Api::Error error) + { + KiwiApp::useInstance().useScheduler().schedule([this, message = error.getMessage()]() { + + hideOverlay(); + showAlert(message, AlertBox::Type::Error); + + }, std::chrono::milliseconds(500)); + }; + + KiwiApp::login(username.toStdString(), + password.toStdString(), + std::move(success_callback), + std::move(error_callback)); + } + + // ================================================================================ // + // SIGNUP FORM // + // ================================================================================ // + + SignUpForm::SignUpForm() + : FormComponent("register", "register...") + { + addField(); + addField("username", "", "Username"); + addField("email", "", "Email"); + addField("password", "", "Password"); + //addField("password_check", "", "Password again..."); + } + + void SignUpForm::onUserSubmit() + { + const auto username = getFieldValue("username").toString(); + const auto email = getFieldValue("email").toString(); + const auto password = getFieldValue("password").toString(); + //const auto password_check = getFieldValue("password_check").toString(); + + if(username.trim().length() < 3) + { + showAlert("Please enter a valid user name!", AlertBox::Type::Error); + return; + } + + if(email.trim().length() < 3) + { + showAlert("Please enter a valid email address!", AlertBox::Type::Error); + return; + } + + if(password.trim().length() < 3) + { + showAlert("Please enter a valid password!", AlertBox::Type::Error); + return; + } + + /* + if(password != password_check) + { + showAlert("The two passwords must be the same!", AlertBox::Type::Error); + return; + } + */ + + showOverlay(); + + auto success_callback = [this]() + { + KiwiApp::useInstance().useScheduler().schedule([this]() { + + showSuccessOverlay("Registering success !"); + + KiwiApp::useInstance().useScheduler().schedule([this]() { + + if(AuthPanel* auth_panel = findParentComponentOfClass()) + { + hideOverlay(); + auth_panel->setCurrentTabIndex(AuthPanel::FormType::Login); + } + + }, std::chrono::milliseconds(1000)); + + }, std::chrono::milliseconds(500)); + }; + + auto error_callback = [this](Api::Error error) + { + KiwiApp::useInstance().useScheduler().schedule([this, message = error.getMessage()](){ + + hideOverlay(); + showAlert(message, AlertBox::Type::Error); + + }, std::chrono::milliseconds(500)); + }; + + KiwiApp::signup(username.toStdString(), + email.toStdString(), + password.toStdString(), + std::move(success_callback), + std::move(error_callback)); + } + + // ================================================================================ // + // AUTH PANEL // + // ================================================================================ // + + AuthPanel::AuthPanel(FormType form_type) + : juce::TabbedComponent(juce::TabbedButtonBar::Orientation::TabsAtTop) + , m_login_form() + , m_signup_form() + { + auto& lf = KiwiApp::useLookAndFeel(); + const auto bgcolor = lf.getCurrentColourScheme().getUIColour(juce::LookAndFeel_V4::ColourScheme::UIColour::windowBackground); + + addTab("Login", bgcolor, &m_login_form, false, static_cast(FormType::Login)); + addTab("Register", bgcolor, &m_signup_form, false, static_cast(FormType::SignUp)); + + m_login_form.addComponentListener(this); + m_signup_form.addComponentListener(this); + setCurrentTabIndex(static_cast(form_type)); + + setColour(juce::TabbedComponent::ColourIds::outlineColourId, juce::Colours::transparentBlack); + setColour(juce::TabbedComponent::ColourIds::backgroundColourId, bgcolor.contrasting(0.05)); + + const int width = 440; + m_login_form.setSize(width, m_login_form.getBestHeight()); + m_signup_form.setSize(width, m_signup_form.getBestHeight()); + + auto& current_comp = dynamic_cast(*getCurrentContentComponent()); + setSize(width, current_comp.getBestHeight()); + } + + AuthPanel::~AuthPanel() + { + ; + } + + void AuthPanel::updateSize(FormType type) + { + switch(type) + { + case FormType::Login: + { + setSize(getWidth(), m_login_form.getBestHeight()); + break; + } + case FormType::SignUp: + { + setSize(getWidth(), m_signup_form.getBestHeight()); + break; + } + default: break; + } + } + + void AuthPanel::currentTabChanged(int new_tab_index, juce::String const& /*new_tab_name*/) + { + updateSize(FormType(new_tab_index)); + } + + void AuthPanel::componentMovedOrResized(juce::Component& /*component*/, bool /*moved*/, bool resized) + { + if(resized) + { + updateSize(FormType(getCurrentTabIndex())); + } + } +} diff --git a/Client/Source/KiwiApp_Auth/KiwiApp_AuthPanel.h b/Client/Source/KiwiApp_Auth/KiwiApp_AuthPanel.h new file mode 100644 index 00000000..a6c8e5f7 --- /dev/null +++ b/Client/Source/KiwiApp_Auth/KiwiApp_AuthPanel.h @@ -0,0 +1,110 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include "../KiwiApp_Components/KiwiApp_FormComponent.h" + +namespace kiwi +{ + // ================================================================================ // + // LOGIN FORM // + // ================================================================================ // + + class LoginForm : public FormComponent + { + public: // methods + + //! @brief Constructor. + //! @details Creates a login form. + LoginForm(); + + //! @brief Destructor. + ~LoginForm() = default; + + private: // methods + + void onUserSubmit() override; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(LoginForm) + }; + + // ================================================================================ // + // SIGNUP FORM // + // ================================================================================ // + + class SignUpForm : public FormComponent + { + public: // methods + + //! @brief Constructor. + //! @details Creates a signup form. + SignUpForm(); + + //! @brief Destructor. + ~SignUpForm() = default; + + private: // methods + + void onUserSubmit() override; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(SignUpForm) + }; + + // ================================================================================ // + // AUTH PANEL // + // ================================================================================ // + + class AuthPanel + : public juce::TabbedComponent + , public juce::ComponentListener + { + public: // methods + + enum FormType + { + Login = 0, + SignUp, + UserProfile, + None, + }; + + AuthPanel(FormType form_type = FormType::None); + + ~AuthPanel(); + + private: // methods + + void updateSize(FormType type); + + //! @brief Callback method to indicate the selected tab has been changed. + void currentTabChanged(int new_tab_index, juce::String const& new_tab_name) override; + + void componentMovedOrResized(juce::Component& component, + bool wasMoved, + bool wasResized) override; + + private: // variables + + LoginForm m_login_form; + SignUpForm m_signup_form; + }; +} diff --git a/Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.cpp b/Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.cpp deleted file mode 100644 index 2a4e860d..00000000 --- a/Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.cpp +++ /dev/null @@ -1,392 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#include "KiwiApp_LoginForm.h" -#include "../KiwiApp.h" - -#include "../KiwiApp_Ressources/KiwiApp_BinaryData.h" - -namespace kiwi -{ - AlertBox::AlertBox(std::string const& message, - AlertBox::Type type, - bool can_cancel, - std::function on_close) - : m_message(message) - , m_type(type) - , m_close_fn(on_close) - { - if(can_cancel) - { - m_close_btn.reset(new juce::TextButton("X", "Close")); - m_close_btn->setColour(juce::TextButton::buttonColourId, juce::Colours::transparentBlack); - addAndMakeVisible(*m_close_btn); - m_close_btn->addListener(this); - } - } - - AlertBox::~AlertBox() - { - if(m_close_btn) - { - m_close_btn->removeListener(this); - } - } - - void AlertBox::paint(juce::Graphics& g) - { - const auto bgcolor = [](Type const& type) { - switch (type) { - case Type::Success: return juce::Colour::fromRGB(72, 175, 95); - case Type::Error: return juce::Colour::fromRGB(252, 99, 93); - default: return juce::Colours::grey; - } - }(m_type).withAlpha(1.f); - - g.setColour(bgcolor); - g.fillRoundedRectangle(getLocalBounds().reduced(1).toFloat(), 0.f); - - g.setFont(16.f); - g.setColour(bgcolor.contrasting(0.9)); - g.drawText(m_message, getLocalBounds().reduced(10), juce::Justification::verticallyCentred); - } - - void AlertBox::resized() - { - if(m_close_btn) - { - const int margin = 5; - const auto bounds = getLocalBounds(); - m_close_btn->setSize(20, 20); - m_close_btn->setTopRightPosition(bounds.getWidth() - margin, margin); - } - } - - void AlertBox::buttonClicked(juce::Button* b) - { - if(b == m_close_btn.get()) - { - if(m_close_fn) - { - m_close_fn(); - } - else - { - // close alert box - } - } - } - - struct Spinner : public juce::Component, private juce::Timer - { - Spinner() { startTimer(1000 / 50); } - void timerCallback() override { repaint(); } - - void paint(juce::Graphics& g) override - { - getLookAndFeel().drawSpinningWaitAnimation(g, juce::Colours::whitesmoke, 0, 0, getWidth(), getHeight()); - } - }; - - class LoginForm::OverlayComp : public juce::Component - { - public: // methods - - OverlayComp(juce::String message) - : m_message(message) - { - addAndMakeVisible(spinner); - } - - ~OverlayComp() = default; - - void paint(juce::Graphics& g) override - { - auto& lf = KiwiApp::useLookAndFeel(); - const auto bgcolor = lf.getCurrentColourScheme().getUIColour(juce::LookAndFeel_V4::ColourScheme::UIColour::windowBackground); - - g.fillAll(bgcolor.withAlpha(0.97f)); - - g.setColour(juce::Colours::whitesmoke); - g.setFont(22.0f); - - g.drawFittedText(m_message, - getLocalBounds().reduced(20, 0) - .removeFromTop(proportionOfHeight(0.6f)), - juce::Justification::centred, 5); - } - - void resized() override - { - const int spinnerSize = 40; - spinner.setBounds((getWidth() - spinnerSize) / 2, - proportionOfHeight(0.5f), - spinnerSize, spinnerSize); - } - - private: // variables - - Spinner spinner; - juce::String m_message; - - JUCE_LEAK_DETECTOR(LoginForm::OverlayComp); - }; - - static juce::juce_wchar getDefaultPasswordChar() noexcept - { - #if JUCE_LINUX - return 0x2022; - #else - return 0x25cf; - #endif - } - - LoginForm::LoginForm() - : m_password_box(juce::String(), getDefaultPasswordChar()) - , m_submit_btn(TRANS("Login")) - , m_cancel_btn(TRANS("Cancel")) - , m_remember_me_checkbox("Remember me") - , m_kiwi_app_image(juce::ImageCache::getFromMemory(binary_data::images::kiwi_icon_png, - binary_data::images::kiwi_icon_png_size)) - { - //(force use of a default system font to make sure it has the password blob character) - juce::Font font(juce::Font::getDefaultTypefaceForFont(juce::Font(juce::Font::getDefaultSansSerifFontName(), - juce::Font::getDefaultStyle(), 5.0f))); - - font.setHeight(22); - - m_email_box.setInputRestrictions(512); - m_email_box.setFont(font); - m_email_box.setText(KiwiApp::getCurrentUser().getName(), false); - - m_password_box.setInputRestrictions(64); - m_password_box.setFont(font); - - addAndMakeVisible(m_email_box); - addAndMakeVisible(m_password_box); - addAndMakeVisible(m_remember_me_checkbox); - addAndMakeVisible(m_submit_btn); - addAndMakeVisible(m_cancel_btn); - - m_remember_me_checkbox.setToggleState(getAppSettings().network().getRememberUserFlag(), - juce::NotificationType::dontSendNotification); - - m_email_box.setEscapeAndReturnKeysConsumed(false); - m_password_box.setEscapeAndReturnKeysConsumed(false); - - m_submit_btn.addShortcut(juce::KeyPress(juce::KeyPress::returnKey)); - - m_submit_btn.addListener(this); - m_cancel_btn.addListener(this); - - lookAndFeelChanged(); - setSize(400, 330); - resized(); - } - - LoginForm::~LoginForm() - { - m_overlay.deleteAndZero(); - } - - void LoginForm::paint(juce::Graphics& g) - { - auto& lf = KiwiApp::useLookAndFeel(); - const auto bgcolor = lf.getCurrentColourScheme().getUIColour(juce::LookAndFeel_V4::ColourScheme::UIColour::windowBackground); - - g.fillAll(bgcolor); - - float img_size = 100; - int padding = 15; - - auto bounds = getLocalBounds(); - bounds.removeFromTop((m_alert_box != nullptr) ? m_alert_box->getHeight() : 0); - - g.drawImage(m_kiwi_app_image, - bounds.reduced(padding) - .removeFromTop(img_size).toFloat(), - juce::RectanglePlacement::xMid, false); - } - - void LoginForm::resized() - { - const int alert_height = 50; - const int button_height = 35; - - juce::Rectangle r(getLocalBounds()); - - if(m_alert_box) - { - m_alert_box->setBounds(r.removeFromTop(alert_height)); - } - - r.removeFromTop(120); - - r.reduce(10, 10); - - const int boxHeight = 32; - - m_email_box.setBounds(r.removeFromTop(boxHeight)); - - r.removeFromTop(20); - m_password_box.setBounds(r.removeFromTop(boxHeight)); - - r.removeFromTop(10); - m_remember_me_checkbox.setBounds(r.removeFromTop(boxHeight)); - - r.removeFromTop(10); - juce::Rectangle buttonArea(r.removeFromTop(button_height)); - m_submit_btn.changeWidthToFitText(button_height); - m_cancel_btn.changeWidthToFitText(button_height); - - const int gap = 20; - buttonArea = buttonArea.withSizeKeepingCentre(m_submit_btn.getWidth() - +(m_cancel_btn.isVisible() ? gap + m_cancel_btn.getWidth() : 0), - button_height); - - m_submit_btn.setBounds(buttonArea.removeFromLeft(m_submit_btn.getWidth())); - buttonArea.removeFromLeft(gap); - m_cancel_btn.setBounds(buttonArea); - - if(m_overlay != nullptr) - { - m_overlay->setBounds(getLocalBounds()); - } - } - - void LoginForm::lookAndFeelChanged() - { - juce::Colour labelCol(findColour(juce::TextEditor::backgroundColourId).contrasting(0.5f)); - - m_email_box.setTextToShowWhenEmpty(TRANS("Username or Email"), labelCol); - m_password_box.setTextToShowWhenEmpty(TRANS("Password"), labelCol); - } - - void LoginForm::showOverlay() - { - if(m_overlay == nullptr) - { - addAndMakeVisible(m_overlay = new OverlayComp("login...")); - resized(); - } - } - - void LoginForm::hideOverlay() - { - if(m_overlay) - { - removeChildComponent(m_overlay); - m_overlay.deleteAndZero(); - } - } - - void LoginForm::showAlert(std::string const& message, AlertBox::Type type) - { - const bool was_showing = (m_alert_box != nullptr); - if(was_showing) - { - removeChildComponent(m_alert_box.get()); - } - - m_alert_box.reset(new AlertBox(message, type, true, [this](){ - removeChildComponent(m_alert_box.get()); - m_alert_box.reset(); - setBounds(getBounds().withHeight(getHeight() - 50)); - })); - - addAndMakeVisible(*m_alert_box); - - if(!was_showing) - { - setBounds(getBounds().withHeight(getHeight() + 50)); - } - else - { - resized(); - } - } - - void LoginForm::buttonClicked(juce::Button* b) - { - if(b == &m_submit_btn) - { - attemptRegistration(); - } - else if(b == &m_cancel_btn) - { - dismiss(); - } - } - - - void LoginForm::attemptRegistration() - { - if(m_overlay == nullptr) - { - if(m_email_box.getText().trim().length() < 3) - { - showAlert("Please enter a valid email address or username!", AlertBox::Type::Error); - return; - } - - if(m_password_box.getText().trim().length() < 3) - { - showAlert("Please enter a valid password!", AlertBox::Type::Error); - return; - } - - showOverlay(); - - auto success_callback = [this]() - { - KiwiApp::useInstance().useScheduler().schedule([this]() { - getAppSettings().network().setRememberUserFlag(m_remember_me_checkbox.getToggleState()); - dismiss(); - }, std::chrono::milliseconds(500)); - }; - - auto error_callback = [this](Api::Error error) - { - KiwiApp::useInstance().useScheduler().schedule([this, message = error.getMessage()](){ - - std::cout << "Error: " << message << "\n"; - - hideOverlay(); - showAlert(message, AlertBox::Type::Error); - - }, std::chrono::milliseconds(500)); - }; - - KiwiApp::login(m_email_box.getText().toStdString(), - m_password_box.getText().toStdString(), - std::move(success_callback), - std::move(error_callback)); - } - } - - void LoginForm::dismiss() - { - if(Window* parent_window = findParentComponentOfClass()) - { - parent_window->close(); - } - } -} diff --git a/Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.h b/Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.h deleted file mode 100644 index cee53fc6..00000000 --- a/Client/Source/KiwiApp_Auth/KiwiApp_LoginForm.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#pragma once - -#include - -namespace kiwi -{ - class AlertBox : public juce::Component, private juce::ButtonListener - { - public: // methods - - enum class Type : uint8_t - { - Info = 0, - Success = 1, - Error = 2 - }; - - //! @brief Constructor. - AlertBox(std::string const& message, - Type type = Type::Info, - bool can_cancel = true, - std::function on_close = nullptr); - - //! @brief Destructor. - ~AlertBox(); - - private: // methods - - //! @internal paint method - void paint(juce::Graphics&) override; - - //! @internal resized method - void resized() override; - - //! @internal juce::ButtonListener - void buttonClicked(juce::Button*) override; - - private: // variables - - std::string m_message; - Type m_type = Type::Info; - std::unique_ptr m_close_btn; - std::function m_close_fn; - }; - - class LoginForm : public juce::Component, private juce::ButtonListener - { - public: // methods - - //! @brief Constructor. - //! @details Creates a login form. - LoginForm(); - - //! @brief Destructor. - ~LoginForm(); - - //! @brief This is called when the form is dismissed - //! @details (either cancelled or when registration succeeds). - void dismiss(); - - private: // methods - - //! @internal paint method - void paint(juce::Graphics&) override; - - //! @internal resized method - void resized() override; - - //! @internal lookAndFeelChanged method - void lookAndFeelChanged() override; - - //! @internal Show overlay - void showOverlay(); - - //! @internal Hide overlay - void hideOverlay(); - - void showAlert(std::string const& message, AlertBox::Type type = AlertBox::Type::Error); - - void buttonClicked(juce::Button*) override; - void attemptRegistration(); - - private: // variables - - juce::TextEditor m_email_box, m_password_box; - juce::TextButton m_submit_btn, m_cancel_btn; - - juce::ToggleButton m_remember_me_checkbox; - - std::unique_ptr m_alert_box; - - juce::Image m_kiwi_app_image; - - class OverlayComp; - friend class OverlayComp; - Component::SafePointer m_overlay; - - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LoginForm) - }; -} diff --git a/Client/Source/KiwiApp_Components/KiwiApp_FormComponent.cpp b/Client/Source/KiwiApp_Components/KiwiApp_FormComponent.cpp new file mode 100644 index 00000000..fe439939 --- /dev/null +++ b/Client/Source/KiwiApp_Components/KiwiApp_FormComponent.cpp @@ -0,0 +1,523 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include "KiwiApp_FormComponent.h" + +#include "../KiwiApp.h" +#include "../KiwiApp_Ressources/KiwiApp_BinaryData.h" + +namespace kiwi +{ + // ================================================================================ // + // ALERT BOX // + // ================================================================================ // + + AlertBox::AlertBox(std::string const& message, + AlertBox::Type type, + bool can_cancel, + std::function on_close) + : m_message(message) + , m_type(type) + , m_close_fn(on_close) + { + if(can_cancel) + { + m_close_btn.reset(new juce::TextButton("X", "Close")); + m_close_btn->setColour(juce::TextButton::buttonColourId, juce::Colours::transparentBlack); + addAndMakeVisible(*m_close_btn); + m_close_btn->addListener(this); + } + } + + AlertBox::~AlertBox() + { + if(m_close_btn) + { + m_close_btn->removeListener(this); + } + } + + void AlertBox::paint(juce::Graphics& g) + { + const auto bgcolor = [](Type const& type) { + switch (type) { + case Type::Success: return juce::Colour::fromRGB(72, 175, 95); + case Type::Error: return juce::Colour::fromRGB(252, 99, 93); + default: return juce::Colours::grey; + } + }(m_type).withAlpha(1.f); + + g.setColour(bgcolor); + g.fillRoundedRectangle(getLocalBounds().reduced(1).toFloat(), 0.f); + + g.setFont(16.f); + g.setColour(bgcolor.contrasting(0.9)); + g.drawText(m_message, getLocalBounds().reduced(10), juce::Justification::verticallyCentred); + } + + void AlertBox::resized() + { + if(m_close_btn) + { + const int margin = 5; + const auto bounds = getLocalBounds(); + m_close_btn->setSize(20, 20); + m_close_btn->setTopRightPosition(bounds.getWidth() - margin, margin); + } + } + + void AlertBox::buttonClicked(juce::Button* b) + { + if(b == m_close_btn.get()) + { + if(m_close_fn) + { + m_close_fn(); + } + else + { + // close alert box + } + } + } + + // ================================================================================ // + // SPINNER // + // ================================================================================ // + + struct Spinner : public juce::Component, private juce::Timer + { + Spinner() { startTimer(1000 / 50); } + void timerCallback() override { repaint(); } + + void paint(juce::Graphics& g) override + { + getLookAndFeel().drawSpinningWaitAnimation(g, juce::Colours::whitesmoke, 0, 0, getWidth(), getHeight()); + } + }; + + // ================================================================================ // + // FORM COMPONENT OVERLAY // + // ================================================================================ // + + class FormComponent::OverlayComp : public juce::Component + { + public: // methods + + OverlayComp(juce::String message) + : m_message(message) + , m_show_success(false) + { + addAndMakeVisible(spinner); + } + + ~OverlayComp() = default; + + void paint(juce::Graphics& g) override + { + auto& lf = KiwiApp::useLookAndFeel(); + + const auto bgcolor = lf.getCurrentColourScheme().getUIColour(juce::LookAndFeel_V4::ColourScheme::UIColour::windowBackground); + + g.fillAll(bgcolor.withAlpha(0.97f)); + + g.setColour(juce::Colours::whitesmoke); + g.setFont(22.0f); + + g.drawFittedText(m_message, + getLocalBounds().reduced(20, 0) + .removeFromTop(proportionOfHeight(0.6f)), + juce::Justification::centred, 5); + } + + void resized() override + { + const int spinnerSize = 40; + spinner.setBounds((getWidth() - spinnerSize) / 2, + proportionOfHeight(0.5f), + spinnerSize, spinnerSize); + } + + void showSuccess(juce::String message) + { + m_show_success = true; + m_message = message; + spinner.setVisible(false); + repaint(); + } + + private: // variables + + Spinner spinner; + juce::String m_message; + bool m_show_success = false; + + JUCE_LEAK_DETECTOR(LoginForm::OverlayComp); + }; + + static juce::juce_wchar getDefaultPasswordChar() noexcept + { + #if JUCE_LINUX + return 0x2022; + #else + return 0x25cf; + #endif + } + + // ================================================================================ // + // FORM COMPONENT FIELD // + // ================================================================================ // + + FormComponent::Field::Field(std::string name) + : juce::Component(name) + , m_name(name) + { + ; + } + + std::string const& FormComponent::Field::getName() const + { + return m_name; + } + + int FormComponent::Field::getPreferedHeight() + { + return 32; + } + + // ================================================================================ // + // SINGLE LINE FIELD // + // ================================================================================ // + + FormComponent::Field::SingleLineText::SingleLineText(std::string name, + std::string text, + std::string placeholder_text) + : Field(name) + , m_text_editor() + { + //(force use of a default system font to make sure it has the password blob character) + static juce::Font font(juce::Font::getDefaultTypefaceForFont(juce::Font(juce::Font::getDefaultSansSerifFontName(), + juce::Font::getDefaultStyle(), 5.0f))); + m_text_editor.setFont(font.withHeight(22)); + + m_text_editor.setInputRestrictions(512); + m_text_editor.setText(text, false); + m_text_editor.setEscapeAndReturnKeysConsumed(false); + + juce::Colour labelCol(findColour(juce::TextEditor::backgroundColourId).contrasting(0.5f)); + m_text_editor.setTextToShowWhenEmpty(placeholder_text, labelCol); + + addAndMakeVisible(m_text_editor); + } + + juce::Value& FormComponent::Field::SingleLineText::getValue() + { + return m_text_editor.getTextValue(); + } + + void FormComponent::Field::SingleLineText::resized() + { + m_text_editor.setBounds(getLocalBounds()); + } + + // ================================================================================ // + // PASWWORD FIELD // + // ================================================================================ // + + FormComponent::Field::Password::Password(std::string name, + std::string text, + std::string placeholder_text) + : SingleLineText(name, text, placeholder_text) + { + m_text_editor.setPasswordCharacter(getDefaultPasswordChar()); + m_text_editor.setInputRestrictions(64); + } + + // ================================================================================ // + // TOGGLE BUTTON FIELD // + // ================================================================================ // + + FormComponent::Field::ToggleButton::ToggleButton(std::string name, + std::string text, + bool _default) + : Field(name) + , m_button(text) + { + m_button.setToggleState(_default, juce::NotificationType::dontSendNotification); + addAndMakeVisible(m_button); + } + + juce::Value& FormComponent::Field::ToggleButton::getValue() + { + return m_button.getToggleStateValue(); + } + + void FormComponent::Field::ToggleButton::resized() + { + m_button.setBounds(getLocalBounds()); + } + + int FormComponent::Field::ToggleButton::getPreferedHeight() + { + return 20; + } + + // ================================================================================ // + // KIWI LOGO FIELD // + // ================================================================================ // + + FormComponent::Field::KiwiLogo::KiwiLogo() + : Field("KiwiLogo") + , m_kiwi_app_image(juce::ImageCache::getFromMemory(binary_data::images::kiwi_icon_png, + binary_data::images::kiwi_icon_png_size)) + { + ; + } + + void FormComponent::Field::KiwiLogo::paint(juce::Graphics& g) + { + int padding = 0; + + auto bounds = getLocalBounds(); + + g.drawImage(m_kiwi_app_image, + bounds.reduced(padding).toFloat(), + juce::RectanglePlacement::xMid, false); + } + + juce::Value& FormComponent::Field::KiwiLogo::getValue() + { + return m_useless_value; + } + + int FormComponent::Field::KiwiLogo::getPreferedHeight() + { + return 100; + } + + // ================================================================================ // + // FORM COMPONENT // + // ================================================================================ // + + FormComponent::FormComponent(std::string const& submit_button_text, + std::string const& overlay_text) + : m_submit_button_text(submit_button_text) + , m_overlay_text(overlay_text) + , m_submit_btn(m_submit_button_text) + , m_cancel_btn(TRANS("Cancel")) + { + addAndMakeVisible(m_submit_btn); + addAndMakeVisible(m_cancel_btn); + m_submit_btn.addShortcut(juce::KeyPress(juce::KeyPress::returnKey)); + m_submit_btn.addListener(this); + m_cancel_btn.addListener(this); + } + + FormComponent::~FormComponent() + { + m_overlay.deleteAndZero(); + } + + void FormComponent::paint(juce::Graphics& g) + { + auto& lf = KiwiApp::useLookAndFeel(); + const auto bgcolor = lf.getCurrentColourScheme().getUIColour(juce::LookAndFeel_V4::ColourScheme::UIColour::windowBackground); + + g.fillAll(bgcolor); + + auto bounds = getLocalBounds(); + bounds.removeFromTop((m_alert_box != nullptr) ? m_alert_box->getHeight() : 0); + + g.setColour(bgcolor.contrasting(0.05)); + g.fillRect(getButtonArea()); + } + + void FormComponent::resized() + { + const auto bounds(getLocalBounds()); + auto r(bounds); + + if(m_alert_box) + { + const int alert_height = 50; + m_alert_box->setBounds(r.removeFromTop(alert_height)); + } + + r.reduce(10, 10); + + for(auto& field : m_fields) + { + field->setBounds(r.removeFromTop(field->getPreferedHeight())); + r.removeFromTop(20); + } + + const int button_height = 30; + m_submit_btn.changeWidthToFitText(button_height); + m_cancel_btn.changeWidthToFitText(button_height); + + const int gap = 15; + const int sep = 5; + auto buttonArea = getButtonArea().reduced(gap); + auto submit_bounds = buttonArea.removeFromLeft(buttonArea.getWidth()*0.5); + m_submit_btn.setTopRightPosition(submit_bounds.getRight() - sep, submit_bounds.getY()); + m_cancel_btn.setTopLeftPosition(buttonArea.getX() + sep, buttonArea.getY()); + + if(m_overlay != nullptr) + { + m_overlay->setBounds(bounds); + } + } + + juce::Rectangle FormComponent::getButtonArea() const + { + const int button_height = 30; + return {getLocalBounds().removeFromBottom(button_height*2)}; + } + + void FormComponent::showOverlay() + { + if(m_overlay == nullptr) + { + addAndMakeVisible(m_overlay = new OverlayComp(m_overlay_text)); + resized(); + } + } + + void FormComponent::showSuccessOverlay(juce::String const& message) + { + showOverlay(); + m_overlay->showSuccess(message); + } + + void FormComponent::hideOverlay() + { + if(m_overlay) + { + removeChildComponent(m_overlay); + m_overlay.deleteAndZero(); + } + } + + bool FormComponent::hasOverlay() + { + return (m_overlay != nullptr); + } + + void FormComponent::showAlert(std::string const& message, AlertBox::Type type) + { + const bool was_showing = (m_alert_box != nullptr); + if(was_showing) + { + removeChildComponent(m_alert_box.get()); + } + + const int alert_height = 50; + + m_alert_box.reset(new AlertBox(message, type, true, [this, alert_height](){ + removeChildComponent(m_alert_box.get()); + m_alert_box.reset(); + setBounds(getBounds().withHeight(getHeight() - alert_height)); + })); + + addAndMakeVisible(*m_alert_box); + + if(!was_showing) + { + setBounds(getBounds().withHeight(getHeight() + alert_height)); + } + else + { + resized(); + } + } + + void FormComponent::buttonClicked(juce::Button* b) + { + if(b == &m_submit_btn) + { + if(!hasOverlay()) + { + onUserSubmit(); + } + } + else if(b == &m_cancel_btn) + { + onUserCancelled(); + } + } + + void FormComponent::onUserCancelled() + { + dismiss(); + } + + void FormComponent::dismiss() + { + if(Window* parent_window = findParentComponentOfClass()) + { + parent_window->close(); + } + } + + juce::Value FormComponent::getFieldValue(std::string const& name) + { + for(auto& field : m_fields) + { + if(field->getName() == name) + { + return field->getValue(); + } + } + + return {}; + } + + int FormComponent::getFieldsHeight() + { + int total = 0; + for(auto& field : m_fields) + { + total += field->getPreferedHeight(); + } + + return total; + } + + int FormComponent::getBestHeight() + { + // TODO: add margin concept in Field to replace this messy hard typed height computation... + + int best_height = 0; + best_height += (m_alert_box != nullptr) ? m_alert_box->getHeight() : 0; + best_height += 10; + best_height += getFieldsHeight(); + + // field margin bottom + best_height += (m_fields.size() * 20); + + best_height += 10; + best_height += getButtonArea().getHeight(); + + best_height += 20; + + return best_height; + } +} diff --git a/Client/Source/KiwiApp_Components/KiwiApp_FormComponent.h b/Client/Source/KiwiApp_Components/KiwiApp_FormComponent.h new file mode 100644 index 00000000..a6e0bcba --- /dev/null +++ b/Client/Source/KiwiApp_Components/KiwiApp_FormComponent.h @@ -0,0 +1,284 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi +{ + // ================================================================================ // + // ALERT BOX // + // ================================================================================ // + + class AlertBox : public juce::Component, private juce::ButtonListener + { + public: // methods + + enum class Type : uint8_t + { + Info = 0, + Success = 1, + Error = 2 + }; + + //! @brief Constructor. + AlertBox(std::string const& message, + Type type = Type::Info, + bool can_cancel = true, + std::function on_close = nullptr); + + //! @brief Destructor. + ~AlertBox(); + + private: // methods + + //! @internal paint method + void paint(juce::Graphics&) override; + + //! @internal resized method + void resized() override; + + //! @internal juce::ButtonListener + void buttonClicked(juce::Button*) override; + + private: // variables + + std::string m_message; + Type m_type = Type::Info; + std::unique_ptr m_close_btn; + std::function m_close_fn; + }; + + // ================================================================================ // + // FORM COMPONENT // + // ================================================================================ // + + class FormComponent : public juce::Component, private juce::ButtonListener + { + public: // methods + + class Field; + + //! @brief Constructor. + //! @details Creates a login form. + FormComponent(std::string const& submit_button_text, + std::string const& overlay_text = ""); + + //! @brief Destructor. + virtual ~FormComponent(); + + //! @brief This is called when the form is dismissed + //! @details (either cancelled or when registration succeeds). + virtual void dismiss(); + + //! @brief Computes and returns the best height for this form. + //! @details It will be based on the number of fields and form components. + int getBestHeight(); + + protected: // methods + + //! @brief Add a new field. + template + FieldType& addField(Args&&... args); + + //! @brief Returns a field Value. + juce::Value getFieldValue(std::string const& name); + + //! @brief Show an Alert on the top of the form; + void showAlert(std::string const& message, + AlertBox::Type type = AlertBox::Type::Error); + + //! @brief Show overlay + void showOverlay(); + + //! @brief Show success overlay + void showSuccessOverlay(juce::String const& message); + + //! @brief Hide overlay + void hideOverlay(); + + //! @brief Returns true if the overlay component is visible. + bool hasOverlay(); + + //! @brief Called when the user clicked the submit button. + //! @details Subclasses need to override this to perform form submission. + virtual void onUserSubmit() = 0; + + //! @brief Called when the user clicked the cancel button. + //! @details The default implementation will call the dismiss() method, + //! Subclasses can override this to react to the user cancel action. + virtual void onUserCancelled(); + + //! @internal resized method + void resized() override; + + //! @brief Returns the height of all fields + int getFieldsHeight(); + + private: // methods + + //! @internal paint method + void paint(juce::Graphics&) override final; + + void buttonClicked(juce::Button*) override; + + juce::Rectangle getButtonArea() const; + + private: // variables + + std::string m_submit_button_text; + std::string m_overlay_text; + + juce::TextButton m_submit_btn, m_cancel_btn; + + std::unique_ptr m_alert_box; + + std::vector> m_fields; + + class OverlayComp; + friend class OverlayComp; + Component::SafePointer m_overlay; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(FormComponent) + }; + + // ================================================================================ // + // FORM COMPONENT FIELD // + // ================================================================================ // + + class FormComponent::Field : public juce::Component + { + public: // methods + + class SingleLineText; + class Password; + class ToggleButton; + class KiwiLogo; + + Field(std::string name); + + virtual ~Field() = default; + + std::string const& getName() const; + + virtual juce::Value& getValue() = 0; + + virtual int getPreferedHeight(); + + private: // variables + + std::string m_name; + }; + + // ================================================================================ // + // SINGLE LINE FIELD // + // ================================================================================ // + + class FormComponent::Field::SingleLineText : public Field + { + public: // methods + + SingleLineText(std::string name, std::string text, std::string placeholder_text); + + virtual ~SingleLineText() = default; + + juce::Value& getValue() override; + + void resized() override; + + protected: // variables + + juce::TextEditor m_text_editor; + }; + + // ================================================================================ // + // PASWWORD FIELD // + // ================================================================================ // + + class FormComponent::Field::Password : public SingleLineText + { + public: // methods + + Password(std::string name, std::string text, std::string placeholder_text); + ~Password() = default; + }; + + // ================================================================================ // + // TOGGLE BUTTON FIELD // + // ================================================================================ // + + class FormComponent::Field::ToggleButton : public Field + { + public: // methods + + ToggleButton(std::string name, std::string text, bool _default = false); + + ~ToggleButton() = default; + + juce::Value& getValue() override; + + void resized() override; + + int getPreferedHeight() override; + + private: // variables + + juce::ToggleButton m_button; + }; + + // ================================================================================ // + // KIWI LOGO FIELD // + // ================================================================================ // + + class FormComponent::Field::KiwiLogo : public Field + { + public: // methods + + KiwiLogo(); + + ~KiwiLogo() = default; + + void paint(juce::Graphics& g) override; + + juce::Value& getValue() override; + + int getPreferedHeight() override; + + private: // variables + + juce::Image m_kiwi_app_image; + juce::Value m_useless_value; + }; + + // ================================================================================ // + // FORM COMPONENT - template definitions // + // ================================================================================ // + + template + FieldType& FormComponent::addField(Args&&... args) + { + auto field = std::make_unique(std::forward(args)...); + addAndMakeVisible(*field); + auto it = m_fields.emplace(m_fields.end(), std::move(field)); + return dynamic_cast(*(it->get())); + } +} diff --git a/Client/Source/KiwiApp_Components/KiwiApp_Window.h b/Client/Source/KiwiApp_Components/KiwiApp_Window.h index 616f543d..ba29f92e 100644 --- a/Client/Source/KiwiApp_Components/KiwiApp_Window.h +++ b/Client/Source/KiwiApp_Components/KiwiApp_Window.h @@ -97,7 +97,7 @@ namespace kiwi enum class WindowId : std::size_t { Console = 0, - AuthForm, + FormComponent, AboutKiwi, DocumentBrowser, ApplicationSettings, diff --git a/Client/Source/KiwiApp_General/KiwiApp_CommandIDs.h b/Client/Source/KiwiApp_General/KiwiApp_CommandIDs.h index dc5ca39f..aa8a0e94 100644 --- a/Client/Source/KiwiApp_General/KiwiApp_CommandIDs.h +++ b/Client/Source/KiwiApp_General/KiwiApp_CommandIDs.h @@ -89,7 +89,7 @@ namespace kiwi clearAll = 0xf40001, ///< Clear all content login = 0xf50000, ///< Log-in the user. - signin = 0xf50010, ///< Sign-in the user. + signup = 0xf50010, ///< Register the user. logout = 0xf50020, ///< Log-out the user. remember_me = 0xf50030, ///< Toggle the "remember me" option to save user profile. }; diff --git a/Client/Source/KiwiApp_General/KiwiApp_StoredSettings.cpp b/Client/Source/KiwiApp_General/KiwiApp_StoredSettings.cpp index 0038cf23..5088e4ac 100644 --- a/Client/Source/KiwiApp_General/KiwiApp_StoredSettings.cpp +++ b/Client/Source/KiwiApp_General/KiwiApp_StoredSettings.cpp @@ -88,9 +88,15 @@ namespace kiwi json getJsonFromFile(juce::String const& filename) { - juce::File file = getPropertyFileOptionsFor(filename, "json").getDefaultFile(); - std::string json_user_str = file.loadFileAsString().toStdString(); - return json::parse(json_user_str); + const juce::File file = getPropertyFileOptionsFor(filename, "json").getDefaultFile(); + + if (file.exists()) + { + std::string json_user_str = file.loadFileAsString().toStdString(); + return json::parse(json_user_str); + } + + return {}; } // ================================================================================ // diff --git a/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp b/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp index 5ce14af3..09c7d0e0 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp +++ b/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp @@ -83,7 +83,7 @@ namespace kiwi if(j.is_object() && j.count("user")) { - AuthUser user(j["user"]); + AuthUser user(j["user"].get()); if(user.isLoggedIn()) { @@ -104,6 +104,56 @@ namespace kiwi storeFuture(session->PostAsync(std::move(cb))); } + void Api::signup(std::string const& username, + std::string const& email, + std::string const& password, + CallbackFn success_cb, + ErrorCallback error_cb) + { + assert(!username.empty()); + assert(!email.empty()); + assert(!password.empty()); + + auto session = makeSession(Endpoint::users, false); + + session->setPayload({ + {"username", username}, + {"email", email}, + {"password", password} + }); + + auto cb = [success = std::move(success_cb), + fail = std::move(error_cb)](Response res) + { + if (!res.error + && hasJsonHeader(res) + && res.result() == beast::http::status::ok) + { + const auto j = json::parse(res.body); + + if(j.is_object() && j.count("user")) + { + User user(j["user"]); + + if(user.isValid()) + { + success(std::move(user)); + } + else + { + fail({res.result_int(), "Failed to parse result"}); + } + + return; + } + } + + fail(res); + }; + + storeFuture(session->PostAsync(std::move(cb))); + } + void Api::getDocuments(std::function callback) { auto cb = [callback = std::move(callback)](Response res) @@ -295,6 +345,14 @@ namespace kiwi return m_api_version; } + void Api::User::resetWith(User const& other) + { + m_api_version = other.m_api_version; + m_id = other.m_id; + m_name = other.m_name; + m_email = other.m_email; + } + void to_json(json& j, Api::User const& user) { j = json{ @@ -317,14 +375,32 @@ namespace kiwi // API AUTH USER // // ================================================================================ // - /* - Api::AuthUser::AuthUser(AuthUser&& other) + Api::AuthUser::AuthUser(User const& other) : Api::User(other) + , m_token() + { + + } + + Api::AuthUser::AuthUser(AuthUser const& other) + : Api::User(other) + , m_token(other.getToken()) + { + + } + + Api::AuthUser::AuthUser(AuthUser&& other) + : Api::User(std::forward(other)) , m_token(std::move(other.m_token)) { } - */ + + void Api::AuthUser::resetWith(AuthUser const& other) + { + User::resetWith(static_cast(other)); + m_token = other.m_token; + } bool Api::AuthUser::isLoggedIn() const { diff --git a/Client/Source/KiwiApp_Network/KiwiApp_Api.h b/Client/Source/KiwiApp_Network/KiwiApp_Api.h index 6d283cd0..3127b5d0 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_Api.h +++ b/Client/Source/KiwiApp_Network/KiwiApp_Api.h @@ -71,7 +71,7 @@ namespace kiwi public: // requests - //! @brief Attempt to log the user in. + //! @brief Attempt to log-in the user. //! @param username_or_email user name or email address //! @param password password void login(std::string const& username_or_email, @@ -79,6 +79,16 @@ namespace kiwi CallbackFn success_cb, ErrorCallback error_cb); + //! @brief Attempt to register/signup the user. + //! @param username user name + //! @param email email address + //! @param password password + void signup(std::string const& username, + std::string const& email, + std::string const& password, + CallbackFn success_cb, + ErrorCallback error_cb); + //! @brief Make an async API request to get a list of documents void getDocuments(std::function callback); @@ -198,9 +208,7 @@ namespace kiwi //! @brief Returns true if the user has a valid id and email. bool isValid() const noexcept; - private: // deleted methods - - //User(User const&) = delete; + void resetWith(User const& other); private: // variables @@ -231,10 +239,16 @@ namespace kiwi AuthUser() = default; - //AuthUser(AuthUser&& other); + AuthUser(User const& other); + + AuthUser(AuthUser const& other); + + AuthUser(AuthUser && other); ~AuthUser() = default; + void resetWith(AuthUser const& other); + //! @brief Returns true if the user has a token. //! @see getToken bool isLoggedIn() const; @@ -245,8 +259,6 @@ namespace kiwi private: // variables - //AuthUser(AuthUser&& other) = default; - friend void from_json(json const&, Api::AuthUser&); friend Api::Controller; diff --git a/Client/Source/KiwiApp_Network/KiwiApp_ApiController.cpp b/Client/Source/KiwiApp_Network/KiwiApp_ApiController.cpp index 1ce17bfa..4e91bc52 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_ApiController.cpp +++ b/Client/Source/KiwiApp_Network/KiwiApp_ApiController.cpp @@ -54,13 +54,19 @@ namespace kiwi bool ApiController::saveAuthUserProfile() { - return saveJsonToFile("AuthUser", getAuthUser()); + return saveJsonToFile("UserProfile", {{"user", getAuthUser()}}); } bool ApiController::restoreAuthUserProfile() { - from_json(getJsonFromFile("AuthUser"), m_auth_user); - return true; + auto j = getJsonFromFile("UserProfile"); + if(j.count("user")) + { + from_json(j["user"], m_auth_user); + return true; + } + + return false; } void ApiController::networkSettingsChanged(NetworkSettings const& settings, @@ -96,7 +102,7 @@ namespace kiwi auto& scheduler = KiwiApp::useInstance().useScheduler(); scheduler.schedule([this, success_callback, user](){ - m_auth_user = std::move(user); + m_auth_user.resetWith(user); m_listeners.call(&ApiController::Listener::AuthUserChanged, m_auth_user); KiwiApp::commandStatusChanged(); @@ -108,6 +114,30 @@ namespace kiwi KiwiApp::useApi().login(name_or_email, password, std::move(success_cb), std::move(error_callback)); } + void ApiController::signup(std::string const& username, + std::string const& email, + std::string const& password, + std::function success_callback, + Api::ErrorCallback error_callback) + { + auto success_cb = [this, success_callback = std::move(success_callback)](Api::User user){ + + auto& scheduler = KiwiApp::useInstance().useScheduler(); + scheduler.schedule([this, success_callback, user](){ + + m_auth_user.resetWith(user); + m_listeners.call(&ApiController::Listener::AuthUserChanged, m_auth_user); + + KiwiApp::commandStatusChanged(); + + success_callback(); + }); + }; + + KiwiApp::useApi().signup(username, email, password, + std::move(success_cb), std::move(error_callback)); + } + void ApiController::logout() { Api::Controller::clearToken(); diff --git a/Client/Source/KiwiApp_Network/KiwiApp_ApiController.h b/Client/Source/KiwiApp_Network/KiwiApp_ApiController.h index f11a2d53..4a0cfdbc 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_ApiController.h +++ b/Client/Source/KiwiApp_Network/KiwiApp_ApiController.h @@ -27,7 +27,6 @@ #include "../KiwiApp_Network/KiwiApp_Api.h" #include "../KiwiApp_General/KiwiApp_StoredSettings.h" -#include "../KiwiApp_Auth/KiwiApp_LoginForm.h" namespace kiwi { @@ -69,6 +68,16 @@ namespace kiwi std::function success_callback, Api::ErrorCallback error_callback); + //! @brief Attempt to register/signup the user. + //! @param username user name + //! @param email email address + //! @param password password + void signup(std::string const& username, + std::string const& email, + std::string const& password, + std::function success_cb, + Api::ErrorCallback error_cb); + //! @brief Log-out the user. //! @see login, isUserLoggedIn void logout(); From d4479bc13fb5882ce3cf823b7a8fcbb0aebcce86 Mon Sep 17 00:00:00 2001 From: eliott PARIS Date: Sun, 27 Aug 2017 20:11:02 +0200 Subject: [PATCH 037/148] make Drive an ApiConnectStatusListener --- Client/Source/KiwiApp.cpp | 10 +++++++ Client/Source/KiwiApp.h | 8 ++++++ .../KiwiApp_DocumentBrowserView.cpp | 2 ++ .../KiwiApp_Network/KiwiApp_ApiController.cpp | 18 +++++------- .../KiwiApp_Network/KiwiApp_ApiController.h | 28 +++++++++---------- .../KiwiApp_DocumentBrowser.cpp | 23 +++++++++++++-- .../KiwiApp_Network/KiwiApp_DocumentBrowser.h | 11 +++++++- 7 files changed, 71 insertions(+), 29 deletions(-) diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index e156aa8c..5cdce585 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -249,6 +249,16 @@ namespace kiwi } } + void KiwiApp::addApiConnectStatusListener(ApiConnectStatusListener& listener) + { + KiwiApp::use().m_api_controller->addListener(listener); + } + + void KiwiApp::removeApiConnectStatusListener(ApiConnectStatusListener& listener) + { + KiwiApp::use().m_api_controller->removeListener(listener); + } + uint64_t KiwiApp::userID() { // refactor this (maybe a useless method) diff --git a/Client/Source/KiwiApp.h b/Client/Source/KiwiApp.h index 9c0f0dcc..15454755 100644 --- a/Client/Source/KiwiApp.h +++ b/Client/Source/KiwiApp.h @@ -121,6 +121,14 @@ namespace kiwi //! @brief Log-out the user static void logout(); + //! @brief Adds an api connect status listener. + //! @see ApiConnectStatusListener + static void addApiConnectStatusListener(ApiConnectStatusListener& listener); + + //! @brief Removes an api connect status listener. + //! @see ApiConnectStatusListener + static void removeApiConnectStatusListener(ApiConnectStatusListener& listener); + //! @brief Get the current running engine instance. static engine::Instance& useEngineInstance(); diff --git a/Client/Source/KiwiApp_Application/KiwiApp_DocumentBrowserView.cpp b/Client/Source/KiwiApp_Application/KiwiApp_DocumentBrowserView.cpp index e16fc00f..5126b794 100644 --- a/Client/Source/KiwiApp_Application/KiwiApp_DocumentBrowserView.cpp +++ b/Client/Source/KiwiApp_Application/KiwiApp_DocumentBrowserView.cpp @@ -280,6 +280,7 @@ namespace kiwi juce::RectanglePlacement::yMid, false); g.setColour(juce::Colours::whitesmoke); + g.setFont(18); g.drawFittedText(m_drive.getName(), bounds .withLeft(folder_img_bounds.getRight() + 10) @@ -327,6 +328,7 @@ namespace kiwi void DocumentBrowserView::DriveView::driveChanged() { updateContent(); + repaint(); } int DocumentBrowserView::DriveView::getNumRows() diff --git a/Client/Source/KiwiApp_Network/KiwiApp_ApiController.cpp b/Client/Source/KiwiApp_Network/KiwiApp_ApiController.cpp index 4e91bc52..7b8305b2 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_ApiController.cpp +++ b/Client/Source/KiwiApp_Network/KiwiApp_ApiController.cpp @@ -52,7 +52,7 @@ namespace kiwi saveAuthUserProfile(); } - bool ApiController::saveAuthUserProfile() + bool ApiController::saveAuthUserProfile() const { return saveJsonToFile("UserProfile", {{"user", getAuthUser()}}); } @@ -70,7 +70,7 @@ namespace kiwi } void ApiController::networkSettingsChanged(NetworkSettings const& settings, - const juce::Identifier& id) + juce::Identifier const& id) { if(id == Ids::host) { @@ -82,12 +82,12 @@ namespace kiwi } } - void ApiController::addListener(Listener& listener) + void ApiController::addListener(ApiConnectStatusListener& listener) { m_listeners.add(listener); } - void ApiController::removeListener(Listener& listener) + void ApiController::removeListener(ApiConnectStatusListener& listener) { m_listeners.remove(listener); } @@ -103,9 +103,7 @@ namespace kiwi scheduler.schedule([this, success_callback, user](){ m_auth_user.resetWith(user); - m_listeners.call(&ApiController::Listener::AuthUserChanged, m_auth_user); - - KiwiApp::commandStatusChanged(); + m_listeners.call(&ApiConnectStatusListener::userLoggedIn, m_auth_user); success_callback(); }); @@ -126,9 +124,7 @@ namespace kiwi scheduler.schedule([this, success_callback, user](){ m_auth_user.resetWith(user); - m_listeners.call(&ApiController::Listener::AuthUserChanged, m_auth_user); - - KiwiApp::commandStatusChanged(); + m_listeners.call(&ApiConnectStatusListener::authUserChanged, m_auth_user); success_callback(); }); @@ -141,6 +137,6 @@ namespace kiwi void ApiController::logout() { Api::Controller::clearToken(); - m_listeners.call(&ApiController::Listener::AuthUserChanged, getAuthUser()); + m_listeners.call(&ApiConnectStatusListener::userLoggedOut, getAuthUser()); } } diff --git a/Client/Source/KiwiApp_Network/KiwiApp_ApiController.h b/Client/Source/KiwiApp_Network/KiwiApp_ApiController.h index 4a0cfdbc..44fe92b4 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_ApiController.h +++ b/Client/Source/KiwiApp_Network/KiwiApp_ApiController.h @@ -23,26 +23,24 @@ #include -#include - #include "../KiwiApp_Network/KiwiApp_Api.h" #include "../KiwiApp_General/KiwiApp_StoredSettings.h" namespace kiwi { + struct ApiConnectStatusListener + { + virtual ~ApiConnectStatusListener() {} + + virtual void userLoggedIn(Api::AuthUser const&) = 0; + virtual void userLoggedOut(Api::AuthUser const&) = 0; + virtual void authUserChanged(Api::AuthUser const&) = 0; + }; + class ApiController : public Api::Controller , private NetworkSettings::Listener { - public: // nested classes - - struct Listener - { - virtual ~Listener() {} - virtual void userConnectedCallback(Api::AuthUser const&) = 0; - virtual void AuthUserChanged(Api::AuthUser const&) = 0; - }; - public: // methods //! @brief Constructor @@ -54,10 +52,10 @@ namespace kiwi ~ApiController(); //! @brief Adds a listener. - void addListener(Listener& listener); + void addListener(ApiConnectStatusListener& listener); //! @brief Removes a listener. - void removeListener(Listener& listener); + void removeListener(ApiConnectStatusListener& listener); //! @brief Attempt to log the client api user in (Async). //! @param name_or_email The name or email of the user. @@ -84,7 +82,7 @@ namespace kiwi private: // methods - bool saveAuthUserProfile(); + bool saveAuthUserProfile() const; bool restoreAuthUserProfile(); //! @brief Called when the network settings has changed. @@ -92,6 +90,6 @@ namespace kiwi private: // variables - engine::Listeners m_listeners; + engine::Listeners m_listeners; }; } diff --git a/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp b/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp index e64bac29..0ef218a6 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp +++ b/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp @@ -38,8 +38,9 @@ namespace kiwi m_distant_drive(nullptr) { auto& settings = getAppSettings().network(); + settings.addListener(*this); - m_distant_drive.reset(new Drive("Remote patchers", settings.getSessionPort())); + m_distant_drive.reset(new Drive("Remote Drive", settings.getSessionPort())); int time = settings.getRefreshInterval(); if(time > 0) @@ -47,11 +48,13 @@ namespace kiwi start(time); } - settings.addListener(*this); + authUserChanged(KiwiApp::getCurrentUser()); + KiwiApp::addApiConnectStatusListener(*this); } DocumentBrowser::~DocumentBrowser() { + KiwiApp::removeApiConnectStatusListener(*this); getAppSettings().network().removeListener(*this); stop(); } @@ -112,6 +115,21 @@ namespace kiwi m_distant_drive->refresh(); } + void DocumentBrowser::userLoggedIn(Api::AuthUser const& user) + { + m_distant_drive->setName(user.getName()); + } + + void DocumentBrowser::userLoggedOut(Api::AuthUser const&) + { + m_distant_drive->setName("logged out..."); + } + + void DocumentBrowser::authUserChanged(Api::AuthUser const& user) + { + m_distant_drive->setName(user.isLoggedIn() ? user.getName() : "logged out..."); + } + // ================================================================================ // // DOCUMENT BROWSER DRIVE // // ================================================================================ // @@ -147,6 +165,7 @@ namespace kiwi void DocumentBrowser::Drive::setName(std::string const& name) { m_name = name; + m_listeners.call(&Listener::driveChanged); } std::string const& DocumentBrowser::Drive::getName() const diff --git a/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.h b/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.h index 2363677d..cad0cd6a 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.h +++ b/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.h @@ -30,6 +30,8 @@ #include "../KiwiApp_General/KiwiApp_StoredSettings.h" +#include "KiwiApp_ApiController.h" + namespace kiwi { // ================================================================================ // @@ -37,7 +39,10 @@ namespace kiwi // ================================================================================ // //! @brief Request Patcher document informations through a Kiwi API. - class DocumentBrowser : public juce::Timer, public NetworkSettings::Listener + class DocumentBrowser + : public juce::Timer + , public NetworkSettings::Listener + , public ApiConnectStatusListener { public: // nested classes @@ -77,6 +82,10 @@ namespace kiwi void networkSettingsChanged(NetworkSettings const&, const juce::Identifier& id) override; + void userLoggedIn(Api::AuthUser const&) override; + void userLoggedOut(Api::AuthUser const&) override; + void authUserChanged(Api::AuthUser const&) override; + private: // variables std::unique_ptr m_distant_drive; From 8313891ad11a8dcba5e03064c9e255b96d640ee0 Mon Sep 17 00:00:00 2001 From: jean-millot Date: Wed, 30 Aug 2017 14:06:44 +0200 Subject: [PATCH 038/148] Add function defer to scheduler. --- .../KiwiApp_Application/KiwiApp_Console.cpp | 12 +- Modules/KiwiEngine/KiwiEngine_Objects.cpp | 15 +-- Modules/KiwiEngine/KiwiEngine_Scheduler.h | 15 +++ Modules/KiwiEngine/KiwiEngine_Scheduler.hpp | 44 ++++++ Test/Engine/test_Scheduler.cpp | 127 ++++++++++++++++++ 5 files changed, 193 insertions(+), 20 deletions(-) diff --git a/Client/Source/KiwiApp_Application/KiwiApp_Console.cpp b/Client/Source/KiwiApp_Application/KiwiApp_Console.cpp index 87cc4f8b..57863e0a 100644 --- a/Client/Source/KiwiApp_Application/KiwiApp_Console.cpp +++ b/Client/Source/KiwiApp_Application/KiwiApp_Console.cpp @@ -142,19 +142,11 @@ namespace kiwi { engine::Scheduler<> &scheduler = KiwiApp::useInstance().useScheduler(); - if (scheduler.isThisConsumerThread()) + scheduler.defer([this]() { m_table.updateContent(); m_table.repaint(); - } - else - { - scheduler.schedule([this]() - { - m_table.updateContent(); - m_table.repaint(); - }); - } + }); } // ================================================================================ // diff --git a/Modules/KiwiEngine/KiwiEngine_Objects.cpp b/Modules/KiwiEngine/KiwiEngine_Objects.cpp index b83e0ee2..c7ece93a 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects.cpp @@ -244,16 +244,11 @@ namespace kiwi { if (!args.empty()) { - if (!getScheduler().isThisConsumerThread()) - { - std::shared_ptr task(new Task(*this, args)); - getScheduler().schedule(task, std::chrono::milliseconds(0)); - m_tasks.insert(std::move(task)); - } - else - { - send(0, args); - } + std::shared_ptr task(new Task(*this, args)); + + m_tasks.insert(task); + + getScheduler().defer(task); } } diff --git a/Modules/KiwiEngine/KiwiEngine_Scheduler.h b/Modules/KiwiEngine/KiwiEngine_Scheduler.h index db7fcc25..9e3a8bb1 100644 --- a/Modules/KiwiEngine/KiwiEngine_Scheduler.h +++ b/Modules/KiwiEngine/KiwiEngine_Scheduler.h @@ -102,6 +102,21 @@ namespace kiwi //! @details Internally create a callback that will be executed and destroyed by the scheduler. void schedule(std::function && func, duration_t delay = std::chrono::milliseconds(0)); + //! @brief Conditionally schedule a task in the consumer thread. + //! @details The task is scheduled only if the calling thread is not the consumer thread. Otherwise + //! it is executed right away. + void defer(std::shared_ptr const& task); + + //! @brief Conditionally schedule a task in the consumer thread. + //! @details The task is scheduled only if the calling thread is not the consumer thread. + //! Otherwise it is executed right away. Task is destroyed when executed. + void defer(std::shared_ptr && task); + + //! @brief Conditionally schedule a function in the consumer thread. + //! @details The function is scheduled only if the calling thread is not the consumer thread. + //! Otherwise it is executed right away. + void defer(std::function && func); + //! @brief Used to cancel the execution of a previously scheduled task. //! @details If the task is currently being processed by the scheduler, this method does't //! wait for the execution to finish but only guarantee that further execution will no occur. diff --git a/Modules/KiwiEngine/KiwiEngine_Scheduler.hpp b/Modules/KiwiEngine/KiwiEngine_Scheduler.hpp index 03c9ca0a..3b85e9bf 100644 --- a/Modules/KiwiEngine/KiwiEngine_Scheduler.hpp +++ b/Modules/KiwiEngine/KiwiEngine_Scheduler.hpp @@ -75,6 +75,50 @@ namespace kiwi { schedule(std::make_shared(func), delay); } + + template + void Scheduler::defer(std::shared_ptr const& task) + { + assert(task); + + if (!isThisConsumerThread()) + { + schedule(task); + } + else + { + task->execute(); + } + } + + template + void Scheduler::defer(std::shared_ptr && task) + { + assert(task); + + if (!isThisConsumerThread()) + { + schedule(std::move(task)); + } + else + { + task->execute(); + task.reset(); + } + } + + template + void Scheduler::defer(std::function && func) + { + if (!isThisConsumerThread()) + { + schedule(std::move(func)); + } + else + { + func(); + } + } template void Scheduler::unschedule(std::shared_ptr const& task) diff --git a/Test/Engine/test_Scheduler.cpp b/Test/Engine/test_Scheduler.cpp index d50c26bb..dfb344bc 100644 --- a/Test/Engine/test_Scheduler.cpp +++ b/Test/Engine/test_Scheduler.cpp @@ -394,6 +394,133 @@ TEST_CASE("Scheduler", "[Scheduler]") sch.setThreadAsConsumer(); } + + SECTION("defering tasks") + { + class DeferTask : public engine::Scheduler<>::Task + { + public: + + DeferTask(std::atomic & thread): + m_thread(thread) + { + } + + void execute() override final + { + m_thread.store(std::this_thread::get_id()); + } + + private: + + std::atomic & m_thread; + + }; + + { + // copy + { + std::atomic exec_thread; + + std::shared_ptr::Task> task(new DeferTask(exec_thread)); + + sch.defer(task); + + CHECK(task.use_count() == 1); + CHECK(exec_thread == std::this_thread::get_id()); + } + + // move + { + std::atomic exec_thread; + + std::shared_ptr::Task> task(new DeferTask(exec_thread)); + + sch.defer(std::move(task)); + + CHECK(task.use_count() == 0); + CHECK(exec_thread == std::this_thread::get_id()); + } + + // function + { + std::atomic exec_thread; + + std::shared_ptr::Task> task(new DeferTask(exec_thread)); + + sch.defer([&exec_thread]() + { + exec_thread.store(std::this_thread::get_id()); + }); + + CHECK(exec_thread == std::this_thread::get_id()); + } + } + + { + std::atomic quit_requested(false); + + std::thread consumer([&sch, &quit_requested]() + { + sch.setThreadAsConsumer(); + + while(!quit_requested.load()) + { + sch.process(); + } + }); + + while(sch.isThisConsumerThread()){} + + // copy + { + std::atomic exec_thread; + + std::shared_ptr::Task> task(new DeferTask(exec_thread)); + + sch.schedule(task); + + while(exec_thread != consumer.get_id()){} + + CHECK(task.use_count() == 1); + CHECK(exec_thread == consumer.get_id()); + } + + // move + { + std::atomic exec_thread; + + std::shared_ptr::Task> task(new DeferTask(exec_thread)); + + sch.defer(std::move(task)); + + while(exec_thread == consumer.get_id()){} + + CHECK(task.use_count() == 0); + CHECK(exec_thread == consumer.get_id()); + } + + // function + { + std::atomic exec_thread; + + std::shared_ptr::Task> task(new DeferTask(exec_thread)); + + sch.defer([&exec_thread]() + { + exec_thread.store(std::this_thread::get_id()); + }); + + while(exec_thread != consumer.get_id()){} + + CHECK(exec_thread == consumer.get_id()); + } + + quit_requested.store(true); + + consumer.join(); + } + } } } From ef4b87e2601720fc72fef22665b8538fccf8a7cb Mon Sep 17 00:00:00 2001 From: jean-millot Date: Thu, 31 Aug 2017 12:27:54 +0200 Subject: [PATCH 039/148] Separate code for all objects creating categories. --- .../KiwiApp_Patcher/KiwiApp_ObjectView.cpp | 3 +- .../KiwiApp_Patcher/KiwiApp_PatcherView.cpp | 4 +- .../KiwiEngine/KiwiEngine_CircularBuffer.h | 2 + Modules/KiwiEngine/KiwiEngine_Factory.cpp | 2 +- Modules/KiwiEngine/KiwiEngine_Factory.h | 2 +- Modules/KiwiEngine/KiwiEngine_Instance.cpp | 2 +- Modules/KiwiEngine/KiwiEngine_Object.h | 2 + Modules/KiwiEngine/KiwiEngine_Objects.cpp | 1063 ----------------- Modules/KiwiEngine/KiwiEngine_Objects.h | 473 -------- .../KiwiEngine_Basic/KiwiEngine_ErrorBox.cpp | 48 + .../KiwiEngine_Basic/KiwiEngine_ErrorBox.h | 45 + .../KiwiEngine_Basic/KiwiEngine_NewBox.cpp | 43 + .../KiwiEngine_Basic/KiwiEngine_NewBox.h | 42 + .../KiwiEngine_Dsp/KiwiEngine_AdcTilde.cpp | 58 + .../KiwiEngine_Dsp/KiwiEngine_AdcTilde.h | 46 + .../KiwiEngine_Dsp/KiwiEngine_DacTilde.cpp | 58 + .../KiwiEngine_Dsp/KiwiEngine_DacTilde.h | 45 + .../KiwiEngine_DelaySimpleTilde.cpp | 155 +++ .../KiwiEngine_DelaySimpleTilde.h | 70 ++ .../KiwiEngine_Dsp/KiwiEngine_OscTilde.cpp | 154 +++ .../KiwiEngine_Dsp/KiwiEngine_OscTilde.h | 68 ++ .../KiwiEngine_Dsp/KiwiEngine_PlusTilde.cpp | 104 ++ .../KiwiEngine_Dsp/KiwiEngine_PlusTilde.h | 54 + .../KiwiEngine_Dsp/KiwiEngine_SigTilde.cpp | 66 + .../KiwiEngine_Dsp/KiwiEngine_SigTilde.h | 51 + .../KiwiEngine_Dsp/KiwiEngine_TimesTilde.cpp | 102 ++ .../KiwiEngine_Dsp/KiwiEngine_TimesTilde.h | 54 + .../KiwiEngine_Math/KiwiEngine_Plus.cpp | 71 ++ .../KiwiEngine_Math/KiwiEngine_Plus.h | 50 + .../KiwiEngine_Math/KiwiEngine_Times.cpp | 70 ++ .../KiwiEngine_Math/KiwiEngine_Times.h | 50 + .../KiwiEngine_Loadmess.cpp | 50 + .../KiwiEngine_Message/KiwiEngine_Loadmess.h | 51 + .../KiwiEngine_Message/KiwiEngine_Print.cpp | 47 + .../KiwiEngine_Message/KiwiEngine_Print.h | 46 + .../KiwiEngine_Message/KiwiEngine_Receive.cpp | 111 ++ .../KiwiEngine_Message/KiwiEngine_Receive.h | 56 + .../KiwiEngine_Objects/KiwiEngine_Objects.h | 64 + .../KiwiEngine_Time/KiwiEngine_Delay.cpp | 85 ++ .../KiwiEngine_Time/KiwiEngine_Delay.h | 60 + .../KiwiEngine_Time/KiwiEngine_Metro.cpp | 80 ++ .../KiwiEngine_Time/KiwiEngine_Metro.h | 51 + .../KiwiEngine_Time/KiwiEngine_Pipe.cpp | 102 ++ .../KiwiEngine_Time/KiwiEngine_Pipe.h | 54 + .../KiwiEngine_AudioInterface.cpp | 95 ++ .../KiwiEngine_AudioInterface.h | 55 + .../KiwiEngine_Utils/KiwiEngine_Router.cpp | 64 + .../KiwiEngine_Utils/KiwiEngine_Router.h | 68 ++ Modules/KiwiModel/KiwiModel_DataModel.cpp | 2 +- Modules/KiwiModel/KiwiModel_Objects.cpp | 639 ---------- Modules/KiwiModel/KiwiModel_Objects.h | 379 ------ .../KiwiModel_Basic/KiwiModel_ErrorBox.cpp | 58 + .../KiwiModel_Basic/KiwiModel_ErrorBox.h | 58 + .../KiwiModel_Basic/KiwiModel_NewBox.cpp | 49 + .../KiwiModel_Basic/KiwiModel_NewBox.h | 50 + .../KiwiModel_Dsp/KiwiModel_AdcTilde.cpp | 125 ++ .../KiwiModel_Dsp/KiwiModel_AdcTilde.h | 54 + .../KiwiModel_Dsp/KiwiModel_DacTilde.cpp | 128 ++ .../KiwiModel_Dsp/KiwiModel_DacTilde.h | 53 + .../KiwiModel_DelaySimpleTilde.cpp | 78 ++ .../KiwiModel_DelaySimpleTilde.h | 50 + .../KiwiModel_Dsp/KiwiModel_OscTilde.cpp | 68 ++ .../KiwiModel_Dsp/KiwiModel_OscTilde.h | 49 + .../KiwiModel_Dsp/KiwiModel_PlusTilde.cpp | 56 + .../KiwiModel_Dsp/KiwiModel_PlusTilde.h | 50 + .../KiwiModel_Dsp/KiwiModel_SigTilde.cpp | 54 + .../KiwiModel_Dsp/KiwiModel_SigTilde.h | 50 + .../KiwiModel_Dsp/KiwiModel_TimesTilde.cpp | 56 + .../KiwiModel_Dsp/KiwiModel_TimesTilde.h | 50 + .../KiwiModel_Math/KiwiModel_Plus.cpp | 56 + .../KiwiModel_Math/KiwiModel_Plus.h | 50 + .../KiwiModel_Math/KiwiModel_Times.cpp | 56 + .../KiwiModel_Math/KiwiModel_Times.h | 50 + .../KiwiModel_Message/KiwiModel_Loadmess.cpp | 54 + .../KiwiModel_Message/KiwiModel_Loadmess.h | 50 + .../KiwiModel_Message/KiwiModel_Print.cpp | 49 + .../KiwiModel_Message/KiwiModel_Print.h | 50 + .../KiwiModel_Message/KiwiModel_Receive.cpp | 54 + .../KiwiModel_Message/KiwiModel_Receive.h | 50 + .../KiwiModel_Objects/KiwiModel_Objects.h | 64 + .../KiwiModel_Time/KiwiModel_Delay.cpp | 77 ++ .../KiwiModel_Time/KiwiModel_Delay.h | 50 + .../KiwiModel_Time/KiwiModel_Metro.cpp | 76 ++ .../KiwiModel_Time/KiwiModel_Metro.h | 50 + .../KiwiModel_Time/KiwiModel_Pipe.cpp | 77 ++ .../KiwiModel_Time/KiwiModel_Pipe.h | 50 + 86 files changed, 4755 insertions(+), 2560 deletions(-) delete mode 100644 Modules/KiwiEngine/KiwiEngine_Objects.cpp delete mode 100644 Modules/KiwiEngine/KiwiEngine_Objects.h create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Basic/KiwiEngine_ErrorBox.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Basic/KiwiEngine_ErrorBox.h create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Basic/KiwiEngine_NewBox.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Basic/KiwiEngine_NewBox.h create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_AdcTilde.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_AdcTilde.h create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_DacTilde.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_DacTilde.h create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_DelaySimpleTilde.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_DelaySimpleTilde.h create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_OscTilde.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_OscTilde.h create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_PlusTilde.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_PlusTilde.h create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_SigTilde.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_SigTilde.h create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_TimesTilde.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_TimesTilde.h create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Math/KiwiEngine_Plus.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Math/KiwiEngine_Plus.h create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Math/KiwiEngine_Times.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Math/KiwiEngine_Times.h create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Loadmess.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Loadmess.h create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Print.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Print.h create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Receive.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Receive.h create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Delay.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Delay.h create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Metro.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Metro.h create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Pipe.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Pipe.h create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Utils/KiwiEngine_AudioInterface.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Utils/KiwiEngine_AudioInterface.h create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Utils/KiwiEngine_Router.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Utils/KiwiEngine_Router.h delete mode 100755 Modules/KiwiModel/KiwiModel_Objects.cpp delete mode 100755 Modules/KiwiModel/KiwiModel_Objects.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_ErrorBox.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_ErrorBox.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_NewBox.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_NewBox.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_AdcTilde.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_AdcTilde.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_DacTilde.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_DacTilde.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_DelaySimpleTilde.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_DelaySimpleTilde.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_OscTilde.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_OscTilde.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_PlusTilde.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_PlusTilde.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_SigTilde.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_SigTilde.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_TimesTilde.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_TimesTilde.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Math/KiwiModel_Plus.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Math/KiwiModel_Plus.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Math/KiwiModel_Times.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Math/KiwiModel_Times.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Loadmess.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Loadmess.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Print.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Print.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Receive.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Receive.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Delay.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Delay.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Metro.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Metro.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Pipe.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Pipe.h diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_ObjectView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_ObjectView.cpp index e798252d..bb929fb5 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_ObjectView.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_ObjectView.cpp @@ -20,7 +20,8 @@ */ #include -#include +#include +#include #include "../KiwiApp.h" #include "../KiwiApp_Network/KiwiApp_DocumentManager.h" diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp index 85fa87a2..90e4ee34 100755 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp @@ -19,7 +19,9 @@ ============================================================================== */ -#include +#include +#include +#include #include "KiwiApp_PatcherView.h" diff --git a/Modules/KiwiEngine/KiwiEngine_CircularBuffer.h b/Modules/KiwiEngine/KiwiEngine_CircularBuffer.h index 57a5c2bd..2ccdaea8 100644 --- a/Modules/KiwiEngine/KiwiEngine_CircularBuffer.h +++ b/Modules/KiwiEngine/KiwiEngine_CircularBuffer.h @@ -21,7 +21,9 @@ #pragma once +#include #include +#include namespace kiwi { diff --git a/Modules/KiwiEngine/KiwiEngine_Factory.cpp b/Modules/KiwiEngine/KiwiEngine_Factory.cpp index f3293114..0f7ed335 100644 --- a/Modules/KiwiEngine/KiwiEngine_Factory.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Factory.cpp @@ -22,7 +22,7 @@ #include #include "KiwiEngine_Factory.h" -#include "KiwiEngine_Objects.h" + namespace kiwi { diff --git a/Modules/KiwiEngine/KiwiEngine_Factory.h b/Modules/KiwiEngine/KiwiEngine_Factory.h index 4fb2a85e..1f896cfb 100644 --- a/Modules/KiwiEngine/KiwiEngine_Factory.h +++ b/Modules/KiwiEngine/KiwiEngine_Factory.h @@ -21,7 +21,7 @@ #pragma once -#include "KiwiEngine_Def.h" +#include namespace kiwi { diff --git a/Modules/KiwiEngine/KiwiEngine_Instance.cpp b/Modules/KiwiEngine/KiwiEngine_Instance.cpp index 3e872e29..cd532374 100644 --- a/Modules/KiwiEngine/KiwiEngine_Instance.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Instance.cpp @@ -20,7 +20,7 @@ */ #include "KiwiEngine_Factory.h" -#include "KiwiEngine_Objects.h" +#include #include "KiwiEngine_Instance.h" namespace kiwi diff --git a/Modules/KiwiEngine/KiwiEngine_Object.h b/Modules/KiwiEngine/KiwiEngine_Object.h index 82355346..06990f99 100644 --- a/Modules/KiwiEngine/KiwiEngine_Object.h +++ b/Modules/KiwiEngine/KiwiEngine_Object.h @@ -24,6 +24,8 @@ #include "KiwiEngine_Def.h" #include "KiwiEngine_Scheduler.h" +#include + #include namespace kiwi diff --git a/Modules/KiwiEngine/KiwiEngine_Objects.cpp b/Modules/KiwiEngine/KiwiEngine_Objects.cpp deleted file mode 100644 index c7ece93a..00000000 --- a/Modules/KiwiEngine/KiwiEngine_Objects.cpp +++ /dev/null @@ -1,1063 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#ifndef KIWI_ENGINE_OBJECTS_HPP_INCLUDED -#define KIWI_ENGINE_OBJECTS_HPP_INCLUDED - -#include -#include - -#include "KiwiEngine_Console.h" -#include "KiwiEngine_Objects.h" -#include "KiwiEngine_Patcher.h" - -namespace kiwi -{ - namespace engine - { - // ================================================================================ // - // NEWBOX // - // ================================================================================ // - - NewBox::NewBox(model::Object const& model, Patcher& patcher, std::vector const& args) - : Object(model, patcher) - { - ; - } - - void NewBox::receive(size_t index, std::vector const& args) - { - ; - } - - // ================================================================================ // - // ERRORBOX // - // ================================================================================ // - - ErrorBox::ErrorBox(model::Object const& model, Patcher& patcher, std::vector const& args) - : AudioObject(model, patcher) - { - ; - } - - void ErrorBox::receive(size_t index, std::vector const& args) - { - ; - } - - void ErrorBox::prepare(dsp::Processor::PrepareInfo const& infos) - { - ; - } - - // ================================================================================ // - // OBJECT PLUS // - // ================================================================================ // - - Plus::Plus(model::Object const& model, Patcher& patcher, std::vector const& args) - : Object(model, patcher) - { - m_lhs = 0.; - if(!args.empty() && args[0].isNumber()) - { - m_rhs = args[0].getFloat(); - } - } - - void Plus::receive(size_t index, std::vector const& args) - { - if(!args.empty()) - { - if(args[0].isNumber()) - { - if(index == 0) - { - m_lhs = args[0].getFloat(); - bang(); - } - else if(index == 1) - { - m_rhs = args[0].getFloat(); - } - } - else if(index == 0 && args[0].getString() == "bang") - { - bang(); - } - } - } - - void Plus::bang() - { - send(0, {m_rhs + m_lhs}); - } - - // ================================================================================ // - // OBJECT TIMES // - // ================================================================================ // - - Times::Times(model::Object const& model, Patcher& patcher, std::vector const& args) - : Object(model, patcher) - { - m_lhs = 0.; - if(!args.empty() && args[0].isNumber()) - { - m_rhs = args[0].getFloat(); - } - } - - void Times::receive(size_t index, std::vector const& args) - { - if(!args.empty()) - { - if(args[0].isNumber()) - { - if(index == 0) - { - m_lhs = args[0].getFloat(); - bang(); - } - else if(index == 1) - { - m_rhs = args[0].getFloat(); - } - } - else if(index == 0 && args[0].getString() == "bang") - { - bang(); - } - } - } - - void Times::bang() - { - send(0, {m_rhs * m_lhs}); - } - - // ================================================================================ // - // OBJECT PRINT // - // ================================================================================ // - - Print::Print(model::Object const& model, Patcher& patcher, std::vector const& args) - : Object(model, patcher) - { - m_name = !args.empty() ? args[0].getString() : "print"; - } - - void Print::receive(size_t, std::vector const& args) - { - if(!args.empty()) - { - post(m_name + " \xe2\x80\xa2 " + AtomHelper::toString(args)); - } - } - - // ================================================================================ // - // OBJECT RECEIVE // - // ================================================================================ // - - class Receive::Task final : public Scheduler<>::Task - { - public: // methods - - Task(Receive& object, std::vector const& atoms): - Scheduler<>::Task(), - m_object(object), - m_atoms(atoms) - { - } - - ~Task() - { - } - - void execute() override - { - m_object.send(0, m_atoms); - - m_object.m_tasks.erase(std::find_if(m_object.m_tasks.begin(), - m_object.m_tasks.end(), - [this](std::shared_ptr const& task) - { - return task.get() == this; - })); - } - - private: // members - - Receive& m_object; - std::vector m_atoms; - }; - - Receive::Receive(model::Object const& model, Patcher& patcher, std::vector const& args): - Object(model, patcher), - m_name(), - m_tasks() - { - m_name = !args.empty() ? args[0].getString() : ""; - - if(!m_name.empty()) - { - Beacon& beacon = getBeacon(m_name); - beacon.bind(*this); - } - } - - Receive::~Receive() - { - for (std::shared_ptr const& task : m_tasks) - { - getScheduler().unschedule(task); - } - - if(!m_name.empty()) - { - Beacon& beacon = getBeacon(m_name); - beacon.unbind(*this); - } - } - - void Receive::receive(size_t, std::vector const& args) - { - - } - - void Receive::receive(std::vector const& args) - { - if (!args.empty()) - { - std::shared_ptr task(new Task(*this, args)); - - m_tasks.insert(task); - - getScheduler().defer(task); - } - } - - // ================================================================================ // - // OBJECT LOADMESS // - // ================================================================================ // - - Loadmess::Loadmess(model::Object const& model, Patcher& patcher, std::vector const& args) - : Object(model, patcher), - m_args(args) - { - ; - } - - void Loadmess::receive(size_t, std::vector const& args) - { - send(0ul, m_args); - } - - void Loadmess::loadbang() - { - send(0ul, m_args); - } - - // ================================================================================ // - // OBJECT DELAY // - // ================================================================================ // - - Delay::Task::Task(Delay& object): - Scheduler<>::Task(), - m_object(object) - { - } - - void Delay::Task::execute() - { - m_object.send(0, {"bang"}); - } - - Delay::Delay(model::Object const& model, Patcher& patcher, std::vector const& args): - Object(model, patcher), - m_task(new Task(*this)), - m_delay(std::chrono::milliseconds(0)) - { - if (!args.empty()) - { - m_delay = std::chrono::milliseconds(args[0].getInt()); - } - } - - Delay::~Delay() - { - getScheduler().unschedule(m_task); - } - - void Delay::receive(size_t index, std::vector const& args) - { - if (!args.empty()) - { - if (index == 0) - { - if(args[0].isString() && args[0].getString() == "bang") - { - getScheduler().schedule(m_task, m_delay); - } - else if(args[0].isString() && args[0].getString() == "stop") - { - getScheduler().unschedule(m_task); - } - } - else if(index == 1) - { - if (args[0].isNumber()) - { - m_delay = std::chrono::milliseconds(args[0].getInt()); - } - } - } - } - - // ================================================================================ // - // OBJECT PIPE // - // ================================================================================ // - - class Pipe::Task final : public Scheduler<>::Task - { - public: // methods - - Task(Pipe & object, std::vector const& atoms): - Scheduler<>::Task(), - m_object(object), - m_atoms(atoms) - { - } - - ~Task() - { - } - - void execute() - { - m_object.send(0, m_atoms); - - m_object.m_tasks.erase(std::find_if(m_object.m_tasks.begin(), - m_object.m_tasks.end(), - [this](std::shared_ptr const& task) - { - return task.get() == this; - })); - } - - private: // members - - Pipe& m_object; - std::vector m_atoms; - }; - - Pipe::Pipe(model::Object const& model, Patcher& patcher, std::vector const& args): - Object(model, patcher), - m_tasks(), - m_delay(std::chrono::milliseconds(0)) - { - if (!args.empty()) - { - m_delay = std::chrono::milliseconds(args[0].getInt()); - } - } - - Pipe::~Pipe() - { - for (std::shared_ptr const& task : m_tasks) - { - getScheduler().unschedule(task); - } - } - - void Pipe::receive(size_t index, std::vector const& args) - { - if (!args.empty()) - { - if (index == 0) - { - std::shared_ptr task(new Task(*this, args)); - getScheduler().schedule(task, m_delay); - m_tasks.insert(std::move(task)); - } - else if(index == 1 && args[0].isNumber()) - { - m_delay = std::chrono::milliseconds(args[0].getInt()); - } - } - } - - // ================================================================================ // - // OBJECT METRO // - // ================================================================================ // - - Metro::Metro(model::Object const& model, Patcher& patcher, std::vector const& args): - engine::Object(model, patcher), - Scheduler<>::Timer(patcher.getScheduler()), - m_period(std::chrono::milliseconds(0)) - { - if(!args.empty()) - { - m_period = std::chrono::milliseconds(args[0].getInt()); - } - } - - Metro::~Metro() - { - } - - void Metro::receive(size_t index, std::vector const& args) - { - if (!args.empty()) - { - if (index == 0) - { - if((args[0].isString() && args[0].getString() == "start") - || (args[0].isNumber() && static_cast(args[0].getInt()))) - { - startTimer(m_period); - } - else if((args[0].isString() && args[0].getString() == "stop") - || (args[0].isNumber() && !static_cast(args[0].getInt()))) - { - stopTimer(); - } - } - else if(index == 1) - { - if (args[0].isNumber()) - { - m_period = std::chrono::milliseconds(args[0].getInt()); - } - } - } - } - - void Metro::timerCallBack() - { - send(0, {"bang"}); - } - - // ================================================================================ // - // ROUTER // - // ================================================================================ // - - Router::Cnx::Cnx(size_t input, size_t output): - m_input(input), - m_output(output) - { - } - - bool Router::Cnx::operator<(Cnx const& other) const - { - return m_input < other.m_input - || (m_input == other.m_input && m_output < other.m_output); - } - - void Router::connect(size_t input_index, size_t output_index) - { - m_cnx.insert(Cnx(input_index, output_index)); - } - - void Router::disconnect(size_t input_index, size_t ouptut_index) - { - m_cnx.erase(Cnx(input_index, ouptut_index)); - } - - size_t Router::getNumberOfConnections() const - { - return m_cnx.size(); - } - - std::set const& Router::getConnections() const - { - return m_cnx; - } - - // ================================================================================ // - // AUDIOINTERFACE // - // ================================================================================ // - - AudioInterfaceObject::AudioInterfaceObject(model::Object const& model, - Patcher& patcher, - std::vector const& args): - AudioObject(model, patcher), - m_router(), - m_audio_controler(patcher.getAudioControler()) - { - } - - std::vector AudioInterfaceObject::parseArgs(std::vector const& args) const - { - std::vector routes; - - for(Atom const& arg : args) - { - if (arg.isNumber()) - { - routes.push_back(arg.getInt() - 1); - } - else if(arg.isString()) - { - std::string inputs(arg.getString()); - - int left_input = std::stoi(inputs.substr(0, inputs.find(":"))) - 1; - int right_input = std::stoi(inputs.substr(inputs.find(":") + 1)) - 1; - - bool rev = left_input > right_input; - - for (int channel = left_input; rev ? channel >= right_input : channel <= right_input; rev ? --channel : ++channel) - { - routes.push_back(channel); - } - } - } - - if (routes.empty()) - { - routes = {0, 1}; - } - - return routes; - } - - void AudioInterfaceObject::receive(size_t index, std::vector const & args) - { - if(!args.empty()) - { - if(args[0].isString()) - { - const std::string sym = args[0].getString(); - - if(sym == "start") - { - m_audio_controler.startAudio(); - } - else if(sym == "stop") - { - m_audio_controler.stopAudio(); - } - } - } - } - - // ================================================================================ // - // ADC~ // - // ================================================================================ // - - AdcTilde::AdcTilde(model::Object const& model, Patcher& patcher, std::vector const& args): - AudioInterfaceObject(model, patcher, args) - { - std::vector routes = parseArgs(args); - - for (size_t index = 0; index < routes.size(); ++index) - { - m_router.connect(routes[index], index); - } - } - - void AdcTilde::perform(dsp::Buffer const& input, dsp::Buffer& output) noexcept - { - std::set const& connections = m_router.getConnections(); - - for(Router::Cnx const& connection : connections) - { - m_audio_controler.getFromChannel(connection.m_input, output[connection.m_output]); - } - } - - void AdcTilde::prepare(dsp::Processor::PrepareInfo const& infos) - { - setPerformCallBack(this, &AdcTilde::perform); - } - - // ================================================================================ // - // DAC~ // - // ================================================================================ // - - DacTilde::DacTilde(model::Object const& model, Patcher& patcher, std::vector const& args): - AudioInterfaceObject(model, patcher, args) - { - std::vector routes = parseArgs(args); - - for (size_t index = 0; index < routes.size(); ++index) - { - m_router.connect(index, routes[index]); - } - } - - void DacTilde::perform(dsp::Buffer const& input, dsp::Buffer& output) noexcept - { - std::set const& connections = m_router.getConnections(); - - for(Router::Cnx const& connection : connections) - { - m_audio_controler.addToChannel(connection.m_output, input[connection.m_input]); - } - } - - void DacTilde::prepare(dsp::Processor::PrepareInfo const& infos) - { - setPerformCallBack(this, &DacTilde::perform); - } - - // ================================================================================ // - // OSC~ // - // ================================================================================ // - - OscTilde::OscTilde(model::Object const& model, Patcher& patcher, std::vector const& args) - : AudioObject(model, patcher) - { - if (!args.empty() && args[0].isNumber()) - { - setFrequency(args[0].getFloat()); - } - } - - void OscTilde::setFrequency(dsp::sample_t const& freq) noexcept - { - m_freq = freq; - } - - void OscTilde::setSampleRate(dsp::sample_t const& sample_rate) - { - m_sr = sample_rate; - } - - void OscTilde::setOffset(dsp::sample_t const& offset) noexcept - { - m_offset = fmodf(offset, 1.f); - } - - void OscTilde::receive(size_t index, std::vector const& args) - { - if (index == 0 && args[0].isNumber()) - { - setFrequency(args[0].getFloat()); - } - else if(index == 1 && args[0].isNumber()) - { - setOffset(args[0].getFloat()); - } - } - - void OscTilde::prepare(PrepareInfo const& infos) - { - setSampleRate(static_cast(infos.sample_rate)); - - if (infos.inputs[0] && infos.inputs[1]) - { - setPerformCallBack(this, &OscTilde::performPhaseAndFreq); - } - else if(infos.inputs[0]) - { - setPerformCallBack(this, &OscTilde::performFreq); - } - else if(infos.inputs[1]) - { - setPerformCallBack(this, &OscTilde::performPhase); - } - else - { - setPerformCallBack(this, &OscTilde::performValue); - } - } - - void OscTilde::performValue(dsp::Buffer const& input, dsp::Buffer& output) noexcept - { - dsp::sample_t *sig_data = output[0ul].data(); - size_t sample_index = output[0ul].size(); - dsp::sample_t const time_inc = m_freq/m_sr; - dsp::sample_t const offset = m_offset; - - while(sample_index--) - { - *sig_data++ = std::cos(2.f * dsp::pi * (m_time + offset)); - m_time += time_inc; - } - - m_time = fmodf(m_time, 1.f); - } - - void OscTilde::performFreq(dsp::Buffer const& input, dsp::Buffer& output) noexcept - { - size_t sample_index = output[0ul].size(); - dsp::sample_t* output_sig = output[0ul].data(); - dsp::sample_t const* freq = input[0ul].data(); - dsp::sample_t const offset = m_offset; - - while(sample_index--) - { - *output_sig++ = std::cos(2.f *dsp::pi * (m_time + offset)); - m_time += (*freq++ / m_sr); - } - - m_time = fmodf(m_time, 1.f); - } - - void OscTilde::performPhase(dsp::Buffer const& input, dsp::Buffer& output) noexcept - { - dsp::sample_t* output_sig = output[0ul].data(); - size_t sample_index = output[0ul].size(); - dsp::sample_t const* phase = input[1ul].data(); - dsp::sample_t const time_inc = m_freq/m_sr; - - while(sample_index--) - { - *output_sig++ = std::cos(2.f * dsp::pi * (m_time + fmodf(*phase++, 1.f))); - m_time += time_inc; - } - - m_time = fmodf(m_time, 1.f); - } - - void OscTilde::performPhaseAndFreq(dsp::Buffer const& input, dsp::Buffer& output) noexcept - { - size_t sample_index = output[0].size(); - dsp::sample_t* output_sig = output[0].data(); - dsp::sample_t const* freq = input[0].data(); - dsp::sample_t const* phase = input[1].data(); - - while(sample_index--) - { - *output_sig++ = std::cos(2.f * dsp::pi * (m_time + fmodf(*phase++, 1.f))); - m_time += (*freq++ / m_sr); - } - - m_time = fmodf(m_time, 1.f); - } - - // ================================================================================ // - // TIMES~ // - // ================================================================================ // - - TimesTilde::TimesTilde(model::Object const& model, Patcher& patcher, std::vector const& args) - : AudioObject(model, patcher) - { - if (!args.empty() && args[0].isNumber()) - { - m_value = args[0].getFloat(); - } - } - - void TimesTilde::receive(size_t index, std::vector const& args) - { - if(index == 1 && args[0].isNumber()) - { - m_value = args[0].getFloat(); - } - } - - void TimesTilde::performValue(dsp::Buffer const& input, dsp::Buffer& output) noexcept - { - const size_t size = input[0ul].size(); - dsp::sample_t const* in1 = input[0ul].data(); - dsp::sample_t* out = output[0ul].data(); - - dsp::sample_t const value = m_value; - - for(size_t i = size>>3; i; --i, in1 += 8, out += 8) - { - out[0] = in1[0] * value; out[1] = in1[1] * value; - out[2] = in1[2] * value; out[3] = in1[3] * value; - out[4] = in1[4] * value; out[5] = in1[5] * value; - out[6] = in1[6] * value; out[7] = in1[7] * value; - } - for(size_t i = size&7; i; --i, in1++, out++) - { - out[0] = in1[0] * value; - } - } - - void TimesTilde::performVec(dsp::Buffer const& input, dsp::Buffer& output) noexcept - { - const size_t size = input[0ul].size(); - dsp::sample_t const* in1 = input[0ul].data(); - dsp::sample_t const* in2 = input[1ul].data(); - dsp::sample_t* out = output[0ul].data(); - - for(size_t i = size>>3; i; --i, in1 += 8, in2 += 8, out += 8) - { - out[0] = in1[0] * in2[0]; out[1] = in1[1] * in2[1]; - out[2] = in1[2] * in2[2]; out[3] = in1[3] * in2[3]; - out[4] = in1[4] * in2[4]; out[5] = in1[5] * in2[5]; - out[6] = in1[6] * in2[6]; out[7] = in1[7] * in2[7]; - } - for(size_t i = size&7; i; --i, in1++, in2++, out++) - { - out[0] = in1[0] * in2[0]; - } - } - - void TimesTilde::prepare(PrepareInfo const& infos) - { - if (infos.inputs.size() > 1 && infos.inputs[1]) - { - setPerformCallBack(this, &TimesTilde::performVec); - } - else - { - setPerformCallBack(this, &TimesTilde::performValue); - } - } - - // ================================================================================ // - // PLUS~ // - // ================================================================================ // - - PlusTilde::PlusTilde(model::Object const& model, Patcher& patcher, std::vector const& args) - : AudioObject(model, patcher) - { - if (!args.empty() && args[0].isNumber()) - { - m_value = args[0].getFloat(); - } - } - - void PlusTilde::receive(size_t index, std::vector const& args) - { - if(index == 1 && args[0].isNumber()) - { - m_value = args[0].getFloat(); - } - } - - void PlusTilde::performValue(dsp::Buffer const& input, dsp::Buffer& output) noexcept - { - dsp::Signal const& in = input[0]; - const size_t size = in.size(); - dsp::sample_t const* in1 = in.data(); - dsp::sample_t* out = output[0].data(); - - dsp::sample_t const value = m_value; - - for(size_t i = size>>3; i; --i, in1 += 8, out += 8) - { - out[0] = in1[0] + value; out[1] = in1[1] + value; - out[2] = in1[2] + value; out[3] = in1[3] + value; - out[4] = in1[4] + value; out[5] = in1[5] + value; - out[6] = in1[6] + value; out[7] = in1[7] + value; - } - for(size_t i = size&7; i; --i, in1++, out++) - { - out[0] = in1[0] * value; - } - } - - void PlusTilde::performVec(dsp::Buffer const& input, dsp::Buffer& output) noexcept - { - dsp::Signal const& in = input[0]; - const size_t size = in.size(); - dsp::sample_t const* in1 = in.data(); - dsp::sample_t const* in2 = input[1].data(); - dsp::sample_t* out = output[0].data(); - - for(size_t i = size>>3; i; --i, in1 += 8, in2 += 8, out += 8) - { - out[0] = in1[0] + in2[0]; out[1] = in1[1] + in2[1]; - out[2] = in1[2] + in2[2]; out[3] = in1[3] + in2[3]; - out[4] = in1[4] + in2[4]; out[5] = in1[5] + in2[5]; - out[6] = in1[6] + in2[6]; out[7] = in1[7] + in2[7]; - } - for(size_t i = size&7; i; --i, in1++, in2++, out++) - { - out[0] = in1[0] * in2[0]; - } - } - - void PlusTilde::prepare(PrepareInfo const& infos) - { - if (infos.inputs.size() > 1 && infos.inputs[1]) - { - setPerformCallBack(this, &PlusTilde::performVec); - } - else - { - setPerformCallBack(this, &PlusTilde::performValue); - } - } - - // ================================================================================ // - // SIG~ // - // ================================================================================ // - - SigTilde::SigTilde(model::Object const& model, Patcher& patcher, std::vector const& args): - AudioObject(model, patcher) - { - if (!args.empty() && args[0].isNumber()) - { - m_value = args[0].getFloat(); - } - } - - void SigTilde::receive(size_t index, std::vector const& args) - { - if (index == 0 && args[0].isNumber()) - { - m_value = args[0].getFloat(); - } - } - - void SigTilde::perform(dsp::Buffer const& input, dsp::Buffer& output) noexcept - { - size_t sample_index = output[0].size(); - dsp::sample_t* output_sig = output[0].data(); - dsp::sample_t const value = m_value; - - while(sample_index--) - { - *output_sig++ = value; - } - } - - void SigTilde::prepare(dsp::Processor::PrepareInfo const& infos) - { - setPerformCallBack(this, &SigTilde::perform); - } - - // ================================================================================ // - // DELAYSIMPLETILDE // - // ================================================================================ // - - DelaySimpleTilde::DelaySimpleTilde(model::Object const& model, Patcher& patcher, std::vector const& args): - AudioObject(model, patcher), - m_circular_buffer(), - m_reinject_signal(), - m_max_delay(60.), - m_delay(1.), - m_reinject_level(0.), - m_sr(0.), - m_vector_size(0), - m_mutex() - { - } - - void DelaySimpleTilde::receive(size_t index, std::vector const& args) - { - if (index == 0 && args[0].isString()) - { - std::lock_guard lock(m_mutex); - - m_circular_buffer->assign(m_circular_buffer->size(), 0); - } - if (index == 1 && args[0].isNumber()) - { - m_delay.store(args[0].getFloat() / 1000.); - } - else if(index == 2 && args[0].isNumber()) - { - m_reinject_level.store(std::max(0., std::min(1., args[0].getFloat()))); - } - } - - dsp::sample_t DelaySimpleTilde::cubicInterpolate(float const& x, - float const& y0, - float const& y1, - float const& y2, - float const& y3) - { - return y1 + 0.5 * x * (y2 - y0 + x * (2.0 * y0 - 5.0 * y1 + 4.0 * y2 - y3 - + x * (3.0 * (y1 - y2) + y3 - y0))); - } - - void DelaySimpleTilde::perform(dsp::Buffer const& input, dsp::Buffer& output) noexcept - { - std::lock_guard lock(m_mutex); - - size_t buffer_size = input[0].size(); - - for (int i = 0; i < buffer_size; ++i) - { - m_circular_buffer->push_back(input[0][i] + m_reinject_signal->operator[](i)); - } - - float delay = std::max(1. / m_sr, std::min(m_delay.load(), m_max_delay)); - float offset = m_circular_buffer->size() - (delay * m_sr) - (buffer_size - 1); - size_t offset_floor = std::floor(offset); - float decimal_part = offset - offset_floor; - - for(int i = 0; i < buffer_size; ++i) - { - output[0][i] = cubicInterpolate(decimal_part, - m_circular_buffer->operator[](offset_floor - 1), - m_circular_buffer->operator[](offset_floor), - m_circular_buffer->operator[](offset_floor + 1), - m_circular_buffer->operator[](offset_floor + 2)); - - m_reinject_signal->operator[](i) = m_reinject_level.load() * output[0][i]; - ++offset_floor; - } - } - - void DelaySimpleTilde::performDelay(dsp::Buffer const& input, dsp::Buffer& output) noexcept - { - //! Durty solution to synchronize circular buffer. - //! Should be implemented as an atomic shared pointer and a release pool - //! https://www.youtube.com/watch?v=boPEO2auJj4 48' - std::lock_guard lock(m_mutex); - - size_t buffer_size = input[0].size(); - - for (int i = 0; i < buffer_size; ++i) - { - m_circular_buffer->push_back(input[0][i] + m_reinject_signal->operator[](i)); - } - - for(int i = 0; i < buffer_size; ++i) - { - float delay = std::max(1. / m_sr, std::min(input[1][i] / 1000., m_max_delay)); - float offset = m_circular_buffer->size() - (delay * m_sr) - (buffer_size - 1) + i; - size_t offset_floor = std::floor(offset); - - output[0][i] = cubicInterpolate(offset - offset_floor, - m_circular_buffer->operator[](offset_floor - 1), - m_circular_buffer->operator[](offset_floor), - m_circular_buffer->operator[](offset_floor + 1), - m_circular_buffer->operator[](offset_floor + 2)); - - m_reinject_signal->operator[](i) = m_reinject_level.load() * output[0][i]; - } - } - - void DelaySimpleTilde::prepare(dsp::Processor::PrepareInfo const& infos) - { - if (infos.sample_rate != m_sr || infos.vector_size != m_vector_size) - { - m_sr = infos.sample_rate; - m_vector_size = infos.vector_size; - - size_t buffer_size = std::ceil(m_max_delay * m_sr) + 1 + m_vector_size; - - m_circular_buffer.reset(new CircularBuffer(buffer_size, buffer_size, 0.)); - m_reinject_signal.reset(new dsp::Signal(m_vector_size)); - } - - if (infos.inputs.size() > 1 && infos.inputs[1]) - { - setPerformCallBack(this, &DelaySimpleTilde::performDelay); - } - else - { - setPerformCallBack(this, &DelaySimpleTilde::perform); - } - } - } -} - - -#endif // KIWI_ENGINE_OBJECTS_HPP_INCLUDED diff --git a/Modules/KiwiEngine/KiwiEngine_Objects.h b/Modules/KiwiEngine/KiwiEngine_Objects.h deleted file mode 100644 index 5388e93a..00000000 --- a/Modules/KiwiEngine/KiwiEngine_Objects.h +++ /dev/null @@ -1,473 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#pragma once - -#include -#include -#include - -#include "KiwiEngine_Object.h" -#include "KiwiEngine_Beacon.h" -#include "KiwiEngine_CircularBuffer.h" -#include "KiwiEngine_AudioControler.h" -#include "KiwiEngine_Scheduler.h" - -namespace kiwi -{ - namespace engine - { - // ================================================================================ // - // NEWBOX // - // ================================================================================ // - - class NewBox : public engine::Object - { - public: - NewBox(model::Object const& model, Patcher& patcher, std::vector const& args); - - void receive(size_t index, std::vector const& args) override; - }; - - // ================================================================================ // - // ERRORBOX // - // ================================================================================ // - - class ErrorBox : public AudioObject - { - public: - ErrorBox(model::Object const& model, Patcher& patcher, std::vector const& args); - - void receive(size_t index, std::vector const& args) override; - - void prepare(dsp::Processor::PrepareInfo const& infos) override final; - }; - - // ================================================================================ // - // OBJECT PLUS // - // ================================================================================ // - - class Plus : public engine::Object - { - public: - - Plus(model::Object const& model, Patcher& patcher, std::vector const& args); - - void receive(size_t index, std::vector const& args) override; - - void bang(); - - private: - double m_lhs = 0.0; - double m_rhs = 0.0; - }; - - // ================================================================================ // - // OBJECT TIMES // - // ================================================================================ // - - class Times : public engine::Object - { - public: - - Times(model::Object const& model, Patcher& patcher, std::vector const& args); - - void receive(size_t index, std::vector const& args) override; - - void bang(); - - private: - double m_lhs = 0.0; - double m_rhs = 0.0; - }; - - // ================================================================================ // - // OBJECT PRINT // - // ================================================================================ // - - class Print : public engine::Object - { - public: - - Print(model::Object const& model, Patcher& patcher, std::vector const& args); - - void receive(size_t, std::vector const& args) override; - - private: - std::string m_name; - }; - - // ================================================================================ // - // OBJECT RECEIVE // - // ================================================================================ // - - class Receive : public engine::Object, public Beacon::Castaway - { - private: // classes - - class Task; - - public: // methods - - Receive(model::Object const& model, Patcher& patcher, std::vector const& args); - - ~Receive(); - - void receive(size_t, std::vector const& args) override; - - void receive(std::vector const& args) override; - - private: // members - - std::string m_name; - std::set> m_tasks; - }; - - // ================================================================================ // - // OBJECT LOADMESS // - // ================================================================================ // - - class Loadmess : public engine::Object - { - public: - - Loadmess(model::Object const& model, Patcher& patcher, std::vector const& args); - - ~Loadmess() = default; - - void receive(size_t, std::vector const& args) override; - - void loadbang() override; - - private: - - const std::vector m_args; - }; - - // ================================================================================ // - // OBJECT DELAY // - // ================================================================================ // - - class Delay final : public engine::Object - { - public: // methods - - Delay(model::Object const& model, Patcher& patcher, std::vector const& args); - - ~Delay(); - - void receive(size_t index, std::vector const& args) override; - - private: // members - - struct Task final : public Scheduler<>::Task - { - Task(Delay & object); - ~Task() = default; - void execute() override; - - private: - Delay& m_object; - }; - - std::shared_ptr m_task; - Scheduler<>::clock_t::duration m_delay; - }; - - // ================================================================================ // - // OBJECT PIPE // - // ================================================================================ // - - class Pipe final : public engine::Object - { - public: // classes - - class Task; - - public: // methods - - Pipe(model::Object const& model, Patcher& patcher, std::vector const& args); - - ~Pipe(); - - void receive(size_t index, std::vector const& args) override; - - private: // members - - std::set> m_tasks; - Scheduler<>::clock_t::duration m_delay; - }; - - // ================================================================================ // - // OBJECT METRO // - // ================================================================================ // - - class Metro final : public engine::Object, Scheduler<>::Timer - { - public: // methods - - Metro(model::Object const& model, Patcher& patcher, std::vector const& args); - - ~Metro(); - - void receive(size_t index, std::vector const& args) override; - - void timerCallBack() override; - - private: // members - - Scheduler<>::duration_t m_period; - }; - - - // ================================================================================ // - // ROUTER // - // ================================================================================ // - - class Router - { - public: // classes - - struct Cnx - { - Cnx(size_t input, size_t output); - - bool operator<(Cnx const& other) const; - - size_t m_input = 0; - size_t m_output = 0; - }; - - public: // method - - Router() = default; - - void connect(size_t input_index, size_t output_index); - - void disconnect(size_t intput_index, size_t output_index); - - size_t getNumberOfConnections() const; - - std::set const& getConnections() const; - - ~Router() = default; - - private: // memebers - - std::set m_cnx; - }; - - // ================================================================================ // - // AUDIO_INTERFACE // - // ================================================================================ // - - class AudioInterfaceObject : public AudioObject - { - public: // methods - - AudioInterfaceObject(model::Object const& model, Patcher& patcher, std::vector const& args); - - void receive(size_t index, std::vector const & args) override final; - - std::vector parseArgs(std::vector const& args) const; - - virtual ~AudioInterfaceObject() = default; - - protected: // members - - Router m_router; - engine::AudioControler& m_audio_controler; - }; - - // ================================================================================ // - // ADC~ // - // ================================================================================ // - - class AdcTilde : public AudioInterfaceObject - { - public: // methods - - AdcTilde(model::Object const& model, Patcher& patcher, std::vector const& args); - - void perform(dsp::Buffer const& input, dsp::Buffer& output) noexcept; - - void prepare(dsp::Processor::PrepareInfo const& infos) override final; - }; - - // ================================================================================ // - // DAC~ // - // ================================================================================ // - - class DacTilde : public AudioInterfaceObject - { - public: // methods - - DacTilde(model::Object const& model, Patcher& patcher, std::vector const& args); - - void perform(dsp::Buffer const& input, dsp::Buffer& output) noexcept; - - void prepare(dsp::Processor::PrepareInfo const& infos) override final; - }; - - // ================================================================================ // - // OSC~ // - // ================================================================================ // - - class OscTilde : public AudioObject - { - public: // methods - - OscTilde(model::Object const& model, Patcher& patcher, std::vector const& args); - - void receive(size_t index, std::vector const& args) override; - - void performValue(dsp::Buffer const& input, dsp::Buffer& output) noexcept; - - void performFreq(dsp::Buffer const& input, dsp::Buffer& output) noexcept; - - void performPhase(dsp::Buffer const& input, dsp::Buffer& output) noexcept; - - void performPhaseAndFreq(dsp::Buffer const& input, dsp::Buffer& output) noexcept; - - void prepare(dsp::Processor::PrepareInfo const& infos) override final; - - private: // methods - - void setFrequency(dsp::sample_t const& freq) noexcept; - - void setOffset(dsp::sample_t const& offset) noexcept; - - void setSampleRate(dsp::sample_t const& sample_rate); - - private: // members - - dsp::sample_t m_sr = 0.f; - dsp::sample_t m_time = 0.f; - std::atomic m_freq{0.f}; - std::atomic m_offset{0.f}; - }; - - // ================================================================================ // - // TIMES~ // - // ================================================================================ // - - class TimesTilde : public AudioObject - { - public: // methods - - TimesTilde(model::Object const& model, Patcher& patcher, std::vector const& args); - - void receive(size_t index, std::vector const& args) override; - - void performValue(dsp::Buffer const& input, dsp::Buffer& output) noexcept; - - void performVec(dsp::Buffer const& input, dsp::Buffer& output) noexcept; - - void prepare(dsp::Processor::PrepareInfo const& infos) override final; - - private: // members - - std::atomic m_value{0.f}; - }; - - // ================================================================================ // - // PLUS~ // - // ================================================================================ // - - class PlusTilde : public AudioObject - { - public: // methods - - PlusTilde(model::Object const& model, Patcher& patcher, std::vector const& args); - - void receive(size_t index, std::vector const& args) override; - - void performValue(dsp::Buffer const& input, dsp::Buffer& output) noexcept; - - void performVec(dsp::Buffer const& input, dsp::Buffer& output) noexcept; - - void prepare(dsp::Processor::PrepareInfo const& infos) override final; - - private: // members - - std::atomic m_value{0.f}; - }; - - // ================================================================================ // - // SIG~ // - // ================================================================================ // - - class SigTilde : public AudioObject - { - public: // methods - - SigTilde(model::Object const& model, Patcher& patcher, std::vector const& args); - - void receive(size_t index, std::vector const& args) override final; - - void perform(dsp::Buffer const& input, dsp::Buffer& output) noexcept; - - void prepare(dsp::Processor::PrepareInfo const& infos) override final; - - private: // members - - std::atomic m_value{0.f}; - }; - - // ================================================================================ // - // DELAYSIMPLETILDE // - // ================================================================================ // - - class DelaySimpleTilde : public AudioObject - { - public: // methods - - DelaySimpleTilde(model::Object const& model, Patcher& patcher, std::vector const& args); - - void receive(size_t index, std::vector const& args) override final; - - void perform(dsp::Buffer const& input, dsp::Buffer& output) noexcept; - - void performDelay(dsp::Buffer const& input, dsp::Buffer& output) noexcept; - - void prepare(dsp::Processor::PrepareInfo const& infos) override final; - - private: // methods - - dsp::sample_t cubicInterpolate(float const& x, - float const& y0, - float const& y1, - float const& y2, - float const& y3); - - private: // members - - std::unique_ptr> m_circular_buffer; - std::unique_ptr m_reinject_signal; - float m_max_delay; - std::atomic m_delay; - std::atomic m_reinject_level; - dsp::sample_t m_sr; - size_t m_vector_size; - mutable std::mutex m_mutex; - }; - } -} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Basic/KiwiEngine_ErrorBox.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Basic/KiwiEngine_ErrorBox.cpp new file mode 100644 index 00000000..74b04849 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Basic/KiwiEngine_ErrorBox.cpp @@ -0,0 +1,48 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +namespace kiwi +{ + namespace engine + { + // ================================================================================ // + // ERRORBOX // + // ================================================================================ // + + ErrorBox::ErrorBox(model::Object const& model, Patcher& patcher, std::vector const& args) + : AudioObject(model, patcher) + { + ; + } + + void ErrorBox::receive(size_t index, std::vector const& args) + { + ; + } + + void ErrorBox::prepare(dsp::Processor::PrepareInfo const& infos) + { + ; + } + } +} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Basic/KiwiEngine_ErrorBox.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Basic/KiwiEngine_ErrorBox.h new file mode 100644 index 00000000..65e7bc22 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Basic/KiwiEngine_ErrorBox.h @@ -0,0 +1,45 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi +{ + namespace engine + { + // ================================================================================ // + // ERRORBOX // + // ================================================================================ // + + class ErrorBox : public AudioObject + { + public: + ErrorBox(model::Object const& model, Patcher& patcher, std::vector const& args); + + void receive(size_t index, std::vector const& args) override; + + void prepare(dsp::Processor::PrepareInfo const& infos) override final; + }; + + } +} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Basic/KiwiEngine_NewBox.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Basic/KiwiEngine_NewBox.cpp new file mode 100644 index 00000000..a7c37b0a --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Basic/KiwiEngine_NewBox.cpp @@ -0,0 +1,43 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +namespace kiwi +{ + namespace engine + { + // ================================================================================ // + // NEWBOX // + // ================================================================================ // + + NewBox::NewBox(model::Object const& model, Patcher& patcher, std::vector const& args) + : Object(model, patcher) + { + ; + } + + void NewBox::receive(size_t index, std::vector const& args) + { + ; + } + } +} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Basic/KiwiEngine_NewBox.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Basic/KiwiEngine_NewBox.h new file mode 100644 index 00000000..27e9af27 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Basic/KiwiEngine_NewBox.h @@ -0,0 +1,42 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi +{ + namespace engine + { + // ================================================================================ // + // NEWBOX // + // ================================================================================ // + + class NewBox : public engine::Object + { + public: + NewBox(model::Object const& model, Patcher& patcher, std::vector const& args); + + void receive(size_t index, std::vector const& args) override; + }; + } +} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_AdcTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_AdcTilde.cpp new file mode 100644 index 00000000..55030efb --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_AdcTilde.cpp @@ -0,0 +1,58 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +namespace kiwi +{ + namespace engine + { + // ================================================================================ // + // ADC~ // + // ================================================================================ // + + AdcTilde::AdcTilde(model::Object const& model, Patcher& patcher, std::vector const& args): + AudioInterfaceObject(model, patcher, args) + { + std::vector routes = parseArgs(args); + + for (size_t index = 0; index < routes.size(); ++index) + { + m_router.connect(routes[index], index); + } + } + + void AdcTilde::perform(dsp::Buffer const& input, dsp::Buffer& output) noexcept + { + std::set const& connections = m_router.getConnections(); + + for(Router::Cnx const& connection : connections) + { + m_audio_controler.getFromChannel(connection.m_input, output[connection.m_output]); + } + } + + void AdcTilde::prepare(dsp::Processor::PrepareInfo const& infos) + { + setPerformCallBack(this, &AdcTilde::perform); + } + } +} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_AdcTilde.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_AdcTilde.h new file mode 100644 index 00000000..2e84c98a --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_AdcTilde.h @@ -0,0 +1,46 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi +{ + namespace engine + { + + // ================================================================================ // + // ADC~ // + // ================================================================================ // + + class AdcTilde : public AudioInterfaceObject + { + public: // methods + + AdcTilde(model::Object const& model, Patcher& patcher, std::vector const& args); + + void perform(dsp::Buffer const& input, dsp::Buffer& output) noexcept; + + void prepare(dsp::Processor::PrepareInfo const& infos) override final; + }; + } +} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_DacTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_DacTilde.cpp new file mode 100644 index 00000000..d6b04812 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_DacTilde.cpp @@ -0,0 +1,58 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +namespace kiwi +{ + namespace engine + { + // ================================================================================ // + // DAC~ // + // ================================================================================ // + + DacTilde::DacTilde(model::Object const& model, Patcher& patcher, std::vector const& args): + AudioInterfaceObject(model, patcher, args) + { + std::vector routes = parseArgs(args); + + for (size_t index = 0; index < routes.size(); ++index) + { + m_router.connect(index, routes[index]); + } + } + + void DacTilde::perform(dsp::Buffer const& input, dsp::Buffer& output) noexcept + { + std::set const& connections = m_router.getConnections(); + + for(Router::Cnx const& connection : connections) + { + m_audio_controler.addToChannel(connection.m_output, input[connection.m_input]); + } + } + + void DacTilde::prepare(dsp::Processor::PrepareInfo const& infos) + { + setPerformCallBack(this, &DacTilde::perform); + } + } +} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_DacTilde.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_DacTilde.h new file mode 100644 index 00000000..136b8f36 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_DacTilde.h @@ -0,0 +1,45 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi +{ + namespace engine + { + // ================================================================================ // + // DAC~ // + // ================================================================================ // + + class DacTilde : public AudioInterfaceObject + { + public: // methods + + DacTilde(model::Object const& model, Patcher& patcher, std::vector const& args); + + void perform(dsp::Buffer const& input, dsp::Buffer& output) noexcept; + + void prepare(dsp::Processor::PrepareInfo const& infos) override final; + }; + } +} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_DelaySimpleTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_DelaySimpleTilde.cpp new file mode 100644 index 00000000..86d9a5af --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_DelaySimpleTilde.cpp @@ -0,0 +1,155 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +namespace kiwi +{ + namespace engine + { + // ================================================================================ // + // DELAYSIMPLETILDE // + // ================================================================================ // + + DelaySimpleTilde::DelaySimpleTilde(model::Object const& model, Patcher& patcher, std::vector const& args): + AudioObject(model, patcher), + m_circular_buffer(), + m_reinject_signal(), + m_max_delay(60.), + m_delay(1.), + m_reinject_level(0.), + m_sr(0.), + m_vector_size(0), + m_mutex() + { + } + + void DelaySimpleTilde::receive(size_t index, std::vector const& args) + { + if (index == 0 && args[0].isString()) + { + std::lock_guard lock(m_mutex); + + m_circular_buffer->assign(m_circular_buffer->size(), 0); + } + if (index == 1 && args[0].isNumber()) + { + m_delay.store(args[0].getFloat() / 1000.); + } + else if(index == 2 && args[0].isNumber()) + { + m_reinject_level.store(std::max(0., std::min(1., args[0].getFloat()))); + } + } + + dsp::sample_t DelaySimpleTilde::cubicInterpolate(float const& x, + float const& y0, + float const& y1, + float const& y2, + float const& y3) + { + return y1 + 0.5 * x * (y2 - y0 + x * (2.0 * y0 - 5.0 * y1 + 4.0 * y2 - y3 + + x * (3.0 * (y1 - y2) + y3 - y0))); + } + + void DelaySimpleTilde::perform(dsp::Buffer const& input, dsp::Buffer& output) noexcept + { + std::lock_guard lock(m_mutex); + + size_t buffer_size = input[0].size(); + + for (int i = 0; i < buffer_size; ++i) + { + m_circular_buffer->push_back(input[0][i] + m_reinject_signal->operator[](i)); + } + + float delay = std::max(1. / m_sr, std::min(m_delay.load(), m_max_delay)); + float offset = m_circular_buffer->size() - (delay * m_sr) - (buffer_size - 1); + size_t offset_floor = std::floor(offset); + float decimal_part = offset - offset_floor; + + for(int i = 0; i < buffer_size; ++i) + { + output[0][i] = cubicInterpolate(decimal_part, + m_circular_buffer->operator[](offset_floor - 1), + m_circular_buffer->operator[](offset_floor), + m_circular_buffer->operator[](offset_floor + 1), + m_circular_buffer->operator[](offset_floor + 2)); + + m_reinject_signal->operator[](i) = m_reinject_level.load() * output[0][i]; + ++offset_floor; + } + } + + void DelaySimpleTilde::performDelay(dsp::Buffer const& input, dsp::Buffer& output) noexcept + { + //! Durty solution to synchronize circular buffer. + //! Should be implemented as an atomic shared pointer and a release pool + //! https://www.youtube.com/watch?v=boPEO2auJj4 48' + std::lock_guard lock(m_mutex); + + size_t buffer_size = input[0].size(); + + for (int i = 0; i < buffer_size; ++i) + { + m_circular_buffer->push_back(input[0][i] + m_reinject_signal->operator[](i)); + } + + for(int i = 0; i < buffer_size; ++i) + { + float delay = std::max(1. / m_sr, std::min(input[1][i] / 1000., m_max_delay)); + float offset = m_circular_buffer->size() - (delay * m_sr) - (buffer_size - 1) + i; + size_t offset_floor = std::floor(offset); + + output[0][i] = cubicInterpolate(offset - offset_floor, + m_circular_buffer->operator[](offset_floor - 1), + m_circular_buffer->operator[](offset_floor), + m_circular_buffer->operator[](offset_floor + 1), + m_circular_buffer->operator[](offset_floor + 2)); + + m_reinject_signal->operator[](i) = m_reinject_level.load() * output[0][i]; + } + } + + void DelaySimpleTilde::prepare(dsp::Processor::PrepareInfo const& infos) + { + if (infos.sample_rate != m_sr || infos.vector_size != m_vector_size) + { + m_sr = infos.sample_rate; + m_vector_size = infos.vector_size; + + size_t buffer_size = std::ceil(m_max_delay * m_sr) + 1 + m_vector_size; + + m_circular_buffer.reset(new CircularBuffer(buffer_size, buffer_size, 0.)); + m_reinject_signal.reset(new dsp::Signal(m_vector_size)); + } + + if (infos.inputs.size() > 1 && infos.inputs[1]) + { + setPerformCallBack(this, &DelaySimpleTilde::performDelay); + } + else + { + setPerformCallBack(this, &DelaySimpleTilde::perform); + } + } + } +} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_DelaySimpleTilde.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_DelaySimpleTilde.h new file mode 100644 index 00000000..d168789b --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_DelaySimpleTilde.h @@ -0,0 +1,70 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +#include + +namespace kiwi +{ + namespace engine + { + // ================================================================================ // + // DELAYSIMPLETILDE // + // ================================================================================ // + + class DelaySimpleTilde : public AudioObject + { + public: // methods + + DelaySimpleTilde(model::Object const& model, Patcher& patcher, std::vector const& args); + + void receive(size_t index, std::vector const& args) override final; + + void perform(dsp::Buffer const& input, dsp::Buffer& output) noexcept; + + void performDelay(dsp::Buffer const& input, dsp::Buffer& output) noexcept; + + void prepare(dsp::Processor::PrepareInfo const& infos) override final; + + private: // methods + + dsp::sample_t cubicInterpolate(float const& x, + float const& y0, + float const& y1, + float const& y2, + float const& y3); + + private: // members + + std::unique_ptr> m_circular_buffer; + std::unique_ptr m_reinject_signal; + float m_max_delay; + std::atomic m_delay; + std::atomic m_reinject_level; + dsp::sample_t m_sr; + size_t m_vector_size; + mutable std::mutex m_mutex; + }; + } +} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_OscTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_OscTilde.cpp new file mode 100644 index 00000000..29b96195 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_OscTilde.cpp @@ -0,0 +1,154 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +namespace kiwi +{ + namespace engine + { + // ================================================================================ // + // OSC~ // + // ================================================================================ // + + OscTilde::OscTilde(model::Object const& model, Patcher& patcher, std::vector const& args) + : AudioObject(model, patcher) + { + if (!args.empty() && args[0].isNumber()) + { + setFrequency(args[0].getFloat()); + } + } + + void OscTilde::setFrequency(dsp::sample_t const& freq) noexcept + { + m_freq = freq; + } + + void OscTilde::setSampleRate(dsp::sample_t const& sample_rate) + { + m_sr = sample_rate; + } + + void OscTilde::setOffset(dsp::sample_t const& offset) noexcept + { + m_offset = fmodf(offset, 1.f); + } + + void OscTilde::receive(size_t index, std::vector const& args) + { + if (index == 0 && args[0].isNumber()) + { + setFrequency(args[0].getFloat()); + } + else if(index == 1 && args[0].isNumber()) + { + setOffset(args[0].getFloat()); + } + } + + void OscTilde::prepare(PrepareInfo const& infos) + { + setSampleRate(static_cast(infos.sample_rate)); + + if (infos.inputs[0] && infos.inputs[1]) + { + setPerformCallBack(this, &OscTilde::performPhaseAndFreq); + } + else if(infos.inputs[0]) + { + setPerformCallBack(this, &OscTilde::performFreq); + } + else if(infos.inputs[1]) + { + setPerformCallBack(this, &OscTilde::performPhase); + } + else + { + setPerformCallBack(this, &OscTilde::performValue); + } + } + + void OscTilde::performValue(dsp::Buffer const& input, dsp::Buffer& output) noexcept + { + dsp::sample_t *sig_data = output[0ul].data(); + size_t sample_index = output[0ul].size(); + dsp::sample_t const time_inc = m_freq/m_sr; + dsp::sample_t const offset = m_offset; + + while(sample_index--) + { + *sig_data++ = std::cos(2.f * dsp::pi * (m_time + offset)); + m_time += time_inc; + } + + m_time = fmodf(m_time, 1.f); + } + + void OscTilde::performFreq(dsp::Buffer const& input, dsp::Buffer& output) noexcept + { + size_t sample_index = output[0ul].size(); + dsp::sample_t* output_sig = output[0ul].data(); + dsp::sample_t const* freq = input[0ul].data(); + dsp::sample_t const offset = m_offset; + + while(sample_index--) + { + *output_sig++ = std::cos(2.f *dsp::pi * (m_time + offset)); + m_time += (*freq++ / m_sr); + } + + m_time = fmodf(m_time, 1.f); + } + + void OscTilde::performPhase(dsp::Buffer const& input, dsp::Buffer& output) noexcept + { + dsp::sample_t* output_sig = output[0ul].data(); + size_t sample_index = output[0ul].size(); + dsp::sample_t const* phase = input[1ul].data(); + dsp::sample_t const time_inc = m_freq/m_sr; + + while(sample_index--) + { + *output_sig++ = std::cos(2.f * dsp::pi * (m_time + fmodf(*phase++, 1.f))); + m_time += time_inc; + } + + m_time = fmodf(m_time, 1.f); + } + + void OscTilde::performPhaseAndFreq(dsp::Buffer const& input, dsp::Buffer& output) noexcept + { + size_t sample_index = output[0].size(); + dsp::sample_t* output_sig = output[0].data(); + dsp::sample_t const* freq = input[0].data(); + dsp::sample_t const* phase = input[1].data(); + + while(sample_index--) + { + *output_sig++ = std::cos(2.f * dsp::pi * (m_time + fmodf(*phase++, 1.f))); + m_time += (*freq++ / m_sr); + } + + m_time = fmodf(m_time, 1.f); + } + } +} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_OscTilde.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_OscTilde.h new file mode 100644 index 00000000..e3bffeea --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_OscTilde.h @@ -0,0 +1,68 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi +{ + namespace engine + { + // ================================================================================ // + // OSC~ // + // ================================================================================ // + + class OscTilde : public AudioObject + { + public: // methods + + OscTilde(model::Object const& model, Patcher& patcher, std::vector const& args); + + void receive(size_t index, std::vector const& args) override; + + void performValue(dsp::Buffer const& input, dsp::Buffer& output) noexcept; + + void performFreq(dsp::Buffer const& input, dsp::Buffer& output) noexcept; + + void performPhase(dsp::Buffer const& input, dsp::Buffer& output) noexcept; + + void performPhaseAndFreq(dsp::Buffer const& input, dsp::Buffer& output) noexcept; + + void prepare(dsp::Processor::PrepareInfo const& infos) override final; + + private: // methods + + void setFrequency(dsp::sample_t const& freq) noexcept; + + void setOffset(dsp::sample_t const& offset) noexcept; + + void setSampleRate(dsp::sample_t const& sample_rate); + + private: // members + + dsp::sample_t m_sr = 0.f; + dsp::sample_t m_time = 0.f; + std::atomic m_freq{0.f}; + std::atomic m_offset{0.f}; + }; + } +} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_PlusTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_PlusTilde.cpp new file mode 100644 index 00000000..73011fb4 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_PlusTilde.cpp @@ -0,0 +1,104 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +namespace kiwi +{ + namespace engine + { + // ================================================================================ // + // PLUS~ // + // ================================================================================ // + + PlusTilde::PlusTilde(model::Object const& model, Patcher& patcher, std::vector const& args) + : AudioObject(model, patcher) + { + if (!args.empty() && args[0].isNumber()) + { + m_value = args[0].getFloat(); + } + } + + void PlusTilde::receive(size_t index, std::vector const& args) + { + if(index == 1 && args[0].isNumber()) + { + m_value = args[0].getFloat(); + } + } + + void PlusTilde::performValue(dsp::Buffer const& input, dsp::Buffer& output) noexcept + { + dsp::Signal const& in = input[0]; + const size_t size = in.size(); + dsp::sample_t const* in1 = in.data(); + dsp::sample_t* out = output[0].data(); + + dsp::sample_t const value = m_value; + + for(size_t i = size>>3; i; --i, in1 += 8, out += 8) + { + out[0] = in1[0] + value; out[1] = in1[1] + value; + out[2] = in1[2] + value; out[3] = in1[3] + value; + out[4] = in1[4] + value; out[5] = in1[5] + value; + out[6] = in1[6] + value; out[7] = in1[7] + value; + } + for(size_t i = size&7; i; --i, in1++, out++) + { + out[0] = in1[0] * value; + } + } + + void PlusTilde::performVec(dsp::Buffer const& input, dsp::Buffer& output) noexcept + { + dsp::Signal const& in = input[0]; + const size_t size = in.size(); + dsp::sample_t const* in1 = in.data(); + dsp::sample_t const* in2 = input[1].data(); + dsp::sample_t* out = output[0].data(); + + for(size_t i = size>>3; i; --i, in1 += 8, in2 += 8, out += 8) + { + out[0] = in1[0] + in2[0]; out[1] = in1[1] + in2[1]; + out[2] = in1[2] + in2[2]; out[3] = in1[3] + in2[3]; + out[4] = in1[4] + in2[4]; out[5] = in1[5] + in2[5]; + out[6] = in1[6] + in2[6]; out[7] = in1[7] + in2[7]; + } + for(size_t i = size&7; i; --i, in1++, in2++, out++) + { + out[0] = in1[0] * in2[0]; + } + } + + void PlusTilde::prepare(PrepareInfo const& infos) + { + if (infos.inputs.size() > 1 && infos.inputs[1]) + { + setPerformCallBack(this, &PlusTilde::performVec); + } + else + { + setPerformCallBack(this, &PlusTilde::performValue); + } + } + } +} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_PlusTilde.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_PlusTilde.h new file mode 100644 index 00000000..faf62cbe --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_PlusTilde.h @@ -0,0 +1,54 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi +{ + namespace engine + { + + // ================================================================================ // + // PLUS~ // + // ================================================================================ // + + class PlusTilde : public AudioObject + { + public: // methods + + PlusTilde(model::Object const& model, Patcher& patcher, std::vector const& args); + + void receive(size_t index, std::vector const& args) override; + + void performValue(dsp::Buffer const& input, dsp::Buffer& output) noexcept; + + void performVec(dsp::Buffer const& input, dsp::Buffer& output) noexcept; + + void prepare(dsp::Processor::PrepareInfo const& infos) override final; + + private: // members + + std::atomic m_value{0.f}; + }; + } +} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_SigTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_SigTilde.cpp new file mode 100644 index 00000000..e89a50aa --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_SigTilde.cpp @@ -0,0 +1,66 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +namespace kiwi +{ + namespace engine + { + // ================================================================================ // + // SIG~ // + // ================================================================================ // + + SigTilde::SigTilde(model::Object const& model, Patcher& patcher, std::vector const& args): + AudioObject(model, patcher) + { + if (!args.empty() && args[0].isNumber()) + { + m_value = args[0].getFloat(); + } + } + + void SigTilde::receive(size_t index, std::vector const& args) + { + if (index == 0 && args[0].isNumber()) + { + m_value = args[0].getFloat(); + } + } + + void SigTilde::perform(dsp::Buffer const& input, dsp::Buffer& output) noexcept + { + size_t sample_index = output[0].size(); + dsp::sample_t* output_sig = output[0].data(); + dsp::sample_t const value = m_value; + + while(sample_index--) + { + *output_sig++ = value; + } + } + + void SigTilde::prepare(dsp::Processor::PrepareInfo const& infos) + { + setPerformCallBack(this, &SigTilde::perform); + } + } +} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_SigTilde.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_SigTilde.h new file mode 100644 index 00000000..6dd42e66 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_SigTilde.h @@ -0,0 +1,51 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi +{ + namespace engine + { + // ================================================================================ // + // SIG~ // + // ================================================================================ // + + class SigTilde : public AudioObject + { + public: // methods + + SigTilde(model::Object const& model, Patcher& patcher, std::vector const& args); + + void receive(size_t index, std::vector const& args) override final; + + void perform(dsp::Buffer const& input, dsp::Buffer& output) noexcept; + + void prepare(dsp::Processor::PrepareInfo const& infos) override final; + + private: // members + + std::atomic m_value{0.f}; + }; + } +} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_TimesTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_TimesTilde.cpp new file mode 100644 index 00000000..751bb93b --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_TimesTilde.cpp @@ -0,0 +1,102 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +namespace kiwi +{ + namespace engine + { + // ================================================================================ // + // TIMES~ // + // ================================================================================ // + + TimesTilde::TimesTilde(model::Object const& model, Patcher& patcher, std::vector const& args) + : AudioObject(model, patcher) + { + if (!args.empty() && args[0].isNumber()) + { + m_value = args[0].getFloat(); + } + } + + void TimesTilde::receive(size_t index, std::vector const& args) + { + if(index == 1 && args[0].isNumber()) + { + m_value = args[0].getFloat(); + } + } + + void TimesTilde::performValue(dsp::Buffer const& input, dsp::Buffer& output) noexcept + { + const size_t size = input[0ul].size(); + dsp::sample_t const* in1 = input[0ul].data(); + dsp::sample_t* out = output[0ul].data(); + + dsp::sample_t const value = m_value; + + for(size_t i = size>>3; i; --i, in1 += 8, out += 8) + { + out[0] = in1[0] * value; out[1] = in1[1] * value; + out[2] = in1[2] * value; out[3] = in1[3] * value; + out[4] = in1[4] * value; out[5] = in1[5] * value; + out[6] = in1[6] * value; out[7] = in1[7] * value; + } + for(size_t i = size&7; i; --i, in1++, out++) + { + out[0] = in1[0] * value; + } + } + + void TimesTilde::performVec(dsp::Buffer const& input, dsp::Buffer& output) noexcept + { + const size_t size = input[0ul].size(); + dsp::sample_t const* in1 = input[0ul].data(); + dsp::sample_t const* in2 = input[1ul].data(); + dsp::sample_t* out = output[0ul].data(); + + for(size_t i = size>>3; i; --i, in1 += 8, in2 += 8, out += 8) + { + out[0] = in1[0] * in2[0]; out[1] = in1[1] * in2[1]; + out[2] = in1[2] * in2[2]; out[3] = in1[3] * in2[3]; + out[4] = in1[4] * in2[4]; out[5] = in1[5] * in2[5]; + out[6] = in1[6] * in2[6]; out[7] = in1[7] * in2[7]; + } + for(size_t i = size&7; i; --i, in1++, in2++, out++) + { + out[0] = in1[0] * in2[0]; + } + } + + void TimesTilde::prepare(PrepareInfo const& infos) + { + if (infos.inputs.size() > 1 && infos.inputs[1]) + { + setPerformCallBack(this, &TimesTilde::performVec); + } + else + { + setPerformCallBack(this, &TimesTilde::performValue); + } + } + } +} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_TimesTilde.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_TimesTilde.h new file mode 100644 index 00000000..b3c18f7d --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_TimesTilde.h @@ -0,0 +1,54 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi +{ + namespace engine + { + + /// ================================================================================ // + // TIMES~ // + // ================================================================================ // + + class TimesTilde : public AudioObject + { + public: // methods + + TimesTilde(model::Object const& model, Patcher& patcher, std::vector const& args); + + void receive(size_t index, std::vector const& args) override; + + void performValue(dsp::Buffer const& input, dsp::Buffer& output) noexcept; + + void performVec(dsp::Buffer const& input, dsp::Buffer& output) noexcept; + + void prepare(dsp::Processor::PrepareInfo const& infos) override final; + + private: // members + + std::atomic m_value{0.f}; + }; + } +} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Math/KiwiEngine_Plus.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Math/KiwiEngine_Plus.cpp new file mode 100644 index 00000000..f987c58e --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Math/KiwiEngine_Plus.cpp @@ -0,0 +1,71 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +namespace kiwi +{ + namespace engine + { + + // ================================================================================ // + // OBJECT PLUS // + // ================================================================================ // + + Plus::Plus(model::Object const& model, Patcher& patcher, std::vector const& args) + : Object(model, patcher) + { + m_lhs = 0.; + if(!args.empty() && args[0].isNumber()) + { + m_rhs = args[0].getFloat(); + } + } + + void Plus::receive(size_t index, std::vector const& args) + { + if(!args.empty()) + { + if(args[0].isNumber()) + { + if(index == 0) + { + m_lhs = args[0].getFloat(); + bang(); + } + else if(index == 1) + { + m_rhs = args[0].getFloat(); + } + } + else if(index == 0 && args[0].getString() == "bang") + { + bang(); + } + } + } + + void Plus::bang() + { + send(0, {m_rhs + m_lhs}); + } + } +} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Math/KiwiEngine_Plus.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Math/KiwiEngine_Plus.h new file mode 100644 index 00000000..392984eb --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Math/KiwiEngine_Plus.h @@ -0,0 +1,50 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi +{ + namespace engine + { + // ================================================================================ // + // OBJECT PLUS // + // ================================================================================ // + + class Plus : public engine::Object + { + public: + + Plus(model::Object const& model, Patcher& patcher, std::vector const& args); + + void receive(size_t index, std::vector const& args) override; + + void bang(); + + private: + + double m_lhs = 0.0; + double m_rhs = 0.0; + }; + } +} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Math/KiwiEngine_Times.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Math/KiwiEngine_Times.cpp new file mode 100644 index 00000000..4c801f7d --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Math/KiwiEngine_Times.cpp @@ -0,0 +1,70 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +namespace kiwi +{ + namespace engine + { + // ================================================================================ // + // OBJECT TIMES // + // ================================================================================ // + + Times::Times(model::Object const& model, Patcher& patcher, std::vector const& args) + : Object(model, patcher) + { + m_lhs = 0.; + if(!args.empty() && args[0].isNumber()) + { + m_rhs = args[0].getFloat(); + } + } + + void Times::receive(size_t index, std::vector const& args) + { + if(!args.empty()) + { + if(args[0].isNumber()) + { + if(index == 0) + { + m_lhs = args[0].getFloat(); + bang(); + } + else if(index == 1) + { + m_rhs = args[0].getFloat(); + } + } + else if(index == 0 && args[0].getString() == "bang") + { + bang(); + } + } + } + + void Times::bang() + { + send(0, {m_rhs * m_lhs}); + } + } +} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Math/KiwiEngine_Times.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Math/KiwiEngine_Times.h new file mode 100644 index 00000000..6a385251 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Math/KiwiEngine_Times.h @@ -0,0 +1,50 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi +{ + namespace engine + { + // ================================================================================ // + // OBJECT TIMES // + // ================================================================================ // + + class Times : public engine::Object + { + public: + + Times(model::Object const& model, Patcher& patcher, std::vector const& args); + + void receive(size_t index, std::vector const& args) override; + + void bang(); + + private: + + double m_lhs = 0.0; + double m_rhs = 0.0; + }; + } +} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Loadmess.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Loadmess.cpp new file mode 100644 index 00000000..8df96d8e --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Loadmess.cpp @@ -0,0 +1,50 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +namespace kiwi +{ + namespace engine + { + // ================================================================================ // + // OBJECT LOADMESS // + // ================================================================================ // + + Loadmess::Loadmess(model::Object const& model, Patcher& patcher, std::vector const& args) + : Object(model, patcher), + m_args(args) + { + ; + } + + void Loadmess::receive(size_t, std::vector const& args) + { + send(0ul, m_args); + } + + void Loadmess::loadbang() + { + send(0ul, m_args); + } + } +} + diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Loadmess.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Loadmess.h new file mode 100644 index 00000000..23b2321a --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Loadmess.h @@ -0,0 +1,51 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi +{ + namespace engine + { + // ================================================================================ // + // OBJECT LOADMESS // + // ================================================================================ // + + class Loadmess : public engine::Object + { + public: + + Loadmess(model::Object const& model, Patcher& patcher, std::vector const& args); + + ~Loadmess() = default; + + void receive(size_t, std::vector const& args) override; + + void loadbang() override; + + private: + + const std::vector m_args; + }; + } +} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Print.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Print.cpp new file mode 100644 index 00000000..0d546ca6 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Print.cpp @@ -0,0 +1,47 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +namespace kiwi +{ + namespace engine + { + // ================================================================================ // + // OBJECT PRINT // + // ================================================================================ // + + Print::Print(model::Object const& model, Patcher& patcher, std::vector const& args) + : Object(model, patcher) + { + m_name = !args.empty() ? args[0].getString() : "print"; + } + + void Print::receive(size_t, std::vector const& args) + { + if(!args.empty()) + { + post(m_name + " \xe2\x80\xa2 " + AtomHelper::toString(args)); + } + } + } +} + diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Print.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Print.h new file mode 100644 index 00000000..bde76681 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Print.h @@ -0,0 +1,46 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi +{ + namespace engine + { + // ================================================================================ // + // OBJECT PRINT // + // ================================================================================ // + + class Print : public engine::Object + { + public: + + Print(model::Object const& model, Patcher& patcher, std::vector const& args); + + void receive(size_t, std::vector const& args) override; + + private: + std::string m_name; + }; + } +} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Receive.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Receive.cpp new file mode 100644 index 00000000..26248e25 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Receive.cpp @@ -0,0 +1,111 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +namespace kiwi +{ + namespace engine + { + // ================================================================================ // + // OBJECT RECEIVE // + // ================================================================================ // + + class Receive::Task final : public Scheduler<>::Task + { + public: // methods + + Task(Receive& object, std::vector const& atoms): + Scheduler<>::Task(), + m_object(object), + m_atoms(atoms) + { + } + + ~Task() + { + } + + void execute() override + { + m_object.send(0, m_atoms); + + m_object.m_tasks.erase(std::find_if(m_object.m_tasks.begin(), + m_object.m_tasks.end(), + [this](std::shared_ptr const& task) + { + return task.get() == this; + })); + } + + private: // members + + Receive& m_object; + std::vector m_atoms; + }; + + Receive::Receive(model::Object const& model, Patcher& patcher, std::vector const& args): + Object(model, patcher), + m_name(), + m_tasks() + { + m_name = !args.empty() ? args[0].getString() : ""; + + if(!m_name.empty()) + { + Beacon& beacon = getBeacon(m_name); + beacon.bind(*this); + } + } + + Receive::~Receive() + { + for (std::shared_ptr const& task : m_tasks) + { + getScheduler().unschedule(task); + } + + if(!m_name.empty()) + { + Beacon& beacon = getBeacon(m_name); + beacon.unbind(*this); + } + } + + void Receive::receive(size_t, std::vector const& args) + { + + } + + void Receive::receive(std::vector const& args) + { + if (!args.empty()) + { + std::shared_ptr task(new Task(*this, args)); + + m_tasks.insert(task); + + getScheduler().defer(task); + } + } + } +} + diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Receive.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Receive.h new file mode 100644 index 00000000..ed06fab9 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Receive.h @@ -0,0 +1,56 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi +{ + namespace engine + { + // ================================================================================ // + // OBJECT RECEIVE // + // ================================================================================ // + + class Receive : public engine::Object, public Beacon::Castaway + { + private: // classes + + class Task; + + public: // methods + + Receive(model::Object const& model, Patcher& patcher, std::vector const& args); + + ~Receive(); + + void receive(size_t, std::vector const& args) override; + + void receive(std::vector const& args) override; + + private: // members + + std::string m_name; + std::set> m_tasks; + }; + } +} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h new file mode 100644 index 00000000..5fb9c62f --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h @@ -0,0 +1,64 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +// ================================================================================ // +// BASIC OBJECTS // +// ================================================================================ // + +#include +#include + +// ================================================================================ // +// DSP OBJECTS // +// ================================================================================ // + +#include +#include +#include +#include +#include +#include +#include + +// ================================================================================ // +// MATH OBJECTS // +// ================================================================================ // + +#include +#include + +// ================================================================================ // +// MESSAGE OBJECTS // +// ================================================================================ // + +#include +#include +#include + +// ================================================================================ // +// TIME OBJECTS // +// ================================================================================ // + +#include +#include +#include diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Delay.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Delay.cpp new file mode 100644 index 00000000..fc9fff0f --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Delay.cpp @@ -0,0 +1,85 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +namespace kiwi +{ + namespace engine + { + // ================================================================================ // + // OBJECT DELAY // + // ================================================================================ // + + Delay::Task::Task(Delay& object): + Scheduler<>::Task(), + m_object(object) + { + } + + void Delay::Task::execute() + { + m_object.send(0, {"bang"}); + } + + Delay::Delay(model::Object const& model, Patcher& patcher, std::vector const& args): + Object(model, patcher), + m_task(new Task(*this)), + m_delay(std::chrono::milliseconds(0)) + { + if (!args.empty()) + { + m_delay = std::chrono::milliseconds(args[0].getInt()); + } + } + + Delay::~Delay() + { + getScheduler().unschedule(m_task); + } + + void Delay::receive(size_t index, std::vector const& args) + { + if (!args.empty()) + { + if (index == 0) + { + if(args[0].isString() && args[0].getString() == "bang") + { + getScheduler().schedule(m_task, m_delay); + } + else if(args[0].isString() && args[0].getString() == "stop") + { + getScheduler().unschedule(m_task); + } + } + else if(index == 1) + { + if (args[0].isNumber()) + { + m_delay = std::chrono::milliseconds(args[0].getInt()); + } + } + } + } + } +} + diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Delay.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Delay.h new file mode 100644 index 00000000..12d214bd --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Delay.h @@ -0,0 +1,60 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi +{ + namespace engine + { + // ================================================================================ // + // OBJECT DELAY // + // ================================================================================ // + + class Delay final : public engine::Object + { + public: // methods + + Delay(model::Object const& model, Patcher& patcher, std::vector const& args); + + ~Delay(); + + void receive(size_t index, std::vector const& args) override; + + private: // members + + struct Task final : public Scheduler<>::Task + { + Task(Delay & object); + ~Task() = default; + void execute() override; + + private: + Delay& m_object; + }; + + std::shared_ptr m_task; + Scheduler<>::clock_t::duration m_delay; + }; + } +} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Metro.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Metro.cpp new file mode 100644 index 00000000..e257cf41 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Metro.cpp @@ -0,0 +1,80 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +namespace kiwi +{ + namespace engine + { + // ================================================================================ // + // OBJECT METRO // + // ================================================================================ // + + Metro::Metro(model::Object const& model, Patcher& patcher, std::vector const& args): + engine::Object(model, patcher), + Scheduler<>::Timer(patcher.getScheduler()), + m_period(std::chrono::milliseconds(0)) + { + if(!args.empty()) + { + m_period = std::chrono::milliseconds(args[0].getInt()); + } + } + + Metro::~Metro() + { + } + + void Metro::receive(size_t index, std::vector const& args) + { + if (!args.empty()) + { + if (index == 0) + { + if((args[0].isString() && args[0].getString() == "start") + || (args[0].isNumber() && static_cast(args[0].getInt()))) + { + startTimer(m_period); + } + else if((args[0].isString() && args[0].getString() == "stop") + || (args[0].isNumber() && !static_cast(args[0].getInt()))) + { + stopTimer(); + } + } + else if(index == 1) + { + if (args[0].isNumber()) + { + m_period = std::chrono::milliseconds(args[0].getInt()); + } + } + } + } + + void Metro::timerCallBack() + { + send(0, {"bang"}); + } + + } +} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Metro.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Metro.h new file mode 100644 index 00000000..2148d000 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Metro.h @@ -0,0 +1,51 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi +{ + namespace engine + { + // ================================================================================ // + // OBJECT METRO // + // ================================================================================ // + + class Metro final : public engine::Object, Scheduler<>::Timer + { + public: // methods + + Metro(model::Object const& model, Patcher& patcher, std::vector const& args); + + ~Metro(); + + void receive(size_t index, std::vector const& args) override; + + void timerCallBack() override; + + private: // members + + Scheduler<>::duration_t m_period; + }; + } +} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Pipe.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Pipe.cpp new file mode 100644 index 00000000..8682afb8 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Pipe.cpp @@ -0,0 +1,102 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +namespace kiwi +{ + namespace engine + { + // ================================================================================ // + // OBJECT PIPE // + // ================================================================================ // + + class Pipe::Task final : public Scheduler<>::Task + { + public: // methods + + Task(Pipe & object, std::vector const& atoms): + Scheduler<>::Task(), + m_object(object), + m_atoms(atoms) + { + } + + ~Task() + { + } + + void execute() + { + m_object.send(0, m_atoms); + + m_object.m_tasks.erase(std::find_if(m_object.m_tasks.begin(), + m_object.m_tasks.end(), + [this](std::shared_ptr const& task) + { + return task.get() == this; + })); + } + + private: // members + + Pipe& m_object; + std::vector m_atoms; + }; + + Pipe::Pipe(model::Object const& model, Patcher& patcher, std::vector const& args): + Object(model, patcher), + m_tasks(), + m_delay(std::chrono::milliseconds(0)) + { + if (!args.empty()) + { + m_delay = std::chrono::milliseconds(args[0].getInt()); + } + } + + Pipe::~Pipe() + { + for (std::shared_ptr const& task : m_tasks) + { + getScheduler().unschedule(task); + } + } + + void Pipe::receive(size_t index, std::vector const& args) + { + if (!args.empty()) + { + if (index == 0) + { + std::shared_ptr task(new Task(*this, args)); + getScheduler().schedule(task, m_delay); + m_tasks.insert(std::move(task)); + } + else if(index == 1 && args[0].isNumber()) + { + m_delay = std::chrono::milliseconds(args[0].getInt()); + } + } + } + } +} + diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Pipe.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Pipe.h new file mode 100644 index 00000000..e76037a6 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Pipe.h @@ -0,0 +1,54 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi +{ + namespace engine + { + // ================================================================================ // + // OBJECT PIPE // + // ================================================================================ // + + class Pipe final : public engine::Object + { + public: // classes + + class Task; + + public: // methods + + Pipe(model::Object const& model, Patcher& patcher, std::vector const& args); + + ~Pipe(); + + void receive(size_t index, std::vector const& args) override; + + private: // members + + std::set> m_tasks; + Scheduler<>::clock_t::duration m_delay; + }; + } +} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Utils/KiwiEngine_AudioInterface.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Utils/KiwiEngine_AudioInterface.cpp new file mode 100644 index 00000000..d01343d9 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Utils/KiwiEngine_AudioInterface.cpp @@ -0,0 +1,95 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +namespace kiwi +{ + namespace engine + { + // ================================================================================ // + // AUDIOINTERFACE // + // ================================================================================ // + + AudioInterfaceObject::AudioInterfaceObject(model::Object const& model, + Patcher& patcher, + std::vector const& args): + AudioObject(model, patcher), + m_router(), + m_audio_controler(patcher.getAudioControler()) + { + } + + std::vector AudioInterfaceObject::parseArgs(std::vector const& args) const + { + std::vector routes; + + for(Atom const& arg : args) + { + if (arg.isNumber()) + { + routes.push_back(arg.getInt() - 1); + } + else if(arg.isString()) + { + std::string inputs(arg.getString()); + + int left_input = std::stoi(inputs.substr(0, inputs.find(":"))) - 1; + int right_input = std::stoi(inputs.substr(inputs.find(":") + 1)) - 1; + + bool rev = left_input > right_input; + + for (int channel = left_input; rev ? channel >= right_input : channel <= right_input; rev ? --channel : ++channel) + { + routes.push_back(channel); + } + } + } + + if (routes.empty()) + { + routes = {0, 1}; + } + + return routes; + } + + void AudioInterfaceObject::receive(size_t index, std::vector const & args) + { + if(!args.empty()) + { + if(args[0].isString()) + { + const std::string sym = args[0].getString(); + + if(sym == "start") + { + m_audio_controler.startAudio(); + } + else if(sym == "stop") + { + m_audio_controler.stopAudio(); + } + } + } + } + } +} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Utils/KiwiEngine_AudioInterface.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Utils/KiwiEngine_AudioInterface.h new file mode 100644 index 00000000..6ea23c27 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Utils/KiwiEngine_AudioInterface.h @@ -0,0 +1,55 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include +#include + +#include + +namespace kiwi +{ + namespace engine + { + // ================================================================================ // + // AUDIO_INTERFACE // + // ================================================================================ // + + class AudioInterfaceObject : public AudioObject + { + public: // methods + + AudioInterfaceObject(model::Object const& model, Patcher& patcher, std::vector const& args); + + void receive(size_t index, std::vector const & args) override final; + + std::vector parseArgs(std::vector const& args) const; + + virtual ~AudioInterfaceObject() = default; + + protected: // members + + Router m_router; + engine::AudioControler& m_audio_controler; + }; + } +} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Utils/KiwiEngine_Router.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Utils/KiwiEngine_Router.cpp new file mode 100644 index 00000000..4d545dc4 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Utils/KiwiEngine_Router.cpp @@ -0,0 +1,64 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +namespace kiwi +{ + namespace engine + { + // ================================================================================ // + // ROUTER // + // ================================================================================ // + + Router::Cnx::Cnx(size_t input, size_t output): + m_input(input), + m_output(output) + { + } + + bool Router::Cnx::operator<(Cnx const& other) const + { + return m_input < other.m_input + || (m_input == other.m_input && m_output < other.m_output); + } + + void Router::connect(size_t input_index, size_t output_index) + { + m_cnx.insert(Cnx(input_index, output_index)); + } + + void Router::disconnect(size_t input_index, size_t ouptut_index) + { + m_cnx.erase(Cnx(input_index, ouptut_index)); + } + + size_t Router::getNumberOfConnections() const + { + return m_cnx.size(); + } + + std::set const& Router::getConnections() const + { + return m_cnx; + } + } +} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Utils/KiwiEngine_Router.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Utils/KiwiEngine_Router.h new file mode 100644 index 00000000..773d6e7e --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Utils/KiwiEngine_Router.h @@ -0,0 +1,68 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include +#include + +namespace kiwi +{ + namespace engine + { + // ================================================================================ // + // ROUTER // + // ================================================================================ // + + class Router + { + public: // classes + + struct Cnx + { + Cnx(size_t input, size_t output); + + bool operator<(Cnx const& other) const; + + size_t m_input = 0; + size_t m_output = 0; + }; + + public: // method + + Router() = default; + + void connect(size_t input_index, size_t output_index); + + void disconnect(size_t intput_index, size_t output_index); + + size_t getNumberOfConnections() const; + + std::set const& getConnections() const; + + ~Router() = default; + + private: // memebers + + std::set m_cnx; + }; + } +} diff --git a/Modules/KiwiModel/KiwiModel_DataModel.cpp b/Modules/KiwiModel/KiwiModel_DataModel.cpp index 6b1ee86a..59ebc359 100644 --- a/Modules/KiwiModel/KiwiModel_DataModel.cpp +++ b/Modules/KiwiModel/KiwiModel_DataModel.cpp @@ -24,7 +24,7 @@ #include "KiwiModel_Def.h" #include "KiwiModel_DataModel.h" #include "KiwiModel_PatcherUser.h" -#include "KiwiModel_Objects.h" +#include namespace kiwi { diff --git a/Modules/KiwiModel/KiwiModel_Objects.cpp b/Modules/KiwiModel/KiwiModel_Objects.cpp deleted file mode 100755 index e55360f6..00000000 --- a/Modules/KiwiModel/KiwiModel_Objects.cpp +++ /dev/null @@ -1,639 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#include "KiwiModel_Objects.h" - -#include "KiwiModel_DataModel.h" - -namespace kiwi -{ - namespace model - { - // ================================================================================ // - // NEWBOX // - // ================================================================================ // - - void NewBox::declare() - { - Factory::add("newbox").setInternal(true); - } - - NewBox::NewBox(std::string const& name, std::vector const& args) - { - pushInlet({PinType::IType::Control}); - } - - std::string NewBox::getIODescription(bool is_inlet, size_t index) const - { - return "(nothing here)"; - } - - // ================================================================================ // - // ERRORBOX // - // ================================================================================ // - - void ErrorBox::declare() - { - Factory::add("errorbox").setInternal(true); - } - - ErrorBox::ErrorBox(std::string const& name, std::vector const& args) - { - } - - void ErrorBox::setInlets(flip::Array const& inlets) - { - model::Object::setInlets(inlets); - } - - void ErrorBox::setOutlets(flip::Array const& outlets) - { - model::Object::setOutlets(outlets); - } - - std::string ErrorBox::getIODescription(bool is_inlet, size_t index) const - { - return "(nothing here)"; - } - - // ================================================================================ // - // OBJECT PLUS // - // ================================================================================ // - - void Plus::declare() - { - Factory::add("plus").addAlias("+"); - } - - Plus::Plus(std::string const& name, std::vector const& args) - { - pushInlet({PinType::IType::Control}); - - if (args.empty() || !args[0].isNumber()) - { - pushInlet({PinType::IType::Control}); - } - - pushOutlet(PinType::IType::Control); - } - - std::string Plus::getIODescription(bool is_inlet, size_t index) const - { - return is_inlet ? (index == 0) ? "Left operand" : "Right operand" : "Result"; - } - - // ================================================================================ // - // OBJECT TIMES // - // ================================================================================ // - - void Times::declare() - { - Factory::add("times").addAlias("*"); - } - - Times::Times(std::string const& name, std::vector const& args) - { - pushInlet({PinType::IType::Control}); - - if (args.empty() || !args[0].isNumber()) - { - pushInlet({PinType::IType::Control}); - } - - pushOutlet(PinType::IType::Control); - } - - std::string Times::getIODescription(bool is_inlet, size_t index) const - { - return is_inlet ? (index == 0) ? "Left operand" : "Right operand" : "Result"; - } - - // ================================================================================ // - // OBJECT PRINT // - // ================================================================================ // - - Print::Print(std::string const& name, std::vector const& args) - { - pushInlet({PinType::IType::Control}); - } - - void Print::declare() - { - Factory::add("print"); - } - - std::string Print::getIODescription(bool is_inlet, size_t index) const - { - return "Message to post in the Kiwi console"; - } - - // ================================================================================ // - // OBJECT RECEIVE // - // ================================================================================ // - - Receive::Receive(std::string const& name, std::vector const& args) - { - pushOutlet(PinType::IType::Control); - } - - void Receive::declare() - { - Factory::add("receive").addAlias("r"); - } - - std::string Receive::getIODescription(bool is_inlet, size_t index) const - { - if(!is_inlet) - { - return "Receive messages"; - } - - return {}; - } - - // ================================================================================ // - // OBJECT LOADMESS // - // ================================================================================ // - - Loadmess::Loadmess(std::string const& name, std::vector const& args) - { - pushOutlet(PinType::IType::Control); - } - - void Loadmess::declare() - { - Factory::add("loadmess"); - } - - std::string Loadmess::getIODescription(bool is_inlet, size_t index) const - { - if(is_inlet) - { - return "Receive messages when the patch is loaded"; - } - - return {}; - } - - // ================================================================================ // - // OBJECT DELAY // - // ================================================================================ // - - Delay::Delay(std::string const& name, std::vector const& args) - { - if (args.size() > 1 || (args.size() == 1 && !args[0].isNumber())) - { - throw std::runtime_error("wrong argument for object Delay"); - } - - pushInlet({PinType::IType::Control}); - - if (args.empty()) - { - pushInlet({PinType::IType::Control}); - } - - pushOutlet(PinType::IType::Control); - } - - void Delay::declare() - { - Factory::add("delay"); - } - - std::string Delay::getIODescription(bool is_inlet, size_t index) const - { - if(is_inlet) - { - if(index == 0) - { - return "bang gets delayed, message \"stop\" cancels"; - } - else if(index == 1) - { - return "Set delay time"; - } - } - else - { - return "Delayed bang"; - } - - return {}; - } - - // ================================================================================ // - // OBJECT PIPE // - // ================================================================================ // - - Pipe::Pipe(std::string const& name, std::vector const& args) - { - if (args.size() > 1 || (args.size() == 1 && !args[0].isNumber())) - { - throw std::runtime_error("wrong argument for object Pipe"); - } - - pushInlet({PinType::IType::Control}); - - if (args.empty()) - { - pushInlet({PinType::IType::Control}); - } - - pushOutlet(PinType::IType::Control); - } - - void Pipe::declare() - { - Factory::add("pipe"); - } - - std::string Pipe::getIODescription(bool is_inlet, size_t index) const - { - if(is_inlet) - { - if(index == 0) - { - return "Anything to be delayed"; - } - else if(index == 1) - { - return "Set delay time"; - } - } - else - { - return "Delayed messages"; - } - - return {}; - } - - // ================================================================================ // - // OBJECT METRO // - // ================================================================================ // - - Metro::Metro(std::string const& name, std::vector const& args) - { - if (args.size() < 1 || (args.size() == 1 && !args[0].isNumber())) - { - throw std::runtime_error("wrong argument for object Metro"); - } - - pushInlet({PinType::IType::Control}); - - if (args.empty()) - { - pushInlet({PinType::IType::Control}); - } - - pushOutlet(PinType::IType::Control); - } - - void Metro::declare() - { - Factory::add("metro"); - } - - std::string Metro::getIODescription(bool is_inlet, size_t index) const - { - if(is_inlet) - { - if(index == 0) - { - return "Start/Stop metronome"; - } - else if(index == 1) - { - return "Set time interval"; - } - } - else - { - return "Outputs metronome ticks as bang"; - } - - return {}; - } - - // ================================================================================ // - // OBJECT ADC~ // - // ================================================================================ // - - std::vector parseArgsAsChannelRoutes(std::vector const& args) - { - std::vector routes; - - for(Atom const& arg : args) - { - if (arg.isNumber()) - { - if (arg.getInt() <= 0) - { - throw std::runtime_error("null or negative channel"); - } - - routes.push_back(arg.getInt() - 1); - } - else if(arg.isString()) - { - std::string inputs(arg.getString()); - - size_t sep_pos = inputs.find(":"); - - if (sep_pos == std::string::npos) - { - throw std::runtime_error("wrong symbol syntax"); - } - - int left_input = std::stoi(inputs.substr(0, sep_pos)) - 1; - int right_input = std::stoi(inputs.substr(inputs.find(":") + 1)) - 1; - - if (left_input < 0 || right_input < 0) - { - throw std::runtime_error("null or negative channel"); - } - - const bool rev = left_input > right_input; - - for (int channel = left_input; - rev ? channel >= right_input : channel <= right_input; - rev ? --channel : ++channel) - { - routes.push_back(channel); - } - } - } - - if (routes.empty()) - { - routes = {0, 1}; - } - - return routes; - } - - AdcTilde::AdcTilde(std::string const& name, std::vector const& args) - { - size_t channels = parseArgsAsChannelRoutes(args).size(); - - pushInlet({PinType::IType::Control}); - - for (int i = 0; i < channels; ++i) - { - pushOutlet({PinType::IType::Signal}); - } - } - - void AdcTilde::declare() - { - Factory::add("adc~"); - } - - std::string AdcTilde::getIODescription(bool is_inlet, size_t index) const - { - if(is_inlet) - { - return "Start/Stop dsp"; - } - else - { - if(index < getNumberOfOutlets()) - { - auto text_atoms = AtomHelper::parse(getText()); - text_atoms.erase(text_atoms.cbegin()); - const auto routes = parseArgsAsChannelRoutes(text_atoms); - - return "(signal) Audio In Channel " + std::to_string(routes[index] + 1); - } - } - - return {}; - } - - // ================================================================================ // - // OBJECT DAC~ // - // ================================================================================ // - - DacTilde::DacTilde(std::string const& name, std::vector const& args) - { - size_t channels = parseArgsAsChannelRoutes(args).size(); - - pushInlet({PinType::IType::Signal, PinType::IType::Control}); - - for (int i = 1; i < channels; ++i) - { - pushInlet({PinType::IType::Signal}); - } - } - - void DacTilde::declare() - { - Factory::add("dac~"); - } - - std::string DacTilde::getIODescription(bool is_inlet, size_t index) const - { - if(is_inlet) - { - if(index < getNumberOfInlets()) - { - auto text_atoms = AtomHelper::parse(getText()); - text_atoms.erase(text_atoms.cbegin()); - const auto routes = parseArgsAsChannelRoutes(text_atoms); - - if(index == 0) - { - return "Start/Stop dsp, (signal) Audio Out Channel " + std::to_string(routes[0] + 1); - } - else - { - return "(signal) Audio Out Channel " + std::to_string(routes[index] + 1); - } - } - } - - return {}; - } - - // ================================================================================ // - // OBJECT OSC~ // - // ================================================================================ // - - OscTilde::OscTilde(std::string const& name, std::vector const& args) - { - pushInlet({PinType::IType::Control, PinType::IType::Signal}); - pushInlet({PinType::IType::Control, PinType::IType::Signal}); - - pushOutlet(PinType::IType::Signal); - } - - void OscTilde::declare() - { - Factory::add("osc~"); - } - - std::string OscTilde::getIODescription(bool is_inlet, size_t index) const - { - if(is_inlet) - { - if(index == 0) - { - return "(signal/float) Set frequency"; - } - else if(index == 1) - { - return "(signal/float) Set phase (0-1)"; - } - } - else - { - return "(signal) Output"; - } - - return {}; - } - - // ================================================================================ // - // OBJECT TIMES~ // - // ================================================================================ // - - TimesTilde::TimesTilde(std::string const& name, std::vector const& args) - { - pushInlet({PinType::IType::Signal}); - - if (args.empty() || !args[0].isNumber()) - { - pushInlet({PinType::IType::Signal, PinType::IType::Control}); - } - - pushOutlet(PinType::IType::Signal); - } - - void TimesTilde::declare() - { - Factory::add("times~").addAlias("*~"); - } - - std::string TimesTilde::getIODescription(bool is_inlet, size_t index) const - { - return is_inlet ? (index == 0) ? "(signal) Left operand" : "(signal) Right operand" : "(signal) Output"; - } - - // ================================================================================ // - // OBJECT PLUS~ // - // ================================================================================ // - - PlusTilde::PlusTilde(std::string const& name, std::vector const& args) - { - pushInlet({PinType::IType::Signal}); - - if (args.empty() || !args[0].isNumber()) - { - pushInlet({PinType::IType::Signal, PinType::IType::Control}); - } - - pushOutlet(PinType::IType::Signal); - } - - void PlusTilde::declare() - { - Factory::add("plus~").addAlias("+~"); - } - - std::string PlusTilde::getIODescription(bool is_inlet, size_t index) const - { - return is_inlet ? (index == 0) ? "(signal) Left operand" : "(signal) Right operand" : "(signal) Output"; - } - - // ================================================================================ // - // OBJECT SIG~ // - // ================================================================================ // - - SigTilde::SigTilde(std::string const& name, std::vector const& args) - { - if (args.empty() || !args[0].isNumber()) - { - pushInlet({PinType::IType::Control}); - } - - pushOutlet(PinType::IType::Signal); - } - - void SigTilde::declare() - { - Factory::add("sig~"); - } - - std::string SigTilde::getIODescription(bool is_inlet, size_t index) const - { - return is_inlet ? "(float/int) Set signal value" : "(signal) Output value"; - } - - // ================================================================================ // - // OBJECT DELAYSIMPLE~ // - // ================================================================================ // - - DelaySimpleTilde::DelaySimpleTilde(std::string const& name, std::vector const& args) - { - if (args.size() > 0) - { - throw ("wrong argument for object delay~"); - } - - pushInlet({PinType::IType::Control, PinType::IType::Signal}); - pushInlet({PinType::IType::Control, PinType::IType::Signal}); - pushInlet({PinType::IType::Control}); - - pushOutlet(PinType::IType::Signal); - } - - void DelaySimpleTilde::declare() - { - Factory::add("delaysimple~"); - } - - std::string DelaySimpleTilde::getIODescription(bool is_inlet, size_t index) const - { - if(is_inlet) - { - if(index == 0) - { - return "(signal) Input to be delayed"; - } - else if(index == 1) - { - return "(signal/float) Delay time (ms)"; - } - else if(index == 2) - { - return "(float) Feedback (0-1)"; - } - } - else - { - return "(signal) Delayed output signal"; - } - - return {}; - } - } -} diff --git a/Modules/KiwiModel/KiwiModel_Objects.h b/Modules/KiwiModel/KiwiModel_Objects.h deleted file mode 100755 index 5d6dacae..00000000 --- a/Modules/KiwiModel/KiwiModel_Objects.h +++ /dev/null @@ -1,379 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#pragma once - -#include "KiwiModel_Object.h" -#include "KiwiModel_Factory.h" - -namespace kiwi -{ - namespace model - { - // ================================================================================ // - // NEWBOX // - // ================================================================================ // - - class NewBox : public model::Object - { - public: - - //! @brief flip Default Constructor - NewBox(flip::Default& d) : model::Object(d) {} - - //! @brief Constructor - NewBox(std::string const& name, std::vector const& args); - - std::string getIODescription(bool is_inlet, size_t index) const override; - - //! @internal flip static declare method - static void declare(); - }; - - // ================================================================================ // - // ERRORBOX // - // ================================================================================ // - - class ErrorBox : public model::Object - { - public: - - //! @brief flip Default Constructor - ErrorBox(flip::Default& d) : model::Object(d) {} - - //! @brief Constructor - ErrorBox(std::string const& name, std::vector const& args); - - //! @brief Set the number of inlets. - //! @param inlets The number of inlets. - void setInlets(flip::Array const& inlets); - - //! @brief Set the number of inlets. - //! @param inlets The number of inlets. - void setOutlets(flip::Array const& outlets); - - std::string getIODescription(bool is_inlet, size_t index) const override; - - //! @internal flip static declare method - static void declare(); - }; - - // ================================================================================ // - // OBJECT PLUS // - // ================================================================================ // - - class Plus : public model::Object - { - public: - - //! @brief flip Default Constructor - Plus(flip::Default& d) : model::Object(d) {} - - //! @brief Constructor - Plus(std::string const& name, std::vector const& args); - - std::string getIODescription(bool is_inlet, size_t index) const override; - - //! @internal flip static declare method - static void declare(); - }; - - // ================================================================================ // - // OBJECT TIMES // - // ================================================================================ // - - class Times : public model::Object - { - public: - - //! @brief flip Default Constructor - Times(flip::Default& d) : model::Object(d) {} - - //! @brief Constructor - Times(std::string const& name, std::vector const& args); - - std::string getIODescription(bool is_inlet, size_t index) const override; - - //! @internal flip static declare method - static void declare(); - }; - - // ================================================================================ // - // OBJECT PRINT // - // ================================================================================ // - - class Print : public model::Object - { - public: - - //! @brief flip Default Constructor - Print(flip::Default& d) : model::Object(d) {} - - //! @brief Constructor - Print(std::string const& name, std::vector const& args); - - std::string getIODescription(bool is_inlet, size_t index) const override; - - //! @internal flip static declare method - static void declare(); - }; - - // ================================================================================ // - // OBJECT RECEIVE // - // ================================================================================ // - - class Receive : public model::Object - { - public: - - //! @brief flip Default Constructor - Receive(flip::Default& d) : model::Object(d) {} - - //! @brief Constructor - Receive(std::string const& name, std::vector const& args); - - std::string getIODescription(bool is_inlet, size_t index) const override; - - //! @internal flip static declare method - static void declare(); - }; - - // ================================================================================ // - // OBJECT LOADMESS // - // ================================================================================ // - - class Loadmess : public model::Object - { - public: - - //! @brief flip Default Constructor - Loadmess(flip::Default& d) : model::Object(d) {} - - //! @brief Constructor - Loadmess(std::string const& name, std::vector const& args); - - std::string getIODescription(bool is_inlet, size_t index) const override; - - //! @internal flip static declare method - static void declare(); - }; - - // ================================================================================ // - // OBJECT DELAY // - // ================================================================================ // - - class Delay : public model::Object - { - public: // methods - - //! @brief flip Default Constructor - Delay(flip::Default& d) : model::Object(d) {}; - - //! @brief Constructor - Delay(std::string const& name, std::vector const& args); - - std::string getIODescription(bool is_inlet, size_t index) const override; - - //! @internal flip static declare method - static void declare(); - }; - - // ================================================================================ // - // OBJECT PIPE // - // ================================================================================ // - - class Pipe : public model::Object - { - public: // methods - - //! @brief flip Default Constructor - Pipe(flip::Default& d) : model::Object(d) {}; - - //! @brief Constructor - Pipe(std::string const& name, std::vector const& args); - - std::string getIODescription(bool is_inlet, size_t index) const override; - - //! @internal flip static declare method - static void declare(); - }; - - // ================================================================================ // - // OBJECT METRO // - // ================================================================================ // - - class Metro : public model::Object - { - public: // methods - - //! @brief flip Default Constructor - Metro(flip::Default& d) : model::Object(d) {}; - - //! @brief Constructor - Metro(std::string const& name, std::vector const& args); - - std::string getIODescription(bool is_inlet, size_t index) const override; - - //! @internal flip static declare method - static void declare(); - }; - - // ================================================================================ // - // OBJECT OSC~ // - // ================================================================================ // - - class OscTilde : public model::Object - { - public: - //! @brief flip Default Constructor - OscTilde(flip::Default& d): model::Object(d){}; - - //! @brief Constructor - OscTilde(std::string const& name, std::vector const& args); - - std::string getIODescription(bool is_inlet, size_t index) const override; - - //! @internal flip static declare method - static void declare(); - }; - - // ================================================================================ // - // OBJECT ADC~ // - // ================================================================================ // - - class AdcTilde : public model::Object - { - public: - - //! @brief flip Default Constructor - AdcTilde(flip::Default& d): model::Object(d){} - - //! @brief Constructor - AdcTilde(std::string const& name, std::vector const& args); - - std::string getIODescription(bool is_inlet, size_t index) const override; - - //! @internal flip static declare method - static void declare(); - }; - - // ================================================================================ // - // OBJECT DAC~ // - // ================================================================================ // - - - class DacTilde : public model::Object - { - public: - - //! @brief flip Default Constructor - DacTilde(flip::Default& d): model::Object(d){} - - //! @brief Constructor - DacTilde(std::string const& name, std::vector const& args); - - std::string getIODescription(bool is_inlet, size_t index) const override; - - //! @internal flip static declare method - static void declare(); - }; - - // ================================================================================ // - // OBJECT *~ // - // ================================================================================ // - - class TimesTilde : public model::Object - { - public: - - //! @brief flip Default Constructor - TimesTilde(flip::Default& d): model::Object(d){}; - - //! @brief Constructor - TimesTilde(std::string const& name, std::vector const& args); - - std::string getIODescription(bool is_inlet, size_t index) const override; - - //! @internal flip static declare method - static void declare(); - }; - - // ================================================================================ // - // OBJECT +~ // - // ================================================================================ // - - class PlusTilde : public model::Object - { - public: - - //! @brief flip Default Constructor - PlusTilde(flip::Default& d): model::Object(d){}; - - //! @brief Constructor - PlusTilde(std::string const& name, std::vector const& args); - - std::string getIODescription(bool is_inlet, size_t index) const override; - - //! @internal flip static declare method - static void declare(); - }; - - // ================================================================================ // - // OBJECT SIG~ // - // ================================================================================ // - - class SigTilde : public model::Object - { - public: - - //! @brief flip Default Constructor - SigTilde(flip::Default& d): model::Object(d){}; - - //! @brief Constructor - SigTilde(std::string const& name, std::vector const& args); - - std::string getIODescription(bool is_inlet, size_t index) const override; - - //! @internal flip static declare method - static void declare(); - }; - - // ================================================================================ // - // OBJECT DELAYSIMPLETILDE~ // - // ================================================================================ // - - class DelaySimpleTilde : public model::Object - { - public: - - //! @brief flip Default Constructor - DelaySimpleTilde(flip::Default& d): model::Object(d){}; - - //! @brief Constructor - DelaySimpleTilde(std::string const& name, std::vector const& args); - - std::string getIODescription(bool is_inlet, size_t index) const override; - - //! @internal flip static declare method - static void declare(); - }; - } -} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_ErrorBox.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_ErrorBox.cpp new file mode 100755 index 00000000..b7b60f44 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_ErrorBox.cpp @@ -0,0 +1,58 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include + +namespace kiwi +{ + namespace model + { + // ================================================================================ // + // ERRORBOX // + // ================================================================================ // + + void ErrorBox::declare() + { + Factory::add("errorbox").setInternal(true); + } + + ErrorBox::ErrorBox(std::string const& name, std::vector const& args) + { + } + + void ErrorBox::setInlets(flip::Array const& inlets) + { + model::Object::setInlets(inlets); + } + + void ErrorBox::setOutlets(flip::Array const& outlets) + { + model::Object::setOutlets(outlets); + } + + std::string ErrorBox::getIODescription(bool is_inlet, size_t index) const + { + return "(nothing here)"; + } + } +} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_ErrorBox.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_ErrorBox.h new file mode 100755 index 00000000..909d82fa --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_ErrorBox.h @@ -0,0 +1,58 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi +{ + namespace model + { + // ================================================================================ // + // ERRORBOX // + // ================================================================================ // + + class ErrorBox : public model::Object + { + public: + + //! @brief flip Default Constructor + ErrorBox(flip::Default& d) : model::Object(d) {} + + //! @brief Constructor + ErrorBox(std::string const& name, std::vector const& args); + + //! @brief Set the number of inlets. + //! @param inlets The number of inlets. + void setInlets(flip::Array const& inlets); + + //! @brief Set the number of inlets. + //! @param inlets The number of inlets. + void setOutlets(flip::Array const& outlets); + + std::string getIODescription(bool is_inlet, size_t index) const override; + + //! @internal flip static declare method + static void declare(); + }; + } +} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_NewBox.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_NewBox.cpp new file mode 100755 index 00000000..d656302b --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_NewBox.cpp @@ -0,0 +1,49 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include + +namespace kiwi +{ + namespace model + { + // ================================================================================ // + // NEWBOX // + // ================================================================================ // + + void NewBox::declare() + { + Factory::add("newbox").setInternal(true); + } + + NewBox::NewBox(std::string const& name, std::vector const& args) + { + pushInlet({PinType::IType::Control}); + } + + std::string NewBox::getIODescription(bool is_inlet, size_t index) const + { + return "(nothing here)"; + } + } +} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_NewBox.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_NewBox.h new file mode 100755 index 00000000..abcd4f7f --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_NewBox.h @@ -0,0 +1,50 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi +{ + namespace model + { + // ================================================================================ // + // NEWBOX // + // ================================================================================ // + + class NewBox : public model::Object + { + public: + + //! @brief flip Default Constructor + NewBox(flip::Default& d) : model::Object(d) {} + + //! @brief Constructor + NewBox(std::string const& name, std::vector const& args); + + std::string getIODescription(bool is_inlet, size_t index) const override; + + //! @internal flip static declare method + static void declare(); + }; + } +} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_AdcTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_AdcTilde.cpp new file mode 100755 index 00000000..5cfbc08b --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_AdcTilde.cpp @@ -0,0 +1,125 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include + +namespace kiwi +{ + namespace model + { + // ================================================================================ // + // OBJECT ADC~ // + // ================================================================================ // + + AdcTilde::AdcTilde(std::string const& name, std::vector const& args) + { + size_t channels = parseArgsAsChannelRoutes(args).size(); + + pushInlet({PinType::IType::Control}); + + for (int i = 0; i < channels; ++i) + { + pushOutlet({PinType::IType::Signal}); + } + } + + std::vector AdcTilde::parseArgsAsChannelRoutes(std::vector const& args) const + { + std::vector routes; + + for(Atom const& arg : args) + { + if (arg.isNumber()) + { + if (arg.getInt() <= 0) + { + throw std::runtime_error("null or negative channel"); + } + + routes.push_back(arg.getInt() - 1); + } + else if(arg.isString()) + { + std::string inputs(arg.getString()); + + size_t sep_pos = inputs.find(":"); + + if (sep_pos == std::string::npos) + { + throw std::runtime_error("wrong symbol syntax"); + } + + int left_input = std::stoi(inputs.substr(0, sep_pos)) - 1; + int right_input = std::stoi(inputs.substr(inputs.find(":") + 1)) - 1; + + if (left_input < 0 || right_input < 0) + { + throw std::runtime_error("null or negative channel"); + } + + const bool rev = left_input > right_input; + + for (int channel = left_input; + rev ? channel >= right_input : channel <= right_input; + rev ? --channel : ++channel) + { + routes.push_back(channel); + } + } + } + + if (routes.empty()) + { + routes = {0, 1}; + } + + return routes; + } + + void AdcTilde::declare() + { + Factory::add("adc~"); + } + + std::string AdcTilde::getIODescription(bool is_inlet, size_t index) const + { + if(is_inlet) + { + return "Start/Stop dsp"; + } + else + { + if(index < getNumberOfOutlets()) + { + auto text_atoms = AtomHelper::parse(getText()); + text_atoms.erase(text_atoms.cbegin()); + const auto routes = parseArgsAsChannelRoutes(text_atoms); + + return "(signal) Audio In Channel " + std::to_string(routes[index] + 1); + } + } + + return {}; + } + } +} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_AdcTilde.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_AdcTilde.h new file mode 100755 index 00000000..349d1607 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_AdcTilde.h @@ -0,0 +1,54 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi +{ + namespace model + { + // ================================================================================ // + // OBJECT ADC~ // + // ================================================================================ // + + class AdcTilde : public model::Object + { + public: + + //! @brief flip Default Constructor + AdcTilde(flip::Default& d): model::Object(d){} + + //! @brief Parses args to construct routes + //! @todo Mutualize with adc tilde object. + std::vector parseArgsAsChannelRoutes(std::vector const& args) const; + + //! @brief Constructor + AdcTilde(std::string const& name, std::vector const& args); + + std::string getIODescription(bool is_inlet, size_t index) const override; + + //! @internal flip static declare method + static void declare(); + }; + } +} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_DacTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_DacTilde.cpp new file mode 100755 index 00000000..7774c500 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_DacTilde.cpp @@ -0,0 +1,128 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include + +namespace kiwi +{ + namespace model + { + // ================================================================================ // + // OBJECT DAC~ // + // ================================================================================ // + + DacTilde::DacTilde(std::string const& name, std::vector const& args) + { + size_t channels = parseArgsAsChannelRoutes(args).size(); + + pushInlet({PinType::IType::Signal, PinType::IType::Control}); + + for (int i = 1; i < channels; ++i) + { + pushInlet({PinType::IType::Signal}); + } + } + + std::vector DacTilde::parseArgsAsChannelRoutes(std::vector const& args) const + { + std::vector routes; + + for(Atom const& arg : args) + { + if (arg.isNumber()) + { + if (arg.getInt() <= 0) + { + throw std::runtime_error("null or negative channel"); + } + + routes.push_back(arg.getInt() - 1); + } + else if(arg.isString()) + { + std::string inputs(arg.getString()); + + size_t sep_pos = inputs.find(":"); + + if (sep_pos == std::string::npos) + { + throw std::runtime_error("wrong symbol syntax"); + } + + int left_input = std::stoi(inputs.substr(0, sep_pos)) - 1; + int right_input = std::stoi(inputs.substr(inputs.find(":") + 1)) - 1; + + if (left_input < 0 || right_input < 0) + { + throw std::runtime_error("null or negative channel"); + } + + const bool rev = left_input > right_input; + + for (int channel = left_input; + rev ? channel >= right_input : channel <= right_input; + rev ? --channel : ++channel) + { + routes.push_back(channel); + } + } + } + + if (routes.empty()) + { + routes = {0, 1}; + } + + return routes; + } + + void DacTilde::declare() + { + Factory::add("dac~"); + } + + std::string DacTilde::getIODescription(bool is_inlet, size_t index) const + { + if(is_inlet) + { + if(index < getNumberOfInlets()) + { + auto text_atoms = AtomHelper::parse(getText()); + text_atoms.erase(text_atoms.cbegin()); + const auto routes = parseArgsAsChannelRoutes(text_atoms); + + if(index == 0) + { + return "Start/Stop dsp, (signal) Audio Out Channel " + std::to_string(routes[0] + 1); + } + else + { + return "(signal) Audio Out Channel " + std::to_string(routes[index] + 1); + } + } + } + + return {}; + } + } +} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_DacTilde.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_DacTilde.h new file mode 100755 index 00000000..683aed03 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_DacTilde.h @@ -0,0 +1,53 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi +{ + namespace model + { + // ================================================================================ // + // OBJECT DAC~ // + // ================================================================================ // + + class DacTilde : public model::Object + { + public: + + //! @brief flip Default Constructor + DacTilde(flip::Default& d): model::Object(d){} + + //! @brief Parses args to construct routes + std::vector parseArgsAsChannelRoutes(std::vector const& args) const; + + //! @brief Constructor + DacTilde(std::string const& name, std::vector const& args); + + std::string getIODescription(bool is_inlet, size_t index) const override; + + //! @internal flip static declare method + static void declare(); + }; + } +} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_DelaySimpleTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_DelaySimpleTilde.cpp new file mode 100755 index 00000000..f712010f --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_DelaySimpleTilde.cpp @@ -0,0 +1,78 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include + +namespace kiwi +{ + namespace model + { + // ================================================================================ // + // OBJECT DELAYSIMPLE~ // + // ================================================================================ // + + DelaySimpleTilde::DelaySimpleTilde(std::string const& name, std::vector const& args) + { + if (args.size() > 0) + { + throw ("wrong argument for object delay~"); + } + + pushInlet({PinType::IType::Control, PinType::IType::Signal}); + pushInlet({PinType::IType::Control, PinType::IType::Signal}); + pushInlet({PinType::IType::Control}); + + pushOutlet(PinType::IType::Signal); + } + + void DelaySimpleTilde::declare() + { + Factory::add("delaysimple~"); + } + + std::string DelaySimpleTilde::getIODescription(bool is_inlet, size_t index) const + { + if(is_inlet) + { + if(index == 0) + { + return "(signal) Input to be delayed"; + } + else if(index == 1) + { + return "(signal/float) Delay time (ms)"; + } + else if(index == 2) + { + return "(float) Feedback (0-1)"; + } + } + else + { + return "(signal) Delayed output signal"; + } + + return {}; + } + } +} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_DelaySimpleTilde.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_DelaySimpleTilde.h new file mode 100755 index 00000000..65300540 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_DelaySimpleTilde.h @@ -0,0 +1,50 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi +{ + namespace model + { + // ================================================================================ // + // OBJECT DELAYSIMPLETILDE~ // + // ================================================================================ // + + class DelaySimpleTilde : public model::Object + { + public: + + //! @brief flip Default Constructor + DelaySimpleTilde(flip::Default& d): model::Object(d){}; + + //! @brief Constructor + DelaySimpleTilde(std::string const& name, std::vector const& args); + + std::string getIODescription(bool is_inlet, size_t index) const override; + + //! @internal flip static declare method + static void declare(); + }; + } +} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_OscTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_OscTilde.cpp new file mode 100755 index 00000000..9667ec1a --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_OscTilde.cpp @@ -0,0 +1,68 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include + +namespace kiwi +{ + namespace model + { + // ================================================================================ // + // OBJECT OSC~ // + // ================================================================================ // + + OscTilde::OscTilde(std::string const& name, std::vector const& args) + { + pushInlet({PinType::IType::Control, PinType::IType::Signal}); + pushInlet({PinType::IType::Control, PinType::IType::Signal}); + + pushOutlet(PinType::IType::Signal); + } + + void OscTilde::declare() + { + Factory::add("osc~"); + } + + std::string OscTilde::getIODescription(bool is_inlet, size_t index) const + { + if(is_inlet) + { + if(index == 0) + { + return "(signal/float) Set frequency"; + } + else if(index == 1) + { + return "(signal/float) Set phase (0-1)"; + } + } + else + { + return "(signal) Output"; + } + + return {}; + } + } +} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_OscTilde.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_OscTilde.h new file mode 100755 index 00000000..f7f4b3c5 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_OscTilde.h @@ -0,0 +1,49 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi +{ + namespace model + { + // ================================================================================ // + // OBJECT OSC~ // + // ================================================================================ // + + class OscTilde : public model::Object + { + public: + //! @brief flip Default Constructor + OscTilde(flip::Default& d): model::Object(d){}; + + //! @brief Constructor + OscTilde(std::string const& name, std::vector const& args); + + std::string getIODescription(bool is_inlet, size_t index) const override; + + //! @internal flip static declare method + static void declare(); + }; + } +} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_PlusTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_PlusTilde.cpp new file mode 100755 index 00000000..ae1ddd54 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_PlusTilde.cpp @@ -0,0 +1,56 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include + +namespace kiwi +{ + namespace model + { + // ================================================================================ // + // OBJECT PLUS~ // + // ================================================================================ // + + PlusTilde::PlusTilde(std::string const& name, std::vector const& args) + { + pushInlet({PinType::IType::Signal}); + + if (args.empty() || !args[0].isNumber()) + { + pushInlet({PinType::IType::Signal, PinType::IType::Control}); + } + + pushOutlet(PinType::IType::Signal); + } + + void PlusTilde::declare() + { + Factory::add("plus~").addAlias("+~"); + } + + std::string PlusTilde::getIODescription(bool is_inlet, size_t index) const + { + return is_inlet ? (index == 0) ? "(signal) Left operand" : "(signal) Right operand" : "(signal) Output"; + } + } +} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_PlusTilde.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_PlusTilde.h new file mode 100755 index 00000000..0751c617 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_PlusTilde.h @@ -0,0 +1,50 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi +{ + namespace model + { + // ================================================================================ // + // OBJECT PLUS~ // + // ================================================================================ // + + class PlusTilde : public model::Object + { + public: + + //! @brief flip Default Constructor + PlusTilde(flip::Default& d): model::Object(d){}; + + //! @brief Constructor + PlusTilde(std::string const& name, std::vector const& args); + + std::string getIODescription(bool is_inlet, size_t index) const override; + + //! @internal flip static declare method + static void declare(); + }; + } +} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_SigTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_SigTilde.cpp new file mode 100755 index 00000000..746e5fad --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_SigTilde.cpp @@ -0,0 +1,54 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include + +namespace kiwi +{ + namespace model + { + // ================================================================================ // + // OBJECT SIG~ // + // ================================================================================ // + + SigTilde::SigTilde(std::string const& name, std::vector const& args) + { + if (args.empty() || !args[0].isNumber()) + { + pushInlet({PinType::IType::Control}); + } + + pushOutlet(PinType::IType::Signal); + } + + void SigTilde::declare() + { + Factory::add("sig~"); + } + + std::string SigTilde::getIODescription(bool is_inlet, size_t index) const + { + return is_inlet ? "(float/int) Set signal value" : "(signal) Output value"; + } + } +} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_SigTilde.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_SigTilde.h new file mode 100755 index 00000000..550dc8f0 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_SigTilde.h @@ -0,0 +1,50 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi +{ + namespace model + { + // ================================================================================ // + // OBJECT SIG~ // + // ================================================================================ // + + class SigTilde : public model::Object + { + public: + + //! @brief flip Default Constructor + SigTilde(flip::Default& d): model::Object(d){}; + + //! @brief Constructor + SigTilde(std::string const& name, std::vector const& args); + + std::string getIODescription(bool is_inlet, size_t index) const override; + + //! @internal flip static declare method + static void declare(); + }; + } +} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_TimesTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_TimesTilde.cpp new file mode 100755 index 00000000..dce92da7 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_TimesTilde.cpp @@ -0,0 +1,56 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include + +namespace kiwi +{ + namespace model + { + // ================================================================================ // + // OBJECT TIMES~ // + // ================================================================================ // + + TimesTilde::TimesTilde(std::string const& name, std::vector const& args) + { + pushInlet({PinType::IType::Signal}); + + if (args.empty() || !args[0].isNumber()) + { + pushInlet({PinType::IType::Signal, PinType::IType::Control}); + } + + pushOutlet(PinType::IType::Signal); + } + + void TimesTilde::declare() + { + Factory::add("times~").addAlias("*~"); + } + + std::string TimesTilde::getIODescription(bool is_inlet, size_t index) const + { + return is_inlet ? (index == 0) ? "(signal) Left operand" : "(signal) Right operand" : "(signal) Output"; + } + } +} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_TimesTilde.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_TimesTilde.h new file mode 100755 index 00000000..ec49d732 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_TimesTilde.h @@ -0,0 +1,50 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi +{ + namespace model + { + // ================================================================================ // + // OBJECT *~ // + // ================================================================================ // + + class TimesTilde : public model::Object + { + public: + + //! @brief flip Default Constructor + TimesTilde(flip::Default& d): model::Object(d){}; + + //! @brief Constructor + TimesTilde(std::string const& name, std::vector const& args); + + std::string getIODescription(bool is_inlet, size_t index) const override; + + //! @internal flip static declare method + static void declare(); + }; + } +} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Math/KiwiModel_Plus.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Math/KiwiModel_Plus.cpp new file mode 100755 index 00000000..cb18194a --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Math/KiwiModel_Plus.cpp @@ -0,0 +1,56 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include + +namespace kiwi +{ + namespace model + { + // ================================================================================ // + // OBJECT PLUS // + // ================================================================================ // + + void Plus::declare() + { + Factory::add("plus").addAlias("+"); + } + + Plus::Plus(std::string const& name, std::vector const& args) + { + pushInlet({PinType::IType::Control}); + + if (args.empty() || !args[0].isNumber()) + { + pushInlet({PinType::IType::Control}); + } + + pushOutlet(PinType::IType::Control); + } + + std::string Plus::getIODescription(bool is_inlet, size_t index) const + { + return is_inlet ? (index == 0) ? "Left operand" : "Right operand" : "Result"; + } + } +} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Math/KiwiModel_Plus.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Math/KiwiModel_Plus.h new file mode 100755 index 00000000..27c4f78e --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Math/KiwiModel_Plus.h @@ -0,0 +1,50 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi +{ + namespace model + { + // ================================================================================ // + // OBJECT PLUS // + // ================================================================================ // + + class Plus : public model::Object + { + public: + + //! @brief flip Default Constructor + Plus(flip::Default& d) : model::Object(d) {} + + //! @brief Constructor + Plus(std::string const& name, std::vector const& args); + + std::string getIODescription(bool is_inlet, size_t index) const override; + + //! @internal flip static declare method + static void declare(); + }; + } +} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Math/KiwiModel_Times.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Math/KiwiModel_Times.cpp new file mode 100755 index 00000000..b0b64ea8 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Math/KiwiModel_Times.cpp @@ -0,0 +1,56 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include + +namespace kiwi +{ + namespace model + { + // ================================================================================ // + // OBJECT TIMES // + // ================================================================================ // + + void Times::declare() + { + Factory::add("times").addAlias("*"); + } + + Times::Times(std::string const& name, std::vector const& args) + { + pushInlet({PinType::IType::Control}); + + if (args.empty() || !args[0].isNumber()) + { + pushInlet({PinType::IType::Control}); + } + + pushOutlet(PinType::IType::Control); + } + + std::string Times::getIODescription(bool is_inlet, size_t index) const + { + return is_inlet ? (index == 0) ? "Left operand" : "Right operand" : "Result"; + } + } +} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Math/KiwiModel_Times.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Math/KiwiModel_Times.h new file mode 100755 index 00000000..a1877bc0 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Math/KiwiModel_Times.h @@ -0,0 +1,50 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi +{ + namespace model + { + // ================================================================================ // + // OBJECT TIMES // + // ================================================================================ // + + class Times : public model::Object + { + public: + + //! @brief flip Default Constructor + Times(flip::Default& d) : model::Object(d) {} + + //! @brief Constructor + Times(std::string const& name, std::vector const& args); + + std::string getIODescription(bool is_inlet, size_t index) const override; + + //! @internal flip static declare method + static void declare(); + }; + } +} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Loadmess.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Loadmess.cpp new file mode 100755 index 00000000..7ea67911 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Loadmess.cpp @@ -0,0 +1,54 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include + +namespace kiwi +{ + namespace model + { + // ================================================================================ // + // OBJECT LOADMESS // + // ================================================================================ // + + Loadmess::Loadmess(std::string const& name, std::vector const& args) + { + pushOutlet(PinType::IType::Control); + } + + void Loadmess::declare() + { + Factory::add("loadmess"); + } + + std::string Loadmess::getIODescription(bool is_inlet, size_t index) const + { + if(is_inlet) + { + return "Receive messages when the patch is loaded"; + } + + return {}; + } + } +} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Loadmess.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Loadmess.h new file mode 100755 index 00000000..7fb63dc0 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Loadmess.h @@ -0,0 +1,50 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi +{ + namespace model + { + // ================================================================================ // + // OBJECT LOADMESS // + // ================================================================================ // + + class Loadmess : public model::Object + { + public: + + //! @brief flip Default Constructor + Loadmess(flip::Default& d) : model::Object(d) {} + + //! @brief Constructor + Loadmess(std::string const& name, std::vector const& args); + + std::string getIODescription(bool is_inlet, size_t index) const override; + + //! @internal flip static declare method + static void declare(); + }; + } +} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Print.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Print.cpp new file mode 100755 index 00000000..40f8ece3 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Print.cpp @@ -0,0 +1,49 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include + +namespace kiwi +{ + namespace model + { + // ================================================================================ // + // OBJECT PRINT // + // ================================================================================ // + + Print::Print(std::string const& name, std::vector const& args) + { + pushInlet({PinType::IType::Control}); + } + + void Print::declare() + { + Factory::add("print"); + } + + std::string Print::getIODescription(bool is_inlet, size_t index) const + { + return "Message to post in the Kiwi console"; + } + } +} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Print.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Print.h new file mode 100755 index 00000000..75e338a3 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Print.h @@ -0,0 +1,50 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi +{ + namespace model + { + // ================================================================================ // + // OBJECT PRINT // + // ================================================================================ // + + class Print : public model::Object + { + public: + + //! @brief flip Default Constructor + Print(flip::Default& d) : model::Object(d) {} + + //! @brief Constructor + Print(std::string const& name, std::vector const& args); + + std::string getIODescription(bool is_inlet, size_t index) const override; + + //! @internal flip static declare method + static void declare(); + }; + } +} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Receive.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Receive.cpp new file mode 100755 index 00000000..696aa413 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Receive.cpp @@ -0,0 +1,54 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include + +namespace kiwi +{ + namespace model + { + // ================================================================================ // + // OBJECT RECEIVE // + // ================================================================================ // + + Receive::Receive(std::string const& name, std::vector const& args) + { + pushOutlet(PinType::IType::Control); + } + + void Receive::declare() + { + Factory::add("receive").addAlias("r"); + } + + std::string Receive::getIODescription(bool is_inlet, size_t index) const + { + if(!is_inlet) + { + return "Receive messages"; + } + + return {}; + } + } +} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Receive.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Receive.h new file mode 100755 index 00000000..a1593170 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Receive.h @@ -0,0 +1,50 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi +{ + namespace model + { + // ================================================================================ // + // OBJECT RECEIVE // + // ================================================================================ // + + class Receive : public model::Object + { + public: + + //! @brief flip Default Constructor + Receive(flip::Default& d) : model::Object(d) {} + + //! @brief Constructor + Receive(std::string const& name, std::vector const& args); + + std::string getIODescription(bool is_inlet, size_t index) const override; + + //! @internal flip static declare method + static void declare(); + }; + } +} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h new file mode 100755 index 00000000..0a0b6257 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h @@ -0,0 +1,64 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +// ================================================================================ // +// BASIC OBJECTS // +// ================================================================================ // + +#include +#include + +// ================================================================================ // +// DSP OBJECTS // +// ================================================================================ // + +#include +#include +#include +#include +#include +#include +#include + +// ================================================================================ // +// MATH OBJECTS // +// ================================================================================ // + +#include +#include + +// ================================================================================ // +// MESSAGE OBJECTS // +// ================================================================================ // + +#include +#include +#include + +// ================================================================================ // +// TIME OBJECTS // +// ================================================================================ // + +#include +#include +#include diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Delay.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Delay.cpp new file mode 100755 index 00000000..b8bf4da5 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Delay.cpp @@ -0,0 +1,77 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include + +namespace kiwi +{ + namespace model + { + // ================================================================================ // + // OBJECT DELAY // + // ================================================================================ // + + Delay::Delay(std::string const& name, std::vector const& args) + { + if (args.size() > 1 || (args.size() == 1 && !args[0].isNumber())) + { + throw std::runtime_error("wrong argument for object Delay"); + } + + pushInlet({PinType::IType::Control}); + + if (args.empty()) + { + pushInlet({PinType::IType::Control}); + } + + pushOutlet(PinType::IType::Control); + } + + void Delay::declare() + { + Factory::add("delay"); + } + + std::string Delay::getIODescription(bool is_inlet, size_t index) const + { + if(is_inlet) + { + if(index == 0) + { + return "bang gets delayed, message \"stop\" cancels"; + } + else if(index == 1) + { + return "Set delay time"; + } + } + else + { + return "Delayed bang"; + } + + return {}; + } + } +} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Delay.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Delay.h new file mode 100755 index 00000000..303e489b --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Delay.h @@ -0,0 +1,50 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi +{ + namespace model + { + // ================================================================================ // + // OBJECT DELAY // + // ================================================================================ // + + class Delay : public model::Object + { + public: // methods + + //! @brief flip Default Constructor + Delay(flip::Default& d) : model::Object(d) {}; + + //! @brief Constructor + Delay(std::string const& name, std::vector const& args); + + std::string getIODescription(bool is_inlet, size_t index) const override; + + //! @internal flip static declare method + static void declare(); + }; + } +} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Metro.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Metro.cpp new file mode 100755 index 00000000..084893ed --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Metro.cpp @@ -0,0 +1,76 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include + +namespace kiwi +{ + namespace model + { + // ================================================================================ // + // OBJECT METRO // + // ================================================================================ // + + Metro::Metro(std::string const& name, std::vector const& args) + { + if (args.size() < 1 || (args.size() == 1 && !args[0].isNumber())) + { + throw std::runtime_error("wrong argument for object Metro"); + } + + pushInlet({PinType::IType::Control}); + + if (args.empty()) + { + pushInlet({PinType::IType::Control}); + } + + pushOutlet(PinType::IType::Control); + } + + void Metro::declare() + { + Factory::add("metro"); + } + + std::string Metro::getIODescription(bool is_inlet, size_t index) const + { + if(is_inlet) + { + if(index == 0) + { + return "Start/Stop metronome"; + } + else if(index == 1) + { + return "Set time interval"; + } + } + else + { + return "Outputs metronome ticks as bang"; + } + + return {}; + } } +} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Metro.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Metro.h new file mode 100755 index 00000000..ea7bfc0c --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Metro.h @@ -0,0 +1,50 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi +{ + namespace model + { + // ================================================================================ // + // OBJECT METRO // + // ================================================================================ // + + class Metro : public model::Object + { + public: // methods + + //! @brief flip Default Constructor + Metro(flip::Default& d) : model::Object(d) {}; + + //! @brief Constructor + Metro(std::string const& name, std::vector const& args); + + std::string getIODescription(bool is_inlet, size_t index) const override; + + //! @internal flip static declare method + static void declare(); + }; + } +} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Pipe.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Pipe.cpp new file mode 100755 index 00000000..eded951e --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Pipe.cpp @@ -0,0 +1,77 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include + +namespace kiwi +{ + namespace model + { + // ================================================================================ // + // OBJECT PIPE // + // ================================================================================ // + + Pipe::Pipe(std::string const& name, std::vector const& args) + { + if (args.size() > 1 || (args.size() == 1 && !args[0].isNumber())) + { + throw std::runtime_error("wrong argument for object Pipe"); + } + + pushInlet({PinType::IType::Control}); + + if (args.empty()) + { + pushInlet({PinType::IType::Control}); + } + + pushOutlet(PinType::IType::Control); + } + + void Pipe::declare() + { + Factory::add("pipe"); + } + + std::string Pipe::getIODescription(bool is_inlet, size_t index) const + { + if(is_inlet) + { + if(index == 0) + { + return "Anything to be delayed"; + } + else if(index == 1) + { + return "Set delay time"; + } + } + else + { + return "Delayed messages"; + } + + return {}; + } + } +} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Pipe.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Pipe.h new file mode 100755 index 00000000..e62ccb0c --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Pipe.h @@ -0,0 +1,50 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi +{ + namespace model + { + // ================================================================================ // + // OBJECT PIPE // + // ================================================================================ // + + class Pipe : public model::Object + { + public: // methods + + //! @brief flip Default Constructor + Pipe(flip::Default& d) : model::Object(d) {}; + + //! @brief Constructor + Pipe(std::string const& name, std::vector const& args); + + std::string getIODescription(bool is_inlet, size_t index) const override; + + //! @internal flip static declare method + static void declare(); + }; + } +} From 3260022e1f8db2feff2a723752dd00353b66a49e Mon Sep 17 00:00:00 2001 From: jean-millot Date: Thu, 31 Aug 2017 12:44:47 +0200 Subject: [PATCH 040/148] Creating an object frame, wrapper around the object's view. Update suggest editor behavior. --- CMakeLists.txt | 2 +- .../KiwiApp_SuggestEditor.cpp | 279 +++++---- .../KiwiApp_SuggestEditor.h | 415 ++++++------- .../KiwiApp_Patcher/KiwiApp_LinkView.cpp | 12 +- .../Source/KiwiApp_Patcher/KiwiApp_LinkView.h | 8 +- .../KiwiApp_Patcher/KiwiApp_ObjectView.cpp | 559 ------------------ .../KiwiApp_Patcher/KiwiApp_ObjectView.h | 154 ----- .../KiwiApp_Basic/KiwiApp_ClassicView.cpp | 196 ++++++ .../KiwiApp_Basic/KiwiApp_ClassicView.h | 123 ++++ .../KiwiApp_Objects/KiwiApp_ObjectFrame.cpp | 439 ++++++++++++++ .../KiwiApp_Objects/KiwiApp_ObjectFrame.h | 174 ++++++ .../KiwiApp_Objects/KiwiApp_ObjectView.cpp | 51 ++ .../KiwiApp_Objects/KiwiApp_ObjectView.h | 73 +++ .../KiwiApp_Objects/KiwiApp_Objects.h | 28 + .../KiwiApp_Patcher/KiwiApp_PatcherView.cpp | 164 +++-- .../KiwiApp_Patcher/KiwiApp_PatcherView.h | 55 +- .../KiwiApp_PatcherViewHitTester.cpp | 9 +- .../KiwiApp_PatcherViewHitTester.h | 12 +- .../KiwiApp_PatcherViewIoletHighlighter.cpp | 9 +- .../KiwiApp_PatcherViewIoletHighlighter.h | 8 +- .../KiwiApp_PatcherViewLasso.cpp | 15 +- .../KiwiApp_PatcherViewLasso.h | 2 +- .../KiwiApp_PatcherViewport.cpp | 7 +- .../KiwiApp_Patcher/KiwiApp_PatcherViewport.h | 4 +- 24 files changed, 1611 insertions(+), 1187 deletions(-) delete mode 100644 Client/Source/KiwiApp_Patcher/KiwiApp_ObjectView.cpp delete mode 100644 Client/Source/KiwiApp_Patcher/KiwiApp_ObjectView.h create mode 100644 Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.cpp create mode 100644 Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.h create mode 100644 Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.cpp create mode 100644 Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.h create mode 100644 Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectView.cpp create mode 100644 Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectView.h create mode 100644 Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Objects.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 6e9856ac..78f5912e 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -418,7 +418,7 @@ target_add_dependency(Kiwi KiwiEngine) target_add_dependency(Kiwi KiwiModel) target_add_dependency(Kiwi KiwiDsp) target_add_dependency(Kiwi Juce) -target_include_directories(Kiwi PUBLIC ${JSON_INCLUDE_DIRS}) +target_include_directories(Kiwi PUBLIC ${JSON_INCLUDE_DIRS} ${ROOT_DIR}/Client/Source) if (APPLE) set_target_properties(Kiwi PROPERTIES MACOSX_BUNDLE TRUE diff --git a/Client/Source/KiwiApp_Components/KiwiApp_SuggestEditor.cpp b/Client/Source/KiwiApp_Components/KiwiApp_SuggestEditor.cpp index 1bfbd92b..82ff26f2 100644 --- a/Client/Source/KiwiApp_Components/KiwiApp_SuggestEditor.cpp +++ b/Client/Source/KiwiApp_Components/KiwiApp_SuggestEditor.cpp @@ -19,8 +19,8 @@ ============================================================================== */ -#include "KiwiApp_SuggestEditor.h" -#include "../KiwiApp.h" +#include +#include namespace kiwi { @@ -30,7 +30,11 @@ namespace kiwi SuggestEditor::Menu::Menu(SuggestList& list) : m_suggest_list(list), - m_resizable_corner(this, &m_constrainer) + m_suggest_list_box(), + m_constrainer(), + m_resizable_corner(this, &m_constrainer), + m_validated_action(), + m_selected_action() { setAlwaysOnTop(true); setOpaque(true); @@ -99,11 +103,16 @@ namespace kiwi m_suggest_list_box.selectRow(0); } + void SuggestEditor::Menu::unselectRow() + { + m_suggest_list_box.selectRow(-1); + } + void SuggestEditor::Menu::selectPreviousRow() { const auto rows = getNumRows(); const auto row_sel = m_suggest_list_box.getSelectedRow(); - const auto new_row_sel = (row_sel == -1) ? rows - 1 : ((row_sel <= 0) ? rows - 1 : row_sel - 1); + const auto new_row_sel = (row_sel == -1) ? rows - 1 : ((row_sel <= 0) ? - 1 : row_sel - 1); m_suggest_list_box.selectRow(new_row_sel); } @@ -111,7 +120,7 @@ namespace kiwi { const auto rows = getNumRows(); const auto row_sel = m_suggest_list_box.getSelectedRow(); - const auto new_row_sel = (row_sel == -1) ? 0 : ((row_sel >= rows) ? 0 : row_sel + 1); + const auto new_row_sel = (row_sel == -1) ? 0 : ((row_sel >= rows) ? -1 : row_sel + 1); m_suggest_list_box.selectRow(new_row_sel); } @@ -120,19 +129,24 @@ namespace kiwi m_suggest_list_box.updateContent(); } - void SuggestEditor::Menu::setItemClickedAction(action_method_t function) + void SuggestEditor::Menu::setItemValidatedAction(action_method_t function) { - m_clicked_action = function; + m_validated_action = function; } - void SuggestEditor::Menu::setItemDoubleClickedAction(action_method_t function) + void SuggestEditor::Menu::setSelectedItemAction(action_method_t function) { - m_double_clicked_action = function; + m_selected_action = function; } - void SuggestEditor::Menu::setSelectedItemAction(action_method_t function) + void SuggestEditor::Menu::setUnselectedItemAction(std::function function) { - m_selected_action = function; + m_unselected_action = function; + } + + int SuggestEditor::Menu::getSelectedRow() const + { + return m_suggest_list_box.getSelectedRow(); } // ================================================================================ // @@ -159,28 +173,43 @@ namespace kiwi void SuggestEditor::Menu::listBoxItemClicked(int row, juce::MouseEvent const& e) { - if(m_clicked_action && (row < m_suggest_list.size())) + if(m_selected_action && (row < m_suggest_list.size())) { std::string const& str = *(m_suggest_list.begin() + row); - m_clicked_action(str); + m_selected_action(str); + } + } + + void SuggestEditor::Menu::validateSelectedRow() + { + int selected_row = m_suggest_list_box.getSelectedRow(); + + if (selected_row != -1 && m_validated_action) + { + std::string const& str = *(m_suggest_list.begin() + selected_row); + m_validated_action(str); } } void SuggestEditor::Menu::listBoxItemDoubleClicked(int row, juce::MouseEvent const& e) { - if(m_double_clicked_action && (row < m_suggest_list.size())) + if (row < m_suggest_list.size()) { - std::string const& str = *(m_suggest_list.begin() + row); - m_double_clicked_action(str); + selectRow(row); + validateSelectedRow(); } } void SuggestEditor::Menu::selectedRowsChanged(int last_row_selected) { - if(m_selected_action && (last_row_selected < m_suggest_list.size())) + if (last_row_selected == -1 && m_unselected_action) { - std::string const& str = *(m_suggest_list.begin() + last_row_selected); - m_selected_action(str); + m_unselected_action(); + } + else if((last_row_selected < m_suggest_list.size()) && m_selected_action) + { + std::string const& suggestion = *(m_suggest_list.begin() + last_row_selected);; + m_selected_action(suggestion); } } @@ -188,8 +217,11 @@ namespace kiwi // SUGGEST EDITOR // // ================================================================================ // - SuggestEditor::SuggestEditor(SuggestList::entries_t entries) - : m_suggest_list(std::move(entries)) + SuggestEditor::SuggestEditor(SuggestList::entries_t entries) : + m_suggest_list(std::move(entries)), + m_split_text(), + m_menu(), + m_update_enabled(true) { setReturnKeyStartsNewLine(false); setTabKeyUsedAsCharacter(false); @@ -203,24 +235,14 @@ namespace kiwi closeMenu(); } - void SuggestEditor::addListener(SuggestEditor::Listener& listener) - { - m_listeners.add(listener); - } - - void SuggestEditor::removeListener(SuggestEditor::Listener& listener) - { - m_listeners.remove(listener); - } - void SuggestEditor::showMenu() { m_menu.reset(new Menu(m_suggest_list)); using namespace std::placeholders; // for _1, _2 etc. - m_menu->setSelectedItemAction(std::bind(&SuggestEditor::menuSelectionChanged, this, _1)); - m_menu->setItemClickedAction(std::bind(&SuggestEditor::menuItemClicked, this, _1)); - m_menu->setItemDoubleClickedAction(std::bind(&SuggestEditor::menuItemDoubleClicked, this, _1)); + m_menu->setSelectedItemAction(std::bind(&SuggestEditor::menuItemSelected, this, _1)); + m_menu->setItemValidatedAction(std::bind(&SuggestEditor::menuItemValidated, this, _1)); + m_menu->setUnselectedItemAction(std::bind(&SuggestEditor::menuItemUnselected, this)); m_menu->addToDesktop(juce::ComponentPeer::windowIsTemporary | juce::ComponentPeer::windowHasDropShadow @@ -230,8 +252,6 @@ namespace kiwi m_menu->setTopLeftPosition(sb.getX() - 2, sb.getBottom() + 2); m_menu->setVisible(true); - m_need_complete = true; - startTimer(200); } @@ -249,87 +269,108 @@ namespace kiwi } } + void SuggestEditor::disableUpdate() + { + m_update_enabled = false; + } + + void SuggestEditor::enableUpdate() + { + m_update_enabled = true; + } + void SuggestEditor::textEditorTextChanged(juce::TextEditor&) { - m_typed_text = getText(); - m_suggest_list.applyFilter(m_typed_text.toStdString()); - - setCaretVisible(true); - - if(isMenuOpened() && m_suggest_list.empty()) - { - closeMenu(); - } - else if(!m_suggest_list.empty()) + if (m_update_enabled) { - if(isMenuOpened()) - m_menu->update(); - else if(!m_typed_text.isEmpty()) - showMenu(); + setCaretVisible(true); + + m_split_text.clear(); + m_split_text.addTokens(getText(), " "); - if(!m_typed_text.isEmpty() && m_need_complete) + if (m_split_text.size() == 1) { - const juce::String best_suggestion = *m_suggest_list.begin(); - const auto caret_pos = getCaretPosition(); - const int suggest_length = static_cast(best_suggestion.length()); - if(caret_pos < suggest_length && best_suggestion.startsWith(m_typed_text)) + m_suggest_list.applyFilter(m_split_text[0].toStdString()); + + if(isMenuOpened() && m_suggest_list.empty()) { - setText(best_suggestion, juce::dontSendNotification); - setHighlightedRegion({caret_pos, suggest_length}); - setCaretVisible(false); - m_menu->selectFirstRow(); + closeMenu(); } + else if(!m_suggest_list.empty()) + { + if(isMenuOpened()) + { + if (m_menu->getSelectedRow() != -1) + { + m_menu->unselectRow(); + } + + m_menu->update(); + } + else + { + showMenu(); + } + } + } + else if (isMenuOpened()) + { + closeMenu(); } } - - m_need_complete = true; - m_listeners.call(&Listener::suggestEditorTextChanged, *this); - } - - void SuggestEditor::returnPressed() - { - TextEditor::returnPressed(); - m_listeners.call(&Listener::suggestEditorReturnKeyPressed, *this); - } - - void SuggestEditor::escapePressed() - { - m_listeners.call(&Listener::suggestEditorEscapeKeyPressed, *this); - } - - void SuggestEditor::focusLost(juce::Component::FocusChangeType focus_change) - { - juce::TextEditor::focusLost(focus_change); - m_listeners.call(&Listener::suggestEditorFocusLost, *this); } - void SuggestEditor::menuSelectionChanged(juce::String const& text) + void SuggestEditor::menuItemSelected(juce::String const& text) { - setText(text, juce::dontSendNotification); - const auto caret_pos = getCaretPosition(); - const auto typed_text_lenght = m_typed_text.length(); - const auto startpos = typed_text_lenght >= caret_pos ? caret_pos : typed_text_lenght; - setHighlightedRegion({startpos, text.length()}); - setCaretVisible(text.isEmpty()); - m_listeners.call(&Listener::suggestEditorTextChanged, *this); + juce::String editor_text = getText(); + + int last_word_pos = editor_text.lastIndexOf(" ") + 1; + + juce::String replace_text = editor_text.replaceSection(last_word_pos, + editor_text.length() - last_word_pos, + text); + + disableUpdate(); + + setText(replace_text); + + int highlight_start = std::min(last_word_pos + m_split_text[m_split_text.size() - 1].length(), + replace_text.length()); + + int highlight_end = replace_text.length(); + + setHighlightedRegion({highlight_start, highlight_end}); + + setCaretVisible(false); } - void SuggestEditor::menuItemClicked(juce::String const& text) + void SuggestEditor::menuItemUnselected() { - setText(text, juce::dontSendNotification); - const auto caret_pos = getCaretPosition(); - const auto typed_text_lenght = m_typed_text.length(); - const auto startpos = typed_text_lenght >= caret_pos ? caret_pos : typed_text_lenght; - setHighlightedRegion({startpos, text.length()}); - setCaretVisible(text.isEmpty()); + juce::String editor_text = getText(); + + juce::String replace_text = editor_text.replaceSection(editor_text.lastIndexOf(" ") + 1, + editor_text.length() - editor_text.lastIndexOf(" ") - 1, + m_split_text[m_split_text.size() - 1]); + + disableUpdate(); + + setText(replace_text); } - void SuggestEditor::menuItemDoubleClicked(juce::String const& text) + void SuggestEditor::menuItemValidated(juce::String const& text) { - setText(text, juce::dontSendNotification); - setCaretPosition(text.length()); - setCaretVisible(true); + juce::String editor_text = getText(); + + juce::String replace_text = editor_text.replaceSection(editor_text.lastIndexOf(" ") + 1, + editor_text.length() - editor_text.lastIndexOf(" ") - 1, + text); + + setText(replace_text); + closeMenu(); + + moveCaretToEnd(); + setCaretVisible(true); } void SuggestEditor::timerCallback() @@ -355,24 +396,58 @@ namespace kiwi } } + bool SuggestEditor::keyStateChanged(bool isKeyDown) + { + enableUpdate(); + + return TextEditor::keyStateChanged(isKeyDown); + } + bool SuggestEditor::keyPressed(juce::KeyPress const& key) { setCaretVisible(true); - m_need_complete = !(key == juce::KeyPress::deleteKey || key == juce::KeyPress::backspaceKey); - bool result = false; - if(isMenuOpened() && key == juce::KeyPress::downKey) + if(key == juce::KeyPress::downKey && isMenuOpened()) { m_menu->selectNextRow(); result = true; } - else if(isMenuOpened() && key == juce::KeyPress::upKey) + else if(key == juce::KeyPress::upKey && isMenuOpened()) { m_menu->selectPreviousRow(); result = true; } + else if(key == juce::KeyPress::escapeKey) + { + if (isMenuOpened()) + { + if (m_menu->getSelectedRow() != -1) + { + m_menu->unselectRow(); + } + + closeMenu(); + } + else + { + m_split_text.clear(); + m_split_text.addTokens(getText(), " "); + + if (m_split_text.size() <= 1) + { + m_suggest_list.applyFilter(m_split_text[0].toStdString()); + + if (m_suggest_list.size() > 0) + { + showMenu(); + } + } + } + + result = true; + } if(!result) { diff --git a/Client/Source/KiwiApp_Components/KiwiApp_SuggestEditor.h b/Client/Source/KiwiApp_Components/KiwiApp_SuggestEditor.h index 853514d0..19c84364 100644 --- a/Client/Source/KiwiApp_Components/KiwiApp_SuggestEditor.h +++ b/Client/Source/KiwiApp_Components/KiwiApp_SuggestEditor.h @@ -1,220 +1,195 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#pragma once - -#include - -#include - -#include "../KiwiApp_Utils/KiwiApp_SuggestList.h" - -namespace kiwi -{ - // ================================================================================ // - // SUGGEST EDITOR // - // ================================================================================ // - - //! @brief A text editor with auto-completion. - //! @details This component shows a dropdown menu list below it. - class SuggestEditor - : public juce::TextEditor, - public juce::TextEditor::Listener, - public juce::Timer - { - public: // classes - - struct Listener; - - public: // methods - - //! @brief Constructor. - //! @param entries Populate suggestion list with these entries. - SuggestEditor(SuggestList::entries_t entries); - - //! @brief Destructor. - ~SuggestEditor(); - - //! @brief Adds a SuggestEditor::Listener. - void addListener(SuggestEditor::Listener& listener); - - //! @brief Removes a SuggestEditor::Listener. - void removeListener(SuggestEditor::Listener& listener); - - //! @brief Shows the menu. - void showMenu(); - - //! @brief Returns true if the menu is currently opened. - bool isMenuOpened() const noexcept; - - //! @brief Close the menu. - void closeMenu(); - - //! @brief juce::TextEditor::Listener - void textEditorTextChanged(juce::TextEditor& ed) override; - - //! @brief Called when the user presses the return key. - void returnPressed() override; - - //! @brief Called when the user presses the escape key. - void escapePressed() override; - - //! @brief Called when the text editor loses focus. - void focusLost(juce::Component::FocusChangeType focus_change) override; - - //! @brief juce::TextEditor. - bool keyPressed(juce::KeyPress const& key) override; - - private: // methods - - //! @internal Called every 200ms by a juce::Timer. - //! @details This method will close the menu if its relative position changed - //! or if editor lost the keyboard focus. - void timerCallback() override; - - //! @brief Called when the menu selection has changed. - void menuSelectionChanged(juce::String const& text); - - //! @brief Called when a menu item has been clicked. - void menuItemClicked(juce::String const& text); - - //! @brief Called when a menu item has been double-clicked. - void menuItemDoubleClicked(juce::String const& text); - - private: // classes - - class Menu; - - private: // members - - SuggestList m_suggest_list; - std::unique_ptr m_menu = nullptr; - juce::String m_typed_text; - engine::Listeners m_listeners; - - bool m_need_complete = true; - }; - - // ================================================================================ // - // SUGGEST EDITOR LISTENER // - // ================================================================================ // - - //! @brief Receives callbacks from a SuggestEditor component. - //! @see SuggestEditor::addListener - struct SuggestEditor::Listener - { - //! @brief Destructor. - virtual ~Listener() {} - - //! @brief Called when the user changes the text in some way. - virtual void suggestEditorTextChanged(SuggestEditor& editor) {} - - //! @brief Called when the user presses the return key. - virtual void suggestEditorReturnKeyPressed(SuggestEditor& editor) {} - - //! @brief Called when the user presses the escape key. - virtual void suggestEditorEscapeKeyPressed(SuggestEditor& editor) {} - - //! @brief Called when the text editor loses focus. - virtual void suggestEditorFocusLost(SuggestEditor& editor) {} - }; - - // ================================================================================ // - // MENU // - // ================================================================================ // - - //! @brief Suggestion menu. - class SuggestEditor::Menu : public juce::Component, public juce::ListBoxModel - { - public: // methods - - using action_method_t = std::function; - - //! @brief Constructor. - Menu(SuggestList& list); - - //! @brief Destructor. - ~Menu(); - - //! @brief Set the action to execute when an item has been clicked. - void setItemClickedAction(action_method_t function); - - //! @brief Set the action to execute when an item has been double-clicked. - void setItemDoubleClickedAction(action_method_t function); - - //! @brief Set the action to execute when an item has been selected. - void setSelectedItemAction(action_method_t function); - - //! @brief Select an item of the list. - void selectRow(int idx); - - //! @brief Select the first item of the list. - void selectFirstRow(); - - //! @brief Select the previous item of the list. - void selectPreviousRow(); - - //! @brief Select the next item of the list. - void selectNextRow(); - - //! @brief Update the list. - void update(); - - // juce::Component - void paint(juce::Graphics& g) override; - - // juce::Component - void resized() override; - - private: // methods - - // ================================================================================ // - // SUGGEST LISTBOX MODEL // - // ================================================================================ // - - //! @brief Returns the number of items in the list. - int getNumRows() override; - - //! @brief Draw a row of the list. - void paintListBoxItem(int row_number, juce::Graphics& g, - int width, int height, bool selected) override; - - //! @brief User clicked on a row. - void listBoxItemClicked(int row, juce::MouseEvent const& e) override; - - //! @brief User double-clicked on a row. - void listBoxItemDoubleClicked(int row, juce::MouseEvent const& e) override; - - //! @brief Called when rows are selected or deselected. - void selectedRowsChanged(int last_row_selected) override; - - private: // members - - SuggestList& m_suggest_list; - juce::ListBox m_suggest_list_box; - juce::ResizableCornerComponent m_resizable_corner; - juce::ComponentBoundsConstrainer m_constrainer; - - action_method_t m_clicked_action; - action_method_t m_double_clicked_action; - action_method_t m_selected_action; - }; -} +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +#include +#include + +#include + +namespace kiwi +{ + // ================================================================================ // + // SUGGEST EDITOR // + // ================================================================================ // + + //! @brief A text editor with auto-completion. + //! @details This component shows a dropdown menu list below it. + class SuggestEditor + : public juce::TextEditor, + public juce::TextEditor::Listener, + public juce::Timer + { + public: // methods + + //! @brief Constructor. + //! @param entries Populate suggestion list with these entries. + SuggestEditor(SuggestList::entries_t entries); + + //! @brief Destructor. + ~SuggestEditor(); + + private: // methods + + //! @brief Shows the menu. + void showMenu(); + + //! @brief Returns true if the menu is currently opened. + bool isMenuOpened() const noexcept; + + //! @brief Close the menu. + void closeMenu(); + + //! @brief juce::TextEditor. + bool keyPressed(juce::KeyPress const& key) override; + + //! @brief Called when a key status changed. + bool keyStateChanged(bool isKeyDown) override; + + //! @internal Called every 200ms by a juce::Timer. + //! @details This method will close the menu if its relative position changed + //! or if editor lost the keyboard focus. + void timerCallback() override; + + //! @brief juce::TextEditor::Listener + void textEditorTextChanged(juce::TextEditor& ed) override; + + //! @brief Called when a menu item has been clicked. + void menuItemSelected(juce::String const& text); + + //! @brief Called whenever a selected item is validated. + void menuItemValidated(juce::String const& text); + + //! @brief Called whenever the selected item is unselected. + //! @details Replace suggestion with what was fomerly typed. + void menuItemUnselected(); + + //! @brief Causes the sugesst list to stop updating. + void disableUpdate(); + + //! @brief Causes the suggest list to start updating. + void enableUpdate(); + + private: // classes + + class Menu; + + private: // members + + SuggestList m_suggest_list; + juce::StringArray m_split_text; + std::unique_ptr m_menu = nullptr; + bool m_update_enabled; + }; + + // ================================================================================ // + // MENU // + // ================================================================================ // + + //! @brief Suggestion menu. + class SuggestEditor::Menu : public juce::Component, public juce::ListBoxModel + { + public: // methods + + using action_method_t = std::function; + + //! @brief Constructor. + Menu(SuggestList& list); + + //! @brief Destructor. + ~Menu(); + + //! @brief Set the action to execute when an item has been double-clicked. + void setItemValidatedAction(action_method_t function); + + //! @brief Set the action to execute when an item has been selected. + void setSelectedItemAction(action_method_t function); + + //! @brief Set the action to execute when item are unselected. + void setUnselectedItemAction(std::function function); + + //! @brief Unselect the currently selected row + void unselectRow(); + + //! @brief Select an item of the list. + void selectRow(int idx); + + //! @brief Select the first item of the list. + void selectFirstRow(); + + //! @brief Select the previous item of the list. + void selectPreviousRow(); + + //! @brief Select the next item of the list. + void selectNextRow(); + + //! @brief Called to validate the current selected row. + void validateSelectedRow(); + + //! @brief Update the list. + void update(); + + // juce::Component + void paint(juce::Graphics& g) override; + + // juce::Component + void resized() override; + + //! @brief Returns the curretly selected row + int getSelectedRow() const; + + private: // methods + + // ================================================================================ // + // SUGGEST LISTBOX MODEL // + // ================================================================================ // + + //! @brief Returns the number of items in the list. + int getNumRows() override; + + //! @brief Draw a row of the list. + void paintListBoxItem(int row_number, juce::Graphics& g, + int width, int height, bool selected) override; + + //! @brief User clicked on a row. + void listBoxItemClicked(int row, juce::MouseEvent const& e) override; + + //! @brief User double-clicked on a row. + void listBoxItemDoubleClicked(int row, juce::MouseEvent const& e) override; + + //! @brief Called when rows are selected or deselected. + void selectedRowsChanged(int last_row_selected) override; + + private: // members + + SuggestList& m_suggest_list; + juce::ListBox m_suggest_list_box; + juce::ComponentBoundsConstrainer m_constrainer; + juce::ResizableCornerComponent m_resizable_corner; + + action_method_t m_validated_action; + action_method_t m_selected_action; + std::function m_unselected_action; + }; +} diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_LinkView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_LinkView.cpp index 0f4b394f..98d48f10 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_LinkView.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_LinkView.cpp @@ -66,8 +66,8 @@ namespace kiwi auto& sender_object_m = m_model->getSenderObject(); auto& receiver_object_m = m_model->getReceiverObject(); - ObjectView* jbox_sender = m_patcherview.getObject(sender_object_m); - ObjectView* jbox_receiver = m_patcherview.getObject(receiver_object_m); + ObjectFrame* jbox_sender = m_patcherview.getObject(sender_object_m); + ObjectFrame* jbox_receiver = m_patcherview.getObject(receiver_object_m); if(jbox_sender && jbox_receiver) { @@ -85,14 +85,14 @@ namespace kiwi LinkView::~LinkView() { auto& sender_object_m = m_model->getSenderObject(); - ObjectView* jbox_sender = m_patcherview.getObject(sender_object_m); + ObjectFrame* jbox_sender = m_patcherview.getObject(sender_object_m); if(jbox_sender) { jbox_sender->removeComponentListener(this); } auto& receiver_object_m = m_model->getReceiverObject(); - ObjectView* jbox_receiver = m_patcherview.getObject(receiver_object_m); + ObjectFrame* jbox_receiver = m_patcherview.getObject(receiver_object_m); if(jbox_receiver) { jbox_receiver->removeComponentListener(this); @@ -131,7 +131,7 @@ namespace kiwi void LinkView::componentMovedOrResized(Component& component, bool /*was_moved*/, bool /*was_resized*/) { - ObjectView* jbox = dynamic_cast(&component); + ObjectFrame* jbox = dynamic_cast(&component); if(jbox) { if(&jbox->getModel() == &m_model->getSenderObject()) @@ -218,7 +218,7 @@ namespace kiwi // LINK VIEW CREATOR // // ================================================================================ // - LinkViewCreator::LinkViewCreator(ObjectView& binded_object, + LinkViewCreator::LinkViewCreator(ObjectFrame& binded_object, const size_t index, bool is_sender, juce::Point dragged_pos) : diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_LinkView.h b/Client/Source/KiwiApp_Patcher/KiwiApp_LinkView.h index 27778f8d..8ec6e671 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_LinkView.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_LinkView.h @@ -23,7 +23,7 @@ #include -#include "KiwiApp_ObjectView.h" +#include namespace kiwi { @@ -112,7 +112,7 @@ namespace kiwi public: //! @brief Constructor - LinkViewCreator(ObjectView& binded_object, + LinkViewCreator(ObjectFrame& binded_object, const size_t index, bool is_sender, juce::Point dragged_pos); @@ -121,7 +121,7 @@ namespace kiwi ~LinkViewCreator() = default; //! @brief Get the binded object - ObjectView& getBindedObject() const {return m_binded_object;}; + ObjectFrame& getBindedObject() const {return m_binded_object;}; //! @brief Get the portlet index size_t getBindedIndex() const {return m_index;}; @@ -140,7 +140,7 @@ namespace kiwi private: // members - ObjectView& m_binded_object; + ObjectFrame& m_binded_object; const size_t m_index; const bool m_is_sender; }; diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_ObjectView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_ObjectView.cpp deleted file mode 100644 index bb929fb5..00000000 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_ObjectView.cpp +++ /dev/null @@ -1,559 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#include -#include -#include - -#include "../KiwiApp.h" -#include "../KiwiApp_Network/KiwiApp_DocumentManager.h" -#include "KiwiApp_ObjectView.h" -#include "KiwiApp_PatcherView.h" -#include "../KiwiApp_Ressources/KiwiApp_BinaryData.h" - -namespace kiwi -{ - ObjectView::ObjectView(PatcherView& patcher_view, model::Object& object_m) : - m_patcher_view(patcher_view), - m_model(&object_m), - m_io_color(0.3, 0.3, 0.3), - m_selection_width(4.f), - m_is_selected(m_patcher_view.isSelected(*this)), - m_is_editing(false), - m_is_errorbox((dynamic_cast(m_model) != nullptr)) - { - m_inlets = m_model->getNumberOfInlets(); - m_outlets = m_model->getNumberOfOutlets(); - - lockStatusChanged(m_patcher_view.isLocked()); - updateBounds(false); - } - - ObjectView::~ObjectView() - { - ; - } - - void ObjectView::updateBounds(const bool animate) - { - if(m_model && !m_model->removed()) - { - const juce::Point origin = m_patcher_view.getOriginPosition(); - - const juce::Rectangle bounds(m_model->getX() + origin.getX(), - m_model->getY() + origin.getY(), - m_model->getWidth(), - m_model->getHeight()); - - const auto new_bounds = bounds.expanded(m_selection_width); - - m_local_box_bounds = bounds.withPosition(bounds.getX() - new_bounds.getX(), - bounds.getY() - new_bounds.getY()); - - if(animate) - { - juce::ComponentAnimator& animator = juce::Desktop::getInstance().getAnimator(); - animator.animateComponent(this, new_bounds, 1., 150., false, 0.8, 1.); - } - else - { - setBounds(new_bounds); - } - } - } - - void ObjectView::paint(juce::Graphics & g) - { - const auto bounds = getLocalBounds(); - const auto box_bounds = m_local_box_bounds; - - const juce::Colour selection_color = juce::Colour::fromFloatRGBA(0., 0.5, 1., 0.8); - const juce::Colour other_view_selected_color(0xAA9BFF71); - const juce::Colour distant_selected_color(0xAAFF9B71); - - const juce::Colour errorbox_overlay_color = juce::Colour::fromFloatRGBA(0.6, 0.1, 0.1, 0.4); - - const bool selected = m_is_selected; - const bool other_selected = ! m_distant_selection.empty(); - const bool other_view_selected = (other_selected && - m_distant_selection.find(KiwiApp::userID()) - != m_distant_selection.end()); - - const bool distant_selected = ((other_selected && (other_view_selected && m_distant_selection.size() > 1)) - || (other_selected && !other_view_selected)); - - if(selected || other_view_selected || distant_selected) - { - const juce::Colour color = selected ? selection_color : other_view_selected ? other_view_selected_color : distant_selected_color; - - g.setColour(color.darker(0.4)); - g.drawRect(bounds.reduced(m_selection_width*0.5 + 1), 1); - - g.setColour(color); - g.drawRoundedRectangle(bounds.reduced(m_selection_width*0.5).toFloat(), - m_selection_width*0.5, m_selection_width*0.5); - - g.setColour(color.darker(0.4)); - g.drawRoundedRectangle(bounds.reduced(1).toFloat(), m_selection_width*0.5, 1); - } - - g.setColour(juce::Colours::white); - g.fillRect(box_bounds); - - if(!selected) - { - g.setColour(juce::Colours::black); - g.drawRect(box_bounds); - } - - if(!m_is_editing) - { - g.setColour(juce::Colours::black); - - std::string object_name = m_model->getName(); - if(object_name == "errorbox") - { - std::string const& model_text = m_model->getText(); - std::string draw_text = model_text.substr(model_text.find(" ") + 1); - - g.drawFittedText(draw_text, - box_bounds.reduced(5), - juce::Justification::centredLeft, 1, 1.); - } - else if(object_name != "newbox") - { - g.drawFittedText(m_model->getText(), - box_bounds.reduced(5), - juce::Justification::centredLeft, 1, 1.); - } - } - - if(m_is_errorbox) - { - g.setColour(errorbox_overlay_color); - g.fillRect(box_bounds); - } - - if(!m_is_locked) - { - g.setColour(selected ? m_io_color.brighter(0.6) : m_io_color); - drawInletsOutlets(g); - } - } - - void ObjectView::drawInletsOutlets(juce::Graphics & g) - { - const juce::Rectangle bounds = m_local_box_bounds; - - for(unsigned int i = 0; i < m_inlets; ++i) - { - g.fillRect(getInletLocalBounds(i, bounds)); - } - - for(unsigned int i = 0; i < m_outlets; ++i) - { - g.fillRect(getOutletLocalBounds(i, bounds)); - } - } - - juce::Rectangle ObjectView::getBoxBounds() const - { - return m_local_box_bounds.withPosition(getPosition() + m_local_box_bounds.getPosition()); - } - - bool ObjectView::hitTest(int x, int y) - { - bool allow_click; - bool allow_click_onchild; - getInterceptsMouseClicks(allow_click, allow_click_onchild); - - if (! allow_click) - return false; - - return m_local_box_bounds.contains(x, y); - } - - bool ObjectView::hitTest(juce::Point const& pt, HitTester& hit) const - { - const auto box_bounds = m_local_box_bounds; - - // test body and iolets - if(box_bounds.contains(pt)) - { - if(!m_is_selected) - { - // test inlets - if(m_inlets > 0 && pt.getY() > m_io_height) - { - for(size_t i = 0; i < m_inlets; ++i) - { - if(getInletLocalBounds(i, box_bounds).contains(pt)) - { - hit.m_zone = HitTester::Zone::Inlet; - hit.m_index = i; - return true; - } - } - } - - // test outlets - if(m_outlets > 0 && pt.getY() > box_bounds.getHeight() - m_io_height) - { - for(size_t i = 0; i < m_outlets; ++i) - { - if(getOutletLocalBounds(i, box_bounds).contains(pt)) - { - hit.m_zone = HitTester::Zone::Outlet; - hit.m_index = i; - return true; - } - } - } - } - - // hit the body of the box - hit.m_zone = HitTester::Zone::Inside; - hit.m_index = 0; - return true; - } - else if(m_is_selected) // test borders - { - const auto resizer_bounds = box_bounds.expanded(m_selection_width, m_selection_width); - - if(pt.getY() >= resizer_bounds.getY() && pt.getY() <= box_bounds.getY()) - { - hit.m_zone = HitTester::Zone::Border; - hit.m_border |= HitTester::Border::Top; - } - - if(pt.getX() >= box_bounds.getRight() && pt.getX() <= resizer_bounds.getRight()) - { - hit.m_zone = HitTester::Zone::Border; - hit.m_border |= HitTester::Border::Right; - } - - if(pt.getY() >= box_bounds.getBottom() && pt.getY() <= resizer_bounds.getBottom()) - { - hit.m_zone = HitTester::Zone::Border; - hit.m_border |= HitTester::Border::Bottom; - } - - if(pt.getX() <= box_bounds.getX() && pt.getX() >= resizer_bounds.getX()) - { - hit.m_zone = HitTester::Zone::Border; - hit.m_border |= HitTester::Border::Left; - } - - // remove Border::None flag if we hit a border. - if(hit.m_zone == HitTester::Zone::Border) - { - hit.m_border &= ~HitTester::Border::None; - return true; - } - } - - hit.m_zone = HitTester::Zone::Outside; - hit.m_index = 0; - return false; - } - - bool ObjectView::hitTest(juce::Rectangle const& rect) - { - const juce::Rectangle bounds = getBoxBounds(); - return rect.intersects(bounds) || rect.contains(bounds) || bounds.contains(rect); - } - - bool ObjectView::isSelected() - { - return m_is_selected; - } - - bool ObjectView::isEditing() - { - return m_is_editing; - } - - void ObjectView::objectChanged(model::Patcher::View& view, model::Object& object) - { - bool need_redraw = false; - - if(object.inletsChanged()) - { - m_inlets = object.getNumberOfInlets(); - need_redraw = true; - } - - if(object.outletsChanged()) - { - m_outlets = object.getNumberOfOutlets(); - need_redraw = true; - } - - if(object.boundsChanged()) - { - const auto ctrl = m_model->document().controller(); - const bool animate = (ctrl == flip::Controller::UNDO - || ctrl == flip::Controller::EXTERNAL); - - updateBounds(animate); - - need_redraw = false; - } - - if(view.removed()) - { - m_model = nullptr; - need_redraw = false; - } - - if(need_redraw) - { - repaint(); - } - } - - void ObjectView::localSelectionChanged(bool selected) - { - if(m_is_selected != selected) - { - m_is_selected = selected; - repaint(); - } - } - - void ObjectView::distantSelectionChanged(std::set distant_user_id_selection) - { - m_distant_selection = distant_user_id_selection; - repaint(); - } - - juce::Point ObjectView::getInletPatcherPosition(const size_t index) const - { - return getPosition() + getInletLocalBounds(index, m_local_box_bounds).getCentre(); - } - - juce::Point ObjectView::getOutletPatcherPosition(const size_t index) const - { - return getPosition() + getOutletLocalBounds(index, m_local_box_bounds).getCentre(); - } - - juce::Rectangle ObjectView::getInletLocalBounds(const size_t index, - juce::Rectangle const& object_bounds) const - { - juce::Rectangle rect; - - if(m_inlets > 0 && index < m_inlets) - { - if(m_inlets == 1 && index == 0) - { - rect.setBounds(object_bounds.getX(), object_bounds.getY(), m_io_width, m_io_height); - } - - if(m_inlets > 1) - { - const double ratio = (object_bounds.getWidth() - m_io_width) / (double)(m_inlets - 1); - rect.setBounds(object_bounds.getX() + ratio * index, object_bounds.getY(), - m_io_width, m_io_height); - } - } - - return rect; - } - - juce::Rectangle ObjectView::getOutletLocalBounds(const size_t index, - juce::Rectangle const& object_bounds) const - { - juce::Rectangle rect; - - if(m_outlets > 0 && index < m_outlets) - { - if(m_outlets == 1 && index == 0) - { - rect.setBounds(object_bounds.getX(), - object_bounds.getY() + object_bounds.getHeight() - m_io_height, - m_io_width, m_io_height); - } - - if(m_outlets > 1) - { - const double ratio = (object_bounds.getWidth() - m_io_width) / (double)(m_outlets - 1); - rect.setBounds(object_bounds.getX() + ratio * index, - object_bounds.getY() + object_bounds.getHeight() - m_io_height, - m_io_width, m_io_height); - } - } - - return rect; - } - - void ObjectView::lockStatusChanged(bool locked) - { - m_is_locked = locked; - setInterceptsMouseClicks(locked, locked); - } - - void ObjectView::patcherViewOriginPositionChanged() - { - updateBounds(false); - } - - void ObjectView::mouseDown(juce::MouseEvent const& event) - { - ; - } - - void ObjectView::mouseDrag(juce::MouseEvent const& event) - { - ; - } - - // ================================================================================ // - // CLASSIC BOX // - // ================================================================================ // - - ClassicBox::ClassicBox(PatcherView& patcher_view, model::Object& object_m) : - ObjectView(patcher_view, object_m) - { - setWantsKeyboardFocus(true); - setMouseClickGrabsKeyboardFocus(true); - } - - ClassicBox::~ClassicBox() - { - removeTextEditor(); - } - - void ClassicBox::edit() - { - if(hasKeyboardFocus(true)) return; // abort - - setInterceptsMouseClicks(true, true); - - m_editor.reset(new SuggestEditor(model::Factory::getNames())); - m_editor->setBounds(m_local_box_bounds.expanded(m_selection_width*0.5)); - - std::string text = m_model->getText(); - if(text.compare(0, 8, "errorbox") == 0) - { - text.erase(text.begin(), text.begin()+9); - } - else if(text == "newbox") - { - text.clear(); - } - - m_editor->setColour(juce::TextEditor::highlightColourId, - juce::Colour::fromFloatRGBA(0., 0.5, 1., 0.4)); - - m_editor->setColour(juce::TextEditor::focusedOutlineColourId, - juce::Colour::fromFloatRGBA(0.4, 0.4, 0.4, 0.6)); - - m_editor->setColour(juce::TextEditor::backgroundColourId, - juce::Colours::transparentWhite); - - m_editor->setColour(juce::TextEditor::textColourId, - juce::Colours::black); - - m_editor->setScrollbarsShown(false); - m_editor->setScrollToShowCursor(true); - m_editor->setReturnKeyStartsNewLine(false); - m_editor->setMultiLine(true, false); - - m_editor->setText(text, juce::dontSendNotification); - m_editor->setHighlightedRegion({0, static_cast(text.length())}); - m_editor->setCaretVisible(text.empty()); - - m_editor->addListener(*this); - addAndMakeVisible(*m_editor); - - m_is_editing = true; - m_editor->grabKeyboardFocus(); - } - - void ClassicBox::removeTextEditor() - { - if(m_editor) - { - m_editor->removeListener(*this); - removeChildComponent(m_editor.get()); - m_editor.reset(); - - m_patcher_view.grabKeyboardFocus(); - m_is_editing = false; - } - } - - void ClassicBox::resized() - { - if(m_editor) - { - m_editor->setBounds(m_local_box_bounds.expanded(m_selection_width*0.5)); - } - } - - void ClassicBox::suggestEditorTextChanged(SuggestEditor& e) - { - const juce::String new_text = e.getText(); - const juce::Font font = e.getFont(); - const int text_width = font.getStringWidth(new_text); - const int ed_width = e.getWidth(); - - // boxes only grows up - if(ed_width < text_width + 16) - { - const int new_width = text_width + 24; - m_local_box_bounds.setWidth(new_width-8); - setSize(new_width, getHeight()); - } - } - - void ClassicBox::suggestEditorReturnKeyPressed(SuggestEditor& e) - { - const bool locked = m_is_locked; - setInterceptsMouseClicks(locked, locked); - - std::string new_text = e.getText().toStdString(); - - removeTextEditor(); - - m_patcher_view.endEditBox(*this, new_text); - } - - void ClassicBox::suggestEditorEscapeKeyPressed(SuggestEditor& e) - { - const bool locked = m_is_locked; - setInterceptsMouseClicks(locked, locked); - - removeTextEditor(); - } - - void ClassicBox::suggestEditorFocusLost(SuggestEditor& e) - { - const bool locked = m_is_locked; - setInterceptsMouseClicks(locked, locked); - - std::string new_text = e.getText().toStdString(); - - removeTextEditor(); - - m_patcher_view.endEditBox(*this, new_text); - } -} diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_ObjectView.h b/Client/Source/KiwiApp_Patcher/KiwiApp_ObjectView.h deleted file mode 100644 index f2dd80b5..00000000 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_ObjectView.h +++ /dev/null @@ -1,154 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#pragma once - -#include - -#include - -#include "../KiwiApp_Components/KiwiApp_SuggestEditor.h" - -namespace kiwi -{ - class HitTester; - class PatcherView; - class ClassicBox; - - // ================================================================================ // - // OBJECT VIEW // - // ================================================================================ // - - //! @brief The juce object Component. - class ObjectView : public juce::Component - { - public: - - ObjectView(PatcherView& patcher_view, model::Object& object_m); - ~ObjectView(); - - void objectChanged(model::Patcher::View& view, model::Object& object); - void localSelectionChanged(bool selected_for_view); - void distantSelectionChanged(std::set distant_user_id_selection); - void lockStatusChanged(bool locked); - void patcherViewOriginPositionChanged(); - - // juce::Component - void paint(juce::Graphics& g) override; - void mouseDown(juce::MouseEvent const& event) override; - void mouseDrag(juce::MouseEvent const& event) override; - - //! @brief Returns The box bounds relative to the parent Component - juce::Rectangle getBoxBounds() const; - - //! @brief Returns the inlet position relative to the parent PatcherView component for a given index. - juce::Point getInletPatcherPosition(const size_t index) const; - - //! @brief Returns the outlet position relative to the parent PatcherView component for a given index. - juce::Point getOutletPatcherPosition(const size_t index) const; - - //! Get the Object model - model::Object& getModel() const {return *m_model;}; - - //! @brief overloaded from Component to exclude border size. - bool hitTest(int x, int y) override; - - //! @brief internal kiwi PatcherView HitTesting. - bool hitTest(juce::Point const& pt, HitTester& result) const; - - //! @brief internal kiwi PatcherView HitTesting (overlaps a rectangle). - bool hitTest(juce::Rectangle const& rect); - - //! @brief Returns true if the object is selected. - bool isSelected(); - - //! @brief Returns true if the object is currently being editing. - bool isEditing(); - - private: - - void updateBounds(const bool animate); - void drawInletsOutlets(juce::Graphics & g); - - //! @brief Returns the inlet local bounds for a given index. - juce::Rectangle getInletLocalBounds(const size_t index, - juce::Rectangle const& object_bounds) const; - - //! @brief Returns the outlet local bounds for a given index. - juce::Rectangle getOutletLocalBounds(const size_t index, - juce::Rectangle const& object_bounds) const; - - private: // members - - PatcherView& m_patcher_view; - model::Object* m_model = nullptr; - const unsigned int m_io_width = 6; - const unsigned int m_io_height = 3; - size_t m_inlets = 0; - size_t m_outlets = 0; - const juce::Colour m_io_color; - float m_selection_width = 3.; - juce::Rectangle m_local_box_bounds; - - bool m_is_locked = 0; - - bool m_is_selected = 0; - std::set m_distant_selection; - bool m_is_editing; - bool m_is_errorbox; - - friend ClassicBox; - }; - - // ================================================================================ // - // CLASSIC BOX // - // ================================================================================ // - - //! @brief The ClassicBox let the user change the text of the box - class ClassicBox : public ObjectView, public SuggestEditor::Listener - { - public: - - //! @brief Constructor. - ClassicBox(PatcherView& patcher_view, model::Object& object_m); - - //! @brief Destructor. - ~ClassicBox(); - - //! @brief Let the user edit the text of the box. - void edit(); - - //! @brief Remove the text editor and give focus back to the PatcherView. - void removeTextEditor(); - - //! @brief called when the object is resized. - void resized() override; - - void suggestEditorTextChanged(SuggestEditor& ed) override; - void suggestEditorReturnKeyPressed(SuggestEditor& ed) override; - void suggestEditorEscapeKeyPressed(SuggestEditor& ed) override; - void suggestEditorFocusLost(SuggestEditor& ed) override; - - private: // members - - std::unique_ptr m_editor; - }; -} diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.cpp new file mode 100644 index 00000000..6ba42d09 --- /dev/null +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.cpp @@ -0,0 +1,196 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include + +namespace kiwi +{ + // ================================================================================ // + // CLASSIC VIEW // + // ================================================================================ // + + ClassicView::ClassicView(model::Object& object_model) : + ObjectView(object_model), + m_text(object_model.getText()), + m_editor(nullptr), + m_indent(4), + m_border(1.5), + m_listeners() + { + if(object_model.getName() == "errorbox") + { + m_text.erase(m_text.begin(), m_text.begin() + m_text.find(" ") + 1); + setColour(ObjectView::ColourIds::Background, findColour(ObjectView::ColourIds::Error).withAlpha(0.4f)); + } + else if(object_model.getName() == "newbox") + { + m_text.clear(); + } + } + + ClassicView::~ClassicView() + { + removeTextEditor(); + } + + void ClassicView::addListener(Listener& listener) + { + m_listeners.add(listener); + } + + void ClassicView::removeListener(Listener& listener) + { + m_listeners.remove(listener); + } + + void ClassicView::edit() + { + if(hasKeyboardFocus(true)) return; // abort + + m_editor.reset(new SuggestEditor(model::Factory::getNames())); + + m_editor->setBounds(getLocalBounds()); + m_editor->setIndents(m_indent, m_indent); + m_editor->setBorder(juce::BorderSize(0)); + + m_editor->setColour(juce::TextEditor::ColourIds::textColourId, + findColour(ObjectView::ColourIds::Text)); + + m_editor->setColour(juce::TextEditor::backgroundColourId, + findColour(ObjectView::ColourIds::Background)); + + m_editor->setColour(juce::TextEditor::highlightColourId, + findColour(ObjectView::ColourIds::Highlight).withAlpha(0.4f)); + + m_editor->setColour(juce::TextEditor::highlightColourId, + findColour(ObjectView::ColourIds::Highlight).withAlpha(0.4f)); + + m_editor->setColour(juce::TextEditor::outlineColourId, + juce::Colours::transparentWhite); + + m_editor->setColour(juce::TextEditor::focusedOutlineColourId, + juce::Colours::transparentWhite); + + m_editor->setScrollbarsShown(false); + m_editor->setScrollToShowCursor(true); + m_editor->setReturnKeyStartsNewLine(false); + m_editor->setMultiLine(true, false); + + m_editor->setText(m_text, juce::dontSendNotification); + m_editor->setHighlightedRegion({0, static_cast(m_text.length())}); + m_editor->setCaretVisible(m_text.empty()); + + m_editor->addListener(this); + addAndMakeVisible(*m_editor); + + m_editor->grabKeyboardFocus(); + } + + void ClassicView::removeTextEditor() + { + if(m_editor) + { + m_editor->removeListener(this); + removeChildComponent(m_editor.get()); + m_editor.reset(); + } + } + + void ClassicView::paintOverChildren (juce::Graphics& g) + { + g.setColour (findColour (ObjectView::ColourIds::Outline)); + + int x = getLocalBounds().getX(); + int y = getLocalBounds().getY(); + int height = getHeight(); + int width = getWidth(); + + g.fillRect(x, y, width, m_border.getTop()); + g.fillRect(x, y, m_border.getLeft(), height); + g.fillRect(x, y + height - m_border.getBottom(), width, m_border.getBottom()); + g.fillRect(x + width - m_border.getRight(), y, m_border.getRight(), height); + } + + juce::Rectangle ClassicView::getTextArea() const + { + return getLocalBounds().reduced(m_indent); + } + + void ClassicView::paint(juce::Graphics& g) + { + g.fillAll (findColour (ObjectView::ColourIds::Background)); + + if (!isEditing()) + { + g.setColour (findColour (ObjectView::ColourIds::Text)); + + g.drawText(m_text, getTextArea(), juce::Justification::centredLeft); + } + } + + void ClassicView::resized() + { + if (m_editor) + { + m_editor->setBounds(getLocalBounds()); + } + } + + bool ClassicView::isEditing() const + { + return m_editor != nullptr; + } + + void ClassicView::textEditorTextChanged(juce::TextEditor& editor) + { + const int text_width = editor.getFont().getStringWidth(editor.getText()); + + if(editor.getWidth() < text_width + 16) + { + setSize(text_width + 16, getHeight()); + } + } + + void ClassicView::textEdited(juce::TextEditor& editor) + { + assert(&editor == m_editor.get()); + + removeTextEditor(); + + m_listeners.call(&Listener::textEdited, m_text); + } + + void ClassicView::textEditorReturnKeyPressed(juce::TextEditor& editor) + { + m_text = editor.getText().toStdString(); + + textEdited(editor); + } + + void ClassicView::textEditorFocusLost(juce::TextEditor& editor) + { + m_text = editor.getText().toStdString(); + + textEdited(editor); + } +} diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.h new file mode 100644 index 00000000..588dfb48 --- /dev/null +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.h @@ -0,0 +1,123 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +#include + +#include + +#include + +#include +#include + +namespace kiwi +{ + // ================================================================================ // + // CLASSIC VIEW // + // ================================================================================ // + + //! @brief The view of any textual kiwi object. + class ClassicView : public ObjectView, public juce::TextEditor::Listener + { + public: // classes + + struct Listener + { + //! @brief Destructor. + virtual ~Listener() = default; + + //! @brief Called when the text has been edited and return key was pressed. + virtual void textEdited(std::string const& new_text) = 0; + }; + + public: // methods + + //! @brief Constructor. + ClassicView(model::Object& object_model); + + //! @brief Destructor. + ~ClassicView(); + + //! @brief Add a listener. + void addListener(Listener& listener); + + //! @brief Remove a listener. + void removeListener(Listener& listener); + + //! @brief Lets the user edit the text of the box. + void edit(); + + private: // methods + + //! @brief The component's graphical rendering method. + void paint(juce::Graphics& g) override final; + + //! @brief Called when the object is resized. + void resized() override final; + + //! @brief Called when the text is being typed. + //! @details Used to resize in order to keep text visible. + void textEditorTextChanged(juce::TextEditor& editor) override final; + + //! @brief Called when return key is pressed. + //! @brief Exits edit mode keeping edited text as is. + void textEditorReturnKeyPressed(juce::TextEditor& editor) override final; + + //! @brief Called when the editor has lost focus. + //! @brief Exits edit mode keeping edited text as is. + void textEditorFocusLost(juce::TextEditor& editor) override final; + + //! @brief Returns the text area. + juce::Rectangle getTextArea() const; + + //! @brief Paints elements over the text editor. + void paintOverChildren (juce::Graphics& g) override final; + + //! @brief Called when the classic's view text has been edited. + void textEdited(juce::TextEditor& editor); + + ///! @brief Calls this to end edition and supress the text editor. + void removeTextEditor(); + + //! @brief Returns true if the classic view is currently in edition mode. + bool isEditing() const; + + private: // members + + std::string m_text; + std::unique_ptr m_editor; + size_t m_indent; + juce::BorderSize m_border; + engine::Listeners m_listeners; + + private: // deleted methods + + ClassicView() = delete; + ClassicView(ClassicView const& other) = delete; + ClassicView(ClassicView && other) = delete; + ClassicView& operator=(ClassicView const& other) = delete; + ClassicView& operator=(ClassicView && other) = delete; + }; +} diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.cpp new file mode 100644 index 00000000..8e0bbd4c --- /dev/null +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.cpp @@ -0,0 +1,439 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi +{ + // ================================================================================ // + // OBJECT FRAME // + // ================================================================================ // + + ObjectFrame::ObjectFrame(PatcherView& patcher_view, std::unique_ptr object_view) : + m_object_view(std::move(object_view)), + m_patcher_view(patcher_view), + m_io_width(6), + m_io_height(3), + m_selection_width(4), + m_inlets(getModel().getNumberOfInlets()), + m_outlets(getModel().getNumberOfOutlets()) + { + initColours(); + + addAndMakeVisible(m_object_view.get()); + + updateBounds(false); + + setInterceptsMouseClicks(isLocked(), isLocked()); + } + + ObjectFrame::~ObjectFrame() + { + ; + } + + void ObjectFrame::childBoundsChanged(juce::Component * child) + { + juce::Rectangle object_bounds = getObjectBounds(); + + setBounds(getObjectBounds().expanded(m_selection_width)); + } + + void ObjectFrame::resized() + { + m_object_view->setBounds(getLocalBounds().reduced(m_selection_width)); + } + + void ObjectFrame::updateBounds(bool animate) + { + model::Object const& model = getModel(); + + if(!model.removed()) + { + const juce::Point origin = m_patcher_view.getOriginPosition(); + + const juce::Rectangle object_bounds(model.getX() + origin.getX(), + model.getY() + origin.getY(), + model.getWidth(), + model.getHeight()); + + const juce::Rectangle frame_bounds = object_bounds.expanded(m_selection_width); + + + if (animate) + { + juce::ComponentAnimator& animator = juce::Desktop::getInstance().getAnimator(); + animator.animateComponent(this, frame_bounds, 1., 150., false, 0.8, 1.); + } + else + { + setBounds(frame_bounds); + } + } + } + + void ObjectFrame::paint(juce::Graphics & g) + { + const auto bounds = getLocalBounds(); + + std::set const& distant_selection = getDistantSelection(); + + const bool selected = isSelected(); + const bool other_selected = ! distant_selection.empty(); + const bool other_view_selected = (other_selected && + distant_selection.find(KiwiApp::userID()) + != distant_selection.end()); + + const bool distant_selected = ((other_selected && (other_view_selected && distant_selection.size() > 1)) + || (other_selected && !other_view_selected)); + + if(selected || other_view_selected || distant_selected) + { + juce::Colour selection_color; + + if (selected) + { + selection_color = findColour(ObjectFrame::ColourIds::Selection); + } + else if(other_view_selected) + { + selection_color = findColour(ObjectFrame::ColourIds::SelectionOtherView); + } + else + { + selection_color = findColour(ObjectFrame::ColourIds::SelectionDistant); + } + + g.setColour(selection_color.darker(0.4)); + g.drawRect(bounds.reduced(m_selection_width*0.5 + 1), 1); + + g.setColour(selection_color); + g.drawRoundedRectangle(bounds.reduced(m_selection_width*0.5).toFloat(), + m_selection_width*0.5, m_selection_width*0.5); + + g.setColour(selection_color.darker(0.4)); + g.drawRoundedRectangle(bounds.reduced(1).toFloat(), m_selection_width*0.5, 1); + } + } + + void ObjectFrame::paintOverChildren (juce::Graphics& g) + { + if(!isLocked()) + { + g.setColour(findColour(ObjectFrame::ColourIds::Pin)); + drawInletsOutlets(g); + } + } + + void ObjectFrame::drawInletsOutlets(juce::Graphics & g) + { + const juce::Rectangle bounds = m_object_view->getBounds(); + + for(unsigned int i = 0; i < m_inlets; ++i) + { + g.fillRect(getInletLocalBounds(i)); + } + + for(unsigned int i = 0; i < m_outlets; ++i) + { + g.fillRect(getOutletLocalBounds(i)); + } + } + + juce::Rectangle ObjectFrame::getObjectBounds() const + { + return m_object_view->getBounds().withPosition(getPosition() + m_object_view->getBounds().getPosition()); + } + + bool ObjectFrame::hitTest(int x, int y) + { + bool allow_click; + bool allow_click_onchild; + getInterceptsMouseClicks(allow_click, allow_click_onchild); + + if (! allow_click) + return false; + + return m_object_view->getBounds().contains(x, y); + } + + bool ObjectFrame::hitTest(juce::Point const& pt, HitTester& hit) const + { + const auto box_bounds = m_object_view->getBounds(); + + // test body and iolets + if(box_bounds.contains(pt)) + { + if(!isSelected()) + { + // test inlets + if(m_inlets > 0 && pt.getY() > m_io_height) + { + for(size_t i = 0; i < m_inlets; ++i) + { + if(getInletLocalBounds(i).contains(pt)) + { + hit.m_zone = HitTester::Zone::Inlet; + hit.m_index = i; + return true; + } + } + } + + // test outlets + if(m_outlets > 0 && pt.getY() > box_bounds.getHeight() - m_io_height) + { + for(size_t i = 0; i < m_outlets; ++i) + { + if(getOutletLocalBounds(i).contains(pt)) + { + hit.m_zone = HitTester::Zone::Outlet; + hit.m_index = i; + return true; + } + } + } + } + + // hit the body of the box + hit.m_zone = HitTester::Zone::Inside; + hit.m_index = 0; + return true; + } + else if(isSelected()) // test borders + { + const auto resizer_bounds = box_bounds.expanded(m_selection_width, m_selection_width); + + if(pt.getY() >= resizer_bounds.getY() && pt.getY() <= box_bounds.getY()) + { + hit.m_zone = HitTester::Zone::Border; + hit.m_border |= HitTester::Border::Top; + } + + if(pt.getX() >= box_bounds.getRight() && pt.getX() <= resizer_bounds.getRight()) + { + hit.m_zone = HitTester::Zone::Border; + hit.m_border |= HitTester::Border::Right; + } + + if(pt.getY() >= box_bounds.getBottom() && pt.getY() <= resizer_bounds.getBottom()) + { + hit.m_zone = HitTester::Zone::Border; + hit.m_border |= HitTester::Border::Bottom; + } + + if(pt.getX() <= box_bounds.getX() && pt.getX() >= resizer_bounds.getX()) + { + hit.m_zone = HitTester::Zone::Border; + hit.m_border |= HitTester::Border::Left; + } + + // remove Border::None flag if we hit a border. + if(hit.m_zone == HitTester::Zone::Border) + { + hit.m_border &= ~HitTester::Border::None; + return true; + } + } + + hit.m_zone = HitTester::Zone::Outside; + hit.m_index = 0; + return false; + } + + bool ObjectFrame::hitTest(juce::Rectangle const& rect) const + { + const juce::Rectangle bounds = getObjectBounds(); + return rect.intersects(bounds) || rect.contains(bounds) || bounds.contains(rect); + } + + void ObjectFrame::initColours() + { + setColour(ObjectFrame::ColourIds::Selection, juce::Colour::fromFloatRGBA(0., 0.5, 1., 0.8)); + setColour(ObjectFrame::ColourIds::SelectionOtherView, juce::Colour(0xAA9BFF71)); + setColour(ObjectFrame::ColourIds::SelectionDistant, juce::Colour(0xAA9BFF71)); + setColour(ObjectFrame::ColourIds::Pin, juce::Colour(0.3, 0.3, 0.3)); + } + + bool ObjectFrame::isSelected() const + { + return getPatcherView().isSelected(*this); + } + + std::set ObjectFrame::getDistantSelection() const + { + return getPatcherView().getDistantSelection(*this); + } + + bool ObjectFrame::isLocked() const + { + return getPatcherView().isLocked(); + } + + void ObjectFrame::objectChanged(model::Patcher::View& view, model::Object& object) + { + if(object.inletsChanged()) + { + m_inlets = object.getNumberOfInlets(); + repaint(); + } + + if(object.outletsChanged()) + { + m_outlets = object.getNumberOfOutlets(); + repaint(); + } + + if(object.boundsChanged()) + { + const auto ctrl = object.document().controller(); + const bool animate = (ctrl == flip::Controller::UNDO + || ctrl == flip::Controller::EXTERNAL); + + updateBounds(animate); + + repaint(); + } + } + + void ObjectFrame::textEdited(std::string const& new_text) + { + dynamic_cast(m_object_view.get())->removeListener(*this); + + setInterceptsMouseClicks(isLocked(), isLocked()); + + getPatcherView().objectEdited(*this, new_text); + } + + void ObjectFrame::editObject() + { + ClassicView * object_view = dynamic_cast(m_object_view.get()); + + if (object_view != nullptr) + { + object_view->addListener(*this); + object_view->edit(); + } + } + + void ObjectFrame::localSelectionChanged() + { + repaint(); + } + + void ObjectFrame::distantSelectionChanged() + { + repaint(); + } + + void ObjectFrame::lockStatusChanged() + { + repaint(); + setInterceptsMouseClicks(isLocked(), isLocked()); + } + + void ObjectFrame::patcherViewOriginPositionChanged() + { + updateBounds(false); + } + + juce::Point ObjectFrame::getInletPatcherPosition(const size_t index) const + { + return getPosition() + getInletLocalBounds(index).getCentre(); + } + + juce::Point ObjectFrame::getOutletPatcherPosition(const size_t index) const + { + return getPosition() + getOutletLocalBounds(index).getCentre(); + } + + model::Object& ObjectFrame::getModel() const + { + return m_object_view->getModel(); + } + + size_t ObjectFrame::getPinWidth() const + { + return m_io_width; + } + + size_t ObjectFrame::getPinHeight() const + { + return m_io_height; + } + + juce::Rectangle ObjectFrame::getInletLocalBounds(const size_t index) const + { + juce::Rectangle object_bounds = m_object_view->getBounds(); + + juce::Rectangle rect; + + if(m_inlets > 0 && index < m_inlets) + { + if(m_inlets == 1 && index == 0) + { + rect.setBounds(object_bounds.getX(), object_bounds.getY(), getPinWidth(), getPinHeight()); + } + + if(m_inlets > 1) + { + const double ratio = (object_bounds.getWidth() - getPinWidth()) / (double)(m_inlets - 1); + rect.setBounds(object_bounds.getX() + ratio * index, object_bounds.getY(), + getPinWidth(), getPinHeight()); + } + } + + return rect; + } + + juce::Rectangle ObjectFrame::getOutletLocalBounds(const size_t index) const + { + juce::Rectangle object_bounds = m_object_view->getBounds(); + + juce::Rectangle rect; + + if(m_outlets > 0 && index < m_outlets) + { + if(m_outlets == 1 && index == 0) + { + rect.setBounds(object_bounds.getX(), + object_bounds.getY() + object_bounds.getHeight() - getPinHeight(), + getPinWidth(), getPinHeight()); + } + + if(m_outlets > 1) + { + const double ratio = (object_bounds.getWidth() - getPinWidth()) / (double)(m_outlets - 1); + rect.setBounds(object_bounds.getX() + ratio * index, + object_bounds.getY() + object_bounds.getHeight() - getPinHeight(), + getPinWidth(), getPinHeight()); + } + } + + return rect; + } + + PatcherView& ObjectFrame::getPatcherView() const + { + return m_patcher_view; + } +} diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.h new file mode 100644 index 00000000..d02eba54 --- /dev/null +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.h @@ -0,0 +1,174 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include +#include + +#include + +#include + +#include +#include + +namespace kiwi +{ + // ================================================================================ // + // OBJECT FRAME // + // ================================================================================ // + + //! @brief A juce component holding the object's graphical representation. + //! @details ObjectFrame is implemented as a wrapper around an object view that displays + //! selections and outlet and handle certain interactions. + class ObjectFrame : public juce::Component, + public ClassicView::Listener + { + public: // classes + + enum ColourIds + { + Selection = 0x1100000, + SelectionOtherView = 0x1100001, + SelectionDistant = 0x1100002, + Pin = 0x1100003 + }; + + public: // methods + + //! @brief Constructor. + ObjectFrame(PatcherView& patcher_view, std::unique_ptr object_view); + + //! @brief Destructor. + ~ObjectFrame(); + + //! @brief Called whenever an object's model has changed. + void objectChanged(model::Patcher::View& view, model::Object& object); + + //! @brief Called whenever the client wants to edit an object. + //! @details Will only edit the object if its a textual object. + void editObject(); + + //! @brief Called by the patcher every time the selection status of this object has changed. + void localSelectionChanged(); + + //! @brief Called by the patcher every time the distant selection status of this object has changed. + void distantSelectionChanged(); + + //! @brief Called every time a patcher is locked or unlocked. + void lockStatusChanged(); + + //! @brief Called when the patcher's origin changes. + void patcherViewOriginPositionChanged(); + + //! @brief Returns The object's bounds relative to the patcher position. + juce::Rectangle getObjectBounds() const; + + //! @brief Returns the inlet position relative to the parent PatcherView component for a given index. + juce::Point getInletPatcherPosition(const size_t index) const; + + //! @brief Returns the outlet position relative to the parent PatcherView component for a given index. + juce::Point getOutletPatcherPosition(const size_t index) const; + + //! @brief Returns the object's model. + model::Object& getModel() const; + + //! @brief Overloaded from juce::Component to exclude border size. + bool hitTest(int x, int y) override; + + //! @brief Internal kiwi PatcherView HitTesting. + bool hitTest(juce::Point const& pt, HitTester& result) const; + + //! @brief Internal kiwi PatcherView HitTesting (overlaps a rectangle). + bool hitTest(juce::Rectangle const& rect) const; + + //! @brief Returns true if the object is selected. + bool isSelected() const; + + private: // methods + + //! @brief Component's graphical rendering method. + void paint(juce::Graphics& g) override final; + + //! @brief Paints outlets, inlets over child component. + void paintOverChildren (juce::Graphics& g) override final; + + //! @brief Called whenever the object's size changes. + void resized() override final; + + //! @brief Called once a ClassicView's text has changed. + void textEdited(std::string const& new_text) override final; + + //! @brief Initializes all colours with default values. + //! @todo Set colours in look and feel instead. + void initColours(); + + //! @brief Called to update the bounds of the object. + void updateBounds(bool animate); + + //! @brief Called when the object's view size has changed. + //! @details The obect frame adapts to fit the underlying object's size. + void childBoundsChanged(juce::Component * child) override final; + + //! @brief Returns the patcher view component. + PatcherView& getPatcherView() const; + + //! @brief Returns a list of Users that selected an object. + std::set getDistantSelection() const; + + //! @brief Draws the inlets/outlets of the object. + void drawInletsOutlets(juce::Graphics & g); + + //! @brief Returns the inlet local bounds for a given index. + juce::Rectangle getInletLocalBounds(const size_t index) const; + + //! @brief Returns the outlet local bounds for a given index. + juce::Rectangle getOutletLocalBounds(const size_t index) const; + + //! @brief Returns the width of any outlet/inlet represented in the object's frame. + size_t getPinWidth() const; + + //! @brief Returns the height of any outlet/inlet represented in the object's frame. + size_t getPinHeight() const; + + //! @brief Returns true if the object is locked. + bool isLocked() const; + + private: // members + + std::unique_ptr m_object_view; + PatcherView& m_patcher_view; + const size_t m_io_width; + const size_t m_io_height; + size_t m_selection_width; + size_t m_inlets; + size_t m_outlets; + + private: // deleted methods + + ObjectFrame() = delete; + ObjectFrame(ObjectFrame const& other) = delete; + ObjectFrame(ObjectFrame && other) = delete; + ObjectFrame& operator=(ObjectFrame const& other) = delete; + ObjectFrame& operator=(ObjectFrame && other) = delete; + }; +} diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectView.cpp new file mode 100644 index 00000000..4a2b5dc8 --- /dev/null +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectView.cpp @@ -0,0 +1,51 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include +#include + +namespace kiwi +{ + // ================================================================================ // + // OBJECT VIEW // + // ================================================================================ // + + ObjectView::ObjectView(model::Object & object_model): + m_model(object_model) + { + setColour(ObjectView::ColourIds::Error, juce::Colour::fromFloatRGBA(0.6, 0.1, 0.1, 0.)); + setColour(ObjectView::ColourIds::Background, juce::Colours::white); + setColour(ObjectView::ColourIds::Text, juce::Colours::black); + setColour(ObjectView::ColourIds::Outline, juce::Colours::black); + setColour(ObjectView::ColourIds::Highlight, juce::Colour::fromFloatRGBA(0., 0.5, 1., 0.)); + } + + ObjectView::~ObjectView() + { + } + + model::Object& ObjectView::getModel() const + { + return m_model; + } +} diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectView.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectView.h new file mode 100644 index 00000000..d75f49b7 --- /dev/null +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectView.h @@ -0,0 +1,73 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +#include + +namespace kiwi +{ + class ObjectFrame; + + // ================================================================================ // + // OBJECT VIEW // + // ================================================================================ // + + //! @brief Abstract for objects graphical representation. + class ObjectView : public juce::Component + { + public: // classes + + enum ColourIds + { + Background = 0x1100004, + Error = 0x1100005, + Text = 0x1100006, + Outline = 0x1100007, + Highlight = 0x1100008 + }; + + public: // methods + + //! @brief Constructor. + ObjectView(model::Object& object_model); + + //! @brief Destructor. + virtual ~ObjectView(); + + //! @brief Returns the model represented by the graphical object. + model::Object& getModel() const; + + private: // members + + model::Object& m_model; + + private: // deleted methods + + ObjectView() = delete; + ObjectView(ObjectView const& other) = delete; + ObjectView(ObjectView && other) = delete; + ObjectView& operator=(ObjectView const& other) = delete; + ObjectView& operator=(ObjectView && other) = delete; + }; +} diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Objects.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Objects.h new file mode 100644 index 00000000..16964744 --- /dev/null +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Objects.h @@ -0,0 +1,28 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +// ================================================================================ // +// BASIC OBJECTS // +// ================================================================================ // + +#include diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp index 90e4ee34..d55c3558 100755 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp @@ -25,10 +25,12 @@ #include "KiwiApp_PatcherView.h" +#include +#include + #include "../KiwiApp.h" #include "../KiwiApp_General/KiwiApp_CommandIDs.h" #include "../KiwiApp_Network/KiwiApp_DocumentManager.h" -#include "KiwiApp_ObjectView.h" #include "KiwiApp_LinkView.h" #include "KiwiApp_PatcherComponent.h" @@ -163,37 +165,38 @@ namespace kiwi if(hit.objectTouched()) { - ObjectView* object_view = hit.getObject(); - if(object_view) + ObjectFrame* object_frame = hit.getObject(); + + if(object_frame) { if(hit.getZone() == HitTester::Zone::Inside) { if(e.mods.isAltDown()) { m_copy_on_drag = true; - m_select_on_mouse_down_status = selectOnMouseDown(*object_view, true); + m_select_on_mouse_down_status = selectOnMouseDown(*object_frame, true); } else if (e.mods.isCommandDown()) { - object_view->mouseDown(e.getEventRelativeTo(object_view)); + object_frame->mouseDown(e.getEventRelativeTo(object_frame)); m_object_received_down_event = true; } else { if(e.mods.isPopupMenu()) { - if (!isSelected(*object_view)) + if (!isSelected(*object_frame)) { - m_select_on_mouse_down_status = selectOnMouseDown(*object_view, true); + m_select_on_mouse_down_status = selectOnMouseDown(*object_frame, true); } const auto pos = e.getPosition() - m_viewport.getOriginPosition(); - showObjectPopupMenu(*object_view, pos); + showObjectPopupMenu(*object_frame, pos); } else { - m_select_on_mouse_down_status = selectOnMouseDown(*object_view, !e.mods.isShiftDown()); + m_select_on_mouse_down_status = selectOnMouseDown(*object_frame, !e.mods.isShiftDown()); } } } @@ -202,7 +205,7 @@ namespace kiwi const size_t index = hit.getIndex(); const bool is_sender = hit.getZone() == HitTester::Zone::Outlet; - m_link_creator.reset(new LinkViewCreator(*object_view, index, is_sender, e.getPosition())); + m_link_creator.reset(new LinkViewCreator(*object_frame, index, is_sender, e.getPosition())); addAndMakeVisible(*m_link_creator); } } @@ -273,7 +276,7 @@ namespace kiwi { const bool sender = m_link_creator->isBindedToSender(); - ObjectView* object_view = end_pair.first; + ObjectFrame* object_view = end_pair.first; if(object_view != nullptr) { if(sender) @@ -296,7 +299,7 @@ namespace kiwi if(hit.objectTouched()) { - ObjectView* object_view = hit.getObject(); + ObjectFrame* object_view = hit.getObject(); if(object_view) { if(m_object_received_down_event && hit.getZone() == HitTester::Zone::Inside) @@ -417,7 +420,8 @@ namespace kiwi if(hit.objectTouched() && hit.getZone() == HitTester::Zone::Inside) { - ObjectView* object_view = hit.getObject(); + ObjectFrame* object_view = hit.getObject(); + if(object_view) { if(e.mods.isCommandDown()) @@ -427,7 +431,7 @@ namespace kiwi } else if(m_select_on_mouse_down_status && !m_is_in_move_or_resize_gesture) { - startEditBox(dynamic_cast(object_view)); + editObject(*object_view); } } } @@ -436,7 +440,7 @@ namespace kiwi if(hit.objectTouched()) { - ObjectView* object_view = hit.getObject(); + ObjectFrame* object_view = hit.getObject(); if(object_view) { selectOnMouseUp(*object_view, !e.mods.isShiftDown(), m_is_dragging, @@ -524,7 +528,7 @@ namespace kiwi if(e.mods.isCommandDown() && hit.objectTouched()) { - ObjectView* object_view = hit.getObject(); + ObjectFrame* object_view = hit.getObject(); if(object_view) { object_view->mouseDoubleClick(e.getEventRelativeTo(object_view)); @@ -593,7 +597,7 @@ namespace kiwi m.show(); } - void PatcherView::showObjectPopupMenu(ObjectView const& object, juce::Point const& position) + void PatcherView::showObjectPopupMenu(ObjectFrame const& object, juce::Point const& position) { if(!isLocked()) { @@ -653,7 +657,7 @@ namespace kiwi if(hit.objectTouched()) { - ObjectView* object_view = hit.getObject(); + ObjectFrame* object_view = hit.getObject(); if(object_view) { m_viewport.jumpViewToObject(*object_view); @@ -950,17 +954,29 @@ namespace kiwi } } - bool PatcherView::isSelected(ObjectView const& object) const + bool PatcherView::isSelected(ObjectFrame const& object) const { return m_view_model.isSelected(object.getModel()); } + std::set PatcherView::getDistantSelection(ObjectFrame const& object) const + { + std::set distant_selection; + + if (m_distant_objects_selection.find(object.getModel().ref()) != m_distant_objects_selection.end()) + { + distant_selection = m_distant_objects_selection.at(object.getModel().ref()); + } + + return distant_selection; + } + bool PatcherView::isSelected(LinkView const& link) const { return m_view_model.isSelected(link.getModel()); } - void PatcherView::addToSelectionBasedOnModifiers(ObjectView& object, bool select_only) + void PatcherView::addToSelectionBasedOnModifiers(ObjectFrame& object, bool select_only) { if(select_only) { @@ -992,7 +1008,7 @@ namespace kiwi } } - bool PatcherView::selectOnMouseDown(ObjectView& object, bool select_only) + bool PatcherView::selectOnMouseDown(ObjectFrame& object, bool select_only) { if(isSelected(object)) { @@ -1014,7 +1030,7 @@ namespace kiwi return false; } - void PatcherView::selectOnMouseUp(ObjectView& object, bool select_only, + void PatcherView::selectOnMouseUp(ObjectFrame& object, bool select_only, const bool box_was_dragged, const bool result_of_mouse_down_select_method) { if(result_of_mouse_down_select_method && ! box_was_dragged) @@ -1071,10 +1087,8 @@ namespace kiwi const auto it = findObject(*object_m); if(it != m_objects.cend()) { - if(startEditBox(dynamic_cast(it->get()))) - { - return true; - } + editObject(**it); + return true; } } } @@ -1168,24 +1182,24 @@ namespace kiwi return false; } - std::pair PatcherView::getLinkCreatorNearestEndingIolet() + std::pair PatcherView::getLinkCreatorNearestEndingIolet() { - ObjectView* result_object = nullptr; + ObjectFrame* result_object = nullptr; size_t result_index = 0; if(m_link_creator) { - const ObjectView& binded_object = m_link_creator->getBindedObject(); + const ObjectFrame& binded_object = m_link_creator->getBindedObject(); const juce::Point end_pos = m_link_creator->getEndPosition(); const int max_distance = 50; int min_distance = max_distance; - for(auto& object_view_uptr : m_objects) + for(auto& object_frame_uptr : m_objects) { - if(object_view_uptr.get() != &binded_object) + if(object_frame_uptr.get() != &binded_object) { - model::Object const& object_m = object_view_uptr->getModel(); + model::Object const& object_m = object_frame_uptr->getModel(); const bool sender = m_link_creator->isBindedToSender(); @@ -1193,7 +1207,7 @@ namespace kiwi for(size_t i = 0; i < io_size; ++i) { - const juce::Point io_pos = sender ? object_view_uptr->getInletPatcherPosition(i) : object_view_uptr->getOutletPatcherPosition(i); + const juce::Point io_pos = sender ? object_frame_uptr->getInletPatcherPosition(i) : object_frame_uptr->getOutletPatcherPosition(i); const int distance = end_pos.getDistanceFrom(io_pos); @@ -1212,7 +1226,7 @@ namespace kiwi if(canConnect(from, outlet, to, inlet)) { min_distance = distance; - result_object = object_view_uptr.get(); + result_object = object_frame_uptr.get(); result_index = i; } } @@ -1528,7 +1542,7 @@ namespace kiwi for(auto& object : m_objects) { - object->lockStatusChanged(m_is_locked); + object->lockStatusChanged(); } if(m_is_locked) @@ -1631,7 +1645,7 @@ namespace kiwi if(old_local_selected_state != new_local_selected_state) { - local_object_uptr->localSelectionChanged(new_local_selected_state); + local_object_uptr->localSelectionChanged(); selectionChanged(); } @@ -1649,7 +1663,7 @@ namespace kiwi // notify object if(distant_selection_changed_for_object) { - local_object_uptr->distantSelectionChanged(distant_it.second); + local_object_uptr->distantSelectionChanged(); selectionChanged(); } } @@ -1783,13 +1797,14 @@ namespace kiwi if(it == m_objects.cend()) { const auto it = (zorder > 0) ? m_objects.begin() + zorder : m_objects.end(); - auto new_object_it = m_objects.emplace(it, new ClassicBox(*this, object)); - ObjectView& jobj = *new_object_it->get(); + std::unique_ptr object_view = std::make_unique(object); + + ObjectFrame& object_frame = **(m_objects.emplace(it, new ObjectFrame(*this, std::move(object_view)))); //jobj.setAlpha(0.); //addChildComponent(jobj); - addAndMakeVisible(jobj, zorder); + addAndMakeVisible(object_frame, zorder); //juce::ComponentAnimator& animator = juce::Desktop::getInstance().getAnimator(); //animator.animateComponent(&jobj, jobj.getBounds(), 1., 200., true, 0.8, 1.); @@ -1802,7 +1817,7 @@ namespace kiwi if(it != m_objects.cend()) { - ObjectView& object_view = *it->get(); + ObjectFrame& object_view = *it->get(); object_view.objectChanged(view, object); } } @@ -1813,7 +1828,7 @@ namespace kiwi if(it != m_objects.cend()) { - ObjectView* object_view = it->get(); + ObjectFrame* object_view = it->get(); if(m_hittester.getObject() == object_view) { @@ -1821,16 +1836,6 @@ namespace kiwi m_hittester.reset(); } - if(object_view->isEditing() && m_box_being_edited == object_view) - { - if(auto classic_box = dynamic_cast(object_view)) - { - classic_box->removeTextEditor(); - } - - m_box_being_edited = nullptr; - } - juce::ComponentAnimator& animator = juce::Desktop::getInstance().getAnimator(); animator.animateComponent(object_view, object_view->getBounds(), 0., 200., true, 0.8, 1.); @@ -1874,9 +1879,9 @@ namespace kiwi } } - PatcherView::ObjectViews::iterator PatcherView::findObject(model::Object const& object) + PatcherView::ObjectFrames::iterator PatcherView::findObject(model::Object const& object) { - const auto find_jobj = [&object](std::unique_ptr const& jobj) + const auto find_jobj = [&object](std::unique_ptr const& jobj) { return (&object == &jobj->getModel()); }; @@ -1899,7 +1904,7 @@ namespace kiwi return m_view_model; } - PatcherView::ObjectViews const& PatcherView::getObjects() const + PatcherView::ObjectFrames const& PatcherView::getObjects() const { return m_objects; } @@ -1909,7 +1914,7 @@ namespace kiwi return m_links; } - ObjectView* PatcherView::getObject(model::Object const& object) + ObjectFrame* PatcherView::getObject(model::Object const& object) { const auto it = findObject(object); return (it != m_objects.cend()) ? it->get() : nullptr; @@ -1945,36 +1950,29 @@ namespace kiwi } return m_patcher_model.addObject("errorbox", std::vector(atoms.begin(), atoms.end())); } - - bool PatcherView::startEditBox(ClassicBox* box) + + void PatcherView::editObject(ObjectFrame & object_frame) { assert(m_box_being_edited == nullptr); - if(box) - { - box->edit(); - m_box_being_edited = box; - KiwiApp::commandStatusChanged(); // to disable some command while editing... - return true; - } - - return false; + object_frame.editObject(); + m_box_being_edited = &object_frame; + KiwiApp::commandStatusChanged(); // to disable some command while editing... } - void PatcherView::endEditBox(ClassicBox& box, std::string new_object_text) + void PatcherView::objectEdited(ObjectFrame const& object_frame, std::string const& new_text) { + grabKeyboardFocus(); + + std::string new_object_text = new_text.empty() ? "newbox" : new_text; + assert(m_box_being_edited != nullptr); - assert(m_box_being_edited == &box); + assert(m_box_being_edited == &object_frame); m_box_being_edited = nullptr; - model::Object& old_object_m = box.getModel(); + model::Object& old_object_m = object_frame.getModel(); const std::string old_object_text = old_object_m.getText(); - if(new_object_text.empty()) - { - new_object_text = "newbox"; - } - if(old_object_text != new_object_text) { model::Object& new_object_m = createObjectModel(new_object_text); @@ -1994,7 +1992,7 @@ namespace kiwi const int text_width = juce::Font().getStringWidth(new_object_text); const juce::Point origin = getOriginPosition(); - juce::Rectangle box_bounds = box.getBoxBounds(); + juce::Rectangle box_bounds = object_frame.getObjectBounds(); new_object_m.setPosition(box_bounds.getX() - origin.x, box_bounds.getY() - origin.y); new_object_m.setWidth(text_width + 12); @@ -2096,7 +2094,7 @@ namespace kiwi m_view_model.selectObject(new_object); DocumentManager::commit(m_patcher_model, "Insert New Empty Box"); - + if(give_focus && m_local_objects_selection.size() == 1) { model::Object* object_m = doc.get(*m_local_objects_selection.begin()); @@ -2105,7 +2103,7 @@ namespace kiwi const auto it = findObject(*object_m); if(it != m_objects.cend()) { - startEditBox(dynamic_cast(it->get())); + editObject(**it); } } } @@ -2177,17 +2175,17 @@ namespace kiwi return !m_local_links_selection.empty(); } - void PatcherView::selectObject(ObjectView& object) + void PatcherView::selectObject(ObjectFrame& object) { m_view_model.selectObject(object.getModel()); DocumentManager::commit(m_patcher_model); } - void PatcherView::selectObjects(std::vector const& objects) + void PatcherView::selectObjects(std::vector const& objects) { bool should_commit = false; - for(ObjectView* object : objects) + for(ObjectFrame* object : objects) { if(object != nullptr) { @@ -2227,7 +2225,7 @@ namespace kiwi } } - void PatcherView::unselectObject(ObjectView& object) + void PatcherView::unselectObject(ObjectFrame& object) { m_view_model.unselectObject(object.getModel()); DocumentManager::commit(m_patcher_model); @@ -2239,7 +2237,7 @@ namespace kiwi DocumentManager::commit(m_patcher_model); } - void PatcherView::selectObjectOnly(ObjectView& object) + void PatcherView::selectObjectOnly(ObjectFrame& object) { unselectAll(); selectObject(object); diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.h b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.h index 281c68f7..f375c420 100755 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.h @@ -34,8 +34,7 @@ namespace kiwi { class PatcherManager; - class ObjectView; - class ClassicBox; + class ObjectFrame; class LinkView; class LinkViewCreator; class Instance; @@ -61,7 +60,7 @@ namespace kiwi //! @brief Destructor ~PatcherView(); - using ObjectViews = std::vector>; + using ObjectFrames = std::vector>; using LinkViews = std::vector>; //! @brief Returns the PatcherManager. @@ -73,14 +72,14 @@ namespace kiwi //! @brief Returns the patcher view model. model::Patcher::View& getPatcherViewModel(); - //! @brief Returns the ObjectViews. - ObjectViews const& getObjects() const; + //! @brief Returns the Objects' frames. + ObjectFrames const& getObjects() const; //! @brief Returns the LinkViews. LinkViews const& getLinks() const; - //! @brief Returns the ObjectView corresponding to a given Object model. - ObjectView* getObject(model::Object const& object); + //! @brief Returns the Object's frame corresponding to a given Object model. + ObjectFrame* getObject(model::Object const& object); //! @brief Returns the LinkView corresponding to a given Link model. LinkView* getLink(model::Link const& link); @@ -91,8 +90,11 @@ namespace kiwi //! @brief Get the lock status of the patcher view. bool isLocked() const; + //! @brief Returns a list of Users that selected an object. + std::set getDistantSelection(ObjectFrame const& object) const; + //! @brief Returns true if the object is selected. - bool isSelected(ObjectView const& object) const; + bool isSelected(ObjectFrame const& object) const; //! @brief Returns true if the link is selected. bool isSelected(LinkView const& link) const; @@ -108,12 +110,11 @@ namespace kiwi model::Object& createObjectModel(std::string const& text); //! @brief Call this to switch the box to edit mode - //! @details You will need to call endEditBox() function after calling this. - bool startEditBox(ClassicBox* box); + //! @details Will result in objectEdited being called in case of success. + void editObject(ObjectFrame & object_frame); - //! @brief called by ClassicBox when hmmm.. the text has been edited. - //! @details You will need to call startEditBox() function before calling this. - void endEditBox(ClassicBox& box, std::string new_text); + //! @brief Called once an object has been edited. + void objectEdited(ObjectFrame const& object_frame, std::string const& new_text); //! @internal Update the patcher window title. void updateWindowTitle() const; @@ -223,15 +224,15 @@ namespace kiwi //! @brief Returns the selected links. std::set const& getSelectedLinks() const; - void addToSelectionBasedOnModifiers(ObjectView& object, bool select_only); + void addToSelectionBasedOnModifiers(ObjectFrame& object, bool select_only); void addToSelectionBasedOnModifiers(LinkView& link, bool select_only); - bool selectOnMouseDown(ObjectView& object, bool select_only); + bool selectOnMouseDown(ObjectFrame& object, bool select_only); bool selectOnMouseDown(LinkView& link, bool select_only); - void selectOnMouseUp(ObjectView& box, bool select_only, + void selectOnMouseUp(ObjectFrame& box, bool select_only, const bool box_was_dragged, const bool result_of_mouse_down_select_method); @@ -249,13 +250,13 @@ namespace kiwi bool isAnyLinksSelected(); //! @brief Select an Object. - void selectObject(ObjectView& object); + void selectObject(ObjectFrame& object); //! @brief Select multiple objects - void selectObjects(std::vector const& objects); + void selectObjects(std::vector const& objects); //! @brief Unselect all and select an object. - void selectObjectOnly(ObjectView& object); + void selectObjectOnly(ObjectFrame& object); //! @brief Select a Link. void selectLink(LinkView& link); @@ -267,7 +268,7 @@ namespace kiwi void selectLinkOnly(LinkView& link); //! @brief Unselect an Object. - void unselectObject(ObjectView& object); + void unselectObject(ObjectFrame& object); //! @brief Unselect a Link. void unselectLink(LinkView& link); @@ -323,10 +324,10 @@ namespace kiwi // MISC // // ================================================================================ // - //! @internal Find a ObjectView with a given Object model. - ObjectViews::iterator findObject(model::Object const& object); + //! @internal Finds an ObjectFrame with a given Object model. + ObjectFrames::iterator findObject(model::Object const& object); - //! @internal Find a LinkView with a given Link model. + //! @internal Finds a LinkView with a given Link model. LinkViews::iterator findLink(model::Link const& link); //! @internal Returns true if a link can be created between two objects. @@ -340,7 +341,7 @@ namespace kiwi juce::Rectangle getSelectionBounds(); //! @internal get the nearest valid iolet of the link creator. - std::pair getLinkCreatorNearestEndingIolet(); + std::pair getLinkCreatorNearestEndingIolet(); //! @brief Zoom in Patcher View. void zoomIn(); @@ -356,7 +357,7 @@ namespace kiwi //! @internal Show Object contextual popup menu //! @details Will only show up when the patcher view is unlocked. - void showObjectPopupMenu(ObjectView const& object_view, juce::Point const& position); + void showObjectPopupMenu(ObjectFrame const& object_view, juce::Point const& position); //! @internal Show Link contextual Popup menu //! @details Will only show up when the patcher view is unlocked. @@ -378,7 +379,7 @@ namespace kiwi model::Patcher& m_patcher_model; model::Patcher::View& m_view_model; - ObjectViews m_objects; + ObjectFrames m_objects; LinkViews m_links; std::set m_local_objects_selection; @@ -406,7 +407,7 @@ namespace kiwi bool m_select_on_mouse_down_status = false; bool m_link_downstatus = false; bool m_is_in_move_or_resize_gesture = false; - ObjectView* m_box_being_edited = nullptr; + ObjectFrame* m_box_being_edited = nullptr; long m_object_border_down_status; friend PatcherViewport; diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewHitTester.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewHitTester.cpp index 0b4c50c7..5ad6b069 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewHitTester.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewHitTester.cpp @@ -19,9 +19,10 @@ ============================================================================== */ +#include + #include "KiwiApp_PatcherViewHitTester.h" #include "KiwiApp_PatcherView.h" -#include "KiwiApp_ObjectView.h" #include "KiwiApp_LinkView.h" namespace kiwi @@ -132,13 +133,13 @@ namespace kiwi } void HitTester::test(juce::Rectangle const& rect, - std::vector& objects, std::vector& links) + std::vector& objects, std::vector& links) { testObjects(rect, objects); testLinks(rect, links); } - void HitTester::testObjects(juce::Rectangle const& rect, std::vector& objects) + void HitTester::testObjects(juce::Rectangle const& rect, std::vector& objects) { objects.clear(); @@ -169,7 +170,7 @@ namespace kiwi return m_patcher; } - ObjectView* HitTester::getObject() const noexcept + ObjectFrame* HitTester::getObject() const noexcept { if(m_target == Target::Box) { diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewHitTester.h b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewHitTester.h index 5e55a493..59e0ef74 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewHitTester.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewHitTester.h @@ -26,7 +26,7 @@ namespace kiwi { class PatcherView; - class ObjectView; + class ObjectFrame; class LinkView; // ================================================================================ // @@ -101,14 +101,14 @@ namespace kiwi //! @param objects The vector of objects that will be filled. //! @param links The vector of links that will be filled. void test(juce::Rectangle const& rect, - std::vector& objects, + std::vector& objects, std::vector& links); //! @brief Test a rectangle. //! @details Try to find the objects that overlaps the given rectangle. //! @param rect The rectangle. //! @param objects The vector of objects that will be filled. - void testObjects(juce::Rectangle const& rect, std::vector& objects); + void testObjects(juce::Rectangle const& rect, std::vector& objects); //! @brief Test a rectangle. //! @details Try to find the links that overlaps the given rectangle. @@ -135,7 +135,7 @@ namespace kiwi PatcherView const& getPatcher() const noexcept; //! @brief Get the object box that has been touched by the last hit-test. - ObjectView* getObject() const noexcept; + ObjectFrame* getObject() const noexcept; //! @brief Get the link that has been touched by the last hit-test. LinkView* getLink() const noexcept; @@ -162,7 +162,7 @@ namespace kiwi private: // members PatcherView const& m_patcher; - ObjectView* m_object = nullptr; + ObjectFrame* m_object = nullptr; LinkView* m_link = nullptr; Target m_target = Target::Nothing; Zone m_zone = Zone::Outside; @@ -170,6 +170,6 @@ namespace kiwi size_t m_index = 0; friend class LinkView; - friend class ObjectView; + friend class ObjectFrame; }; } diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewIoletHighlighter.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewIoletHighlighter.cpp index 6e507922..ca1fc7dc 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewIoletHighlighter.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewIoletHighlighter.cpp @@ -19,8 +19,9 @@ ============================================================================== */ +#include + #include "KiwiApp_PatcherViewIoletHighlighter.h" -#include "KiwiApp_ObjectView.h" #include "../KiwiApp.h" namespace kiwi @@ -59,19 +60,19 @@ namespace kiwi g.drawRect(bounds); } - void IoletHighlighter::highlightInlet(ObjectView const& object, const size_t index) + void IoletHighlighter::highlightInlet(ObjectFrame const& object, const size_t index) { m_is_inlet = true; highlight(object, index); } - void IoletHighlighter::highlightOutlet(ObjectView const& object, const size_t index) + void IoletHighlighter::highlightOutlet(ObjectFrame const& object, const size_t index) { m_is_inlet = false; highlight(object, index); } - void IoletHighlighter::highlight(ObjectView const& object, const size_t index) + void IoletHighlighter::highlight(ObjectFrame const& object, const size_t index) { const auto& object_model = object.getModel(); auto new_name = object_model.getName(); diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewIoletHighlighter.h b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewIoletHighlighter.h index d15f2e1d..fcce4758 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewIoletHighlighter.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewIoletHighlighter.h @@ -26,7 +26,7 @@ namespace kiwi { - class ObjectView; + class ObjectFrame; // ================================================================================ // // IOLET HILIGHTER // @@ -51,10 +51,10 @@ namespace kiwi void hide(); //! @brief Highlight inlet - void highlightInlet(ObjectView const& object, const size_t index); + void highlightInlet(ObjectFrame const& object, const size_t index); //! @brief Highlight outlet - void highlightOutlet(ObjectView const& object, const size_t index); + void highlightOutlet(ObjectFrame const& object, const size_t index); //! @brief Returns the string that this object wants to show as its tooltip. juce::String getTooltip() override; @@ -73,7 +73,7 @@ namespace kiwi private: // methods - void highlight(ObjectView const& object, const size_t index); + void highlight(ObjectFrame const& object, const size_t index); private: // members diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewLasso.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewLasso.cpp index 5f4d5eb2..d2db78c5 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewLasso.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewLasso.cpp @@ -19,9 +19,10 @@ ============================================================================== */ +#include + #include "KiwiApp_PatcherViewLasso.h" #include "KiwiApp_PatcherView.h" -#include "KiwiApp_ObjectView.h" #include "KiwiApp_LinkView.h" #include "../KiwiApp.h" @@ -105,17 +106,17 @@ namespace kiwi { if(include_objects) { - PatcherView::ObjectViews const& objects = m_patcher.getObjects(); + PatcherView::ObjectFrames const& objects = m_patcher.getObjects(); HitTester hit(m_patcher); - std::vector lasso_objects; + std::vector lasso_objects; hit.testObjects(bounds, lasso_objects); - for(auto& object_view_uptr : objects) + for(auto& object_frame_uptr : objects) { - if(object_view_uptr) + if(object_frame_uptr) { - ObjectView& object = *object_view_uptr.get(); + ObjectFrame& object = *object_frame_uptr.get(); const bool is_selected = object.isSelected(); const bool was_selected = m_objects.find(object.getModel().ref()) != m_objects.end(); @@ -181,7 +182,7 @@ namespace kiwi if(include_objects) { - std::vector objects; + std::vector objects; hit.testObjects(bounds, objects); m_patcher.selectObjects(objects); } diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewLasso.h b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewLasso.h index ddb54ab9..8de72a48 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewLasso.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewLasso.h @@ -32,7 +32,7 @@ namespace kiwi { class PatcherView; - class ObjectView; + class ObjectFrame; // ================================================================================ // // LASSO // diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewport.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewport.cpp index 5afd2b49..de359706 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewport.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewport.cpp @@ -19,9 +19,10 @@ ============================================================================== */ +#include + #include "KiwiApp_PatcherViewport.h" #include "KiwiApp_PatcherView.h" -#include "KiwiApp_ObjectView.h" namespace kiwi { @@ -110,10 +111,10 @@ namespace kiwi setViewPosition((position + getOriginPosition()) * m_zoom_factor); } - void PatcherViewport::jumpViewToObject(ObjectView const& object_view) + void PatcherViewport::jumpViewToObject(ObjectFrame const& object_frame) { const auto view_area = getRelativeViewArea(); - auto object_bounds = object_view.getBoxBounds(); + auto object_bounds = object_frame.getObjectBounds(); object_bounds.setPosition(((object_bounds.getPosition() - getOriginPosition()))); if(! view_area.contains(object_bounds)) diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewport.h b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewport.h index 6188fd87..6f79532e 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewport.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewport.h @@ -26,7 +26,7 @@ namespace kiwi { class PatcherView; - class ObjectView; + class ObjectFrame; // ================================================================================ // // PATCHER VIEWPORT // @@ -50,7 +50,7 @@ namespace kiwi void resized() override; //! @brief Make the object visible in the viewport area. - void jumpViewToObject(ObjectView const&); + void jumpViewToObject(ObjectFrame const&); //! @brief Attempts to brings the center of the given bounds to the center of the viewport view area void bringRectToCentre(juce::Rectangle bounds); From ec52ff055ca0704834b113bb5e6906d153518c62 Mon Sep 17 00:00:00 2001 From: jmillot Date: Fri, 25 Aug 2017 19:25:36 +0200 Subject: [PATCH 041/148] Update object creation. --- .../KiwiApp_Basic/KiwiApp_ClassicView.cpp | 5 - .../KiwiApp_Patcher/KiwiApp_PatcherView.cpp | 136 +++++------------- .../KiwiApp_Patcher/KiwiApp_PatcherView.h | 3 - Modules/KiwiEngine/KiwiEngine_Factory.cpp | 11 +- Modules/KiwiModel/KiwiModel_Factory.cpp | 38 +++-- Modules/KiwiModel/KiwiModel_Factory.h | 3 +- .../KiwiModel_Basic/KiwiModel_ErrorBox.cpp | 10 ++ .../KiwiModel_Basic/KiwiModel_ErrorBox.h | 10 ++ .../KiwiModel_Basic/KiwiModel_NewBox.cpp | 1 + Modules/KiwiModel/KiwiModel_Patcher.cpp | 47 +++++- Modules/KiwiModel/KiwiModel_Patcher.h | 16 ++- Test/Model/test_PatcherValidator.cpp | 9 +- 12 files changed, 155 insertions(+), 134 deletions(-) diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.cpp index 6ba42d09..e734af52 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.cpp @@ -39,13 +39,8 @@ namespace kiwi { if(object_model.getName() == "errorbox") { - m_text.erase(m_text.begin(), m_text.begin() + m_text.find(" ") + 1); setColour(ObjectView::ColourIds::Background, findColour(ObjectView::ColourIds::Error).withAlpha(0.4f)); } - else if(object_model.getName() == "newbox") - { - m_text.clear(); - } } ClassicView::~ClassicView() diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp index d55c3558..c1caa584 100755 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp @@ -1929,27 +1929,6 @@ namespace kiwi // ================================================================================ // // COMMANDS ACTIONS // // ================================================================================ // - - model::Object& PatcherView::createObjectModel(std::string const& text) - { - // to clean - std::vector atoms = AtomHelper::parse(text); - const std::string name = atoms[0].getString(); - if(model::Factory::has(name)) - { - model::Object* model; - try - { - model = &m_patcher_model.addObject(name, std::vector(atoms.begin()+1, atoms.end())); - } - catch(...) - { - return m_patcher_model.addObject("errorbox", std::vector(atoms.begin(), atoms.end())); - } - return *model; - } - return m_patcher_model.addObject("errorbox", std::vector(atoms.begin(), atoms.end())); - } void PatcherView::editObject(ObjectFrame & object_frame) { @@ -1962,98 +1941,56 @@ namespace kiwi void PatcherView::objectEdited(ObjectFrame const& object_frame, std::string const& new_text) { - grabKeyboardFocus(); - - std::string new_object_text = new_text.empty() ? "newbox" : new_text; - assert(m_box_being_edited != nullptr); assert(m_box_being_edited == &object_frame); m_box_being_edited = nullptr; - model::Object& old_object_m = object_frame.getModel(); - const std::string old_object_text = old_object_m.getText(); - if(old_object_text != new_object_text) + grabKeyboardFocus(); + + model::Object & old_model = object_frame.getModel(); + + if(new_text != old_model.getText()) { - model::Object& new_object_m = createObjectModel(new_object_text); - - const std::string new_object_name = new_object_m.getName(); - const std::string new_object_text = [&new_object_name](std::string text){ - - if(new_object_name == "errorbox") - { - text.erase(text.begin(), text.begin()+9); - } - - return text; - - }(new_object_m.getText()); - - const int text_width = juce::Font().getStringWidth(new_object_text); + std::vector atoms = AtomHelper::parse(new_text); - const juce::Point origin = getOriginPosition(); + std::unique_ptr object_model = model::Factory::create(atoms); + + juce::Point origin = getOriginPosition(); juce::Rectangle box_bounds = object_frame.getObjectBounds(); - new_object_m.setPosition(box_bounds.getX() - origin.x, box_bounds.getY() - origin.y); - new_object_m.setWidth(text_width + 12); - new_object_m.setHeight(box_bounds.getHeight()); + object_model->setPosition(box_bounds.getX() - origin.x, box_bounds.getY() - origin.y); - // handle error box case - if(new_object_name == "errorbox") + if (object_model->getName() == "newbox") { - model::ErrorBox& error_box = dynamic_cast(new_object_m); - error_box.setInlets(old_object_m.getInlets()); - error_box.setOutlets(old_object_m.getOutlets()); + object_model->setWidth(80); + object_model->setHeight(box_bounds.getHeight()); } - - // re-link object - const size_t new_inlets = new_object_m.getNumberOfInlets(); - const size_t new_outlets = new_object_m.getNumberOfOutlets(); - - for(model::Link& link : m_patcher_model.getLinks()) + else { - if(!link.removed()) - { - const model::Object& from = link.getSenderObject(); - const size_t outlet_index = link.getSenderIndex(); - const model::Object& to = link.getReceiverObject(); - const size_t inlet_index = link.getReceiverIndex(); - - if(&from == &old_object_m) - { - if(outlet_index < new_outlets) - { - m_patcher_model.addLink(new_object_m, outlet_index, to, inlet_index); - } - else - { - KiwiApp::error("Link removed (outlet out of range)"); - } - } - - if(&to == &old_object_m) - { - if(inlet_index < new_inlets) - { - m_patcher_model.addLink(from, outlet_index, new_object_m, inlet_index); - } - else - { - KiwiApp::error("Link removed (inlet out of range)"); - } - } - } + object_model->setWidth(juce::Font().getStringWidth(new_text) + 12); + object_model->setHeight(box_bounds.getHeight()); + } + + // handle error box case + if(object_model->getName() == "errorbox") + { + model::ErrorBox& error_box = dynamic_cast(*object_model); + error_box.setInlets(old_model.getInlets()); + error_box.setOutlets(old_model.getOutlets()); + KiwiApp::error(error_box.getError()); } - m_view_model.unselectObject(old_object_m); - m_patcher_model.removeObject(old_object_m); - DocumentManager::commit(m_patcher_model, "Edit Object"); + model::Object & new_object = m_patcher_model.replaceObject(old_model, std::move(object_model)); + + m_view_model.unselectObject(old_model); if(!isLocked()) { - m_view_model.selectObject(new_object_m); - DocumentManager::commit(m_patcher_model); + m_view_model.selectObject(new_object); } + + DocumentManager::commit(m_patcher_model, "Edit Object"); } KiwiApp::commandStatusChanged(); @@ -2065,7 +2002,7 @@ namespace kiwi { bool linked_newbox = m_local_objects_selection.size() == 1; - auto& new_object = createObjectModel("newbox"); + std::unique_ptr new_object = model::Factory::create(AtomHelper::parse("")); juce::Point pos = getMouseXYRelative() - getOriginPosition(); @@ -2082,16 +2019,17 @@ namespace kiwi if(obj->getNumberOfInlets() >= 1) { - m_patcher_model.addLink(*obj, 0, new_object, 0); + m_patcher_model.addLink(*obj, 0, *new_object, 0); } } } - new_object.setPosition(pos.x, pos.y); - new_object.setWidth(80); + new_object->setPosition(pos.x, pos.y); + new_object->setWidth(80); m_view_model.unselectAll(); - m_view_model.selectObject(new_object); + + m_view_model.selectObject(m_patcher_model.addObject(std::move(new_object))); DocumentManager::commit(m_patcher_model, "Insert New Empty Box"); diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.h b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.h index f375c420..9cbad799 100755 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.h @@ -106,9 +106,6 @@ namespace kiwi //! @brief Returns the position of the patcher origin relative to the component position. juce::Point getOriginPosition() const; - //! @brief Create an object model. - model::Object& createObjectModel(std::string const& text); - //! @brief Call this to switch the box to edit mode //! @details Will result in objectEdited being called in case of success. void editObject(ObjectFrame & object_frame); diff --git a/Modules/KiwiEngine/KiwiEngine_Factory.cpp b/Modules/KiwiEngine/KiwiEngine_Factory.cpp index 0f7ed335..d600d756 100644 --- a/Modules/KiwiEngine/KiwiEngine_Factory.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Factory.cpp @@ -34,12 +34,17 @@ namespace kiwi std::unique_ptr Factory::create(Patcher& patcher, model::Object const& model) { - std::vector atoms = AtomHelper::parse(model.getText()); - assert(!atoms.empty() && "The model object isn't valid."); + std::vector args; + + if (!model.getText().empty()) + { + std::vector parsed_text = AtomHelper::parse(model.getText()); + args.insert(args.begin(), parsed_text.begin() + 1, parsed_text.end()); + } auto& creators = getCreators(); assert(creators.count(model.getName()) != 0 && "The object has not been registered."); - return std::unique_ptr(creators[model.getName()](model, patcher, std::vector(atoms.begin() + 1, atoms.end()))); + return std::unique_ptr(creators[model.getName()](model, patcher, args)); } bool Factory::has(std::string const& name) diff --git a/Modules/KiwiModel/KiwiModel_Factory.cpp b/Modules/KiwiModel/KiwiModel_Factory.cpp index cc645222..37517119 100644 --- a/Modules/KiwiModel/KiwiModel_Factory.cpp +++ b/Modules/KiwiModel/KiwiModel_Factory.cpp @@ -19,6 +19,8 @@ ============================================================================== */ +#include + #include "KiwiModel_Factory.h" namespace kiwi @@ -29,21 +31,39 @@ namespace kiwi // FACTORY // // ================================================================================ // - std::unique_ptr Factory::create(std::string const& name, - std::vector const& args) + std::unique_ptr Factory::create(std::vector const& atoms) { - auto const* class_ptr = getClassByName(name); - if(class_ptr != nullptr) + std::unique_ptr object; + + auto * object_class = !atoms.empty() ? getClassByName(atoms[0].getString()) : getClassByName("newbox"); + + if (object_class == nullptr) { - auto object_uptr = class_ptr->create(args); - object_uptr->m_name = class_ptr->getName(); - object_uptr->m_text = args.empty() ? name : name + " " + AtomHelper::toString(args); - return object_uptr; + object_class = getClassByName("errorbox"); + + object = object_class->create(std::vector()); + dynamic_cast(object.get())->setError("object \"" + atoms[0].getString() + "\" not found"); } else { - throw std::runtime_error("Factory can't create object"); + try + { + std::vector args(atoms.empty() ? atoms.begin() : atoms.begin() + 1, atoms.end()); + object = object_class->create(args); + } + catch(std::runtime_error & e) + { + object_class = getClassByName("errorbox"); + + object = object_class->create(std::vector()); + dynamic_cast(object.get())->setError(e.what()); + } } + + object->m_name = object_class->getName(); + object->m_text = AtomHelper::toString(atoms); + + return object; } std::unique_ptr Factory::create(std::string const& name, flip::Mold const& mold) diff --git a/Modules/KiwiModel/KiwiModel_Factory.h b/Modules/KiwiModel/KiwiModel_Factory.h index d4294b17..e7eded48 100644 --- a/Modules/KiwiModel/KiwiModel_Factory.h +++ b/Modules/KiwiModel/KiwiModel_Factory.h @@ -90,8 +90,7 @@ namespace kiwi //! @param name The name of the Object. //! @param args A list of arguments as a vector of Atom. //! @return A ptr to a model::Object. - static std::unique_ptr create(std::string const& name, - std::vector const& args); + static std::unique_ptr create(std::vector const& args); //! @brief Creates a new Object from a flip::Mold. //! @details This function will throw if the object name does not exist. diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_ErrorBox.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_ErrorBox.cpp index b7b60f44..791801f5 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_ErrorBox.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_ErrorBox.cpp @@ -54,5 +54,15 @@ namespace kiwi { return "(nothing here)"; } + + void ErrorBox::setError(std::string const& error_message) + { + m_error = error_message; + } + + std::string ErrorBox::getError() const + { + return m_error; + } } } diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_ErrorBox.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_ErrorBox.h index 909d82fa..e3485c5a 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_ErrorBox.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_ErrorBox.h @@ -49,10 +49,20 @@ namespace kiwi //! @param inlets The number of inlets. void setOutlets(flip::Array const& outlets); + //! @brief Sets the message error that caused the errorbox construction. + void setError(std::string const& error); + + //! @brief Returns the error that caused the errorbox construction. + std::string getError() const; + std::string getIODescription(bool is_inlet, size_t index) const override; //! @internal flip static declare method static void declare(); + + private: // members + + std::string m_error; }; } } diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_NewBox.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_NewBox.cpp index d656302b..e962d77d 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_NewBox.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_NewBox.cpp @@ -34,6 +34,7 @@ namespace kiwi void NewBox::declare() { Factory::add("newbox").setInternal(true); + } NewBox::NewBox(std::string const& name, std::vector const& args) diff --git a/Modules/KiwiModel/KiwiModel_Patcher.cpp b/Modules/KiwiModel/KiwiModel_Patcher.cpp index 0bad6064..aeed7293 100755 --- a/Modules/KiwiModel/KiwiModel_Patcher.cpp +++ b/Modules/KiwiModel/KiwiModel_Patcher.cpp @@ -67,9 +67,52 @@ namespace kiwi m_objects.clear(); } - model::Object& Patcher::addObject(std::string const& name, std::vector const& args) + model::Object & Patcher::addObject(std::unique_ptr && object) { - return *m_objects.insert(m_objects.end(), Factory::create(name, args)); + assert(object != nullptr); + return *m_objects.insert(m_objects.end(), std::move(object)); + } + + model::Object & Patcher::replaceObject(model::Object const& old_object, + std::unique_ptr && new_object) + { + assert(new_object != nullptr); + model::Object & object_ref = addObject(std::move(new_object)); + + // re-link object + const size_t new_inlets = object_ref.getNumberOfInlets(); + const size_t new_outlets = object_ref.getNumberOfOutlets(); + + for(model::Link& link : getLinks()) + { + if(!link.removed()) + { + const model::Object& from = link.getSenderObject(); + const size_t outlet_index = link.getSenderIndex(); + const model::Object& to = link.getReceiverObject(); + const size_t inlet_index = link.getReceiverIndex(); + + if(&from == &old_object) + { + if(outlet_index < new_outlets) + { + addLink(object_ref, outlet_index, to, inlet_index); + } + } + + if(&to == &old_object) + { + if(inlet_index < new_inlets) + { + addLink(from, outlet_index, object_ref, inlet_index); + } + } + } + } + + removeObject(old_object); + + return object_ref; } model::Object& Patcher::addObject(std::string const& name, flip::Mold const& mold) diff --git a/Modules/KiwiModel/KiwiModel_Patcher.h b/Modules/KiwiModel/KiwiModel_Patcher.h index 5753e522..acfc28ba 100755 --- a/Modules/KiwiModel/KiwiModel_Patcher.h +++ b/Modules/KiwiModel/KiwiModel_Patcher.h @@ -49,13 +49,15 @@ namespace kiwi //! @brief Destructor. ~Patcher(); - //! @brief Try to create an Object with a text. - //! @details This function will first parse the input string in a vector of atom - //! to find a registered name object as first atom. - //! the last atoms are passed to the created object as arguments. - //! @param text A string composed by the name of the object optionnally followed by a space and a list of argument values (ex : "plus 42") - //! @return An Object. - model::Object& addObject(std::string const& name, std::vector const& args); + //! @brief Adds an object to the patcher model. + //! @param The object to add in the text. + //! @return A reference to the object added. + model::Object& addObject(std::unique_ptr && object); + + //! @brief Replaces an object by another one. + //! @details This function will rewire the new object. + //! @return A reference to the newly added object. + model::Object& replaceObject(model::Object const& old_object, std::unique_ptr && object); //! @brief create an Object from a flip::Mold. model::Object& addObject(std::string const& name, flip::Mold const& mold); diff --git a/Test/Model/test_PatcherValidator.cpp b/Test/Model/test_PatcherValidator.cpp index 0f7478c3..1dab72d6 100755 --- a/Test/Model/test_PatcherValidator.cpp +++ b/Test/Model/test_PatcherValidator.cpp @@ -30,6 +30,7 @@ #include #include #include +#include using namespace kiwi; @@ -44,8 +45,8 @@ TEST_CASE("Model Validator", "[Validator]") model::PatcherValidator validator; flip::DocumentServer server (model::DataModel::use(), validator, 123456789ULL); - model::Object& plus_up = server.root().addObject("+", std::vector()); - model::Object& plus_down = server.root().addObject("+", std::vector()); + server.root().addObject(model::Factory::create(AtomHelper::parse("+"))); + server.root().addObject(model::Factory::create(AtomHelper::parse("+"))); server.commit(); @@ -107,8 +108,8 @@ TEST_CASE("Model Validator", "[Validator]") model::PatcherValidator validator; flip::DocumentServer server (model::DataModel::use(), validator, 123456789ULL); - model::Object& plus_up = server.root().addObject("+", std::vector()); - model::Object& plus_down = server.root().addObject("+", std::vector()); + server.root().addObject(model::Factory::create(AtomHelper::parse("+"))); + server.root().addObject(model::Factory::create(AtomHelper::parse("+"))); server.commit(); From 5f764df43c56d9e64666a603e3c7b3208c1cb8a7 Mon Sep 17 00:00:00 2001 From: jmillot Date: Thu, 24 Aug 2017 16:57:44 +0200 Subject: [PATCH 042/148] Adding bang object. --- Client/Source/KiwiApp.cpp | 3 + .../KiwiApp_Patcher/KiwiApp_Factory.cpp | 58 ++++++++++ .../Source/KiwiApp_Patcher/KiwiApp_Factory.h | 66 +++++++++++ .../KiwiApp_Basic/KiwiApp_ClassicView.cpp | 4 +- .../KiwiApp_Basic/KiwiApp_ClassicView.h | 6 +- .../KiwiApp_Controller/KiwiApp_BangView.cpp | 107 ++++++++++++++++++ .../KiwiApp_Controller/KiwiApp_BangView.h | 90 +++++++++++++++ .../KiwiApp_Objects/KiwiApp_ObjectFrame.cpp | 14 +++ .../KiwiApp_Objects/KiwiApp_ObjectFrame.h | 3 + .../KiwiApp_Objects/KiwiApp_ObjectView.cpp | 1 + .../KiwiApp_Objects/KiwiApp_ObjectView.h | 3 +- .../KiwiApp_Objects/KiwiApp_Objects.h | 6 + .../KiwiApp_Patcher/KiwiApp_PatcherView.cpp | 36 +++--- .../KiwiApp_Patcher/KiwiApp_PatcherView.h | 4 +- Modules/KiwiEngine/KiwiEngine_Instance.cpp | 1 + .../KiwiEngine_Controller/KiwiEngine_Bang.cpp | 91 +++++++++++++++ .../KiwiEngine_Controller/KiwiEngine_Bang.h | 63 +++++++++++ .../KiwiEngine_Objects/KiwiEngine_Objects.h | 6 + Modules/KiwiModel/KiwiModel_DataModel.cpp | 1 + Modules/KiwiModel/KiwiModel_Object.cpp | 10 ++ Modules/KiwiModel/KiwiModel_Object.h | 39 ++++++- .../KiwiModel_Basic/KiwiModel_NewBox.cpp | 3 + .../KiwiModel_Controller/KiwiModel_Bang.cpp | 77 +++++++++++++ .../KiwiModel_Controller/KiwiModel_Bang.h | 57 ++++++++++ .../KiwiModel_Objects/KiwiModel_Objects.h | 7 ++ 25 files changed, 730 insertions(+), 26 deletions(-) create mode 100644 Client/Source/KiwiApp_Patcher/KiwiApp_Factory.cpp create mode 100644 Client/Source/KiwiApp_Patcher/KiwiApp_Factory.h create mode 100644 Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_BangView.cpp create mode 100644 Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_BangView.h create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Bang.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Bang.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Bang.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Bang.h diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index 5cdce585..e04e61e8 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -21,6 +21,7 @@ #include +#include #include "KiwiApp.h" #include "KiwiApp_General/KiwiApp_CommandIDs.h" @@ -92,6 +93,8 @@ namespace kiwi model::DataModel::init(); + Factory::initialise(); + juce::Desktop::getInstance().setGlobalScaleFactor(1.); juce::LookAndFeel::setDefaultLookAndFeel(&m_looknfeel); diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Factory.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Factory.cpp new file mode 100644 index 00000000..f84cec85 --- /dev/null +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Factory.cpp @@ -0,0 +1,58 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include +#include + +namespace kiwi +{ + std::map Factory::m_creator_map; + + std::unique_ptr createBangView(model::Object & object_model) + { + return std::make_unique(object_model); + } + + std::unique_ptr Factory::createObjectView(model::Object & object_model) + { + std::unique_ptr object_view(nullptr); + + std::string object_name = object_model.getName(); + + if (m_creator_map.find(object_name) != m_creator_map.end()) + { + object_view = std::move(m_creator_map[object_name](object_model)); + } + else + { + object_view = std::move(std::make_unique(object_model)); + } + + return object_view; + } + + void Factory::initialise() + { + m_creator_map["bang"] = std::bind(createBangView, std::placeholders::_1); + } +} diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Factory.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Factory.h new file mode 100644 index 00000000..b07f606a --- /dev/null +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Factory.h @@ -0,0 +1,66 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include +#include + +#include + +#include + +#pragma once + +namespace kiwi +{ + // ================================================================================ // + // FACTORY // + // ================================================================================ // + + class Factory + { + public: // definitions + + using factory_func = std::function(model::Object & model)>; + + public: // methods + + //! @brief The construction methods. + //! @details Returns an object corresponding to a certain object's model. + static std::unique_ptr createObjectView(model::Object & object_model); + + //! @brief Initializes the list of creators adding a function for each type of objects. + static void initialise(); + + private: // members + + static std::map m_creator_map; + + private: // deleted methods + + Factory() = delete; + ~Factory() = delete; + Factory(Factory const& other) = delete; + Factory(Factory && other) = delete; + Factory& operator=(Factory const& other) = delete; + Factory& operator=(Factory && other) = delete; + }; +} diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.cpp index e734af52..d869a127 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.cpp @@ -170,9 +170,9 @@ namespace kiwi { assert(&editor == m_editor.get()); - removeTextEditor(); - m_listeners.call(&Listener::textEdited, m_text); + + removeTextEditor(); } void ClassicView::textEditorReturnKeyPressed(juce::TextEditor& editor) diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.h index 588dfb48..20b68452 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.h @@ -69,6 +69,9 @@ namespace kiwi //! @brief Lets the user edit the text of the box. void edit(); + //! @brief Returns true if the classic view is currently in edition mode. + bool isEditing() const; + private: // methods //! @brief The component's graphical rendering method. @@ -101,9 +104,6 @@ namespace kiwi ///! @brief Calls this to end edition and supress the text editor. void removeTextEditor(); - //! @brief Returns true if the classic view is currently in edition mode. - bool isEditing() const; - private: // members std::string m_text; diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_BangView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_BangView.cpp new file mode 100644 index 00000000..0683f822 --- /dev/null +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_BangView.cpp @@ -0,0 +1,107 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include + +#include + +#include +#include + +namespace kiwi +{ + BangView::BangView(model::Object & model): + ObjectView(model), + m_border(1.5), + m_signal(model.getSignal<>(model::Bang::Signal::TriggerBang)), + m_connection(m_signal.connect(std::bind(&BangView::signalTriggered, this))), + m_active(false), + m_mouse_down(false), + m_switch_off(std::make_shared::CallBack>(std::bind(&BangView::switchOff, this))) + { + } + + BangView::~BangView() + { + } + + void BangView::paint(juce::Graphics & g) + { + g.fillAll(findColour(ObjectView::ColourIds::Background)); + g.setColour(findColour(ObjectView::ColourIds::Outline)); + + g.drawEllipse(getLocalBounds().reduced(3.1).toFloat(), 2); + + int x = getLocalBounds().getX(); + int y = getLocalBounds().getY(); + int height = getHeight(); + int width = getWidth(); + + g.fillRect(x, y, width, m_border.getTop()); + g.fillRect(x, y, m_border.getLeft(), height); + g.fillRect(x, y + height - m_border.getBottom(), width, m_border.getBottom()); + g.fillRect(x + width - m_border.getRight(), y, m_border.getRight(), height); + + if (m_mouse_down || m_active) + { + g.setColour(findColour(ObjectView::ColourIds::Active)); + g.fillEllipse(getLocalBounds().reduced(3.1 + 2).toFloat()); + } + } + + void BangView::mouseDown(juce::MouseEvent const& e) + { + m_mouse_down = true; + repaint(); + + m_signal(); + } + + void BangView::mouseUp(juce::MouseEvent const& e) + { + m_mouse_down = false; + repaint(); + } + + void BangView::flash() + { + if (!m_active) + { + m_active = true; + repaint(); + } + + KiwiApp::useInstance().useScheduler().schedule(m_switch_off, std::chrono::milliseconds(250)); + } + + void BangView::switchOff() + { + m_active = false; + repaint(); + } + + void BangView::signalTriggered() + { + KiwiApp::useInstance().useScheduler().defer(std::bind(&BangView::flash, this)); + } +} diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_BangView.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_BangView.h new file mode 100644 index 00000000..5b866c3e --- /dev/null +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_BangView.h @@ -0,0 +1,90 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +#include + +#include + +#include + +#include + +#include + +namespace kiwi +{ + // ================================================================================ // + // BANG VIEW // + // ================================================================================ // + + class BangView : public ObjectView + { + public: // methods + + //! @brief Constructor. + BangView(model::Object & object_model); + + //! @brief Destructor. + ~BangView(); + + private: // methods + + //! @brief The graphical rendering method. + void paint(juce::Graphics & g) override final; + + //! @brief Called when the bang is clicked. + void mouseDown(juce::MouseEvent const& e) override final; + + //! @brief Called when the bang is unclicked. + void mouseUp(juce::MouseEvent const& e) override final; + + //! @brief Switches the bang view on and schedules to switch it off. + void flash(); + + //! @brief Switches the bang view off. + void switchOff(); + + //! @brief Called whenever bang is trigerred. + void signalTriggered(); + + private: // members + + //! @todo Put border into ObjectView. + juce::BorderSize m_border; + flip::Signal<>& m_signal; + flip::SignalConnection m_connection; + bool m_active; + bool m_mouse_down; + std::shared_ptr::CallBack> m_switch_off; + + private: // deleted methods + + BangView() = delete; + BangView(BangView const& other) = delete; + BangView(BangView && other) = delete; + BangView& operator=(BangView const& other) = delete; + BangView& operator=(BangView && other) = delete; + }; +} diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.cpp index 8e0bbd4c..707d040d 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.cpp @@ -279,6 +279,20 @@ namespace kiwi return getPatcherView().isSelected(*this); } + bool ObjectFrame::isEditing() const + { + bool is_editing = false; + + ClassicView * classic_view = dynamic_cast(m_object_view.get()); + + if (classic_view != nullptr) + { + is_editing = classic_view->isEditing(); + } + + return is_editing; + } + std::set ObjectFrame::getDistantSelection() const { return getPatcherView().getDistantSelection(*this); diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.h index d02eba54..c04d4c0d 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.h @@ -104,6 +104,9 @@ namespace kiwi //! @brief Returns true if the object is selected. bool isSelected() const; + //! @brief Returns true if the underlying object is currently being edited. + bool isEditing() const; + private: // methods //! @brief Component's graphical rendering method. diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectView.cpp index 4a2b5dc8..4207ce4e 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectView.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectView.cpp @@ -38,6 +38,7 @@ namespace kiwi setColour(ObjectView::ColourIds::Text, juce::Colours::black); setColour(ObjectView::ColourIds::Outline, juce::Colours::black); setColour(ObjectView::ColourIds::Highlight, juce::Colour::fromFloatRGBA(0., 0.5, 1., 0.)); + setColour(ObjectView::ColourIds::Active, juce::Colour::fromFloatRGBA(0.2, 0.8, 0.2, 1.)); } ObjectView::~ObjectView() diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectView.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectView.h index d75f49b7..a5d9ba8d 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectView.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectView.h @@ -44,7 +44,8 @@ namespace kiwi Error = 0x1100005, Text = 0x1100006, Outline = 0x1100007, - Highlight = 0x1100008 + Highlight = 0x1100008, + Active = 0x1100009 }; public: // methods diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Objects.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Objects.h index 16964744..b2f7ed04 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Objects.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Objects.h @@ -26,3 +26,9 @@ // ================================================================================ // #include + +// ================================================================================ // +// CONTROLLER OBJECTS // +// ================================================================================ // + +#include diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp index c1caa584..fbd5eb9c 100755 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp @@ -27,6 +27,7 @@ #include #include +#include #include "../KiwiApp.h" #include "../KiwiApp_General/KiwiApp_CommandIDs.h" @@ -1798,7 +1799,7 @@ namespace kiwi { const auto it = (zorder > 0) ? m_objects.begin() + zorder : m_objects.end(); - std::unique_ptr object_view = std::make_unique(object); + std::unique_ptr object_view = Factory::createObjectView(object); ObjectFrame& object_frame = **(m_objects.emplace(it, new ObjectFrame(*this, std::move(object_view)))); @@ -1929,22 +1930,29 @@ namespace kiwi // ================================================================================ // // COMMANDS ACTIONS // // ================================================================================ // + + bool PatcherView::isEditingObject() const + { + auto func = [](std::unique_ptr const& object) + { + return object->isEditing(); + }; + + return std::find_if(m_objects.begin(), m_objects.end(), func) != m_objects.end(); + } void PatcherView::editObject(ObjectFrame & object_frame) { - assert(m_box_being_edited == nullptr); + assert(!isEditingObject() && "Editing two objects simultaneously"); object_frame.editObject(); - m_box_being_edited = &object_frame; + KiwiApp::commandStatusChanged(); // to disable some command while editing... } void PatcherView::objectEdited(ObjectFrame const& object_frame, std::string const& new_text) { - assert(m_box_being_edited != nullptr); - assert(m_box_being_edited == &object_frame); - - m_box_being_edited = nullptr; + assert(isEditingObject() && "Calling object edited without editing object first"); grabKeyboardFocus(); @@ -1961,12 +1969,7 @@ namespace kiwi object_model->setPosition(box_bounds.getX() - origin.x, box_bounds.getY() - origin.y); - if (object_model->getName() == "newbox") - { - object_model->setWidth(80); - object_model->setHeight(box_bounds.getHeight()); - } - else + if (!object_model->hasFlag(model::Object::Flag::DefinedSize)) { object_model->setWidth(juce::Font().getStringWidth(new_text) + 12); object_model->setHeight(box_bounds.getHeight()); @@ -2025,7 +2028,6 @@ namespace kiwi } new_object->setPosition(pos.x, pos.y); - new_object->setWidth(80); m_view_model.unselectAll(); @@ -2268,7 +2270,6 @@ namespace kiwi void PatcherView::getCommandInfo(const juce::CommandID commandID, juce::ApplicationCommandInfo& result) { const bool is_not_in_gesture = !DocumentManager::isInCommitGesture(m_patcher_model); - const bool box_is_not_being_edited = (m_box_being_edited == nullptr); switch(commandID) { @@ -2414,15 +2415,14 @@ namespace kiwi result.setActive(!(result.flags & juce::ApplicationCommandInfo::isDisabled) && is_not_in_gesture - && box_is_not_being_edited); + && !isEditingObject()); } bool PatcherView::perform(const InvocationInfo& info) { // most of the commands below generate conflicts when they are being executed // in a commit gesture or when a box is being edited, so simply not execute them. - if(DocumentManager::isInCommitGesture(m_patcher_model) - || (m_box_being_edited != nullptr)) + if(DocumentManager::isInCommitGesture(m_patcher_model) || isEditingObject()) { return true; } diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.h b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.h index 9cbad799..a9cd1a50 100755 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.h @@ -113,6 +113,9 @@ namespace kiwi //! @brief Called once an object has been edited. void objectEdited(ObjectFrame const& object_frame, std::string const& new_text); + //! @brief Returns true if an object if being edited. + bool isEditingObject() const; + //! @internal Update the patcher window title. void updateWindowTitle() const; @@ -404,7 +407,6 @@ namespace kiwi bool m_select_on_mouse_down_status = false; bool m_link_downstatus = false; bool m_is_in_move_or_resize_gesture = false; - ObjectFrame* m_box_being_edited = nullptr; long m_object_border_down_status; friend PatcherViewport; diff --git a/Modules/KiwiEngine/KiwiEngine_Instance.cpp b/Modules/KiwiEngine/KiwiEngine_Instance.cpp index cd532374..feed44ec 100644 --- a/Modules/KiwiEngine/KiwiEngine_Instance.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Instance.cpp @@ -99,6 +99,7 @@ namespace kiwi engine::Factory::add("plus~"); engine::Factory::add("sig~"); engine::Factory::add("delaysimple~"); + engine::Factory::add("bang"); } // ================================================================================ // diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Bang.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Bang.cpp new file mode 100644 index 00000000..6b2811a2 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Bang.cpp @@ -0,0 +1,91 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include +#include + +namespace kiwi +{ + namespace engine + { + // ================================================================================ // + // OBJECT BANG // + // ================================================================================ // + + class Bang::Task : public Scheduler<>::Task + { + public: // methods + + Task(Bang & object): + m_object(object) + { + } + + ~Task() + { + } + + void execute() override final + { + m_object.send(0, {"bang"}); + } + + private: // members + + Bang & m_object; + }; + + Bang::Bang(model::Object const& model, Patcher& patcher, std::vector const& args): + Object(model, patcher), + m_task(new Task(*this)), + m_signal(model.getSignal<>(model::Bang::Signal::TriggerBang)), + m_connection(m_signal.connect(std::bind(&Bang::signalTriggered, this))) + { + } + + Bang::~Bang() + { + } + + void Bang::signalTriggered() + { + if (!getScheduler().isThisConsumerThread()) + { + getScheduler().schedule(m_task); + } + else + { + send(0, {"bang"}); + } + } + + void Bang::receive(size_t index, std::vector const& args) + { + if (index == 0) + { + m_signal(); + } + } + } +} + diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Bang.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Bang.h new file mode 100644 index 00000000..d4de7ca6 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Bang.h @@ -0,0 +1,63 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include +#include + +#include +#include + +#include + +namespace kiwi +{ + namespace engine + { + // ================================================================================ // + // OBJECT BANG // + // ================================================================================ // + + class Bang : public engine::Object + { + private: // classes + + class Task; + + public: // methods + + Bang(model::Object const& model, Patcher& patcher, std::vector const& args); + + ~Bang(); + + void signalTriggered(); + + void receive(size_t index, std::vector const& args) override final; + + private: // members + + std::shared_ptr m_task; + flip::Signal<> & m_signal; + flip::SignalConnection m_connection; + }; + } +} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h index 5fb9c62f..012b0fcb 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h @@ -62,3 +62,9 @@ #include #include #include + +// ================================================================================ // +// CONTROLLER OBJECTS // +// ================================================================================ // + +#include diff --git a/Modules/KiwiModel/KiwiModel_DataModel.cpp b/Modules/KiwiModel/KiwiModel_DataModel.cpp index 59ebc359..b4663f62 100644 --- a/Modules/KiwiModel/KiwiModel_DataModel.cpp +++ b/Modules/KiwiModel/KiwiModel_DataModel.cpp @@ -78,6 +78,7 @@ namespace kiwi PlusTilde::declare(); SigTilde::declare(); DelaySimpleTilde::declare(); + Bang::declare(); } } } diff --git a/Modules/KiwiModel/KiwiModel_Object.cpp b/Modules/KiwiModel/KiwiModel_Object.cpp index c820edc5..72246504 100755 --- a/Modules/KiwiModel/KiwiModel_Object.cpp +++ b/Modules/KiwiModel/KiwiModel_Object.cpp @@ -298,5 +298,15 @@ namespace kiwi { return (is_inlet ? "inlet " : "outlet ") + std::to_string(index); } + + bool Object::hasFlag(Flag flag) const + { + return (static_cast(flag) & static_cast(m_flags.value())) != 0; + } + + void Object::setFlag(Flag flag) + { + m_flags = static_cast(static_cast(flag) | static_cast(m_flags.value())); + } } } diff --git a/Modules/KiwiModel/KiwiModel_Object.h b/Modules/KiwiModel/KiwiModel_Object.h index 0402d6a8..818b6eb4 100755 --- a/Modules/KiwiModel/KiwiModel_Object.h +++ b/Modules/KiwiModel/KiwiModel_Object.h @@ -21,6 +21,8 @@ #pragma once +//! @todo Clean flip headers below, use only needed one in this file + // ---- Flip headers ---- // #include "flip/Bool.h" #include "flip/Int.h" @@ -151,6 +153,15 @@ namespace kiwi //! @details objects can be instantiated in a Patcher. class Object : public flip::Object { + public: // classes + + using SignalKey = uint32_t; + + enum class Flag : unsigned int + { + DefinedSize = 1 << 0 // Initial object's Size defined by the model. + }; + public: // methods //! @brief Constructor. @@ -222,7 +233,30 @@ namespace kiwi //! @brief Returns inlet or outlet description. virtual std::string getIODescription(bool is_inlet, size_t index) const; - protected: // methods + //! @brief Returns the object's signal referenced by this key. + //! @details Throws an exception if no signal is referenced for key. + template + auto& getSignal(SignalKey key) const + { + flip::SignalBase& signal_base = *m_signals.at(key); + return dynamic_cast&>(signal_base); + } + + //! @brief Checks if the object has this flag set. + bool hasFlag(Flag flag) const; + + protected: + + //! @brief Adds a signal having singal key. + template + void addSignal(SignalKey key, model::Object& object) + { + m_signals.emplace(key, std::make_unique>(key, object)); + } + + //! @brief Sets one of the flag for the object. + //! @details It is a modification of the model and requires commit. + void setFlag(Flag flag); //! @brief Clear and replace all the object's inlets. void setInlets(flip::Array const& inlets); @@ -246,10 +280,13 @@ namespace kiwi private: // members + std::map> m_signals; + flip::String m_name; flip::String m_text; flip::Array m_inlets; flip::Array m_outlets; + flip::Enum m_flags; flip::Float m_position_x; flip::Float m_position_y; diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_NewBox.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_NewBox.cpp index e962d77d..77bfd2e3 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_NewBox.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_NewBox.cpp @@ -39,6 +39,9 @@ namespace kiwi NewBox::NewBox(std::string const& name, std::vector const& args) { + setFlag(Flag::DefinedSize); + setWidth(80); + setHeight(20); pushInlet({PinType::IType::Control}); } diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Bang.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Bang.cpp new file mode 100755 index 00000000..f72d08f3 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Bang.cpp @@ -0,0 +1,77 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include + +namespace kiwi +{ + namespace model + { + // ================================================================================ // + // OBJECT BANG // + // ================================================================================ // + + Bang::Bang(std::string const& name, std::vector const& args): + Object() + { + if (!args.empty()) + { + throw std::runtime_error("wrong arguments for object bang"); + } + + setFlag(Flag::DefinedSize); + addSignal<>(Signal::TriggerBang, *this); + setWidth(20); + setHeight(20); + pushInlet({PinType::IType::Control}); + pushOutlet(PinType::IType::Control); + } + + Bang::Bang(flip::Default& d): + Object() + { + addSignal<>(Signal::TriggerBang, *this); + } + + void Bang::declare() + { + Factory::add("bang"); + } + + std::string Bang::getIODescription(bool is_inlet, size_t index) const + { + if (is_inlet && index == 0) + { + return "Makes the object flash and sends bang through first outlet"; + } + else if(!is_inlet && index == 0) + { + return "Sends bang"; + } + else + { + return ""; + } + } + } +} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Bang.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Bang.h new file mode 100755 index 00000000..77eab576 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Bang.h @@ -0,0 +1,57 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +#include + +namespace kiwi +{ + namespace model + { + // ================================================================================ // + // OBJECT BANG // + // ================================================================================ // + + + class Bang : public model::Object + { + public: // enum + + enum Signal : SignalKey + { + TriggerBang + }; + + public: // methods + + Bang(flip::Default& d); + + Bang(std::string const& name, std::vector const& args); + + std::string getIODescription(bool is_inlet, size_t index) const override; + + static void declare(); + }; + } +} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h index 0a0b6257..fc41970b 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h @@ -62,3 +62,10 @@ #include #include #include + +// ================================================================================ // +// CONTROLLER OBJECTS // +// ================================================================================ // + +#include + From cc053f3783a1804c7524fe8bd2bff4770898002e Mon Sep 17 00:00:00 2001 From: jean-millot Date: Thu, 31 Aug 2017 19:05:53 +0200 Subject: [PATCH 043/148] Enable command click on graphical objects. --- .../KiwiApp_Basic/KiwiApp_ClassicView.cpp | 11 ++++++++--- .../KiwiApp_Basic/KiwiApp_ClassicView.h | 1 + .../KiwiApp_Controller/KiwiApp_BangView.cpp | 3 ++- .../KiwiApp_Objects/KiwiApp_ObjectFrame.cpp | 10 ++++++++++ .../KiwiApp_Objects/KiwiApp_ObjectFrame.h | 6 ++++++ .../KiwiApp_Patcher/KiwiApp_PatcherView.cpp | 17 +++++++++++++---- .../KiwiApp_Patcher/KiwiApp_PatcherView.h | 4 ++-- .../KiwiEngine_Controller/KiwiEngine_Bang.cpp | 10 ++-------- .../KiwiModel_Controller/KiwiModel_Bang.cpp | 2 +- 9 files changed, 45 insertions(+), 19 deletions(-) diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.cpp index d869a127..b428f7ee 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.cpp @@ -35,7 +35,8 @@ namespace kiwi m_editor(nullptr), m_indent(4), m_border(1.5), - m_listeners() + m_listeners(), + m_deleted(false) { if(object_model.getName() == "errorbox") { @@ -46,6 +47,7 @@ namespace kiwi ClassicView::~ClassicView() { removeTextEditor(); + m_deleted = true; } void ClassicView::addListener(Listener& listener) @@ -103,7 +105,7 @@ namespace kiwi void ClassicView::removeTextEditor() { - if(m_editor) + if(m_editor != nullptr) { m_editor->removeListener(this); removeChildComponent(m_editor.get()); @@ -172,7 +174,10 @@ namespace kiwi m_listeners.call(&Listener::textEdited, m_text); - removeTextEditor(); + if (!m_deleted) + { + removeTextEditor(); + } } void ClassicView::textEditorReturnKeyPressed(juce::TextEditor& editor) diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.h index 20b68452..9e81c5f9 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.h @@ -111,6 +111,7 @@ namespace kiwi size_t m_indent; juce::BorderSize m_border; engine::Listeners m_listeners; + bool m_deleted; private: // deleted methods diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_BangView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_BangView.cpp index 0683f822..7c9eb547 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_BangView.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_BangView.cpp @@ -43,6 +43,7 @@ namespace kiwi BangView::~BangView() { + KiwiApp::useInstance().useScheduler().unschedule(m_switch_off); } void BangView::paint(juce::Graphics & g) @@ -91,7 +92,7 @@ namespace kiwi repaint(); } - KiwiApp::useInstance().useScheduler().schedule(m_switch_off, std::chrono::milliseconds(250)); + KiwiApp::useInstance().useScheduler().schedule(m_switch_off, std::chrono::milliseconds(150)); } void BangView::switchOff() diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.cpp index 707d040d..6558a38e 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.cpp @@ -164,6 +164,16 @@ namespace kiwi return m_object_view->getBounds().withPosition(getPosition() + m_object_view->getBounds().getPosition()); } + void ObjectFrame::mouseDown(juce::MouseEvent const& e) + { + m_object_view->mouseDown(e); + } + + void ObjectFrame::mouseUp(juce::MouseEvent const& e) + { + m_object_view->mouseUp(e); + } + bool ObjectFrame::hitTest(int x, int y) { bool allow_click; diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.h index c04d4c0d..e53fd486 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.h @@ -107,6 +107,12 @@ namespace kiwi //! @brief Returns true if the underlying object is currently being edited. bool isEditing() const; + //! @brief Called when object's frame is clicked. + void mouseDown(juce::MouseEvent const& e) override final; + + //! @brief Called when object's frame is clicked. + void mouseUp(juce::MouseEvent const& e) override final; + private: // methods //! @brief Component's graphical rendering method. diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp index fbd5eb9c..da0363d1 100755 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp @@ -537,7 +537,7 @@ namespace kiwi } else if(hit.patcherTouched()) { - createNewBoxModel(true); + createObjectModel("", true); } } } @@ -1999,13 +1999,13 @@ namespace kiwi KiwiApp::commandStatusChanged(); } - void PatcherView::createNewBoxModel(bool give_focus) + void PatcherView::createObjectModel(std::string const& text, bool give_focus) { if(! DocumentManager::isInCommitGesture(m_patcher_model)) { bool linked_newbox = m_local_objects_selection.size() == 1; - std::unique_ptr new_object = model::Factory::create(AtomHelper::parse("")); + std::unique_ptr new_object = model::Factory::create(AtomHelper::parse(text)); juce::Point pos = getMouseXYRelative() - getOriginPosition(); @@ -2255,6 +2255,7 @@ namespace kiwi commands.add(juce::StandardApplicationCommandIDs::selectAll); commands.add(CommandIDs::newBox); + commands.add(CommandIDs::newBang); commands.add(CommandIDs::zoomIn); commands.add(CommandIDs::zoomOut); @@ -2378,6 +2379,13 @@ namespace kiwi result.setActive(!isLocked()); break; } + case CommandIDs::newBang: + { + result.setInfo(TRANS("New Bang Box"), TRANS("Add a new bang"), CommandCategories::editing, 0); + result.addDefaultKeypress('b', juce::ModifierKeys::noModifiers); + result.setActive(!isLocked()); + break; + } case CommandIDs::zoomIn: { result.setInfo(TRANS("Zoom in"), TRANS("Zoom in"), CommandCategories::view, 0); @@ -2445,7 +2453,8 @@ namespace kiwi case juce::StandardApplicationCommandIDs::del: { deleteSelection(); break; } case juce::StandardApplicationCommandIDs::selectAll:{ selectAllObjects(); break; } - case CommandIDs::newBox: { createNewBoxModel(true); break; } + case CommandIDs::newBox: { createObjectModel("", true); break; } + case CommandIDs::newBang: { createObjectModel("bang", true); break; } case CommandIDs::zoomIn: { zoomIn(); break; } case CommandIDs::zoomOut: { zoomOut(); break; } diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.h b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.h index a9cd1a50..27e8b261 100755 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.h @@ -189,8 +189,8 @@ namespace kiwi //! @internal Link model will be removed from the document. void removeLinkView(model::Link& link); - //! @brief Add a newbox Object at current mouse position and optionally give it focus. - void createNewBoxModel(bool give_focus); + //! @brief Add a new object's model at current mouse position and optionally give it focus. + void createObjectModel(std::string const& text, bool give_focus); // ================================================================================ // // UNDO/REDO // diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Bang.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Bang.cpp index 6b2811a2..d54d28ef 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Bang.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Bang.cpp @@ -65,18 +65,12 @@ namespace kiwi Bang::~Bang() { + getScheduler().unschedule(m_task); } void Bang::signalTriggered() { - if (!getScheduler().isThisConsumerThread()) - { - getScheduler().schedule(m_task); - } - else - { - send(0, {"bang"}); - } + getScheduler().defer(m_task); } void Bang::receive(size_t index, std::vector const& args) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Bang.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Bang.cpp index f72d08f3..d6ae18e8 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Bang.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Bang.cpp @@ -48,7 +48,7 @@ namespace kiwi } Bang::Bang(flip::Default& d): - Object() + Object(d) { addSignal<>(Signal::TriggerBang, *this); } From 076d857195c950632bbb54fcd89037236a5113d5 Mon Sep 17 00:00:00 2001 From: jean-millot Date: Fri, 1 Sep 2017 18:19:27 +0200 Subject: [PATCH 044/148] Adding toggle object. --- .../KiwiApp_Patcher/KiwiApp_Factory.cpp | 8 +- .../Source/KiwiApp_Patcher/KiwiApp_Factory.h | 14 ++ .../KiwiApp_Basic/KiwiApp_ClassicView.cpp | 13 +- .../KiwiApp_Basic/KiwiApp_ClassicView.h | 3 +- .../KiwiApp_Controller/KiwiApp_BangView.cpp | 12 +- .../KiwiApp_Controller/KiwiApp_BangView.h | 1 - .../KiwiApp_Controller/KiwiApp_ToggleView.cpp | 151 ++++++++++++++++ .../KiwiApp_Controller/KiwiApp_ToggleView.h | 84 +++++++++ .../KiwiApp_Objects/KiwiApp_ObjectView.cpp | 15 +- .../KiwiApp_Objects/KiwiApp_ObjectView.h | 13 ++ .../KiwiApp_Objects/KiwiApp_Objects.h | 1 + .../KiwiApp_Patcher/KiwiApp_PatcherView.cpp | 9 + Modules/KiwiEngine/KiwiEngine_Instance.cpp | 1 + .../KiwiEngine_Toggle.cpp | 165 ++++++++++++++++++ .../KiwiEngine_Controller/KiwiEngine_Toggle.h | 70 ++++++++ .../KiwiEngine_Objects/KiwiEngine_Objects.h | 1 + Modules/KiwiModel/KiwiModel_DataModel.cpp | 1 + Modules/KiwiModel/KiwiModel_Object.cpp | 1 + .../KiwiModel_Controller/KiwiModel_Toggle.cpp | 77 ++++++++ .../KiwiModel_Controller/KiwiModel_Toggle.h | 62 +++++++ .../KiwiModel_Objects/KiwiModel_Objects.h | 1 + 21 files changed, 672 insertions(+), 31 deletions(-) create mode 100644 Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_ToggleView.cpp create mode 100644 Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_ToggleView.h create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Toggle.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Toggle.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Toggle.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Toggle.h diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Factory.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Factory.cpp index f84cec85..c969facf 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Factory.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Factory.cpp @@ -27,11 +27,6 @@ namespace kiwi { std::map Factory::m_creator_map; - - std::unique_ptr createBangView(model::Object & object_model) - { - return std::make_unique(object_model); - } std::unique_ptr Factory::createObjectView(model::Object & object_model) { @@ -53,6 +48,7 @@ namespace kiwi void Factory::initialise() { - m_creator_map["bang"] = std::bind(createBangView, std::placeholders::_1); + add("bang"); + add("toggle"); } } diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Factory.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Factory.h index b07f606a..6df41eb2 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Factory.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Factory.h @@ -25,6 +25,8 @@ #include +#include + #include #pragma once @@ -52,6 +54,18 @@ namespace kiwi private: // members + //! @brief Adds a object to the factory. + template + static void add(std::string const& name) + { + assert(model::Factory::has(name) && "Adding an engine object that has no corresponding model"); + + m_creator_map[name] = [](model::Object & object_model) + { + return std::make_unique(object_model); + }; + }; + static std::map m_creator_map; private: // deleted methods diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.cpp index b428f7ee..33592cf2 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.cpp @@ -29,12 +29,11 @@ namespace kiwi // CLASSIC VIEW // // ================================================================================ // - ClassicView::ClassicView(model::Object& object_model) : + ClassicView::ClassicView(model::Object & object_model) : ObjectView(object_model), m_text(object_model.getText()), m_editor(nullptr), m_indent(4), - m_border(1.5), m_listeners(), m_deleted(false) { @@ -117,15 +116,7 @@ namespace kiwi { g.setColour (findColour (ObjectView::ColourIds::Outline)); - int x = getLocalBounds().getX(); - int y = getLocalBounds().getY(); - int height = getHeight(); - int width = getWidth(); - - g.fillRect(x, y, width, m_border.getTop()); - g.fillRect(x, y, m_border.getLeft(), height); - g.fillRect(x, y + height - m_border.getBottom(), width, m_border.getBottom()); - g.fillRect(x + width - m_border.getRight(), y, m_border.getRight(), height); + drawOutline(g); } juce::Rectangle ClassicView::getTextArea() const diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.h index 9e81c5f9..272509bc 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.h @@ -55,7 +55,7 @@ namespace kiwi public: // methods //! @brief Constructor. - ClassicView(model::Object& object_model); + ClassicView(model::Object & object_model); //! @brief Destructor. ~ClassicView(); @@ -109,7 +109,6 @@ namespace kiwi std::string m_text; std::unique_ptr m_editor; size_t m_indent; - juce::BorderSize m_border; engine::Listeners m_listeners; bool m_deleted; diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_BangView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_BangView.cpp index 7c9eb547..8e1aa77d 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_BangView.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_BangView.cpp @@ -32,7 +32,6 @@ namespace kiwi { BangView::BangView(model::Object & model): ObjectView(model), - m_border(1.5), m_signal(model.getSignal<>(model::Bang::Signal::TriggerBang)), m_connection(m_signal.connect(std::bind(&BangView::signalTriggered, this))), m_active(false), @@ -49,19 +48,12 @@ namespace kiwi void BangView::paint(juce::Graphics & g) { g.fillAll(findColour(ObjectView::ColourIds::Background)); + g.setColour(findColour(ObjectView::ColourIds::Outline)); g.drawEllipse(getLocalBounds().reduced(3.1).toFloat(), 2); - int x = getLocalBounds().getX(); - int y = getLocalBounds().getY(); - int height = getHeight(); - int width = getWidth(); - - g.fillRect(x, y, width, m_border.getTop()); - g.fillRect(x, y, m_border.getLeft(), height); - g.fillRect(x, y + height - m_border.getBottom(), width, m_border.getBottom()); - g.fillRect(x + width - m_border.getRight(), y, m_border.getRight(), height); + drawOutline(g); if (m_mouse_down || m_active) { diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_BangView.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_BangView.h index 5b866c3e..d6896c21 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_BangView.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_BangView.h @@ -72,7 +72,6 @@ namespace kiwi private: // members //! @todo Put border into ObjectView. - juce::BorderSize m_border; flip::Signal<>& m_signal; flip::SignalConnection m_connection; bool m_active; diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_ToggleView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_ToggleView.cpp new file mode 100644 index 00000000..0a44f7a0 --- /dev/null +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_ToggleView.cpp @@ -0,0 +1,151 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +#include + +#include + +#include + +namespace kiwi +{ + // ================================================================================ // + // TOGGLE VIEW // + // ================================================================================ // + + class ToggleView::Task final : public engine::Scheduler<>::Task + { + public: // methods + + Task(ToggleView & object, model::Toggle::Request request): + engine::Scheduler<>::Task(), + m_object(object), + m_request(request) + { + } + + ~Task() + { + } + + void execute() + { + switch(m_request) + { + case model::Toggle::Request::Switch: + { + m_object.m_is_on = !m_object.m_is_on; + break; + } + case model::Toggle::Request::SwitchOn: + { + m_object.m_is_on = true; + break; + } + case model::Toggle::Request::SwitchOff: + { + m_object.m_is_on = false; + break; + } + } + + m_object.repaint(); + + std::shared_ptr task; + m_object.m_tasks.pop(task); + } + + private: // members + + ToggleView & m_object; + model::Toggle::Request m_request; + }; + + ToggleView::ToggleView(model::Object & model): + ObjectView(model), + m_signal(model.getSignal(model::Toggle::Signal::Switch)), + m_connection(m_signal.connect(std::bind(&ToggleView::toggleSwitched, + this, + std::placeholders::_1, + std::placeholders::_2))), + m_is_on(false), + m_tasks(10) + { + } + + ToggleView::~ToggleView() + { + while(m_tasks.load_size() > 0) + { + std::shared_ptr task; + m_tasks.pop(task); + KiwiApp::useInstance().useScheduler().unschedule(task); + } + } + + void ToggleView::mouseDown(juce::MouseEvent const& e) + { + m_signal(model::Toggle::Request::Switch, true); + } + + void ToggleView::toggleSwitched(model::Toggle::Request request, bool shall_request) + { + std::shared_ptr task(new Task(*this, request)); + m_tasks.push(task); + KiwiApp::useInstance().useScheduler().schedule(task); + } + + void ToggleView::paint(juce::Graphics & g) + { + g.fillAll(findColour(ObjectView::ColourIds::Background)); + + g.setColour(findColour(ObjectView::ColourIds::Outline)); + + drawOutline(g); + + if (m_is_on) + { + g.setColour(findColour(ObjectView::ColourIds::Active)); + } + + juce::Rectangle bounds = getLocalBounds(); + + double cross_stroke_width = 10. * (bounds.getWidth() / 100.); + + juce::Rectangle inner_bounds = bounds.reduced(30. * bounds.getWidth() / 100., + 30. * bounds.getHeight() / 100.); + + g.drawLine(inner_bounds.getBottomLeft().getX(), + inner_bounds.getBottomLeft().getY(), + inner_bounds.getTopRight().getX(), + inner_bounds.getTopRight().getY(), + cross_stroke_width); + + g.drawLine(inner_bounds.getTopLeft().getX(), + inner_bounds.getTopLeft().getY(), + inner_bounds.getBottomRight().getX(), + inner_bounds.getBottomRight().getY(), + cross_stroke_width); + } +} diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_ToggleView.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_ToggleView.h new file mode 100644 index 00000000..8db6c717 --- /dev/null +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_ToggleView.h @@ -0,0 +1,84 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include +#include + +#include + +#include +#include + +#include +#include + +#include + +namespace kiwi +{ + // ================================================================================ // + // TOGGLE VIEW // + // ================================================================================ // + + class ToggleView : public ObjectView + { + private: // classes + + class Task; + + public: // methods + + //! @brief Constructor. + ToggleView(model::Object & object_model); + + //! @brief Destructor. + ~ToggleView(); + + private: // methods + + //! @brief The graphical rendering method. + void paint(juce::Graphics & g) override final; + + //! @brief Called when the bang is clicked. + void mouseDown(juce::MouseEvent const& e) override final; + + //! @brief Called whenever the toggle is switched on or off. + //! @details Can ba called on the engine thread or the gui thread. + void toggleSwitched(model::Toggle::Request request, bool shall_ouptut); + + private: // members + + flip::Signal & m_signal; + flip::SignalConnection m_connection; + bool m_is_on; + engine::ConcurrentQueue> m_tasks; + + private: // deleted methods + + ToggleView() = delete; + ToggleView(ToggleView const& other) = delete; + ToggleView(ToggleView && other) = delete; + ToggleView& operator=(ToggleView const& other) = delete; + ToggleView& operator=(ToggleView && other) = delete; + }; +} diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectView.cpp index 4207ce4e..21bbe4aa 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectView.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectView.cpp @@ -31,7 +31,8 @@ namespace kiwi // ================================================================================ // ObjectView::ObjectView(model::Object & object_model): - m_model(object_model) + m_model(object_model), + m_border_size(1.5) { setColour(ObjectView::ColourIds::Error, juce::Colour::fromFloatRGBA(0.6, 0.1, 0.1, 0.)); setColour(ObjectView::ColourIds::Background, juce::Colours::white); @@ -49,4 +50,16 @@ namespace kiwi { return m_model; } + + juce::Rectangle ObjectView::getOutline() const + { + return getLocalBounds(); + } + + void ObjectView::drawOutline(juce::Graphics & g) + { + juce::Rectangle outline = getOutline(); + + g.drawRect(getOutline(), m_border_size); + } } diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectView.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectView.h index a5d9ba8d..217c381b 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectView.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectView.h @@ -59,9 +59,22 @@ namespace kiwi //! @brief Returns the model represented by the graphical object. model::Object& getModel() const; + protected: // methods + + //! @brief Draws the outlines of the object. + void drawOutline(juce::Graphics & g); + + private: // methods + + //! @brief Override this function if you want it to have a customied outline. + //! @details Used to draw the object's outline. Returns the object's bounds by default. + //! @todo May make it return path instead. + virtual juce::Rectangle getOutline() const; + private: // members model::Object& m_model; + int m_border_size; private: // deleted methods diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Objects.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Objects.h index b2f7ed04..74158797 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Objects.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Objects.h @@ -32,3 +32,4 @@ // ================================================================================ // #include +#include diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp index da0363d1..f97a3f8c 100755 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp @@ -2256,6 +2256,7 @@ namespace kiwi commands.add(CommandIDs::newBox); commands.add(CommandIDs::newBang); + commands.add(CommandIDs::newToggle); commands.add(CommandIDs::zoomIn); commands.add(CommandIDs::zoomOut); @@ -2386,6 +2387,13 @@ namespace kiwi result.setActive(!isLocked()); break; } + case CommandIDs::newToggle: + { + result.setInfo(TRANS("New Toggle Box"), TRANS("Add a new toggle"), CommandCategories::editing, 0); + result.addDefaultKeypress('t', juce::ModifierKeys::noModifiers); + result.setActive(!isLocked()); + break; + } case CommandIDs::zoomIn: { result.setInfo(TRANS("Zoom in"), TRANS("Zoom in"), CommandCategories::view, 0); @@ -2455,6 +2463,7 @@ namespace kiwi case CommandIDs::newBox: { createObjectModel("", true); break; } case CommandIDs::newBang: { createObjectModel("bang", true); break; } + case CommandIDs::newToggle: { createObjectModel("toggle", true); break; } case CommandIDs::zoomIn: { zoomIn(); break; } case CommandIDs::zoomOut: { zoomOut(); break; } diff --git a/Modules/KiwiEngine/KiwiEngine_Instance.cpp b/Modules/KiwiEngine/KiwiEngine_Instance.cpp index feed44ec..2e2e8287 100644 --- a/Modules/KiwiEngine/KiwiEngine_Instance.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Instance.cpp @@ -100,6 +100,7 @@ namespace kiwi engine::Factory::add("sig~"); engine::Factory::add("delaysimple~"); engine::Factory::add("bang"); + engine::Factory::add("toggle"); } // ================================================================================ // diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Toggle.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Toggle.cpp new file mode 100644 index 00000000..1140f314 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Toggle.cpp @@ -0,0 +1,165 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include + +#include + +namespace kiwi +{ + namespace engine + { + // ================================================================================ // + // OBJECT BANG // + // ================================================================================ // + + class Toggle::Task final : public Scheduler<>::Task + { + public: // methods + + Task(Toggle & object, model::Toggle::Request request, bool shall_output): + Scheduler<>::Task(), + m_object(object), + m_request(request), + m_shall_output(shall_output) + { + } + + ~Task() + { + } + + void execute() + { + switch(m_request) + { + case model::Toggle::Request::Switch: + { + m_object.m_is_on = !m_object.m_is_on; + break; + } + case model::Toggle::Request::SwitchOn: + { + m_object.m_is_on = true; + break; + } + case model::Toggle::Request::SwitchOff: + { + m_object.m_is_on = false; + break; + } + } + + if (m_shall_output) + { + if (m_object.m_is_on) + { + m_object.send(0, {1}); + } + else + { + m_object.send(0, {0}); + } + } + + std::shared_ptr task; + m_object.m_tasks.pop(task); + } + + private: // members + + Toggle& m_object; + model::Toggle::Request m_request; + bool m_shall_output; + }; + + Toggle::Toggle(model::Object const& model, Patcher& patcher, std::vector const& args): + Object(model, patcher), + m_signal(model.getSignal(model::Toggle::Signal::Switch)), + m_connection(m_signal.connect(std::bind(&Toggle::toggleSwitched, + this, + std::placeholders::_1, + std::placeholders::_2))), + m_is_on(false), + m_tasks(20) + { + } + + Toggle::~Toggle() + { + while(m_tasks.load_size() > 0) + { + std::shared_ptr task; + m_tasks.pop(task); + getScheduler().unschedule(task); + } + } + + void Toggle::toggleSwitched(model::Toggle::Request request, bool shall_output) + { + std::shared_ptr task(new Task(*this, request, shall_output)); + m_tasks.push(task); + getScheduler().schedule(task); + } + + void Toggle::receive(size_t index, std::vector const& args) + { + if (!args.empty()) + { + if (index == 0) + { + if(args[0].isString()) + { + if (args[0].getString() == "bang") + { + m_signal(model::Toggle::Request::Switch, true); + } + else if(args.size() == 2 && args[0].getString() == "set" && args[1].isNumber()) + { + if (args[1].getFloat() != 0) + { + m_signal(model::Toggle::Request::SwitchOn, false); + } + else + { + m_signal(model::Toggle::Request::SwitchOff, false); + } + } + } + else if(args[0].isNumber()) + { + if (args[0].getFloat() != 0) + { + m_signal(model::Toggle::Request::SwitchOn, true); + } + else + { + m_signal(model::Toggle::Request::SwitchOff, true); + } + } + } + } + } + } +} + diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Toggle.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Toggle.h new file mode 100644 index 00000000..81567bf6 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Toggle.h @@ -0,0 +1,70 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include +#include + +#include + +#include + +#include +#include + +#include + +namespace kiwi +{ + namespace engine + { + // ================================================================================ // + // OBJECT TOGGLE // + // ================================================================================ // + + class Toggle : public engine::Object + { + private: // classes + + class Task; + + public: // methods + + Toggle(model::Object const& model, Patcher& patcher, std::vector const& args); + + ~Toggle(); + + void receive(size_t index, std::vector const& args) override final; + + private: // methods + + void toggleSwitched(model::Toggle::Request request, bool shall_output); + + private: // members + + flip::Signal & m_signal; + flip::SignalConnection m_connection; + bool m_is_on; + engine::ConcurrentQueue> m_tasks; + }; + } +} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h index 012b0fcb..5c03ee95 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h @@ -68,3 +68,4 @@ // ================================================================================ // #include +#include diff --git a/Modules/KiwiModel/KiwiModel_DataModel.cpp b/Modules/KiwiModel/KiwiModel_DataModel.cpp index b4663f62..2410c6c7 100644 --- a/Modules/KiwiModel/KiwiModel_DataModel.cpp +++ b/Modules/KiwiModel/KiwiModel_DataModel.cpp @@ -79,6 +79,7 @@ namespace kiwi SigTilde::declare(); DelaySimpleTilde::declare(); Bang::declare(); + Toggle::declare(); } } } diff --git a/Modules/KiwiModel/KiwiModel_Object.cpp b/Modules/KiwiModel/KiwiModel_Object.cpp index 72246504..44c660a1 100755 --- a/Modules/KiwiModel/KiwiModel_Object.cpp +++ b/Modules/KiwiModel/KiwiModel_Object.cpp @@ -161,6 +161,7 @@ namespace kiwi m_name("noobj"), m_inlets(), m_outlets(), + m_flags(), m_position_x(0.), m_position_y(0.), m_width(60.), diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Toggle.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Toggle.cpp new file mode 100755 index 00000000..dab1ffb6 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Toggle.cpp @@ -0,0 +1,77 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include + +namespace kiwi +{ + namespace model + { + // ================================================================================ // + // OBJECT TOGGLE // + // ================================================================================ // + + Toggle::Toggle(std::string const& name, std::vector const& args): + Object() + { + if (!args.empty()) + { + throw std::runtime_error("wrong arguments for object bang"); + } + + setFlag(Flag::DefinedSize); + addSignal(Signal::Switch, *this); + setWidth(20); + setHeight(20); + pushInlet({PinType::IType::Control}); + pushOutlet(PinType::IType::Control); + } + + Toggle::Toggle(flip::Default& d): + Object(d) + { + addSignal(Signal::Switch, *this); + } + + void Toggle::declare() + { + Factory::add("toggle"); + } + + std::string Toggle::getIODescription(bool is_inlet, size_t index) const + { + if (is_inlet && index == 0) + { + return "Switches the toggle on or of"; + } + else if(!is_inlet && index == 0) + { + return "Sends 0 or 1 when toggle is switched on or off"; + } + else + { + return ""; + } + } + } +} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Toggle.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Toggle.h new file mode 100755 index 00000000..ecc7fb80 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Toggle.h @@ -0,0 +1,62 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi +{ + namespace model + { + // ================================================================================ // + // OBJECT TOGGLE // + // ================================================================================ // + + + class Toggle : public model::Object + { + public: // enum + + enum Signal : SignalKey + { + Switch + }; + + enum class Request + { + Switch, // Switch state. + SwitchOn, // Explicitly switch on. + SwitchOff // Explicitly switch off. + }; + + public: // methods + + Toggle(flip::Default& d); + + Toggle(std::string const& name, std::vector const& args); + + std::string getIODescription(bool is_inlet, size_t index) const override; + + static void declare(); + }; + } +} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h index fc41970b..c2e118b5 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h @@ -68,4 +68,5 @@ // ================================================================================ // #include +#include From 575aee1a28a64bd52586e8fb396ed70cdeae7f88 Mon Sep 17 00:00:00 2001 From: jean-millot Date: Wed, 13 Sep 2017 11:58:37 +0200 Subject: [PATCH 045/148] Implement textual object's view as a juce label. --- .../KiwiApp_Basic/KiwiApp_ClassicView.cpp | 171 ++++++++---------- .../KiwiApp_Basic/KiwiApp_ClassicView.h | 61 ++++--- .../KiwiApp_Objects/KiwiApp_ObjectFrame.cpp | 16 +- .../KiwiApp_Objects/KiwiApp_ObjectFrame.h | 8 +- .../KiwiApp_Patcher/KiwiApp_PatcherView.cpp | 92 +++++----- .../KiwiApp_Patcher/KiwiApp_PatcherView.h | 12 +- 6 files changed, 186 insertions(+), 174 deletions(-) diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.cpp index 33592cf2..8e71530d 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.cpp @@ -23,6 +23,8 @@ #include +#include + namespace kiwi { // ================================================================================ // @@ -31,22 +33,24 @@ namespace kiwi ClassicView::ClassicView(model::Object & object_model) : ObjectView(object_model), - m_text(object_model.getText()), - m_editor(nullptr), - m_indent(4), - m_listeners(), - m_deleted(false) + m_label(*this, object_model.getText()), + m_listeners() { - if(object_model.getName() == "errorbox") - { - setColour(ObjectView::ColourIds::Background, findColour(ObjectView::ColourIds::Error).withAlpha(0.4f)); - } + juce::Colour bg_colour = object_model.getName() == "errorbox" ? + findColour(ObjectView::ColourIds::Error).withAlpha(0.4f) : + findColour(ObjectView::ColourIds::Background); + + + m_label.setColour(juce::Label::backgroundColourId, bg_colour); + m_label.setColour(juce::Label::backgroundWhenEditingColourId, bg_colour); + m_label.setColour(juce::Label::textColourId, findColour(ObjectView::ColourIds::Text)); + m_label.setColour(juce::Label::textWhenEditingColourId, findColour(ObjectView::ColourIds::Text)); + + addAndMakeVisible(m_label); } ClassicView::~ClassicView() { - removeTextEditor(); - m_deleted = true; } void ClassicView::addListener(Listener& listener) @@ -61,55 +65,7 @@ namespace kiwi void ClassicView::edit() { - if(hasKeyboardFocus(true)) return; // abort - - m_editor.reset(new SuggestEditor(model::Factory::getNames())); - - m_editor->setBounds(getLocalBounds()); - m_editor->setIndents(m_indent, m_indent); - m_editor->setBorder(juce::BorderSize(0)); - - m_editor->setColour(juce::TextEditor::ColourIds::textColourId, - findColour(ObjectView::ColourIds::Text)); - - m_editor->setColour(juce::TextEditor::backgroundColourId, - findColour(ObjectView::ColourIds::Background)); - - m_editor->setColour(juce::TextEditor::highlightColourId, - findColour(ObjectView::ColourIds::Highlight).withAlpha(0.4f)); - - m_editor->setColour(juce::TextEditor::highlightColourId, - findColour(ObjectView::ColourIds::Highlight).withAlpha(0.4f)); - - m_editor->setColour(juce::TextEditor::outlineColourId, - juce::Colours::transparentWhite); - - m_editor->setColour(juce::TextEditor::focusedOutlineColourId, - juce::Colours::transparentWhite); - - m_editor->setScrollbarsShown(false); - m_editor->setScrollToShowCursor(true); - m_editor->setReturnKeyStartsNewLine(false); - m_editor->setMultiLine(true, false); - - m_editor->setText(m_text, juce::dontSendNotification); - m_editor->setHighlightedRegion({0, static_cast(m_text.length())}); - m_editor->setCaretVisible(m_text.empty()); - - m_editor->addListener(this); - addAndMakeVisible(*m_editor); - - m_editor->grabKeyboardFocus(); - } - - void ClassicView::removeTextEditor() - { - if(m_editor != nullptr) - { - m_editor->removeListener(this); - removeChildComponent(m_editor.get()); - m_editor.reset(); - } + m_label.showEditor(); } void ClassicView::paintOverChildren (juce::Graphics& g) @@ -119,34 +75,14 @@ namespace kiwi drawOutline(g); } - juce::Rectangle ClassicView::getTextArea() const - { - return getLocalBounds().reduced(m_indent); - } - - void ClassicView::paint(juce::Graphics& g) - { - g.fillAll (findColour (ObjectView::ColourIds::Background)); - - if (!isEditing()) - { - g.setColour (findColour (ObjectView::ColourIds::Text)); - - g.drawText(m_text, getTextArea(), juce::Justification::centredLeft); - } - } - void ClassicView::resized() { - if (m_editor) - { - m_editor->setBounds(getLocalBounds()); - } + m_label.setBounds(getLocalBounds()); } bool ClassicView::isEditing() const { - return m_editor != nullptr; + return m_label.isBeingEdited(); } void ClassicView::textEditorTextChanged(juce::TextEditor& editor) @@ -159,29 +95,68 @@ namespace kiwi } } - void ClassicView::textEdited(juce::TextEditor& editor) + void ClassicView::labelTextChanged (juce::Label* labelThatHasChanged) { - assert(&editor == m_editor.get()); - - m_listeners.call(&Listener::textEdited, m_text); - - if (!m_deleted) - { - removeTextEditor(); - } + m_listeners.call(&ClassicView::Listener::textChanged, m_label.getText().toStdString()); } - void ClassicView::textEditorReturnKeyPressed(juce::TextEditor& editor) + void ClassicView::editorHidden (juce::Label* label, juce::TextEditor& text_editor) { - m_text = editor.getText().toStdString(); - - textEdited(editor); + m_listeners.call(&ClassicView::Listener::editorHidden); + } + + void ClassicView::editorShown (juce::Label* label, juce::TextEditor& text_editor) + { + m_listeners.call(&ClassicView::Listener::editorShown); + } + + // ================================================================================ // + // LABEL // + // ================================================================================ // + + ClassicView::Label::Label(ClassicView & classic_view, std::string const& label): + juce::Label("object name", label), + m_classic_view(classic_view) + { + addListener(&classic_view); + } + + ClassicView::Label::~Label() + { + removeListener(&m_classic_view); } - void ClassicView::textEditorFocusLost(juce::TextEditor& editor) + juce::TextEditor* ClassicView::Label::createEditorComponent() { - m_text = editor.getText().toStdString(); + juce::TextEditor * editor = new SuggestEditor(model::Factory::getNames()); + + editor->setBounds(getLocalBounds()); + editor->setBorder(juce::BorderSize(0)); + + + editor->setColour(juce::TextEditor::ColourIds::textColourId, + findColour(juce::Label::textWhenEditingColourId)); + + editor->setColour(juce::TextEditor::backgroundColourId, + findColour(juce::Label::backgroundWhenEditingColourId)); + + editor->setColour(juce::TextEditor::highlightColourId, + findColour(ObjectView::ColourIds::Highlight, true).withAlpha(0.4f)); + + + editor->setColour(juce::TextEditor::outlineColourId, + juce::Colours::transparentWhite); + + editor->setColour(juce::TextEditor::focusedOutlineColourId, + juce::Colours::transparentWhite); + + editor->setScrollbarsShown(false); + editor->setScrollToShowCursor(true); + editor->setReturnKeyStartsNewLine(false); + editor->setMultiLine(true, false); + + editor->addListener(&m_classic_view); - textEdited(editor); + return editor; } } diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.h index 272509bc..05002c61 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.h @@ -30,7 +30,6 @@ #include #include -#include namespace kiwi { @@ -39,17 +38,43 @@ namespace kiwi // ================================================================================ // //! @brief The view of any textual kiwi object. - class ClassicView : public ObjectView, public juce::TextEditor::Listener + class ClassicView : public ObjectView, + public juce::TextEditor::Listener, + public juce::Label::Listener { public: // classes + class Label : public juce::Label + { + public: // methods + + //! @brief Constructor. + Label(ClassicView & classic_view, std::string const& label); + + //! @brief Destructor. + ~Label(); + + //! @brief Called to create the text editor once edit is called. + juce::TextEditor* createEditorComponent() override final; + + private: // members + + ClassicView & m_classic_view; + }; + struct Listener { //! @brief Destructor. virtual ~Listener() = default; //! @brief Called when the text has been edited and return key was pressed. - virtual void textEdited(std::string const& new_text) = 0; + virtual void textChanged(std::string const& new_text) = 0; + + //! @brief Called when the classic view ends its edition. + virtual void editorHidden() = 0; + + //! @brief Called when the classic view enters its edition mode. + virtual void editorShown() = 0; }; public: // methods @@ -74,9 +99,6 @@ namespace kiwi private: // methods - //! @brief The component's graphical rendering method. - void paint(juce::Graphics& g) override final; - //! @brief Called when the object is resized. void resized() override final; @@ -84,33 +106,22 @@ namespace kiwi //! @details Used to resize in order to keep text visible. void textEditorTextChanged(juce::TextEditor& editor) override final; - //! @brief Called when return key is pressed. - //! @brief Exits edit mode keeping edited text as is. - void textEditorReturnKeyPressed(juce::TextEditor& editor) override final; - - //! @brief Called when the editor has lost focus. - //! @brief Exits edit mode keeping edited text as is. - void textEditorFocusLost(juce::TextEditor& editor) override final; - - //! @brief Returns the text area. - juce::Rectangle getTextArea() const; - //! @brief Paints elements over the text editor. void paintOverChildren (juce::Graphics& g) override final; - //! @brief Called when the classic's view text has been edited. - void textEdited(juce::TextEditor& editor); + //! @brief Called when the label text has changed. + void labelTextChanged (juce::Label* label) override final; + + //! @brief Called when edition ends. + void editorHidden (juce::Label* label, juce::TextEditor& text_editor) override final; - ///! @brief Calls this to end edition and supress the text editor. - void removeTextEditor(); + //! @brief Called when edition begins. + void editorShown(juce::Label* label, juce::TextEditor& text_editor) override final; private: // members - std::string m_text; - std::unique_ptr m_editor; - size_t m_indent; + Label m_label; engine::Listeners m_listeners; - bool m_deleted; private: // deleted methods diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.cpp index 6558a38e..65817aa1 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.cpp @@ -339,13 +339,25 @@ namespace kiwi } } - void ObjectFrame::textEdited(std::string const& new_text) + void ObjectFrame::textChanged(std::string const& new_text) { dynamic_cast(m_object_view.get())->removeListener(*this); + getPatcherView().objectTextChanged(*this, new_text); + } + + void ObjectFrame::editorHidden() + { setInterceptsMouseClicks(isLocked(), isLocked()); - getPatcherView().objectEdited(*this, new_text); + getPatcherView().objectEditorHidden(*this); + } + + void ObjectFrame::editorShown() + { + setInterceptsMouseClicks(true, true); + + getPatcherView().objectEditorShown(*this); } void ObjectFrame::editObject() diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.h index e53fd486..c45a459c 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.h @@ -125,7 +125,13 @@ namespace kiwi void resized() override final; //! @brief Called once a ClassicView's text has changed. - void textEdited(std::string const& new_text) override final; + void textChanged(std::string const& new_text) override final; + + //! @brief Called when the classic view ends its edition. + void editorHidden() override final; + + //! @brief Called when the classic view enters its edition mode. + void editorShown() override final; //! @brief Initializes all colours with default values. //! @todo Set colours in look and feel instead. diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp index f97a3f8c..9af36ca5 100755 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp @@ -1933,12 +1933,7 @@ namespace kiwi bool PatcherView::isEditingObject() const { - auto func = [](std::unique_ptr const& object) - { - return object->isEditing(); - }; - - return std::find_if(m_objects.begin(), m_objects.end(), func) != m_objects.end(); + return m_box_being_edited != nullptr; } void PatcherView::editObject(ObjectFrame & object_frame) @@ -1946,57 +1941,62 @@ namespace kiwi assert(!isEditingObject() && "Editing two objects simultaneously"); object_frame.editObject(); + } + + void PatcherView::objectEditorShown(ObjectFrame const& object_frame) + { + m_box_being_edited = &object_frame; - KiwiApp::commandStatusChanged(); // to disable some command while editing... + KiwiApp::commandStatusChanged(); } - void PatcherView::objectEdited(ObjectFrame const& object_frame, std::string const& new_text) + void PatcherView::objectEditorHidden(ObjectFrame const& object_frame) { - assert(isEditingObject() && "Calling object edited without editing object first"); + assert(m_box_being_edited == &object_frame && "Calling object editor shown outside text edition"); - grabKeyboardFocus(); + m_box_being_edited = nullptr; + KiwiApp::commandStatusChanged(); + } + + void PatcherView::objectTextChanged(ObjectFrame const& object_frame, std::string const& new_text) + { model::Object & old_model = object_frame.getModel(); - if(new_text != old_model.getText()) + std::vector atoms = AtomHelper::parse(new_text); + + std::unique_ptr object_model = model::Factory::create(atoms); + + juce::Point origin = getOriginPosition(); + juce::Rectangle box_bounds = object_frame.getObjectBounds(); + + object_model->setPosition(box_bounds.getX() - origin.x, box_bounds.getY() - origin.y); + + if (!object_model->hasFlag(model::Object::Flag::DefinedSize)) { - std::vector atoms = AtomHelper::parse(new_text); - - std::unique_ptr object_model = model::Factory::create(atoms); - - juce::Point origin = getOriginPosition(); - juce::Rectangle box_bounds = object_frame.getObjectBounds(); - - object_model->setPosition(box_bounds.getX() - origin.x, box_bounds.getY() - origin.y); - - if (!object_model->hasFlag(model::Object::Flag::DefinedSize)) - { - object_model->setWidth(juce::Font().getStringWidth(new_text) + 12); - object_model->setHeight(box_bounds.getHeight()); - } - - // handle error box case - if(object_model->getName() == "errorbox") - { - model::ErrorBox& error_box = dynamic_cast(*object_model); - error_box.setInlets(old_model.getInlets()); - error_box.setOutlets(old_model.getOutlets()); - KiwiApp::error(error_box.getError()); - } - - model::Object & new_object = m_patcher_model.replaceObject(old_model, std::move(object_model)); - - m_view_model.unselectObject(old_model); - - if(!isLocked()) - { - m_view_model.selectObject(new_object); - } - - DocumentManager::commit(m_patcher_model, "Edit Object"); + object_model->setWidth(juce::Font().getStringWidth(new_text) + 12); + object_model->setHeight(box_bounds.getHeight()); } - KiwiApp::commandStatusChanged(); + // handle error box case + if(object_model->getName() == "errorbox") + { + model::ErrorBox& error_box = dynamic_cast(*object_model); + error_box.setInlets(old_model.getInlets()); + error_box.setOutlets(old_model.getOutlets()); + KiwiApp::error(error_box.getError()); + } + + model::Object & new_object = m_patcher_model.replaceObject(old_model, std::move(object_model)); + + m_view_model.unselectObject(old_model); + + if(!isLocked()) + { + m_view_model.selectObject(new_object); + } + + DocumentManager::commit(m_patcher_model, "Edit Object"); } void PatcherView::createObjectModel(std::string const& text, bool give_focus) diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.h b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.h index 27e8b261..1ece97bf 100755 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.h @@ -110,8 +110,14 @@ namespace kiwi //! @details Will result in objectEdited being called in case of success. void editObject(ObjectFrame & object_frame); - //! @brief Called once an object has been edited. - void objectEdited(ObjectFrame const& object_frame, std::string const& new_text); + //! @brief Called when the object has entered edition mode. + void objectEditorShown(ObjectFrame const& object_frame); + + //! @brief Called once an object's text has changed. + void objectTextChanged(ObjectFrame const& object_frame, std::string const& new_text); + + //! @brief Called when the object is quitting edition mode. + void objectEditorHidden(ObjectFrame const& object_frame); //! @brief Returns true if an object if being edited. bool isEditingObject() const; @@ -394,6 +400,8 @@ namespace kiwi Lasso m_lasso; std::unique_ptr m_link_creator; + ObjectFrame const* m_box_being_edited = nullptr; + bool m_is_locked; int m_grid_size; From ea893effafc3afbc88c4a26ec66188c211afa2e5 Mon Sep 17 00:00:00 2001 From: jmillot Date: Fri, 15 Sep 2017 10:32:04 +0200 Subject: [PATCH 046/148] Fix defer scheduler tests. --- Test/Engine/test_Scheduler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Test/Engine/test_Scheduler.cpp b/Test/Engine/test_Scheduler.cpp index dfb344bc..31547c76 100644 --- a/Test/Engine/test_Scheduler.cpp +++ b/Test/Engine/test_Scheduler.cpp @@ -494,7 +494,7 @@ TEST_CASE("Scheduler", "[Scheduler]") sch.defer(std::move(task)); - while(exec_thread == consumer.get_id()){} + while(exec_thread != consumer.get_id()){} CHECK(task.use_count() == 0); CHECK(exec_thread == consumer.get_id()); From bfea07b4166ab674582a6e345c43e79d67fd0f48 Mon Sep 17 00:00:00 2001 From: eliott PARIS Date: Fri, 15 Sep 2017 15:58:59 +0200 Subject: [PATCH 047/148] scheduler tests cleaning --- Test/Engine/test_Scheduler.cpp | 573 ++++++++++++++++----------------- 1 file changed, 280 insertions(+), 293 deletions(-) diff --git a/Test/Engine/test_Scheduler.cpp b/Test/Engine/test_Scheduler.cpp index 31547c76..30f9618d 100644 --- a/Test/Engine/test_Scheduler.cpp +++ b/Test/Engine/test_Scheduler.cpp @@ -31,52 +31,31 @@ #include using namespace kiwi; - using Scheduler = engine::Scheduler; - -using Task = engine::Scheduler<>::Task; - -using CallBack = engine::Scheduler<>::CallBack; - -static std::chrono::high_resolution_clock::time_point current_time = std::chrono::high_resolution_clock::now(); - -struct TickClock -{ - typedef std::chrono::high_resolution_clock::duration duration; - typedef duration::rep rep; - typedef duration::period period; - typedef std::chrono::time_point time_point; - static const bool is_steady = true; - - static void start() {current_time = std::chrono::high_resolution_clock::now();} - - static void tick(){current_time += std::chrono::milliseconds(1);}; - - static time_point now(){return current_time;}; -}; - +using Task = Scheduler::Task; +using CallBack = Scheduler::CallBack; // ==================================================================================== // -// SCHEDULER // +// SCHEDULER // // ==================================================================================== // -TEST_CASE("Scheduler", "[Scheduler]") +TEST_CASE("Scheduler - mono thread", "[Scheduler]") { Scheduler sch; SECTION("Simple add and process") - { + { int counter = 0; - std::function func = [&counter](){++counter;}; + std::function func = [&counter]() { ++counter; }; for(int i = 0 ; i < 10; ++i) { - sch.schedule(std::shared_ptr(new CallBack(func)), - std::chrono::milliseconds(10 * i)); + sch.schedule(std::make_shared(func), + std::chrono::milliseconds(10 * i)); } - while(counter < 10){ sch.process();} + while(counter < 10) { sch.process(); } CHECK(counter == 10); } @@ -121,20 +100,19 @@ TEST_CASE("Scheduler", "[Scheduler]") { struct TestDestructor : public Task { - TestDestructor(int &counter):m_counter(counter){}; - - ~TestDestructor(){++m_counter;}; - - void execute() override final{}; + TestDestructor(int &counter) : m_counter(counter) {} + ~TestDestructor() { ++m_counter; } + void execute() override final {} + private: int& m_counter; }; - + int shared_count = 0; int transfered_count = 0; - std::shared_ptr shared(new TestDestructor(shared_count)); - std::shared_ptr transfered(new TestDestructor(transfered_count)); + auto shared = std::make_shared(shared_count); + auto transfered = std::make_shared(transfered_count); sch.schedule(shared); CHECK(shared.use_count() == 2); @@ -158,9 +136,9 @@ TEST_CASE("Scheduler", "[Scheduler]") std::function func_cancel = [&i_cancel](){++i_cancel;}; std::function func_reschedule = [&i_reschedule](){++i_reschedule;}; - std::shared_ptr standard(new CallBack(func_std)); - std::shared_ptr reschedule(new CallBack(func_reschedule)); - std::shared_ptr cancel(new CallBack(func_cancel)); + auto standard = std::make_shared(func_std); + auto reschedule = std::make_shared(func_reschedule); + auto cancel = std::make_shared(func_cancel); sch.schedule(std::move(standard)); sch.schedule(reschedule); @@ -169,7 +147,7 @@ TEST_CASE("Scheduler", "[Scheduler]") sch.schedule(reschedule, std::chrono::milliseconds(1000 * 60 * 60)); sch.unschedule(cancel); - while(i_standard < 1){sch.process();}; + while(i_standard < 1) { sch.process(); } CHECK(i_standard == 1); CHECK(i_reschedule == 0); @@ -177,88 +155,50 @@ TEST_CASE("Scheduler", "[Scheduler]") sch.schedule(reschedule); - while(i_reschedule < 1){sch.process();}; + while(i_reschedule < 1) { sch.process(); } CHECK(i_reschedule == 1); } +} + + +// ==================================================================================== // +// SCHEDULER - MULTI THREAD // +// ==================================================================================== // + +TEST_CASE("Scheduler - Multithread", "[Scheduler]") +{ + Scheduler sch; - SECTION("Execution order and custom clock") - { - TickClock::start(); - - engine::Scheduler tick_scheduler; - - std::vector order; - - std::function func = [&order](int number){order.push_back(number);}; - - std::shared_ptr::Task> - task_0(new engine::Scheduler::CallBack(std::bind(func, 0))); - - std::shared_ptr::Task> - task_1(new engine::Scheduler::CallBack(std::bind(func, 1))); - - tick_scheduler.schedule(task_0, std::chrono::milliseconds(1)); - tick_scheduler.schedule(task_1, std::chrono::milliseconds(3)); - - std::shared_ptr::Task> - task_2(new engine::Scheduler::CallBack(std::bind(func, 2))); - - std::shared_ptr::Task> - task_3(new engine::Scheduler::CallBack(std::bind(func, 3))); - - tick_scheduler.schedule(std::move(task_2), std::chrono::milliseconds(2)); - tick_scheduler.schedule(std::move(task_3), std::chrono::milliseconds(2)); - - tick_scheduler.schedule(task_0, std::chrono::milliseconds(3)); - tick_scheduler.unschedule(task_1); - - while(order.size() < 3) - { - TickClock::tick(); - tick_scheduler.process(); - } - - tick_scheduler.unschedule(task_0); - - CHECK(order[0] == 2); - CHECK(order[1] == 3); - CHECK(order[2] == 0); - } - - SECTION("Multithreading multiproducer multiconsumer") + SECTION("multiproducer - multiconsumer") { std::atomic count_producer_1(0); std::atomic count_producer_2(0); - std::function func_1 = [&count_producer_1]() - { + std::function func_1 = [&count_producer_1]() { ++count_producer_1; }; - std::function func_2 = [&count_producer_2]() - { + std::function func_2 = [&count_producer_2]() { ++count_producer_2; }; - std::thread producer_1([&count_producer_1, &sch, &func_1]() - { + std::thread producer_1([&count_producer_1, &sch, &func_1]() { size_t count_event = 0; while(count_event < 30) { - sch.schedule(std::shared_ptr(new CallBack(func_1))); + sch.schedule(std::make_shared(func_1)); ++count_event; } }); - std::thread producer_2([&count_producer_2, &sch, &func_2]() - { + std::thread producer_2([&count_producer_2, &sch, &func_2]() { size_t count_event = 0; while(count_event < 20) { - sch.schedule(std::shared_ptr(new CallBack(func_2))); + sch.schedule(std::make_shared(func_2)); ++count_event; } }); @@ -275,252 +215,299 @@ TEST_CASE("Scheduler", "[Scheduler]") producer_2.join(); } - SECTION("Multithreading execution order") + + SECTION("Execution Order") { std::vector order; + std::function func = [&order](int stamp) {order.push_back(stamp);}; - std::function func = [&order](int stamp){order.push_back(stamp);}; - - // Pushing producer 1 before producer 2 - + SECTION("Pushing producer 1 before producer 2") { - std::thread producer_1([&sch, &func]() - { + std::thread producer_1([&sch, &func]() { sch.schedule(std::make_shared(std::bind(func, 1))); }); - + producer_1.join(); - - std::thread producer_2([&sch, &func]() - { + + std::thread producer_2([&sch, &func]() { sch.schedule(std::make_shared(std::bind(func, 2))); }); - + producer_2.join(); - - while(order.size() < 2) - { - sch.process(); - } - + + while(order.size() < 2) { sch.process(); } + // Check that producer 1's task is executed first. - + CHECK(order[0] == 1); CHECK(order[1] == 2); - } - // Pushgin producer 2 before producer 1 - + SECTION("Pushing producer 2 before producer 1") { - std::thread producer_2([&sch, &func]() - { + std::thread producer_2([&sch, &func]() { sch.schedule(std::make_shared(std::bind(func, 2))); }); producer_2.join(); - std::thread producer_1([&sch, &func]() - { + std::thread producer_1([&sch, &func]() { sch.schedule(std::make_shared(std::bind(func, 1))); }); producer_1.join(); - while(order.size() < 4) - { - sch.process(); - } + while(order.size() < 2) { sch.process(); } // Check that producer 2's task is executed first. - CHECK(order[2] == 2); - CHECK(order[3] == 1); + CHECK(order[0] == 2); + CHECK(order[1] == 1); } + } +} + + +// ==================================================================================== // +// SCHEDULER - OWNERSHIP TRANSFER // +// ==================================================================================== // + +TEST_CASE("Scheduler - Thread ids", "[Scheduler]") +{ + Scheduler sch; + + SECTION("Consumer ownership transfer") + { + REQUIRE(sch.isThisConsumerThread()); - SECTION("Thread ids") - { - CHECK(sch.isThisConsumerThread()); - - // Transfer consumer ownership. + // Transfer consumer ownership. + + std::thread consumer_thread([&sch]() { + sch.setThreadAsConsumer(); + REQUIRE(sch.isThisConsumerThread()); + }); + + consumer_thread.join(); + + CHECK(!sch.isThisConsumerThread()); + } +} + + +// ==================================================================================== // +// SCHEDULER - LOCK // +// ==================================================================================== // + +TEST_CASE("Scheduler - Lock", "[Scheduler]") +{ + Scheduler sch; + + SECTION("Scheduler lock") + { + std::atomic quit_requested(false); + + std::thread consumer([&sch, &quit_requested]() { + sch.setThreadAsConsumer(); - std::thread consumer_thread([&sch]() + while(!quit_requested.load()) { - sch.setThreadAsConsumer(); - CHECK(sch.isThisConsumerThread()); - }); - - consumer_thread.join(); + sch.process(); + } + }); + + { + std::unique_lock lock(sch.lock()); - CHECK(!sch.isThisConsumerThread()); + sch.schedule(std::make_shared([&quit_requested]() { + quit_requested.store(true); + })); - // Transfer back the ownership, to enable further test execution. + std::this_thread::sleep_for(std::chrono::seconds(1)); - sch.setThreadAsConsumer(); + REQUIRE(!quit_requested); } - SECTION("Scheduler lock") + consumer.join(); + + CHECK(quit_requested); + } +} + + +// ==================================================================================== // +// SCHEDULER - DEFERING TASKS // +// ==================================================================================== // + +TEST_CASE("Scheduler - Defering tasks", "[Scheduler]") +{ + Scheduler sch; + + struct DeferTask : public Scheduler::Task + { + DeferTask(std::atomic& thread_id, std::atomic_bool& executed_flag) + : m_thread_id(thread_id) + , m_executed_flag(executed_flag) {} + + void execute() override { - std::atomic quit_requested(false); - - std::thread consumer([&sch, &quit_requested]() - { - sch.setThreadAsConsumer(); - - while(!quit_requested.load()) - { - sch.process(); - } + m_executed_flag.store(true); + m_thread_id.store(std::this_thread::get_id()); + } + + private: + std::atomic& m_thread_id; + std::atomic_bool& m_executed_flag; + }; + + SECTION("Defering task on the same thread execute task directly") + { + std::atomic exec_thread; + std::atomic_bool executed_flag(false); + auto task = std::make_shared(exec_thread, executed_flag); + + REQUIRE(!executed_flag); + + SECTION("task copy") + { + sch.defer(task); + CHECK(task.use_count() == 1); + } + + SECTION("task move") + { + sch.defer(std::move(task)); + CHECK(task.use_count() == 0); + } + + SECTION("task lambda") + { + sch.defer([&exec_thread, &executed_flag]() { + executed_flag.store(true); + exec_thread.store(std::this_thread::get_id()); }); + } + + CHECK(executed_flag); + CHECK(exec_thread == std::this_thread::get_id()); + } + + SECTION("Defering task on another thread schedule the task") + { + std::atomic_bool quit_requested(false); + + std::thread consumer([&sch, &quit_requested]() { + sch.setThreadAsConsumer(); + + while(!quit_requested.load()) { - std::unique_lock lock(sch.lock()); - - std::function func = [&quit_requested]() - { - quit_requested.store(true); - }; - - sch.schedule(std::shared_ptr(new CallBack(func))); - - std::this_thread::sleep_for(std::chrono::seconds(1)); - - CHECK(!quit_requested); + sch.process(); } + }); + + std::atomic exec_thread; + std::atomic_bool executed_flag(false); + auto task = std::make_shared(exec_thread, executed_flag); + + while(sch.isThisConsumerThread()){} + + REQUIRE(!executed_flag); + + SECTION("task copy") + { + sch.defer(task); - consumer.join(); - - CHECK(quit_requested); + while(exec_thread != consumer.get_id()){} - sch.setThreadAsConsumer(); + CHECK(task.use_count() == 1); } - SECTION("defering tasks") + SECTION("task move") { - class DeferTask : public engine::Scheduler<>::Task - { - public: - - DeferTask(std::atomic & thread): - m_thread(thread) - { - } - - void execute() override final - { - m_thread.store(std::this_thread::get_id()); - } - - private: - - std::atomic & m_thread; - - }; + sch.defer(std::move(task)); - { - // copy - { - std::atomic exec_thread; - - std::shared_ptr::Task> task(new DeferTask(exec_thread)); - - sch.defer(task); - - CHECK(task.use_count() == 1); - CHECK(exec_thread == std::this_thread::get_id()); - } - - // move - { - std::atomic exec_thread; - - std::shared_ptr::Task> task(new DeferTask(exec_thread)); - - sch.defer(std::move(task)); - - CHECK(task.use_count() == 0); - CHECK(exec_thread == std::this_thread::get_id()); - } - - // function - { - std::atomic exec_thread; - - std::shared_ptr::Task> task(new DeferTask(exec_thread)); - - sch.defer([&exec_thread]() - { - exec_thread.store(std::this_thread::get_id()); - }); - - CHECK(exec_thread == std::this_thread::get_id()); - } - } + while(exec_thread != consumer.get_id()){} - { - std::atomic quit_requested(false); - - std::thread consumer([&sch, &quit_requested]() - { - sch.setThreadAsConsumer(); - - while(!quit_requested.load()) - { - sch.process(); - } - }); - - while(sch.isThisConsumerThread()){} - - // copy - { - std::atomic exec_thread; - - std::shared_ptr::Task> task(new DeferTask(exec_thread)); - - sch.schedule(task); - - while(exec_thread != consumer.get_id()){} - - CHECK(task.use_count() == 1); - CHECK(exec_thread == consumer.get_id()); - } - - // move - { - std::atomic exec_thread; - - std::shared_ptr::Task> task(new DeferTask(exec_thread)); - - sch.defer(std::move(task)); - - while(exec_thread != consumer.get_id()){} - - CHECK(task.use_count() == 0); - CHECK(exec_thread == consumer.get_id()); - } - - // function - { - std::atomic exec_thread; - - std::shared_ptr::Task> task(new DeferTask(exec_thread)); - - sch.defer([&exec_thread]() - { - exec_thread.store(std::this_thread::get_id()); - }); - - while(exec_thread != consumer.get_id()){} - - CHECK(exec_thread == consumer.get_id()); - } - - quit_requested.store(true); - - consumer.join(); - } + CHECK(task.use_count() == 0); } + + SECTION("task lambda") + { + sch.defer([&exec_thread, &executed_flag]() { + executed_flag.store(true); + exec_thread.store(std::this_thread::get_id()); + }); + + while(exec_thread != consumer.get_id()){} + } + + CHECK(executed_flag); + CHECK(exec_thread == consumer.get_id()); + + quit_requested.store(true); + consumer.join(); } } +// ==================================================================================== // +// SCHEDULER - CUSTOM CLOCK // +// ==================================================================================== // + +struct TickClock +{ + using clock_t = std::chrono::high_resolution_clock; + using duration = clock_t::duration; + using time_point = clock_t::time_point; + + static void start() {current_time = clock_t::now();} + + static void tick() {current_time += std::chrono::milliseconds(1);}; + + static time_point now() {return current_time;}; + +private: + static time_point current_time; +}; + +TickClock::time_point TickClock::current_time = TickClock::clock_t::now(); + +TEST_CASE("Scheduler - custom clock", "[Scheduler]") +{ + using TickScheduler = engine::Scheduler; + + SECTION("Execution order and custom clock") + { + TickClock::start(); + + TickScheduler scheduler; + + std::vector order; + + std::function func = [&order](int number){order.push_back(number);}; + + auto task_0 = std::make_shared(std::bind(func, 0)); + auto task_1 = std::make_shared(std::bind(func, 1)); + auto task_2 = std::make_shared(std::bind(func, 2)); + auto task_3 = std::make_shared(std::bind(func, 3)); + + scheduler.schedule(task_0, std::chrono::milliseconds(1)); + scheduler.schedule(task_1, std::chrono::milliseconds(3)); + scheduler.schedule(std::move(task_2), std::chrono::milliseconds(2)); + scheduler.schedule(std::move(task_3), std::chrono::milliseconds(2)); + + scheduler.schedule(task_0, std::chrono::milliseconds(3)); + scheduler.unschedule(task_1); + + while(order.size() < 3) + { + TickClock::tick(); + scheduler.process(); + } + + scheduler.unschedule(task_0); + + CHECK(order[0] == 2); + CHECK(order[1] == 3); + CHECK(order[2] == 0); + } +} From 2d323a8ffb222ecf021828ddb0f0b6b01e59cd0f Mon Sep 17 00:00:00 2001 From: eliott PARIS Date: Tue, 3 Oct 2017 22:02:43 +0200 Subject: [PATCH 048/148] Fix Api::createDocument method (callback called twice) --- Client/Source/KiwiApp_Network/KiwiApp_Api.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp b/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp index 09c7d0e0..9f2eb7f3 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp +++ b/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp @@ -195,6 +195,7 @@ namespace kiwi { // parse object as a document callback(std::move(res), j); + return; } } } From 2fcfa4671e20631a26c4f4bbe4af1bbd1ad6477d Mon Sep 17 00:00:00 2001 From: eliott PARIS Date: Tue, 3 Oct 2017 23:55:36 +0200 Subject: [PATCH 049/148] The default size of a new typed box also depends on its number of IO. --- .../KiwiApp_Patcher/KiwiApp_PatcherView.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp index 9af36ca5..7c2e2e3f 100755 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp @@ -1972,12 +1972,6 @@ namespace kiwi object_model->setPosition(box_bounds.getX() - origin.x, box_bounds.getY() - origin.y); - if (!object_model->hasFlag(model::Object::Flag::DefinedSize)) - { - object_model->setWidth(juce::Font().getStringWidth(new_text) + 12); - object_model->setHeight(box_bounds.getHeight()); - } - // handle error box case if(object_model->getName() == "errorbox") { @@ -1987,6 +1981,16 @@ namespace kiwi KiwiApp::error(error_box.getError()); } + if (!object_model->hasFlag(model::Object::Flag::DefinedSize)) + { + const int text_width = juce::Font().getStringWidth(new_text) + 12; + const int max_io = std::max(object_model->getNumberOfInlets(), + object_model->getNumberOfOutlets()) * 14; + + object_model->setWidth(std::max(text_width, max_io)); + object_model->setHeight(box_bounds.getHeight()); + } + model::Object & new_object = m_patcher_model.replaceObject(old_model, std::move(object_model)); m_view_model.unselectObject(old_model); From 4cc07fbc01020df5ea60f88bc485ea3b9b355288 Mon Sep 17 00:00:00 2001 From: eliott PARIS Date: Thu, 5 Oct 2017 13:50:07 +0200 Subject: [PATCH 050/148] Remove io highlighter when the patcher is locked --- Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp index 7c2e2e3f..5e629645 100755 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp @@ -1144,6 +1144,7 @@ namespace kiwi if(locked) { m_view_model.unselectAll(); + m_io_highlighter.hide(); grabKeyboardFocus(); } From d2b9a45584d2ac33f025153afeae13803e714b77 Mon Sep 17 00:00:00 2001 From: jean-millot Date: Wed, 4 Oct 2017 17:01:22 +0200 Subject: [PATCH 051/148] Reset distant selection colourId. --- .../KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.cpp index 65817aa1..bad1c7a3 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.cpp @@ -280,7 +280,7 @@ namespace kiwi { setColour(ObjectFrame::ColourIds::Selection, juce::Colour::fromFloatRGBA(0., 0.5, 1., 0.8)); setColour(ObjectFrame::ColourIds::SelectionOtherView, juce::Colour(0xAA9BFF71)); - setColour(ObjectFrame::ColourIds::SelectionDistant, juce::Colour(0xAA9BFF71)); + setColour(ObjectFrame::ColourIds::SelectionDistant, juce::Colour(0xAAFF9B71)); setColour(ObjectFrame::ColourIds::Pin, juce::Colour(0.3, 0.3, 0.3)); } From 5426684cb64b8fe890466ca61be062b64de63323 Mon Sep 17 00:00:00 2001 From: jean-millot Date: Wed, 4 Oct 2017 17:18:23 +0200 Subject: [PATCH 052/148] Remove depecrated comments in patcher view. --- Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp index 5e629645..294a2927 100755 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp @@ -1804,12 +1804,7 @@ namespace kiwi ObjectFrame& object_frame = **(m_objects.emplace(it, new ObjectFrame(*this, std::move(object_view)))); - //jobj.setAlpha(0.); - //addChildComponent(jobj); addAndMakeVisible(object_frame, zorder); - - //juce::ComponentAnimator& animator = juce::Desktop::getInstance().getAnimator(); - //animator.animateComponent(&jobj, jobj.getBounds(), 1., 200., true, 0.8, 1.); } } From fef209ec719eb8a0939e8fd5b5bff014289416a5 Mon Sep 17 00:00:00 2001 From: jmillot Date: Wed, 4 Oct 2017 19:46:49 +0200 Subject: [PATCH 053/148] Correcting false positive tests on CI. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c75c1fc8..cd57af96 100755 --- a/.travis.yml +++ b/.travis.yml @@ -96,7 +96,7 @@ matrix: script: - python ./Scripts/configure.py -c Release - - python ./Scripts/build.py -c Release | xcpretty + - python ./Scripts/build.py -c Release before_deploy: - mkdir Kiwi From c88bac8fda166066de004633cefc8c79d684026f Mon Sep 17 00:00:00 2001 From: jmillot Date: Thu, 5 Oct 2017 10:06:25 +0200 Subject: [PATCH 054/148] Fix scheduler tests. --- Test/Engine/test_Scheduler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Test/Engine/test_Scheduler.cpp b/Test/Engine/test_Scheduler.cpp index 30f9618d..cbd67271 100644 --- a/Test/Engine/test_Scheduler.cpp +++ b/Test/Engine/test_Scheduler.cpp @@ -405,7 +405,7 @@ TEST_CASE("Scheduler - Defering tasks", "[Scheduler]") } }); - std::atomic exec_thread; + std::atomic exec_thread(std::this_thread::get_id()); std::atomic_bool executed_flag(false); auto task = std::make_shared(exec_thread, executed_flag); From 9fbd667ae5253e3b3b49cf0ba30e7b48bb457ed8 Mon Sep 17 00:00:00 2001 From: jmillot Date: Thu, 5 Oct 2017 12:29:19 +0200 Subject: [PATCH 055/148] Fix viewport. Patcher area is now computed before object update. --- .../Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp index 294a2927..344b56f9 100755 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp @@ -1411,16 +1411,17 @@ namespace kiwi if(link.added()) { addLinkView(link); } } - bool objects_bounds_changed = false; + bool patcher_area_uptodate = false; // send ObjectView change notification for(auto& object : patcher.getObjects()) { if(object.changed()) { - if(object.boundsChanged()) + if(object.boundsChanged() && !patcher_area_uptodate && !view.removed() && !m_is_in_move_or_resize_gesture) { - objects_bounds_changed = true; + m_viewport.updatePatcherArea(true); + patcher_area_uptodate = true; } objectChanged(view, object); @@ -1447,11 +1448,6 @@ namespace kiwi } } - if(objects_bounds_changed && !view.removed() && !m_is_in_move_or_resize_gesture) - { - m_viewport.updatePatcherArea(true); - } - if(!view.removed() && patcher.nameChanged()) { updateWindowTitle(); From b815327ee7f31ca926e104eeb782859529381537 Mon Sep 17 00:00:00 2001 From: jmillot Date: Thu, 5 Oct 2017 14:51:14 +0200 Subject: [PATCH 056/148] Fix delaysimpletilde argument crash. --- .../KiwiModel_Dsp/KiwiModel_DelaySimpleTilde.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_DelaySimpleTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_DelaySimpleTilde.cpp index f712010f..8b768692 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_DelaySimpleTilde.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_DelaySimpleTilde.cpp @@ -35,7 +35,7 @@ namespace kiwi { if (args.size() > 0) { - throw ("wrong argument for object delay~"); + throw std::runtime_error("wrong argument for object delay~"); } pushInlet({PinType::IType::Control, PinType::IType::Signal}); From 9f4f00345e008401be048c2bf2b0421cbfcebe86 Mon Sep 17 00:00:00 2001 From: jean-millot Date: Thu, 12 Oct 2017 17:46:13 +0200 Subject: [PATCH 057/148] Fix suggest editor mouse behavior. --- .../KiwiApp_SuggestEditor.cpp | 60 ++++++++++--------- .../KiwiApp_SuggestEditor.h | 24 +++++--- 2 files changed, 48 insertions(+), 36 deletions(-) diff --git a/Client/Source/KiwiApp_Components/KiwiApp_SuggestEditor.cpp b/Client/Source/KiwiApp_Components/KiwiApp_SuggestEditor.cpp index 82ff26f2..4b75b6cb 100644 --- a/Client/Source/KiwiApp_Components/KiwiApp_SuggestEditor.cpp +++ b/Client/Source/KiwiApp_Components/KiwiApp_SuggestEditor.cpp @@ -28,9 +28,10 @@ namespace kiwi // SUGGEST EDITOR MENU // // ================================================================================ // - SuggestEditor::Menu::Menu(SuggestList& list) : + SuggestEditor::Menu::Menu(SuggestList& list, SuggestEditor & creator) : m_suggest_list(list), m_suggest_list_box(), + m_creator(creator), m_constrainer(), m_resizable_corner(this, &m_constrainer), m_validated_action(), @@ -149,6 +150,24 @@ namespace kiwi return m_suggest_list_box.getSelectedRow(); } + bool SuggestEditor::Menu::canModalEventBeSentToComponent(juce::Component const* target_component) + { + return target_component == &m_creator; + } + + void SuggestEditor::Menu::inputAttemptWhenModal() + { + if (juce::Desktop::getInstance().getMainMouseSource().getComponentUnderMouse() != &m_creator) + { + exitModalState(0); + m_creator.closeMenu(); + } + else + { + m_creator.setCaretVisible(true); + } + } + // ================================================================================ // // SUGGEST LISTBOX MODEL // // ================================================================================ // @@ -237,7 +256,7 @@ namespace kiwi void SuggestEditor::showMenu() { - m_menu.reset(new Menu(m_suggest_list)); + m_menu.reset(new Menu(m_suggest_list, *this)); using namespace std::placeholders; // for _1, _2 etc. m_menu->setSelectedItemAction(std::bind(&SuggestEditor::menuItemSelected, this, _1)); @@ -248,11 +267,11 @@ namespace kiwi | juce::ComponentPeer::windowHasDropShadow | juce::ComponentPeer::windowIgnoresKeyPresses); + m_menu->enterModalState(false); + const auto sb = getScreenBounds(); m_menu->setTopLeftPosition(sb.getX() - 2, sb.getBottom() + 2); m_menu->setVisible(true); - - startTimer(200); } bool SuggestEditor::isMenuOpened() const noexcept @@ -265,7 +284,6 @@ namespace kiwi if(isMenuOpened()) { m_menu.reset(); - stopTimer(); } } @@ -279,6 +297,15 @@ namespace kiwi m_update_enabled = true; } + void SuggestEditor::textEditorFocusLost(juce::TextEditor & editor) + { + if(isMenuOpened()) + { + m_menu->exitModalState(0); + closeMenu(); + } + } + void SuggestEditor::textEditorTextChanged(juce::TextEditor&) { if (m_update_enabled) @@ -373,29 +400,6 @@ namespace kiwi setCaretVisible(true); } - void SuggestEditor::timerCallback() - { - if(!juce::Process::isForegroundProcess()) - closeMenu(); - - if(isMenuOpened()) - { - const auto sb = getScreenBounds(); - - // check focus lost or menu position change - if((!hasKeyboardFocus(true) && !m_menu->hasKeyboardFocus(true)) - || m_menu->getPosition() != juce::Point(sb.getX() - 2, sb.getBottom() + 2)) - { - closeMenu(); - } - } - else - { - if (!hasKeyboardFocus(true)) - closeMenu(); - } - } - bool SuggestEditor::keyStateChanged(bool isKeyDown) { enableUpdate(); diff --git a/Client/Source/KiwiApp_Components/KiwiApp_SuggestEditor.h b/Client/Source/KiwiApp_Components/KiwiApp_SuggestEditor.h index 19c84364..ab164cd5 100644 --- a/Client/Source/KiwiApp_Components/KiwiApp_SuggestEditor.h +++ b/Client/Source/KiwiApp_Components/KiwiApp_SuggestEditor.h @@ -38,8 +38,7 @@ namespace kiwi //! @details This component shows a dropdown menu list below it. class SuggestEditor : public juce::TextEditor, - public juce::TextEditor::Listener, - public juce::Timer + public juce::TextEditor::Listener { public: // methods @@ -67,14 +66,13 @@ namespace kiwi //! @brief Called when a key status changed. bool keyStateChanged(bool isKeyDown) override; - //! @internal Called every 200ms by a juce::Timer. - //! @details This method will close the menu if its relative position changed - //! or if editor lost the keyboard focus. - void timerCallback() override; - //! @brief juce::TextEditor::Listener void textEditorTextChanged(juce::TextEditor& ed) override; + //! @brief juce::TextEditor::Listener. + //! @details Needs to hide menu when focus is lost on editor. + void textEditorFocusLost(juce::TextEditor & editor) override; + //! @brief Called when a menu item has been clicked. void menuItemSelected(juce::String const& text); @@ -115,7 +113,7 @@ namespace kiwi using action_method_t = std::function; //! @brief Constructor. - Menu(SuggestList& list); + Menu(SuggestList& list, SuggestEditor & creator); //! @brief Destructor. ~Menu(); @@ -161,6 +159,15 @@ namespace kiwi private: // methods + //! @brief Returns true if suggest editor creator is target component. + //! @details Called only for keypressed events not for mouse events. + bool canModalEventBeSentToComponent(juce::Component const* target_component) override final; + + //! @brief Exists modal state if click happens. + //! @details If the creator is clicked it sets the caret visible enabling edition + //! otherwise it exits modal state. Called only on mouse clicks events. + void inputAttemptWhenModal() override final; + // ================================================================================ // // SUGGEST LISTBOX MODEL // // ================================================================================ // @@ -185,6 +192,7 @@ namespace kiwi SuggestList& m_suggest_list; juce::ListBox m_suggest_list_box; + SuggestEditor & m_creator; juce::ComponentBoundsConstrainer m_constrainer; juce::ResizableCornerComponent m_resizable_corner; From 3a86aad131dc47d0667cf7182e95d9bf6f2ad86e Mon Sep 17 00:00:00 2001 From: jean-millot Date: Mon, 16 Oct 2017 18:42:43 +0200 Subject: [PATCH 058/148] Metro sends bang when started. --- .../KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Metro.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Metro.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Metro.cpp index e257cf41..721a26bc 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Metro.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Metro.cpp @@ -53,6 +53,7 @@ namespace kiwi if((args[0].isString() && args[0].getString() == "start") || (args[0].isNumber() && static_cast(args[0].getInt()))) { + timerCallBack(); startTimer(m_period); } else if((args[0].isString() && args[0].getString() == "stop") From 5ebd0d62fabaeda324b22f3e57771905a2a701fc Mon Sep 17 00:00:00 2001 From: jmillot Date: Sat, 9 Sep 2017 00:15:44 +0200 Subject: [PATCH 059/148] Refactoring patcher view's mouse events. --- .../KiwiApp_Patcher/KiwiApp_PatcherView.cpp | 406 +------------ .../KiwiApp_Patcher/KiwiApp_PatcherView.h | 22 +- .../KiwiApp_PatcherViewMouseHandler.cpp | 570 ++++++++++++++++++ .../KiwiApp_PatcherViewMouseHandler.h | 109 ++++ 4 files changed, 697 insertions(+), 410 deletions(-) create mode 100644 Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewMouseHandler.cpp create mode 100644 Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewMouseHandler.h diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp index 344b56f9..595472fa 100755 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp @@ -51,10 +51,10 @@ namespace kiwi m_view_model(view), m_viewport(*this), m_hittester(*this), + m_mouse_handler(*this), m_io_highlighter(), m_lasso(*this), - m_grid_size(20), - m_object_border_down_status(HitTester::Border::None) + m_grid_size(20) { KiwiApp::bindToCommandManager(this); KiwiApp::bindToKeyMapping(this); @@ -152,107 +152,7 @@ namespace kiwi void PatcherView::mouseDown(juce::MouseEvent const& e) { - m_mouse_has_just_been_clicked = true; - - m_object_received_down_event = false; - m_copy_on_drag = false; - m_is_dragging = false; - m_is_dragging_links = false; - - if(!isLocked()) - { - HitTester& hit = m_hittester; - hit.test(e.getPosition()); - - if(hit.objectTouched()) - { - ObjectFrame* object_frame = hit.getObject(); - - if(object_frame) - { - if(hit.getZone() == HitTester::Zone::Inside) - { - if(e.mods.isAltDown()) - { - m_copy_on_drag = true; - m_select_on_mouse_down_status = selectOnMouseDown(*object_frame, true); - } - else if (e.mods.isCommandDown()) - { - object_frame->mouseDown(e.getEventRelativeTo(object_frame)); - m_object_received_down_event = true; - } - else - { - if(e.mods.isPopupMenu()) - { - if (!isSelected(*object_frame)) - { - m_select_on_mouse_down_status = selectOnMouseDown(*object_frame, true); - } - - const auto pos = e.getPosition() - m_viewport.getOriginPosition(); - showObjectPopupMenu(*object_frame, pos); - - } - else - { - m_select_on_mouse_down_status = selectOnMouseDown(*object_frame, !e.mods.isShiftDown()); - } - } - } - else if(hit.getZone() == HitTester::Zone::Outlet || hit.getZone() == HitTester::Zone::Inlet) - { - const size_t index = hit.getIndex(); - const bool is_sender = hit.getZone() == HitTester::Zone::Outlet; - - m_link_creator.reset(new LinkViewCreator(*object_frame, index, is_sender, e.getPosition())); - addAndMakeVisible(*m_link_creator); - } - } - } - else if(hit.linkTouched()) - { - LinkView* link_view = hit.getLink(); - if(link_view) - { - if(hit.getZone() == HitTester::Zone::Inside) - { - if(e.mods.isPopupMenu()) - { - if (!isSelected(*link_view)) - { - m_select_on_mouse_down_status = selectOnMouseDown(*link_view, true); - } - - const auto pos = e.getPosition() - m_viewport.getOriginPosition(); - showLinkPopupMenu(*link_view, pos); - } - else - { - m_select_on_mouse_down_status = selectOnMouseDown(*link_view, !e.mods.isShiftDown()); - } - } - } - } - else if(hit.patcherTouched()) - { - if(e.mods.isRightButtonDown()) - { - showPatcherPopupMenu(e.getPosition() - m_viewport.getOriginPosition()); - } - else - { - m_lasso.begin(e.getPosition(), e.mods.isShiftDown()); - } - } - } - else if(e.mods.isRightButtonDown()) - { - showPatcherPopupMenu(e.getPosition() - m_viewport.getOriginPosition()); - } - - m_last_drag = e.getPosition(); + m_mouse_handler.handleMouseDown(e); } // ================================================================================ // @@ -261,114 +161,7 @@ namespace kiwi void PatcherView::mouseDrag(juce::MouseEvent const& e) { - juce::MouseCursor::StandardCursorType mc = juce::MouseCursor::NormalCursor; - - if(!isLocked()) - { - if(m_lasso.isPerforming()) - { - m_lasso.perform(e.getPosition(), true, e.mods.isAltDown(), e.mods.isShiftDown()); - } - - if(m_link_creator) - { - auto end_pair = getLinkCreatorNearestEndingIolet(); - if(end_pair.first != nullptr) - { - const bool sender = m_link_creator->isBindedToSender(); - - ObjectFrame* object_view = end_pair.first; - if(object_view != nullptr) - { - if(sender) - { - m_io_highlighter.highlightInlet(*object_view, end_pair.second); - } - else - { - m_io_highlighter.highlightOutlet(*object_view, end_pair.second); - } - } - } - else - { - m_io_highlighter.hide(); - } - } - - HitTester& hit = m_hittester; - - if(hit.objectTouched()) - { - ObjectFrame* object_view = hit.getObject(); - if(object_view) - { - if(m_object_received_down_event && hit.getZone() == HitTester::Zone::Inside) - { - if(m_object_received_down_event) - { - object_view->mouseDrag(e.getEventRelativeTo(object_view)); - } - } - else if((hit.getZone() == HitTester::Zone::Outlet - || hit.getZone() == HitTester::Zone::Inlet) && m_link_creator) - { - m_link_creator->setEndPosition(e.getPosition()); - } - else if(m_object_border_down_status != HitTester::Border::None) - { - if(m_mouse_has_just_been_clicked) - { - //startMoveOrResizeObjects(); - } - - //resizeSelectedBoxes(e.getOffsetFromDragStart(), - // m_object_border_down_status, e.mods.isShiftDown()); - - m_last_drag = e.getPosition(); - - mc = getMouseCursorForBorder(m_object_border_down_status); - } - else if(isAnyObjectSelected()) - { - if(! m_is_dragging && (e.getMouseDownPosition() != e.getPosition())) - { - if(m_copy_on_drag) - { - copySelectionToClipboard(); - pasteFromClipboard({0, 0}); - } - - startMoveOrResizeObjects(); - m_is_dragging = true; - } - - if(m_is_dragging) - { - const juce::Point pos = e.getPosition(); - auto delta = pos - m_last_drag; - moveSelectedObjects(delta, true, true); - m_last_drag = pos; - - if(! m_viewport.getRelativeViewArea().contains(pos)) - { - // scroll viewport - beginDragAutoRepeat(50); - const juce::MouseEvent e2(e.getEventRelativeTo(&m_viewport)); - m_viewport.autoScroll(e2.x, e2.y, 5, 5); - } - } - else - { - m_viewport.updatePatcherArea(true); - } - } - } - } - } - - setMouseCursor(mc); - m_mouse_has_just_been_clicked = false; + m_mouse_handler.handleMouseDrag(e); } // ================================================================================ // @@ -377,103 +170,7 @@ namespace kiwi void PatcherView::mouseUp(juce::MouseEvent const& e) { - m_object_border_down_status = HitTester::Border::None; - - if(!isLocked()) - { - if(m_lasso.isPerforming()) - { - m_lasso.end(); - return; - } - - if(m_link_creator) - { - m_io_highlighter.hide(); - - auto end_pair = getLinkCreatorNearestEndingIolet(); - if(end_pair.first != nullptr) - { - const bool sender = m_link_creator->isBindedToSender(); - - model::Object const& binded_object = m_link_creator->getBindedObject().getModel(); - model::Object const& ending_object = end_pair.first->getModel(); - - model::Object const& from = sender ? binded_object : ending_object; - model::Object const& to = sender ? ending_object : binded_object; - - const size_t outlet = sender ? m_link_creator->getBindedIndex() : end_pair.second; - const size_t inlet = sender ? end_pair.second : m_link_creator->getBindedIndex(); - - model::Link* link = m_patcher_model.addLink(from, outlet, to, inlet); - if(link != nullptr) - { - m_view_model.selectLink(*link); - DocumentManager::commit(m_patcher_model, "Add link"); - } - } - - removeChildComponent(m_link_creator.get()); - m_link_creator.reset(); - } - - HitTester& hit = m_hittester; - - if(hit.objectTouched() && hit.getZone() == HitTester::Zone::Inside) - { - ObjectFrame* object_view = hit.getObject(); - - if(object_view) - { - if(e.mods.isCommandDown()) - { - object_view->mouseUp(e.getEventRelativeTo(object_view)); - return; - } - else if(m_select_on_mouse_down_status && !m_is_in_move_or_resize_gesture) - { - editObject(*object_view); - } - } - } - - hit.test(e.getPosition()); - - if(hit.objectTouched()) - { - ObjectFrame* object_view = hit.getObject(); - if(object_view) - { - selectOnMouseUp(*object_view, !e.mods.isShiftDown(), m_is_dragging, - m_select_on_mouse_down_status); - } - } - else if(hit.linkTouched()) - { - LinkView* link_view = hit.getLink(); - if(link_view) - { - selectOnMouseUp(*link_view, !e.mods.isShiftDown(), m_is_dragging, - m_select_on_mouse_down_status); - } - } - else if(e.mods.isCommandDown()) - { - setLock(true); - } - - } - else if(e.mods.isCommandDown()) - { - setLock(false); - } - - if(m_is_in_move_or_resize_gesture) - { - endMoveOrResizeObjects(); - } - - m_mouse_has_just_been_clicked = false; + m_mouse_handler.handleMouseUp(e); } // ================================================================================ // @@ -482,64 +179,16 @@ namespace kiwi void PatcherView::mouseMove(juce::MouseEvent const& event) { - juce::MouseCursor::StandardCursorType mc = juce::MouseCursor::NormalCursor; - - if(!isLocked()) - { - HitTester hit(*this); - hit.test(event.getPosition()); - - if (hit.getZone() != HitTester::Zone::Outlet && hit.getZone() != HitTester::Zone::Inlet) - { - m_io_highlighter.hide(); - } - - if(hit.objectTouched()) - { - if(hit.getZone() == HitTester::Zone::Border) - { - mc = getMouseCursorForBorder(hit.getBorder()); - } - else if(hit.getZone() == HitTester::Zone::Outlet - || hit.getZone() == HitTester::Zone::Inlet) - { - if(hit.getZone() == HitTester::Zone::Inlet) - { - m_io_highlighter.highlightInlet(*hit.getObject(), hit.getIndex()); - } - else - { - m_io_highlighter.highlightOutlet(*hit.getObject(), hit.getIndex()); - } - - mc = juce::MouseCursor::PointingHandCursor; - } - } - } - - setMouseCursor(mc); + m_mouse_handler.handleMouseMove(event); } + // ================================================================================ // + // MOUSE DOUBLE CLICK // + // ================================================================================ // + void PatcherView::mouseDoubleClick(const juce::MouseEvent& e) { - if(!isLocked()) - { - HitTester hit(*this); - hit.test(e.getPosition()); - - if(e.mods.isCommandDown() && hit.objectTouched()) - { - ObjectFrame* object_view = hit.getObject(); - if(object_view) - { - object_view->mouseDoubleClick(e.getEventRelativeTo(object_view)); - } - } - else if(hit.patcherTouched()) - { - createObjectModel("", true); - } - } + m_mouse_handler.handleMouseDoubleClick(e); } juce::MouseCursor::StandardCursorType PatcherView::getMouseCursorForBorder(int border_flag) const @@ -638,34 +287,6 @@ namespace kiwi // SELECTION // // ================================================================================ // - void PatcherView::startMoveOrResizeObjects() - { - m_is_in_move_or_resize_gesture = true; - KiwiApp::commandStatusChanged(); // to disable command like delete selection etc... - - DocumentManager::startCommitGesture(m_patcher_model); - } - - void PatcherView::endMoveOrResizeObjects() - { - DocumentManager::endCommitGesture(m_patcher_model); - m_is_in_move_or_resize_gesture = false; - KiwiApp::commandStatusChanged(); - - m_viewport.updatePatcherArea(true); - - HitTester& hit = m_hittester; - - if(hit.objectTouched()) - { - ObjectFrame* object_view = hit.getObject(); - if(object_view) - { - m_viewport.jumpViewToObject(*object_view); - } - } - } - void PatcherView::resizeSelectedObjects(juce::Point const& delta, const long border_flag, const bool preserve_ratio) { @@ -1068,7 +689,7 @@ namespace kiwi bool PatcherView::keyPressed(const juce::KeyPress& key) { - if(m_is_in_move_or_resize_gesture) + if(m_mouse_handler.getCurrentAction() == MouseHandler::Action::MoveObject) return false; // abort if(key.isKeyCode(juce::KeyPress::deleteKey) || key.isKeyCode(juce::KeyPress::backspaceKey)) @@ -1418,7 +1039,8 @@ namespace kiwi { if(object.changed()) { - if(object.boundsChanged() && !patcher_area_uptodate && !view.removed() && !m_is_in_move_or_resize_gesture) + if(object.boundsChanged() && !patcher_area_uptodate && !view.removed() && + m_mouse_handler.getCurrentAction() != MouseHandler::Action::MoveObject) { m_viewport.updatePatcherArea(true); patcher_area_uptodate = true; diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.h b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.h index 1ece97bf..6a6a54c2 100755 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.h @@ -25,6 +25,8 @@ #include +#include + #include "KiwiApp_PatcherViewport.h" #include "KiwiApp_PatcherViewHitTester.h" #include "KiwiApp_PatcherManager.h" @@ -288,12 +290,6 @@ namespace kiwi //! @brief Unselect all objects. void deleteSelection(); - //! @brief Begins a move or resize gesture. - void startMoveOrResizeObjects(); - - //! @brief Ends a move or resize gesture. - void endMoveOrResizeObjects(); - //! @brief Resize selected objects by a given amount of pixels. //! @param delta The given amount of pixel. //! @param border_flag The border flag (see HitTester::Border enum) @@ -396,6 +392,7 @@ namespace kiwi PatcherViewport m_viewport; HitTester m_hittester; + MouseHandler m_mouse_handler; IoletHighlighter m_io_highlighter; Lasso m_lasso; std::unique_ptr m_link_creator; @@ -404,19 +401,8 @@ namespace kiwi bool m_is_locked; int m_grid_size; - - // mouse interactions flags - juce::Point m_last_drag; - bool m_object_received_down_event = false; - bool m_copy_on_drag = false; - bool m_is_dragging = false; - bool m_is_dragging_links = false; - bool m_mouse_has_just_been_clicked = false; - bool m_select_on_mouse_down_status = false; - bool m_link_downstatus = false; - bool m_is_in_move_or_resize_gesture = false; - long m_object_border_down_status; + friend MouseHandler; friend PatcherViewport; friend Lasso; }; diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewMouseHandler.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewMouseHandler.cpp new file mode 100644 index 00000000..2a84fb6a --- /dev/null +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewMouseHandler.cpp @@ -0,0 +1,570 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include +#include +#include +#include +#include + +namespace kiwi +{ + // ================================================================================ // + // HITTESTER // + // ================================================================================ // + + MouseHandler::MouseHandler(PatcherView & patcher_view): + m_patcher_view(patcher_view), + m_current_action(Action::None), + m_last_drag() + { + } + + MouseHandler::~MouseHandler() + { + } + + MouseHandler::Action MouseHandler::getCurrentAction() + { + return m_current_action; + } + + void MouseHandler::startAction(Action action, juce::MouseEvent const& e) + { + m_current_action = action; + + HitTester& hit_tester = m_patcher_view.m_hittester; + + switch (m_current_action) + { + case Action::CopyOnDrag: + { + ObjectFrame & object = *hit_tester.getObject(); + + if (!m_patcher_view.isSelected(object)) + { + m_patcher_view.selectObjectOnly(object); + } + + break; + } + case Action::Object: + { + ObjectFrame & object = *hit_tester.getObject(); + + object.mouseDown(e.getEventRelativeTo(&object)); + + break; + } + case Action::CreateLink: + { + ObjectFrame & object = *hit_tester.getObject(); + + const size_t index = hit_tester.getIndex(); + + const bool is_sender = hit_tester.getZone() == HitTester::Zone::Outlet; + + m_patcher_view.m_link_creator.reset(new LinkViewCreator(object, + index, + is_sender, + e.getPosition())); + + m_patcher_view.addAndMakeVisible(*m_patcher_view.m_link_creator); + + break; + } + case Action::Lasso: + { + m_patcher_view.m_lasso.begin(e.getPosition(), e.mods.isShiftDown()); + + break; + } + case Action::MoveObject: + { + KiwiApp::commandStatusChanged(); + + DocumentManager::startCommitGesture(m_patcher_view.m_patcher_model); + + break; + } + case Action::PopupMenu: + { + if(hit_tester.objectTouched() && hit_tester.getZone() == HitTester::Zone::Inside) + { + ObjectFrame & object = *hit_tester.getObject(); + + if (!m_patcher_view.isSelected(object)) + { + m_patcher_view.selectObject(object); + } + + const auto pos = e.getPosition() - m_patcher_view.m_viewport.getOriginPosition(); + + m_patcher_view.showObjectPopupMenu(object, pos); + } + else if (hit_tester.linkTouched() && hit_tester.getZone() == HitTester::Zone::Inside) + { + LinkView& link_view = *hit_tester.getLink(); + + if (!m_patcher_view.isSelected(link_view)) + { + m_patcher_view.selectLink(link_view); + } + + const auto pos = e.getPosition() - m_patcher_view.m_viewport.getOriginPosition(); + + m_patcher_view.showLinkPopupMenu(link_view, pos); + } + else if (hit_tester.patcherTouched()) + { + m_patcher_view.showPatcherPopupMenu(e.getPosition() - m_patcher_view.m_viewport.getOriginPosition()); + } + + break; + } + case Action::SwitchSelection: + { + if (hit_tester.objectTouched()) + { + ObjectFrame & object = *hit_tester.getObject(); + + if (m_patcher_view.isSelected(object)) + { + m_patcher_view.unselectObject(object); + } + else + { + m_patcher_view.selectObject(object); + } + } + else if (hit_tester.linkTouched()) + { + LinkView & link = *hit_tester.getLink(); + + if (m_patcher_view.isSelected(link)) + { + m_patcher_view.unselectLink(link); + } + else + { + m_patcher_view.selectLink(link); + } + } + break; + } + case Action::Selection: + { + if (hit_tester.objectTouched()) + { + m_patcher_view.selectObjectOnly(*hit_tester.getObject()); + } + else if (hit_tester.linkTouched()) + { + m_patcher_view.selectLinkOnly(*hit_tester.getLink()); + } + break; + } + default: + { + break; + } + } + } + + void MouseHandler::continueAction(juce::MouseEvent const& e) + { + HitTester& hit_tester = m_patcher_view.m_hittester; + + switch (m_current_action) + { + case Action::CopyOnDrag: + { + if (e.getMouseDownPosition() != e.getPosition()) + { + m_patcher_view.copySelectionToClipboard(); + m_patcher_view.pasteFromClipboard({0, 0}); + + startAction(Action::MoveObject, e); + } + break; + } + case Action::Object: + { + ObjectFrame & object = *hit_tester.getObject(); + + object.mouseDrag(e.getEventRelativeTo(&object)); + + break; + } + case Action::CreateLink: + { + auto end_pair = m_patcher_view.getLinkCreatorNearestEndingIolet(); + + if(end_pair.first != nullptr) + { + const bool sender = m_patcher_view.m_link_creator->isBindedToSender(); + + ObjectFrame* object_view = end_pair.first; + + if(object_view != nullptr) + { + if(sender) + { + m_patcher_view.m_io_highlighter.highlightInlet(*object_view, end_pair.second); + } + else + { + m_patcher_view.m_io_highlighter.highlightOutlet(*object_view, end_pair.second); + } + } + } + else + { + m_patcher_view.m_io_highlighter.hide(); + } + + if (hit_tester.getZone() == HitTester::Zone::Outlet + || hit_tester.getZone() == HitTester::Zone::Inlet) + { + m_patcher_view.m_link_creator->setEndPosition(e.getPosition()); + } + + break; + } + case Action::Lasso: + { + if(m_patcher_view.m_lasso.isPerforming()) + { + m_patcher_view.m_lasso.perform(e.getPosition(), true, e.mods.isAltDown(), e.mods.isShiftDown()); + } + + break; + } + case Action::MoveObject: + { + if (m_patcher_view.isAnyObjectSelected()) + { + m_patcher_view.moveSelectedObjects(e.getPosition() - m_last_drag, true, true); + + if(!m_patcher_view.m_viewport.getRelativeViewArea().contains(e.getPosition())) + { + m_patcher_view.beginDragAutoRepeat(50); + const juce::MouseEvent e2(e.getEventRelativeTo(&m_patcher_view.m_viewport)); + m_patcher_view.m_viewport.autoScroll(e2.x, e2.y, 5, 5); + } + } + + break; + } + case Action::ObjectEdition: + { + if (e.getMouseDownPosition() != e.getPosition()) + { + startAction(Action::MoveObject, e); + } + break; + } + case Action::SwitchSelection: + { + if (e.getMouseDownPosition() != e.getPosition()) + { + startAction(Action::MoveObject, e); + } + + break; + } + case Action::Selection: + { + if (e.getMouseDownPosition() != e.getPosition()) + { + startAction(Action::MoveObject, e); + } + break; + } + default: + { + break; + } + } + } + + void MouseHandler::endAction(juce::MouseEvent const& e) + { + HitTester& hit_tester = m_patcher_view.m_hittester; + + switch (m_current_action) + { + case Action::Object: + { + ObjectFrame & object = *hit_tester.getObject(); + object.mouseUp(e.getEventRelativeTo(&object)); + break; + } + case Action::CreateLink: + { + m_patcher_view.m_io_highlighter.hide(); + + auto end_pair = m_patcher_view.getLinkCreatorNearestEndingIolet(); + + if(end_pair.first != nullptr) + { + LinkViewCreator& link_creator = *m_patcher_view.m_link_creator; + + const bool sender = link_creator.isBindedToSender(); + + model::Object const& binded_object = link_creator.getBindedObject().getModel(); + model::Object const& ending_object = end_pair.first->getModel(); + + model::Object const& from = sender ? binded_object : ending_object; + model::Object const& to = sender ? ending_object : binded_object; + + const size_t outlet = sender ? link_creator.getBindedIndex() : end_pair.second; + const size_t inlet = sender ? end_pair.second : link_creator.getBindedIndex(); + + model::Link* link = m_patcher_view.m_patcher_model.addLink(from, outlet, to, inlet); + + if(link != nullptr) + { + m_patcher_view.m_view_model.selectLink(*link); + DocumentManager::commit(m_patcher_view.m_patcher_model, "Add link"); + } + } + + m_patcher_view.removeChildComponent(m_patcher_view.m_link_creator.get()); + m_patcher_view.m_link_creator.reset(); + break; + } + case Action::Lasso: + { + if(m_patcher_view.m_lasso.isPerforming()) + { + m_patcher_view.m_lasso.end(); + } + break; + } + case Action::MoveObject: + { + DocumentManager::endCommitGesture(m_patcher_view.m_patcher_model); + + KiwiApp::commandStatusChanged(); + + m_patcher_view.m_viewport.updatePatcherArea(true); + + m_patcher_view.m_viewport.jumpViewToObject(*hit_tester.getObject()); + + break; + } + case Action::ObjectEdition: + { + ObjectFrame & object = *hit_tester.getObject(); + m_patcher_view.editObject(object); + break; + } + case Action::SwitchLock: + { + m_patcher_view.setLock(!m_patcher_view.isLocked()); + break; + } + default: + { + break; + } + } + + m_current_action = Action::None; + } + + void MouseHandler::handleMouseDown(juce::MouseEvent const& e) + { + HitTester& hit_tester = m_patcher_view.m_hittester; + + hit_tester.test(e.getPosition()); + + if(!m_patcher_view.isLocked()) + { + if(hit_tester.objectTouched()) + { + if(hit_tester.getZone() == HitTester::Zone::Inside) + { + if(e.mods.isAltDown()) + { + startAction(Action::CopyOnDrag, e); + } + else if (e.mods.isCommandDown()) + { + startAction(Action::Object, e); + } + else + { + if(e.mods.isPopupMenu()) + { + startAction(Action::PopupMenu, e); + } + else + { + ObjectFrame& object = *hit_tester.getObject(); + + if (e.mods.isShiftDown()) + { + startAction(Action::SwitchSelection, e); + } + else if(m_patcher_view.isSelected(object)) + { + startAction(Action::ObjectEdition, e); + } + else + { + startAction(Action::Selection, e); + } + } + } + } + else if(hit_tester.getZone() == HitTester::Zone::Outlet + || hit_tester.getZone() == HitTester::Zone::Inlet) + { + startAction(Action::CreateLink, e); + } + } + else if(hit_tester.linkTouched()) + { + if(hit_tester.getZone() == HitTester::Zone::Inside) + { + if(e.mods.isPopupMenu()) + { + startAction(Action::PopupMenu, e); + } + else + { + if (e.mods.isShiftDown()) + { + startAction(Action::SwitchSelection, e); + } + else + { + startAction(Action::Selection, e); + } + } + } + } + else if(hit_tester.patcherTouched()) + { + if(e.mods.isPopupMenu()) + { + startAction(Action::PopupMenu, e); + } + else if (e.mods.isCommandDown()) + { + startAction(Action::SwitchLock, e); + } + else + { + startAction(Action::Lasso, e); + } + } + } + else if (e.mods.isCommandDown() && hit_tester.patcherTouched()) + { + startAction(Action::SwitchLock, e); + } + else if(e.mods.isRightButtonDown()) + { + startAction(Action::PopupMenu, e); + } + + m_last_drag = e.getPosition(); + } + + void MouseHandler::handleMouseDrag(juce::MouseEvent const& e) + { + continueAction(e); + + m_last_drag = e.getPosition(); + } + + void MouseHandler::handleMouseUp(juce::MouseEvent const& e) + { + endAction(e); + } + + void MouseHandler::handleMouseDoubleClick(juce::MouseEvent const& e) + { + if(!m_patcher_view.isLocked()) + { + HitTester& hit_tester = m_patcher_view.m_hittester; + + hit_tester.test(e.getPosition()); + + if(e.mods.isCommandDown() && hit_tester.objectTouched()) + { + ObjectFrame & object= *hit_tester.getObject(); + + object.mouseDoubleClick(e.getEventRelativeTo(&object)); + } + else if(hit_tester.patcherTouched()) + { + m_patcher_view.createObjectModel("", true); + } + } + } + + void MouseHandler::handleMouseMove(juce::MouseEvent const& e) + { + juce::MouseCursor::StandardCursorType mc = juce::MouseCursor::NormalCursor; + + HitTester& hit_tester = m_patcher_view.m_hittester; + + hit_tester.test(e.getPosition()); + + if (hit_tester.getZone() != HitTester::Zone::Outlet + && hit_tester.getZone() != HitTester::Zone::Inlet) + { + m_patcher_view.m_io_highlighter.hide(); + } + + if(!m_patcher_view.isLocked()) + { + if(hit_tester.objectTouched()) + { + if(hit_tester.getZone() == HitTester::Zone::Border) + { + mc = m_patcher_view.getMouseCursorForBorder(hit_tester.getBorder()); + } + else if(hit_tester.getZone() == HitTester::Zone::Outlet + || hit_tester.getZone() == HitTester::Zone::Inlet) + { + if(hit_tester.getZone() == HitTester::Zone::Inlet) + { + m_patcher_view.m_io_highlighter.highlightInlet(*hit_tester.getObject(), hit_tester.getIndex()); + } + else + { + m_patcher_view.m_io_highlighter.highlightOutlet(*hit_tester.getObject(), hit_tester.getIndex()); + } + + mc = juce::MouseCursor::PointingHandCursor; + } + } + } + + m_patcher_view.setMouseCursor(mc); + } +} diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewMouseHandler.h b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewMouseHandler.h new file mode 100644 index 00000000..64cea6a5 --- /dev/null +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewMouseHandler.h @@ -0,0 +1,109 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +#include + +namespace kiwi +{ + class PatcherView; + class ObjectFrame; + class HitTester; + + // ================================================================================ // + // MOUSEHANDLER // + // ================================================================================ // + + //! @brief The mouse handler is used to make the patcher view react to the mouse interactions. + class MouseHandler + { + public: // enums + + enum class Action + { + None = 0, + CopyOnDrag = 1, + Object = 2, + CreateLink = 3, + Lasso = 4, + MoveObject = 5, + PopupMenu = 6, + ObjectEdition = 7, + SwitchSelection = 8, + Selection = 9, + SwitchLock = 10 + }; + + public: // methods + + //! @brief Returns the current action. + Action getCurrentAction(); + + //! @brief Constructor. + MouseHandler(PatcherView & patcher_view); + + //! @brief Destructor. + ~MouseHandler(); + + //! @brief Handles patcher view's mouse down event. + void handleMouseDown(juce::MouseEvent const& e); + + //! @brief Handles patcher view's mouse drag event. + void handleMouseDrag(juce::MouseEvent const& e); + + //! @brief Handles patcher view's mouse up event. + void handleMouseUp(juce::MouseEvent const& e); + + //! @brief Handles patcher view's mouse double click events. + void handleMouseDoubleClick(juce::MouseEvent const& e); + + //! @brief Handles patcher view's mouse move events. + void handleMouseMove(juce::MouseEvent const& e); + + private: // methods + + //! @brief Starts an interaction with the patcher view. + void startAction(Action action, juce::MouseEvent const& e); + + //! @brief Continues an initiated interaction with the patcher view. + void continueAction(juce::MouseEvent const& e); + + //! @brief Ends an ongoing interaction with patch. + void endAction(juce::MouseEvent const& e); + + private: // members + + PatcherView & m_patcher_view; + Action m_current_action; + juce::Point m_last_drag; + + private: // deleted methods + + MouseHandler() = delete; + MouseHandler(MouseHandler const& other) = delete; + MouseHandler(MouseHandler && other) = delete; + MouseHandler& operator=(MouseHandler const& other) = delete; + MouseHandler& operator=(MouseHandler && other) = delete; + }; +} From a3a3b2261c892d75f16992fb7fced086d2e7ccef Mon Sep 17 00:00:00 2001 From: jmillot Date: Tue, 12 Sep 2017 00:15:44 +0200 Subject: [PATCH 060/148] Enable resizing graphical objects. --- .../KiwiApp_Controller/KiwiApp_BangView.cpp | 10 +- .../KiwiApp_Objects/KiwiApp_ObjectFrame.cpp | 407 +++++++++++++----- .../KiwiApp_Objects/KiwiApp_ObjectFrame.h | 97 ++++- .../KiwiApp_Patcher/KiwiApp_PatcherView.cpp | 67 +-- .../KiwiApp_Patcher/KiwiApp_PatcherView.h | 10 - .../KiwiApp_PatcherViewMouseHandler.cpp | 233 +++++++++- .../KiwiApp_PatcherViewMouseHandler.h | 32 +- Modules/KiwiModel/KiwiModel_Object.cpp | 128 +++++- Modules/KiwiModel/KiwiModel_Object.h | 82 +++- .../KiwiModel_Basic/KiwiModel_NewBox.cpp | 2 +- .../KiwiModel_Controller/KiwiModel_Bang.cpp | 7 +- .../KiwiModel_Controller/KiwiModel_Toggle.cpp | 7 +- 12 files changed, 870 insertions(+), 212 deletions(-) diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_BangView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_BangView.cpp index 8e1aa77d..225d2c20 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_BangView.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_BangView.cpp @@ -51,14 +51,20 @@ namespace kiwi g.setColour(findColour(ObjectView::ColourIds::Outline)); - g.drawEllipse(getLocalBounds().reduced(3.1).toFloat(), 2); + juce::Rectangle bounds = getLocalBounds(); + + double circle_outer = 80 * bounds.getWidth() / 100.; + + double circle_thickness = 10 * bounds.getWidth() / 100.; + + g.drawEllipse(bounds.reduced(bounds.getWidth() - circle_outer).toFloat(), circle_thickness); drawOutline(g); if (m_mouse_down || m_active) { g.setColour(findColour(ObjectView::ColourIds::Active)); - g.fillEllipse(getLocalBounds().reduced(3.1 + 2).toFloat()); + g.fillEllipse(bounds.reduced(bounds.getWidth() - circle_outer + circle_thickness).toFloat()); } } diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.cpp index bad1c7a3..bc99eba6 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.cpp @@ -19,6 +19,9 @@ ============================================================================== */ +#define _USE_MATH_DEFINES +#include + #include #include @@ -33,16 +36,20 @@ namespace kiwi m_patcher_view(patcher_view), m_io_width(6), m_io_height(3), - m_selection_width(4), m_inlets(getModel().getNumberOfInlets()), - m_outlets(getModel().getNumberOfOutlets()) + m_outlets(getModel().getNumberOfOutlets()), + m_outline(10, 4, 1) { initColours(); + addChildComponent(m_outline); + addAndMakeVisible(m_object_view.get()); updateBounds(false); + updateOutline(); + setInterceptsMouseClicks(isLocked(), isLocked()); } @@ -55,12 +62,14 @@ namespace kiwi { juce::Rectangle object_bounds = getObjectBounds(); - setBounds(getObjectBounds().expanded(m_selection_width)); + setBounds(getObjectBounds().expanded(m_outline.getBorderThickness())); } void ObjectFrame::resized() { - m_object_view->setBounds(getLocalBounds().reduced(m_selection_width)); + m_object_view->setBounds(getLocalBounds().reduced(m_outline.getBorderThickness())); + + m_outline.setBounds(getLocalBounds()); } void ObjectFrame::updateBounds(bool animate) @@ -76,7 +85,7 @@ namespace kiwi model.getWidth(), model.getHeight()); - const juce::Rectangle frame_bounds = object_bounds.expanded(m_selection_width); + const juce::Rectangle frame_bounds = object_bounds.expanded(m_outline.getBorderThickness()); if (animate) @@ -91,50 +100,6 @@ namespace kiwi } } - void ObjectFrame::paint(juce::Graphics & g) - { - const auto bounds = getLocalBounds(); - - std::set const& distant_selection = getDistantSelection(); - - const bool selected = isSelected(); - const bool other_selected = ! distant_selection.empty(); - const bool other_view_selected = (other_selected && - distant_selection.find(KiwiApp::userID()) - != distant_selection.end()); - - const bool distant_selected = ((other_selected && (other_view_selected && distant_selection.size() > 1)) - || (other_selected && !other_view_selected)); - - if(selected || other_view_selected || distant_selected) - { - juce::Colour selection_color; - - if (selected) - { - selection_color = findColour(ObjectFrame::ColourIds::Selection); - } - else if(other_view_selected) - { - selection_color = findColour(ObjectFrame::ColourIds::SelectionOtherView); - } - else - { - selection_color = findColour(ObjectFrame::ColourIds::SelectionDistant); - } - - g.setColour(selection_color.darker(0.4)); - g.drawRect(bounds.reduced(m_selection_width*0.5 + 1), 1); - - g.setColour(selection_color); - g.drawRoundedRectangle(bounds.reduced(m_selection_width*0.5).toFloat(), - m_selection_width*0.5, m_selection_width*0.5); - - g.setColour(selection_color.darker(0.4)); - g.drawRoundedRectangle(bounds.reduced(1).toFloat(), m_selection_width*0.5, 1); - } - } - void ObjectFrame::paintOverChildren (juce::Graphics& g) { if(!isLocked()) @@ -193,33 +158,30 @@ namespace kiwi // test body and iolets if(box_bounds.contains(pt)) { - if(!isSelected()) + // test inlets + if(m_inlets > 0 && pt.getY() > m_io_height) { - // test inlets - if(m_inlets > 0 && pt.getY() > m_io_height) + for(size_t i = 0; i < m_inlets; ++i) { - for(size_t i = 0; i < m_inlets; ++i) + if(getInletLocalBounds(i).contains(pt)) { - if(getInletLocalBounds(i).contains(pt)) - { - hit.m_zone = HitTester::Zone::Inlet; - hit.m_index = i; - return true; - } + hit.m_zone = HitTester::Zone::Inlet; + hit.m_index = i; + return true; } } - - // test outlets - if(m_outlets > 0 && pt.getY() > box_bounds.getHeight() - m_io_height) + } + + // test outlets + if(m_outlets > 0 && pt.getY() > box_bounds.getHeight() - m_io_height) + { + for(size_t i = 0; i < m_outlets; ++i) { - for(size_t i = 0; i < m_outlets; ++i) + if(getOutletLocalBounds(i).contains(pt)) { - if(getOutletLocalBounds(i).contains(pt)) - { - hit.m_zone = HitTester::Zone::Outlet; - hit.m_index = i; - return true; - } + hit.m_zone = HitTester::Zone::Outlet; + hit.m_index = i; + return true; } } } @@ -231,36 +193,8 @@ namespace kiwi } else if(isSelected()) // test borders { - const auto resizer_bounds = box_bounds.expanded(m_selection_width, m_selection_width); - - if(pt.getY() >= resizer_bounds.getY() && pt.getY() <= box_bounds.getY()) - { - hit.m_zone = HitTester::Zone::Border; - hit.m_border |= HitTester::Border::Top; - } - - if(pt.getX() >= box_bounds.getRight() && pt.getX() <= resizer_bounds.getRight()) - { - hit.m_zone = HitTester::Zone::Border; - hit.m_border |= HitTester::Border::Right; - } - - if(pt.getY() >= box_bounds.getBottom() && pt.getY() <= resizer_bounds.getBottom()) - { - hit.m_zone = HitTester::Zone::Border; - hit.m_border |= HitTester::Border::Bottom; - } - - if(pt.getX() <= box_bounds.getX() && pt.getX() >= resizer_bounds.getX()) + if (m_outline.hitTest(pt, hit)) { - hit.m_zone = HitTester::Zone::Border; - hit.m_border |= HitTester::Border::Left; - } - - // remove Border::None flag if we hit a border. - if(hit.m_zone == HitTester::Zone::Border) - { - hit.m_border &= ~HitTester::Border::None; return true; } } @@ -370,14 +304,60 @@ namespace kiwi object_view->edit(); } } - - void ObjectFrame::localSelectionChanged() + + void ObjectFrame::updateOutline() { - repaint(); + std::set const& distant_selection = getDistantSelection(); + + const bool selected = isSelected(); + const bool other_selected = ! distant_selection.empty(); + const bool other_view_selected = (other_selected && + distant_selection.find(KiwiApp::userID()) + != distant_selection.end()); + + const bool distant_selected = ((other_selected && (other_view_selected && distant_selection.size() > 1)) + || (other_selected && !other_view_selected)); + + if (selected) + { + m_outline.setVisible(true); + + m_outline.setResizeColour(findColour(ObjectFrame::ColourIds::Selection)); + + if (distant_selected) + { + m_outline.setInnerColour(findColour(ObjectFrame::ColourIds::SelectionDistant)); + } + else if (other_view_selected) + { + m_outline.setInnerColour(findColour(ObjectFrame::ColourIds::SelectionOtherView)); + } + else + { + m_outline.setInnerColour(findColour(ObjectFrame::ColourIds::Selection)); + } + } + else if(distant_selected) + { + m_outline.setVisible(true); + m_outline.setResizeColour(findColour(ObjectFrame::ColourIds::SelectionDistant)); + m_outline.setInnerColour(findColour(ObjectFrame::ColourIds::SelectionDistant)); + } + else if (other_view_selected) + { + m_outline.setVisible(true); + m_outline.setResizeColour(findColour(ObjectFrame::ColourIds::SelectionOtherView)); + m_outline.setInnerColour(findColour(ObjectFrame::ColourIds::SelectionOtherView)); + } + else + { + m_outline.setVisible(false); + } } - - void ObjectFrame::distantSelectionChanged() + + void ObjectFrame::selectionChanged() { + updateOutline(); repaint(); } @@ -419,7 +399,10 @@ namespace kiwi juce::Rectangle ObjectFrame::getInletLocalBounds(const size_t index) const { - juce::Rectangle object_bounds = m_object_view->getBounds(); + juce::Rectangle inlet_bounds = m_object_view->getBounds(); + + inlet_bounds.removeFromLeft(m_outline.getResizeLength() - m_outline.getBorderThickness()); + inlet_bounds.removeFromRight(m_outline.getResizeLength() - m_outline.getBorderThickness()); juce::Rectangle rect; @@ -427,13 +410,13 @@ namespace kiwi { if(m_inlets == 1 && index == 0) { - rect.setBounds(object_bounds.getX(), object_bounds.getY(), getPinWidth(), getPinHeight()); + rect.setBounds(inlet_bounds.getX(), inlet_bounds.getY(), getPinWidth(), getPinHeight()); } if(m_inlets > 1) { - const double ratio = (object_bounds.getWidth() - getPinWidth()) / (double)(m_inlets - 1); - rect.setBounds(object_bounds.getX() + ratio * index, object_bounds.getY(), + const double ratio = (inlet_bounds.getWidth() - getPinWidth()) / (double)(m_inlets - 1); + rect.setBounds(inlet_bounds.getX() + ratio * index, inlet_bounds.getY(), getPinWidth(), getPinHeight()); } } @@ -443,7 +426,10 @@ namespace kiwi juce::Rectangle ObjectFrame::getOutletLocalBounds(const size_t index) const { - juce::Rectangle object_bounds = m_object_view->getBounds(); + juce::Rectangle outlet_bounds = m_object_view->getBounds(); + + outlet_bounds.removeFromLeft(m_outline.getResizeLength() - m_outline.getBorderThickness()); + outlet_bounds.removeFromRight(m_outline.getResizeLength() - m_outline.getBorderThickness()); juce::Rectangle rect; @@ -451,16 +437,16 @@ namespace kiwi { if(m_outlets == 1 && index == 0) { - rect.setBounds(object_bounds.getX(), - object_bounds.getY() + object_bounds.getHeight() - getPinHeight(), + rect.setBounds(outlet_bounds.getX(), + outlet_bounds.getY() + outlet_bounds.getHeight() - getPinHeight(), getPinWidth(), getPinHeight()); } if(m_outlets > 1) { - const double ratio = (object_bounds.getWidth() - getPinWidth()) / (double)(m_outlets - 1); - rect.setBounds(object_bounds.getX() + ratio * index, - object_bounds.getY() + object_bounds.getHeight() - getPinHeight(), + const double ratio = (outlet_bounds.getWidth() - getPinWidth()) / (double)(m_outlets - 1); + rect.setBounds(outlet_bounds.getX() + ratio * index, + outlet_bounds.getY() + outlet_bounds.getHeight() - getPinHeight(), getPinWidth(), getPinHeight()); } } @@ -472,4 +458,199 @@ namespace kiwi { return m_patcher_view; } + + // ================================================================================ // + // OUTLINE // + // ================================================================================ // + + ObjectFrame::Outline::Border operator|(ObjectFrame::Outline::Border const& l_border, + ObjectFrame::Outline::Border const& r_border) + { + return static_cast(static_cast(l_border) | static_cast(r_border)); + } + + ObjectFrame::Outline::Outline(int resize_length, + int resize_thickness, + int inner_thickness): + juce::Component(), + m_resize_length(resize_length), + m_resize_thickness(resize_thickness), + m_inner_thickness(inner_thickness), + m_corners(), + m_borders(), + m_resize_colour(), + m_inner_colour() + { + } + + ObjectFrame::Outline::~Outline() + { + } + + int ObjectFrame::Outline::getBorderThickness() const + { + return m_resize_thickness; + } + + int ObjectFrame::Outline::getResizeLength() const + { + return m_resize_length; + } + + void ObjectFrame::Outline::updateCorners() + { + juce::Rectangle bounds = getLocalBounds(); + + std::array, 3> corner; + + corner[0].setBounds(bounds.getX(), + bounds.getY(), + m_resize_thickness, + m_resize_length); + + corner[1].setBounds(bounds.getX(), + bounds.getY(), + m_resize_length, + m_resize_thickness); + + corner[2] = corner[0]; + corner[2].reduceIfPartlyContainedIn(corner[1]); + + m_corners[Border::Top | Border::Left] = corner; + + juce::AffineTransform transform = juce::AffineTransform::rotation(M_PI / 2, bounds.getX(), bounds.getY()); + transform = transform.translated(bounds.getTopRight()); + + m_corners[Border::Top | Border::Right][0] = corner[0].transformedBy(transform); + m_corners[Border::Top | Border::Right][1] = corner[1].transformedBy(transform); + m_corners[Border::Top | Border::Right][2] = corner[2].transformedBy(transform); + + transform = juce::AffineTransform::rotation(M_PI); + transform = transform.translated(bounds.getBottomRight()); + + m_corners[Border::Bottom | Border::Right][0] = corner[0].transformedBy(transform); + m_corners[Border::Bottom | Border::Right][1] = corner[1].transformedBy(transform); + m_corners[Border::Bottom | Border::Right][2] = corner[2].transformedBy(transform); + + transform = juce::AffineTransform::rotation((3 * M_PI) / 2); + transform = transform.translated(bounds.getBottomLeft()); + + m_corners[Border::Bottom | Border::Left][0] = corner[0].transformedBy(transform); + m_corners[Border::Bottom | Border::Left][1] = corner[1].transformedBy(transform); + m_corners[Border::Bottom | Border::Left][2] = corner[2].transformedBy(transform); + } + + void ObjectFrame::Outline::updateBorders() + { + juce::Rectangle bounds = getLocalBounds(); + + m_borders[Border::Top].setBounds(m_resize_length, + m_resize_thickness - m_inner_thickness, + bounds.getWidth() - 2 * m_resize_length, + m_inner_thickness); + + m_borders[Border::Right].setBounds(bounds.getRight() - m_resize_thickness, + m_resize_length, + m_inner_thickness, + bounds.getHeight() - 2 * m_resize_length); + + m_borders[Border::Bottom].setBounds(m_resize_length, + getBottom() - m_resize_thickness, + bounds.getWidth() - 2 * m_resize_length, + m_inner_thickness); + + m_borders[Border::Left].setBounds(m_resize_thickness - m_inner_thickness, + m_resize_length, + m_inner_thickness, + bounds.getHeight() - 2 * m_resize_length); + } + + void ObjectFrame::Outline::resized() + { + updateBorders(); + updateCorners(); + } + + bool ObjectFrame::Outline::hitTest(juce::Point const& pt, HitTester& hit_tester) const + { + bool success = false; + + if (m_corners.at(Border::Left | Border::Top)[1].contains(pt) + || m_corners.at(Border::Top | Border::Right)[0].contains(pt)) + { + hit_tester.m_zone = HitTester::Zone::Border; + hit_tester.m_border |= HitTester::Border::Top; + success = true; + } + + if(m_corners.at(Border::Top | Border::Right)[1].contains(pt) + || m_corners.at(Border::Right | Border::Bottom)[0].contains(pt)) + { + hit_tester.m_zone = HitTester::Zone::Border; + hit_tester.m_border |= HitTester::Border::Right; + success = true; + } + + if(m_corners.at(Border::Right | Border::Bottom)[1].contains(pt) + || m_corners.at(Border::Bottom | Border::Left)[0].contains(pt)) + { + hit_tester.m_zone = HitTester::Zone::Border; + hit_tester.m_border |= HitTester::Border::Bottom; + success = true; + } + + if(m_corners.at(Border::Bottom | Border::Left)[1].contains(pt) + || m_corners.at(Border::Left | Border::Top)[0].contains(pt)) + { + hit_tester.m_zone = HitTester::Zone::Border; + hit_tester.m_border |= HitTester::Border::Left; + success = true; + } + + if(hit_tester.m_zone == HitTester::Zone::Border) + { + hit_tester.m_border &= ~HitTester::Border::None; + } + + + return success; + } + + void ObjectFrame::Outline::drawCorner(juce::Graphics & g, Border border) + { + g.setColour(m_resize_colour); + + g.fillRect(m_corners[border][2]); + g.fillRect(m_corners[border][1]); + } + + void ObjectFrame::Outline::drawBorder(juce::Graphics & g, Border border) + { + g.setColour(m_inner_colour); + + g.fillRect(m_borders[border]); + } + + void ObjectFrame::Outline::paint(juce::Graphics & g) + { + drawBorder(g, Border::Left); + drawBorder(g, Border::Top); + drawBorder(g, Border::Right); + drawBorder(g, Border::Bottom); + + drawCorner(g, Border::Left | Border::Top); + drawCorner(g, Border::Top | Border::Right); + drawCorner(g, Border::Right | Border::Bottom); + drawCorner(g, Border::Bottom | Border::Left); + } + + void ObjectFrame::Outline::setResizeColour(juce::Colour colour) + { + m_resize_colour = colour; + } + + void ObjectFrame::Outline::setInnerColour(juce::Colour colour) + { + m_inner_colour = colour; + } } diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.h index c45a459c..f5f4c10c 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.h @@ -53,6 +53,76 @@ namespace kiwi Pin = 0x1100003 }; + public: // classes + + struct Outline : public juce::Component + { + public: // classes + + enum class Border : int + { + Top = 1 << 0, + Bottom = 1 << 1, + Left = 1 << 2, + Right = 1 << 3 + }; + + public: // methods + + //! @brief Constructor. + //! @details Defines the resizable corner size, its thickness and the inner border thickness? + Outline(int resize_length, + int resize_thickness, + int inner_thickness); + + //! @brief Tests if the point reaches an interactive resiable corner. + bool hitTest(juce::Point const& pt, HitTester& hit_tester) const; + + //! @brief Returns the corner border width. + int getBorderThickness() const; + + //! @brief Returns the corner border length. + int getResizeLength() const; + + //! @brief Sets the corner colour. + void setResizeColour(juce::Colour colour); + + //! @brief Sets the inner border colour. + void setInnerColour(juce::Colour colour); + + ~Outline(); + + private: // methods + + //! @brief Draws a corner. + void drawCorner(juce::Graphics & g, Border border); + + //! @brief Draws a border. + void drawBorder(juce::Graphics & g, Border border); + + //! @brief Graphical rendering method. + void paint(juce::Graphics & g) override final; + + //! @brief Call once size changed. Recompute borders and corners position. + void resized() override final; + + //! @brief Update the corners position + void updateCorners(); + + //! @brief Update the borders position. + void updateBorders(); + + private: // members + + int m_resize_length; + int m_resize_thickness; + int m_inner_thickness; + std::map, 3>> m_corners; + std::map> m_borders; + juce::Colour m_resize_colour; + juce::Colour m_inner_colour; + }; + public: // methods //! @brief Constructor. @@ -69,10 +139,8 @@ namespace kiwi void editObject(); //! @brief Called by the patcher every time the selection status of this object has changed. - void localSelectionChanged(); - - //! @brief Called by the patcher every time the distant selection status of this object has changed. - void distantSelectionChanged(); + //! @details Function called when local selection or distant selection has changed. + void selectionChanged(); //! @brief Called every time a patcher is locked or unlocked. void lockStatusChanged(); @@ -115,9 +183,6 @@ namespace kiwi private: // methods - //! @brief Component's graphical rendering method. - void paint(juce::Graphics& g) override final; - //! @brief Paints outlets, inlets over child component. void paintOverChildren (juce::Graphics& g) override final; @@ -140,6 +205,10 @@ namespace kiwi //! @brief Called to update the bounds of the object. void updateBounds(bool animate); + //! @brief Updates the outline according to the selection status. + //! @details Makes it visible or not and updates its colour. + void updateOutline(); + //! @brief Called when the object's view size has changed. //! @details The obect frame adapts to fit the underlying object's size. void childBoundsChanged(juce::Component * child) override final; @@ -170,13 +239,13 @@ namespace kiwi private: // members - std::unique_ptr m_object_view; - PatcherView& m_patcher_view; - const size_t m_io_width; - const size_t m_io_height; - size_t m_selection_width; - size_t m_inlets; - size_t m_outlets; + std::unique_ptr m_object_view; + PatcherView& m_patcher_view; + const size_t m_io_width; + const size_t m_io_height; + size_t m_inlets; + size_t m_outlets; + Outline m_outline; private: // deleted methods diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp index 595472fa..b1552b90 100755 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp @@ -191,42 +191,6 @@ namespace kiwi m_mouse_handler.handleMouseDoubleClick(e); } - juce::MouseCursor::StandardCursorType PatcherView::getMouseCursorForBorder(int border_flag) const - { - juce::MouseCursor::StandardCursorType mc = juce::MouseCursor::NormalCursor; - - switch(border_flag) - { - case (HitTester::Border::Top) : - { mc = juce::MouseCursor::TopEdgeResizeCursor; break; } - - case (HitTester::Border::Left): - { mc = juce::MouseCursor::LeftEdgeResizeCursor; break; } - - case (HitTester::Border::Right): - { mc = juce::MouseCursor::RightEdgeResizeCursor; break; } - - case (HitTester::Border::Bottom): - { mc = juce::MouseCursor::BottomEdgeResizeCursor; break; } - - case (HitTester::Border::Top | HitTester::Border::Left): - { mc = juce::MouseCursor::TopLeftCornerResizeCursor; break; } - - case (HitTester::Border::Top | HitTester::Border::Right): - { mc = juce::MouseCursor::TopRightCornerResizeCursor; break;} - - case (HitTester::Border::Bottom | HitTester::Border::Left): - { mc = juce::MouseCursor::BottomLeftCornerResizeCursor; break; } - - case (HitTester::Border::Bottom | HitTester::Border::Right): - { mc = juce::MouseCursor::BottomRightCornerResizeCursor; break; } - - default: break; - } - - return mc; - } - void PatcherView::showPatcherPopupMenu(juce::Point const& position) { juce::PopupMenu m; @@ -287,12 +251,6 @@ namespace kiwi // SELECTION // // ================================================================================ // - void PatcherView::resizeSelectedObjects(juce::Point const& delta, - const long border_flag, const bool preserve_ratio) - { - // todo - } - void PatcherView::moveSelectedObjects(juce::Point const& delta, bool commit, bool commit_gesture) { for(auto* object : m_view_model.getSelectedObjects()) @@ -689,7 +647,8 @@ namespace kiwi bool PatcherView::keyPressed(const juce::KeyPress& key) { - if(m_mouse_handler.getCurrentAction() == MouseHandler::Action::MoveObject) + if(m_mouse_handler.getCurrentAction() == MouseHandler::Action::MoveObject || + m_mouse_handler.getCurrentAction() == MouseHandler::Action::ResizeObject) return false; // abort if(key.isKeyCode(juce::KeyPress::deleteKey) || key.isKeyCode(juce::KeyPress::backspaceKey)) @@ -1039,8 +998,11 @@ namespace kiwi { if(object.changed()) { - if(object.boundsChanged() && !patcher_area_uptodate && !view.removed() && - m_mouse_handler.getCurrentAction() != MouseHandler::Action::MoveObject) + if(object.boundsChanged() + && !patcher_area_uptodate + && !view.removed() + && m_mouse_handler.getCurrentAction() != MouseHandler::Action::MoveObject + && m_mouse_handler.getCurrentAction() != MouseHandler::Action::ResizeObject) { m_viewport.updatePatcherArea(true); patcher_area_uptodate = true; @@ -1252,6 +1214,8 @@ namespace kiwi } } + std::set updated_objects; + // check diff between old and new distant selection // and notify objects if their selection state changed for(auto& local_object_uptr : m_objects) @@ -1265,7 +1229,7 @@ namespace kiwi if(old_local_selected_state != new_local_selected_state) { - local_object_uptr->localSelectionChanged(); + updated_objects.insert(local_object_uptr.get()); selectionChanged(); } @@ -1283,7 +1247,7 @@ namespace kiwi // notify object if(distant_selection_changed_for_object) { - local_object_uptr->distantSelectionChanged(); + updated_objects.insert(local_object_uptr.get()); selectionChanged(); } } @@ -1293,6 +1257,13 @@ namespace kiwi // cache new selection state std::swap(m_distant_objects_selection, new_distant_objects_selection); std::swap(m_local_objects_selection, new_local_objects_selection); + + // call objects reaction. + + for(auto object_frame : updated_objects) + { + object_frame->selectionChanged(); + } } void PatcherView::checkLinksSelectionChanges(model::Patcher& patcher) @@ -1595,7 +1566,7 @@ namespace kiwi KiwiApp::error(error_box.getError()); } - if (!object_model->hasFlag(model::Object::Flag::DefinedSize)) + if (!object_model->hasFlag(model::Flag::IFlag::DefinedSize)) { const int text_width = juce::Font().getStringWidth(new_text) + 12; const int max_io = std::max(object_model->getNumberOfInlets(), diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.h b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.h index 6a6a54c2..a0f4a28c 100755 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.h @@ -290,13 +290,6 @@ namespace kiwi //! @brief Unselect all objects. void deleteSelection(); - //! @brief Resize selected objects by a given amount of pixels. - //! @param delta The given amount of pixel. - //! @param border_flag The border flag (see HitTester::Border enum) - //! @param preserve_ratio Should preserve box ratio - void resizeSelectedObjects(juce::Point const& delta, - const long border_flag, const bool preserve_ratio); - //! @brief Move selected objects by a given amount of pixels. //! @param delta The given amount of pixel. //! @param commit Pass false if you don't want to commit. @@ -370,9 +363,6 @@ namespace kiwi //! @brief Bring all object components in front of link ones. void bringsObjectsToFront(); - - //! Get the appropriate mouse cursor for a given border flag. - juce::MouseCursor::StandardCursorType getMouseCursorForBorder(int border_flag) const; private: // members diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewMouseHandler.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewMouseHandler.cpp index 2a84fb6a..646c39a0 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewMouseHandler.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewMouseHandler.cpp @@ -19,6 +19,10 @@ ============================================================================== */ +#include + +#include + #include #include #include @@ -35,7 +39,9 @@ namespace kiwi MouseHandler::MouseHandler(PatcherView & patcher_view): m_patcher_view(patcher_view), m_current_action(Action::None), - m_last_drag() + m_last_drag(), + m_mousedown_bounds(), + m_direction() { } @@ -183,6 +189,26 @@ namespace kiwi } break; } + case Action::ResizeObject: + { + m_direction = getResizeDirection(hit_tester); + + auto& document = m_patcher_view.m_patcher_model.entity().use(); + + for (flip::Ref const& ref : m_patcher_view.getSelectedObjects()) + { + model::Object const& object = *document.get(ref); + + m_mousedown_bounds[ref] = juce::Rectangle(object.getX(), + object.getY(), + object.getWidth(), + object.getHeight()); + } + + DocumentManager::startCommitGesture(m_patcher_view.m_patcher_model); + + break; + } default: { break; @@ -190,6 +216,63 @@ namespace kiwi } } + void MouseHandler::applyNewBounds(model::Object & object_model, juce::Rectangle new_bounds, double ratio) const + { + juce::ComponentBoundsConstrainer bounds_constrainer; + + if (!object_model.hasFlag(model::Flag::IFlag::ResizeWidth)) + { + bounds_constrainer.setMinimumWidth(object_model.getWidth()); + bounds_constrainer.setMaximumWidth(object_model.getWidth()); + } + else if (object_model.getMinWidth() != 0) + { + bounds_constrainer.setMinimumWidth(object_model.getMinWidth()); + } + + if (!object_model.hasFlag(model::Flag::IFlag::ResizeHeight)) + { + bounds_constrainer.setMinimumHeight(object_model.getHeight()); + bounds_constrainer.setMaximumHeight(object_model.getHeight()); + } + else if (object_model.getMinHeight() != 0) + { + bounds_constrainer.setMinimumHeight(object_model.getMinHeight()); + } + + if (object_model.getRatio() != 0) + { + bounds_constrainer.setFixedAspectRatio(1 / object_model.getRatio()); + } + else if (ratio != 0) + { + bounds_constrainer.setFixedAspectRatio(1 / ratio); + } + + juce::Rectangle limits = m_patcher_view.getBounds(); + + juce::Rectangle previous_bounds(object_model.getX(), + object_model.getY(), + object_model.getWidth(), + object_model.getHeight()); + + juce::Rectangle target_bounds = new_bounds; + + bounds_constrainer.checkBounds(target_bounds, + previous_bounds, + limits, + m_direction & Direction::Up, + m_direction & Direction::Left, + m_direction & Direction::Down, + m_direction & Direction::Right); + + object_model.setPosition(target_bounds.getX(), target_bounds.getY()); + + object_model.setWidth(target_bounds.getWidth()); + + object_model.setHeight(target_bounds.getHeight()); + } + void MouseHandler::continueAction(juce::MouseEvent const& e) { HitTester& hit_tester = m_patcher_view.m_hittester; @@ -300,6 +383,50 @@ namespace kiwi } break; } + case Action::ResizeObject: + { + juce::Point delta = e.getPosition() - e.getMouseDownPosition(); + + for (auto bounds_it : m_mousedown_bounds) + { + juce::Rectangle new_bounds = bounds_it.second; + + double ratio = 0.; + + if (e.mods.isShiftDown() && new_bounds.getWidth() != 0) + { + ratio = static_cast(new_bounds.getHeight()) / static_cast(new_bounds.getWidth()); + } + + if (m_direction & Direction::Left) + { + new_bounds.setLeft(std::min(new_bounds.getX() + delta.getX(), new_bounds.getRight())); + } + + if (m_direction & Direction::Up) + { + new_bounds.setTop(std::min(new_bounds.getY() + delta.getY(), new_bounds.getBottom())); + } + + if (m_direction & Direction::Right) + { + new_bounds.setRight(std::max(new_bounds.getRight() + delta.getX(), new_bounds.getX())); + } + + if (m_direction & Direction::Down) + { + new_bounds.setBottom(std::max(new_bounds.getBottom() + delta.getY(), new_bounds.getY())); + } + + auto& document = m_patcher_view.m_patcher_model.entity().use(); + + applyNewBounds(*document.get(bounds_it.first), new_bounds, ratio); + } + + DocumentManager::commitGesture(m_patcher_view.m_patcher_model, "Resize object"); + + break; + } default: { break; @@ -379,6 +506,19 @@ namespace kiwi m_patcher_view.editObject(object); break; } + case Action::ResizeObject: + { + m_direction = Direction::None; + m_mousedown_bounds.clear(); + + DocumentManager::endCommitGesture(m_patcher_view.m_patcher_model); + + m_patcher_view.m_viewport.updatePatcherArea(true); + + m_patcher_view.m_viewport.jumpViewToObject(*hit_tester.getObject()); + + break; + } case Action::SwitchLock: { m_patcher_view.setLock(!m_patcher_view.isLocked()); @@ -443,6 +583,10 @@ namespace kiwi { startAction(Action::CreateLink, e); } + else if (hit_tester.getZone() == HitTester::Zone::Border) + { + startAction(Action::ResizeObject, e); + } } else if(hit_tester.linkTouched()) { @@ -526,6 +670,91 @@ namespace kiwi } } + int MouseHandler::getResizeDirection(HitTester const& hit_tester) const + { + int border = hit_tester.getBorder(); + + int direction = Direction::None; + + model::Object const& object_model = hit_tester.getObject()->getModel(); + + if ((border & HitTester::Border::Top) && object_model.hasFlag(model::Flag::IFlag::ResizeHeight)) + { + direction |= Direction::Up; + } + + if ((border & HitTester::Border::Right) && object_model.hasFlag(model::Flag::IFlag::ResizeWidth)) + { + direction |= Direction::Right; + } + + if ((border & HitTester::Border::Bottom) && object_model.hasFlag(model::Flag::IFlag::ResizeHeight)) + { + direction |= Direction::Down; + } + + if ((border & HitTester::Border::Left) && object_model.hasFlag(model::Flag::IFlag::ResizeWidth)) + { + direction |= Direction::Left; + } + + return direction; + } + + juce::MouseCursor::StandardCursorType MouseHandler::getMouseCursorForBorder(HitTester const& hit_tester) const + { + juce::MouseCursor::StandardCursorType mc = juce::MouseCursor::NormalCursor; + + int direction = getResizeDirection(hit_tester); + + switch(direction) + { + case (Direction::Up) : + { + mc = juce::MouseCursor::TopEdgeResizeCursor; + break; + } + case (Direction::Left): + { + mc = juce::MouseCursor::LeftEdgeResizeCursor; + break; + } + case (Direction::Right): + { + mc = juce::MouseCursor::RightEdgeResizeCursor; + break; + } + case (Direction::Down): + { + mc = juce::MouseCursor::BottomEdgeResizeCursor; + break; + } + case (Direction::Up | Direction::Left): + { + mc = juce::MouseCursor::TopLeftCornerResizeCursor; + break; + } + case (Direction::Up | Direction::Right): + { + mc = juce::MouseCursor::TopRightCornerResizeCursor; + break; + } + case (Direction::Down | Direction::Left): + { + mc = juce::MouseCursor::BottomLeftCornerResizeCursor; + break; + } + case (Direction::Down | Direction::Right): + { + mc = juce::MouseCursor::BottomRightCornerResizeCursor; + break; + } + default: break; + } + + return mc; + } + void MouseHandler::handleMouseMove(juce::MouseEvent const& e) { juce::MouseCursor::StandardCursorType mc = juce::MouseCursor::NormalCursor; @@ -546,7 +775,7 @@ namespace kiwi { if(hit_tester.getZone() == HitTester::Zone::Border) { - mc = m_patcher_view.getMouseCursorForBorder(hit_tester.getBorder()); + mc = getMouseCursorForBorder(hit_tester); } else if(hit_tester.getZone() == HitTester::Zone::Outlet || hit_tester.getZone() == HitTester::Zone::Inlet) diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewMouseHandler.h b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewMouseHandler.h index 64cea6a5..950bb2c0 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewMouseHandler.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewMouseHandler.h @@ -21,10 +21,18 @@ #pragma once +#include + #include #include +#include + +#include + + + namespace kiwi { class PatcherView; @@ -52,7 +60,17 @@ namespace kiwi ObjectEdition = 7, SwitchSelection = 8, Selection = 9, - SwitchLock = 10 + SwitchLock = 10, + ResizeObject = 11 + }; + + enum Direction : int + { + None = 0, + Up = 1 << 0, + Down = 1 << 1, + Left = 1 << 2, + Right = 1 << 3 }; public: // methods @@ -92,11 +110,23 @@ namespace kiwi //! @brief Ends an ongoing interaction with patch. void endAction(juce::MouseEvent const& e); + //! @brief Returns the resize direction according to the hit_tester. + int getResizeDirection(HitTester const& hit_tester) const; + + //! @brief Applies new bounds to a object model. + //! @details If ratio is set, the function will keep this ratio will resizing. + void applyNewBounds(model::Object & object_model, juce::Rectangle new_bounds, double ratio = 0.) const; + + //! @brief Returns the right resize mouse cursor. + juce::MouseCursor::StandardCursorType getMouseCursorForBorder(HitTester const& hit_tester) const; + private: // members PatcherView & m_patcher_view; Action m_current_action; juce::Point m_last_drag; + std::map> m_mousedown_bounds; + int m_direction; private: // deleted methods diff --git a/Modules/KiwiModel/KiwiModel_Object.cpp b/Modules/KiwiModel/KiwiModel_Object.cpp index 44c660a1..4329b615 100755 --- a/Modules/KiwiModel/KiwiModel_Object.cpp +++ b/Modules/KiwiModel/KiwiModel_Object.cpp @@ -125,6 +125,46 @@ namespace kiwi .member("type"); }; + // ================================================================================ // + // FLAG // + // ================================================================================ // + + Flag::Flag(Flag::IFlag flag): + flip::Object(), + m_flag(flag) + { + } + + Flag::Flag(flip::Default& d): + flip::Object() + { + } + + void Flag::declare() + { + if(DataModel::has()) return; + + DataModel::declare() + .name("cicm.kiwi.iflag") + .enumerator("DefinedSize") + .enumerator("ResizeWidth") + .enumerator("ResizeHeight"); + + DataModel::declare() + .name("cicm.kiwi.flag") + .member, &Flag::m_flag>("flag"); + } + + bool Flag::operator==(Flag const& other) const + { + return m_flag.value() == other.m_flag.value(); + } + + bool Flag::operator!=(Flag const& other) const + { + return !this->operator==(other); + } + // ================================================================================ // // OBJECT::declare // // ================================================================================ // @@ -135,6 +175,7 @@ namespace kiwi Outlet::declare(); Inlet::declare(); + Flag::declare(); DataModel::declare() .name("cicm.kiwi.Object") @@ -142,10 +183,14 @@ namespace kiwi .member("text") .member, &Object::m_inlets>("inlets") .member, &Object::m_outlets>("outlets") + .member, &Object::m_flags>("flags") .member("pos_x") .member("pos_y") .member("width") - .member("height"); + .member("height") + .member("min_width") + .member("min_height") + .member("ratio"); } // ================================================================================ // @@ -165,7 +210,10 @@ namespace kiwi m_position_x(0.), m_position_y(0.), m_width(60.), - m_height(20.) + m_height(20.), + m_min_width(0.), + m_min_height(0.), + m_ratio(0.) { ; } @@ -255,14 +303,79 @@ namespace kiwi return !removed() ? m_position_y.value() : m_position_y.before(); } + void Object::setRatio(double ratio) + { + if (ratio > 0.) + { + m_ratio = ratio; + m_height = m_width * m_ratio; + m_min_height = m_min_width * m_ratio; + } + } + + double Object::getRatio() const + { + return m_ratio; + } + + void Object::setMinWidth(double min_width) + { + if (min_width >= 0.) + { + m_min_width = min_width; + + if (m_ratio > 0.) + { + m_min_height = m_min_width * m_ratio; + } + + setWidth(getWidth()); + } + } + + void Object::setMinHeight(double min_height) + { + if (min_height >= 0.) + { + m_min_height = min_height; + + if (m_ratio > 0.) + { + m_min_width = m_min_height / m_ratio; + } + + setHeight(getHeight()); + } + } + void Object::setWidth(double new_width) { - m_width = std::max(0., new_width); + m_width = std::max(m_min_width.value(), new_width); + + if (m_ratio > 0.) + { + m_height = m_ratio * m_width; + } } void Object::setHeight(double new_height) { - m_height = std::max(0., new_height); + m_height = std::max(m_min_height.value(), new_height); + + if (m_ratio > 0.) + { + m_width = m_height / m_ratio; + } + } + + double Object::getMinWidth() const noexcept + { + return m_min_width.value(); + } + + double Object::getMinHeight() const noexcept + { + return m_min_height.value(); } double Object::getWidth() const noexcept @@ -302,12 +415,15 @@ namespace kiwi bool Object::hasFlag(Flag flag) const { - return (static_cast(flag) & static_cast(m_flags.value())) != 0; + return m_flags.count_if([&flag](Flag const& internal_flag) { return internal_flag == flag;}) != 0; } void Object::setFlag(Flag flag) { - m_flags = static_cast(static_cast(flag) | static_cast(m_flags.value())); + if (!hasFlag(flag)) + { + m_flags.insert(flag); + } } } } diff --git a/Modules/KiwiModel/KiwiModel_Object.h b/Modules/KiwiModel/KiwiModel_Object.h index 818b6eb4..367a8185 100755 --- a/Modules/KiwiModel/KiwiModel_Object.h +++ b/Modules/KiwiModel/KiwiModel_Object.h @@ -144,6 +144,42 @@ namespace kiwi PinType m_type; }; + //! @brief Class that represents an object's property. + //! @details Adding, removing new flags is a data model change and needs migration. + class Flag : public flip::Object + { + public: // classes + + //! @brief The internal enum representation of the flag. + enum class IFlag + { + DefinedSize = 0, // Initial object's Size defined by the model. + ResizeWidth, // Object is resizable horizontally. + ResizeHeight // Object is resizable vertically. + }; + + public: // methods + + //! @brief Flag constructor. + Flag(Flag::IFlag flag); + + //! @brief Flip default constructor. + Flag(flip::Default& d); + + //! @brief Checks if flags are equals. + bool operator==(Flag const& other) const; + + //! @brief Checks if flags are differents. + bool operator!=(Flag const& other) const; + + //! @internal Flip declarator. + static void declare(); + + private: // members + + flip::Enum m_flag; + }; + // ================================================================================ // // OBJECT // @@ -157,11 +193,6 @@ namespace kiwi using SignalKey = uint32_t; - enum class Flag : unsigned int - { - DefinedSize = 1 << 0 // Initial object's Size defined by the model. - }; - public: // methods //! @brief Constructor. @@ -219,10 +250,17 @@ namespace kiwi double getY() const noexcept; //! @brief Sets the width of the object. + //! @details Width will not be lower than minimal width. + //! If ratio was previously set proportions will be kept intact by changing height. void setWidth(double new_width); //! @brief Sets the height of the object. + //! @details Height will not be lower than minimal height. + //! If ratio was previously set proportions will be kept intact by changing width. void setHeight(double new_height); + + //! @brief Returns the aspect ratio. + double getRatio() const; //! @brief Returns the object's width. double getWidth() const noexcept; @@ -230,6 +268,12 @@ namespace kiwi //! @brief Returns the object's height. double getHeight() const noexcept; + //! @brief Returns the minimal width for this object. + double getMinWidth() const noexcept; + + //! @brief Returns the minimal height for this object; + double getMinHeight() const noexcept; + //! @brief Returns inlet or outlet description. virtual std::string getIODescription(bool is_inlet, size_t index) const; @@ -269,7 +313,19 @@ namespace kiwi //! @brief Adds an outlet at end of current outlet list. void pushOutlet(PinType type); - + + //! @brief Sets the ratio height/width. + //! @details If width was previously set. Height will adapt to ratio. + void setRatio(double ratio); + + //! @brief Sets the minimal width that the object can have. + //! @details Will recompute height and width if needed. + void setMinWidth(double min_width); + + //! @brief Sets the minimal height that the object can have. + //! @details Will recompute height and width if needed. + void setMinHeight(double min_height); + public: // internal methods //! @internal flip Default constructor @@ -282,16 +338,20 @@ namespace kiwi std::map> m_signals; - flip::String m_name; - flip::String m_text; - flip::Array m_inlets; - flip::Array m_outlets; - flip::Enum m_flags; + flip::String m_name; + flip::String m_text; + flip::Array m_inlets; + flip::Array m_outlets; + flip::Collection m_flags; flip::Float m_position_x; flip::Float m_position_y; flip::Float m_width; flip::Float m_height; + flip::Float m_min_width; + flip::Float m_min_height; + flip::Float m_ratio; + friend class Factory; diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_NewBox.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_NewBox.cpp index 77bfd2e3..6e874973 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_NewBox.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_NewBox.cpp @@ -39,7 +39,7 @@ namespace kiwi NewBox::NewBox(std::string const& name, std::vector const& args) { - setFlag(Flag::DefinedSize); + setFlag(Flag::IFlag::DefinedSize); setWidth(80); setHeight(20); pushInlet({PinType::IType::Control}); diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Bang.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Bang.cpp index d6ae18e8..d337e6d0 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Bang.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Bang.cpp @@ -39,10 +39,13 @@ namespace kiwi throw std::runtime_error("wrong arguments for object bang"); } - setFlag(Flag::DefinedSize); + setFlag(Flag::IFlag::DefinedSize); + setFlag(Flag::IFlag::ResizeWidth); + setFlag(Flag::IFlag::ResizeHeight); addSignal<>(Signal::TriggerBang, *this); + setRatio(1.); + setMinWidth(20.); setWidth(20); - setHeight(20); pushInlet({PinType::IType::Control}); pushOutlet(PinType::IType::Control); } diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Toggle.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Toggle.cpp index dab1ffb6..db287f74 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Toggle.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Toggle.cpp @@ -39,10 +39,13 @@ namespace kiwi throw std::runtime_error("wrong arguments for object bang"); } - setFlag(Flag::DefinedSize); + setFlag(Flag::IFlag::DefinedSize); + setFlag(Flag::IFlag::ResizeWidth); + setFlag(Flag::IFlag::ResizeHeight); addSignal(Signal::Switch, *this); + setRatio(1.); + setMinWidth(20.); setWidth(20); - setHeight(20); pushInlet({PinType::IType::Control}); pushOutlet(PinType::IType::Control); } From 43cb95823f17ec41182765cfa36504887bb11a0b Mon Sep 17 00:00:00 2001 From: jean-millot Date: Wed, 20 Sep 2017 18:14:54 +0200 Subject: [PATCH 061/148] Adding slider object. --- .../KiwiApp_General/KiwiApp_CommandIDs.h | 1 + .../KiwiApp_Patcher/KiwiApp_Factory.cpp | 1 + .../KiwiApp_Controller/KiwiApp_SliderView.cpp | 156 ++++++++++++++++++ .../KiwiApp_Controller/KiwiApp_SliderView.h | 79 +++++++++ .../KiwiApp_Objects/KiwiApp_ObjectFrame.cpp | 9 +- .../KiwiApp_Objects/KiwiApp_ObjectFrame.h | 3 + .../KiwiApp_Objects/KiwiApp_ObjectView.cpp | 2 +- .../KiwiApp_Objects/KiwiApp_Objects.h | 1 + .../KiwiApp_Patcher/KiwiApp_PatcherView.cpp | 11 ++ .../KiwiApp_PatcherViewMouseHandler.cpp | 2 +- Modules/KiwiEngine/KiwiEngine_Instance.cpp | 1 + .../KiwiEngine_Slider.cpp | 105 ++++++++++++ .../KiwiEngine_Controller/KiwiEngine_Slider.h | 64 +++++++ .../KiwiEngine_Objects/KiwiEngine_Objects.h | 1 + Modules/KiwiModel/KiwiModel_DataModel.cpp | 1 + .../KiwiModel_Controller/KiwiModel_Slider.cpp | 77 +++++++++ .../KiwiModel_Controller/KiwiModel_Slider.h | 57 +++++++ .../KiwiModel_Objects/KiwiModel_Objects.h | 1 + 18 files changed, 568 insertions(+), 4 deletions(-) create mode 100644 Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_SliderView.cpp create mode 100644 Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_SliderView.h create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Slider.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Slider.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Slider.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Slider.h diff --git a/Client/Source/KiwiApp_General/KiwiApp_CommandIDs.h b/Client/Source/KiwiApp_General/KiwiApp_CommandIDs.h index aa8a0e94..d9f764f0 100644 --- a/Client/Source/KiwiApp_General/KiwiApp_CommandIDs.h +++ b/Client/Source/KiwiApp_General/KiwiApp_CommandIDs.h @@ -73,6 +73,7 @@ namespace kiwi newComment = 0xf30304, ///< Add a new "comment" object box to the patcher. newBang = 0xf30305, ///< Add a new "button" object box to the patcher. newToggle = 0xf30306, ///< Add a new "toggle" object box to the patcher. + newSlider = 0xf30307, ///< Add a new "slider" object box to the patcher. showPatcherInspector = 0xf20400, ///< Shows the patcher properties inspector. diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Factory.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Factory.cpp index c969facf..0b0ad556 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Factory.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Factory.cpp @@ -50,5 +50,6 @@ namespace kiwi { add("bang"); add("toggle"); + add("slider"); } } diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_SliderView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_SliderView.cpp new file mode 100644 index 00000000..7456a2ba --- /dev/null +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_SliderView.cpp @@ -0,0 +1,156 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include + +#include + +#include + +#include +#include + +namespace kiwi +{ + // ================================================================================ // + // SLIDER VIEW // + // ================================================================================ // + + class SliderView::Task final : public engine::Scheduler<>::Task + { + public: // methods + + Task(SliderView & object, double new_value): + engine::Scheduler<>::Task(), + m_object(object), + m_new_value(new_value) + { + } + + ~Task() + { + } + + void execute() + { + m_object.m_slider.setValue(m_new_value, juce::NotificationType::dontSendNotification); + m_object.repaint(); + + std::shared_ptr task; + m_object.m_tasks.pop(task); + } + + private: // members + + SliderView & m_object; + double m_new_value; + }; + + SliderView::SliderView(model::Object & object_model): + ObjectView(object_model), + m_slider(juce::Slider::SliderStyle::LinearVertical, juce::Slider::TextEntryBoxPosition::NoTextBox), + m_signal(object_model.getSignal(model::Slider::Signal::ValueChanged)), + m_connection(m_signal.connect(std::bind(&SliderView::valueChanged, this, std::placeholders::_1))), + m_tasks(100) + { + m_slider.setColour(juce::Slider::ColourIds::backgroundColourId, + findColour(ObjectView::ColourIds::Outline)); + + m_slider.setColour(juce::Slider::ColourIds::trackColourId, + findColour(ObjectView::ColourIds::Active).darker(0.5)); + + m_slider.setColour(juce::Slider::ColourIds::thumbColourId, + findColour(ObjectView::ColourIds::Active)); + + m_slider.setRange(0., 1.); + + m_slider.setVelocityModeParameters(1., 1, 0., false); + + m_slider.addListener(this); + + addAndMakeVisible(m_slider); + } + + SliderView::~SliderView() + { + while(m_tasks.load_size() > 0) + { + std::shared_ptr task; + m_tasks.pop(task); + KiwiApp::useInstance().useScheduler().unschedule(task); + } + + m_slider.removeListener(this); + } + + void SliderView::paint(juce::Graphics & g) + { + g.setColour(findColour(ObjectView::ColourIds::Background)); + g.fillRect(getLocalBounds()); + + g.setColour(findColour(ObjectView::ColourIds::Outline)); + drawOutline(g); + } + + void SliderView::mouseDown(juce::MouseEvent const& e) + { + m_slider.mouseDown(e.getEventRelativeTo(&m_slider)); + } + + void SliderView::mouseUp(juce::MouseEvent const& e) + { + m_slider.mouseUp(e.getEventRelativeTo(&m_slider)); + } + + void SliderView::mouseDrag(juce::MouseEvent const& e) + { + m_slider.mouseDrag(e.getEventRelativeTo(&m_slider)); + } + + void SliderView::sliderValueChanged(juce::Slider * slider) + { + m_signal(slider->getValue()); + } + + void SliderView::resized() + { + if (getWidth() > getHeight() && m_slider.isVertical()) + { + m_slider.setSliderStyle(juce::Slider::SliderStyle::LinearHorizontal); + } + + if (getHeight() > getWidth() && m_slider.isHorizontal()) + { + m_slider.setSliderStyle(juce::Slider::SliderStyle::LinearVertical); + } + + m_slider.setBounds(getLocalBounds()); + } + + void SliderView::valueChanged(double new_value) + { + std::shared_ptr task(new Task(*this, new_value)); + m_tasks.push(task); + KiwiApp::useInstance().useScheduler().schedule(task); + } +} diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_SliderView.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_SliderView.h new file mode 100644 index 00000000..7aa50234 --- /dev/null +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_SliderView.h @@ -0,0 +1,79 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +#include + +#include + +namespace kiwi +{ + // ================================================================================ // + // SLIDER VIEW // + // ================================================================================ // + + class SliderView : public ObjectView, juce::Slider::Listener + { + private: // classes + + class Task; + + public: // methods + + SliderView(model::Object & object_model); + + ~SliderView(); + + private: // methods + + void sliderValueChanged(juce::Slider * slider) override final; + + void paint(juce::Graphics & g) override final; + + void mouseDown(juce::MouseEvent const& e) override final; + + void mouseUp(juce::MouseEvent const& e) override final; + + void mouseDrag(juce::MouseEvent const& e) override final; + + void resized() override final; + + void valueChanged(double new_value); + + private: // members + + juce::Slider m_slider; + flip::Signal & m_signal; + flip::SignalConnection m_connection; + engine::ConcurrentQueue> m_tasks; + + private: // delted methods + + SliderView() = delete; + SliderView(SliderView const& other) = delete; + SliderView(SliderView && other) = delete; + SliderView& operator=(SliderView const& other) = delete; + SliderView& operator=(SliderView && other) = delete; + }; +} diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.cpp index bc99eba6..033bd511 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.cpp @@ -131,12 +131,17 @@ namespace kiwi void ObjectFrame::mouseDown(juce::MouseEvent const& e) { - m_object_view->mouseDown(e); + m_object_view->mouseDown(e.getEventRelativeTo(m_object_view.get())); } void ObjectFrame::mouseUp(juce::MouseEvent const& e) { - m_object_view->mouseUp(e); + m_object_view->mouseUp(e.getEventRelativeTo(m_object_view.get())); + } + + void ObjectFrame::mouseDrag(juce::MouseEvent const& e) + { + m_object_view->mouseDrag(e.getEventRelativeTo(m_object_view.get())); } bool ObjectFrame::hitTest(int x, int y) diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.h index f5f4c10c..892df45e 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.h @@ -180,6 +180,9 @@ namespace kiwi //! @brief Called when object's frame is clicked. void mouseUp(juce::MouseEvent const& e) override final; + + //! @brief Called when object's frame is clicked. + void mouseDrag(juce::MouseEvent const& e) override final; private: // methods diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectView.cpp index 21bbe4aa..0edbd442 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectView.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectView.cpp @@ -39,7 +39,7 @@ namespace kiwi setColour(ObjectView::ColourIds::Text, juce::Colours::black); setColour(ObjectView::ColourIds::Outline, juce::Colours::black); setColour(ObjectView::ColourIds::Highlight, juce::Colour::fromFloatRGBA(0., 0.5, 1., 0.)); - setColour(ObjectView::ColourIds::Active, juce::Colour::fromFloatRGBA(0.2, 0.8, 0.2, 1.)); + setColour(ObjectView::ColourIds::Active, juce::Colour(0xff21ba90)); } ObjectView::~ObjectView() diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Objects.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Objects.h index 74158797..c958de12 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Objects.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Objects.h @@ -33,3 +33,4 @@ #include #include +#include diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp index b1552b90..55fb0db0 100755 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp @@ -1846,6 +1846,7 @@ namespace kiwi commands.add(CommandIDs::newBox); commands.add(CommandIDs::newBang); commands.add(CommandIDs::newToggle); + commands.add(CommandIDs::newSlider); commands.add(CommandIDs::zoomIn); commands.add(CommandIDs::zoomOut); @@ -1983,6 +1984,15 @@ namespace kiwi result.setActive(!isLocked()); break; } + case CommandIDs::newSlider: + { + result.setInfo(TRANS("New Slider Box"), + TRANS("Add a new slider"), + CommandCategories::editing, 0); + result.addDefaultKeypress('s', juce::ModifierKeys::noModifiers); + result.setActive(!isLocked()); + break; + } case CommandIDs::zoomIn: { result.setInfo(TRANS("Zoom in"), TRANS("Zoom in"), CommandCategories::view, 0); @@ -2053,6 +2063,7 @@ namespace kiwi case CommandIDs::newBox: { createObjectModel("", true); break; } case CommandIDs::newBang: { createObjectModel("bang", true); break; } case CommandIDs::newToggle: { createObjectModel("toggle", true); break; } + case CommandIDs::newSlider: { createObjectModel("slider", true); break; } case CommandIDs::zoomIn: { zoomIn(); break; } case CommandIDs::zoomOut: { zoomOut(); break; } diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewMouseHandler.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewMouseHandler.cpp index 646c39a0..f0057f15 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewMouseHandler.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewMouseHandler.cpp @@ -39,7 +39,7 @@ namespace kiwi MouseHandler::MouseHandler(PatcherView & patcher_view): m_patcher_view(patcher_view), m_current_action(Action::None), - m_last_drag(), + m_last_drag(), m_mousedown_bounds(), m_direction() { diff --git a/Modules/KiwiEngine/KiwiEngine_Instance.cpp b/Modules/KiwiEngine/KiwiEngine_Instance.cpp index 2e2e8287..6bce0620 100644 --- a/Modules/KiwiEngine/KiwiEngine_Instance.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Instance.cpp @@ -101,6 +101,7 @@ namespace kiwi engine::Factory::add("delaysimple~"); engine::Factory::add("bang"); engine::Factory::add("toggle"); + engine::Factory::add("slider"); } // ================================================================================ // diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Slider.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Slider.cpp new file mode 100644 index 00000000..b528163e --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Slider.cpp @@ -0,0 +1,105 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +#include + +#include +#include + +namespace kiwi { namespace engine { + + class Slider::Task final : public Scheduler<>::Task + { + public: // methods + + Task(double output_value, Slider & slider): + m_output_value(output_value), + m_slider(slider) + { + } + + ~Task() + { + } + + void execute() + { + m_slider.m_value = m_output_value; + m_slider.send(0, {m_slider.m_value}); + } + + private: // members + + double m_output_value; + Slider & m_slider; + }; + + // ================================================================================ // + // OBJECT SLIDER // + // ================================================================================ // + + Slider::Slider(model::Object const& object_model, Patcher& patcher, std::vector const& args): + Object(object_model, patcher), + m_signal(object_model.getSignal(model::Slider::Signal::ValueChanged)), + m_connection(m_signal.connect(std::bind(&Slider::valueChanged, this, std::placeholders::_1))), + m_tasks(100), + m_value(0) + { + } + + + Slider::~Slider() + { + while(m_tasks.load_size() > 0) + { + std::shared_ptr task; + m_tasks.pop(task); + getScheduler().unschedule(task); + } + } + + void Slider::valueChanged(double new_value) + { + std::shared_ptr task(new Task(new_value, *this)); + m_tasks.push(task); + getScheduler().schedule(task); + } + + void Slider::receive(size_t index, std::vector const& args) + { + if (index == 0 && !args.empty()) + { + if (args[0].isNumber()) + { + m_signal(std::max(0., std::min(args[0].getFloat(), 1.))); + } + else if (args[0].isString() && args[0].getString() == "bang") + { + send(0, {m_value}); + } + } + } + +}} + diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Slider.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Slider.h new file mode 100644 index 00000000..11ddbe23 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Slider.h @@ -0,0 +1,64 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include +#include + +#include + +#include +#include + +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OBJECT BANG // + // ================================================================================ // + + class Slider : public engine::Object + { + private: // classes + + class Task; + + public: // methods + + Slider(model::Object const& model, Patcher& patcher, std::vector const& args); + + ~Slider(); + + void valueChanged(double new_value); + + void receive(size_t index, std::vector const& args) override final; + + private: // members + + flip::Signal & m_signal; + flip::SignalConnection m_connection; + engine::ConcurrentQueue> m_tasks; + double m_value; + }; + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h index 5c03ee95..eaf551b3 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h @@ -69,3 +69,4 @@ #include #include +#include diff --git a/Modules/KiwiModel/KiwiModel_DataModel.cpp b/Modules/KiwiModel/KiwiModel_DataModel.cpp index 2410c6c7..9fba2827 100644 --- a/Modules/KiwiModel/KiwiModel_DataModel.cpp +++ b/Modules/KiwiModel/KiwiModel_DataModel.cpp @@ -80,6 +80,7 @@ namespace kiwi DelaySimpleTilde::declare(); Bang::declare(); Toggle::declare(); + Slider::declare(); } } } diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Slider.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Slider.cpp new file mode 100755 index 00000000..bd3f34ff --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Slider.cpp @@ -0,0 +1,77 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT SLIDER // + // ================================================================================ // + + Slider::Slider(std::string const& name, std::vector const& args): + Object() + { + if (!args.empty()) + { + throw std::runtime_error("wrong arguments for object bang"); + } + + setFlag(Flag::IFlag::DefinedSize); + setFlag(Flag::IFlag::ResizeWidth); + setFlag(Flag::IFlag::ResizeHeight); + addSignal(Signal::ValueChanged, *this); + setMinWidth(20.); + setMinHeight(20.); + setWidth(20); + setHeight(50.); + pushInlet({PinType::IType::Control}); + pushOutlet(PinType::IType::Control); + } + + Slider::Slider(flip::Default& d): + Object(d) + { + addSignal(Signal::ValueChanged, *this); + } + + void Slider::declare() + { + Factory::add("slider"); + } + + std::string Slider::getIODescription(bool is_inlet, size_t index) const + { + if (is_inlet && index == 0) + { + return "Sets current slider value. Value is between 0 and 1"; + } + else if(!is_inlet && index == 0) + { + return "Outputs the slider's value"; + } + else + { + return ""; + } + } +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Slider.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Slider.h new file mode 100755 index 00000000..3110f466 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Slider.h @@ -0,0 +1,57 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include +#include + +#include + +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT SLIDER // + // ================================================================================ // + + class Slider : public model::Object + { + public: // enums + + enum Signal : SignalKey + { + ValueChanged + }; + + public: // methods + + Slider(flip::Default& d); + + Slider(std::string const& name, std::vector const& args); + + std::string getIODescription(bool is_inlet, size_t index) const override; + + static void declare(); + }; +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h index c2e118b5..ed6b6a12 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h @@ -69,4 +69,5 @@ #include #include +#include From 8a99ad85ba519b4b3b93420413d0df593c8e3faa Mon Sep 17 00:00:00 2001 From: jmillot Date: Thu, 5 Oct 2017 20:21:13 +0200 Subject: [PATCH 062/148] Adding meter object. --- .../KiwiApp_Patcher/KiwiApp_Factory.cpp | 1 + .../KiwiApp_Dsp/KiwiApp_MeterTildeView.cpp | 185 ++++++++++++++++++ .../KiwiApp_Dsp/KiwiApp_MeterTildeView.h | 102 ++++++++++ .../KiwiApp_Objects/KiwiApp_Objects.h | 6 + Modules/KiwiEngine/KiwiEngine_Instance.cpp | 1 + .../KiwiEngine_Dsp/KiwiEngine_MeterTilde.cpp | 98 ++++++++++ .../KiwiEngine_Dsp/KiwiEngine_MeterTilde.h | 77 ++++++++ .../KiwiEngine_Objects/KiwiEngine_Objects.h | 1 + Modules/KiwiModel/KiwiModel_DataModel.cpp | 1 + .../KiwiModel_Dsp/KiwiModel_MeterTilde.cpp | 79 ++++++++ .../KiwiModel_Dsp/KiwiModel_MeterTilde.h | 57 ++++++ .../KiwiModel_Objects/KiwiModel_Objects.h | 1 + 12 files changed, 609 insertions(+) create mode 100644 Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Dsp/KiwiApp_MeterTildeView.cpp create mode 100644 Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Dsp/KiwiApp_MeterTildeView.h create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_MeterTilde.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_MeterTilde.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_MeterTilde.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_MeterTilde.h diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Factory.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Factory.cpp index 0b0ad556..bc4e393b 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Factory.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Factory.cpp @@ -51,5 +51,6 @@ namespace kiwi add("bang"); add("toggle"); add("slider"); + add("meter~"); } } diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Dsp/KiwiApp_MeterTildeView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Dsp/KiwiApp_MeterTildeView.cpp new file mode 100644 index 00000000..cf755cc7 --- /dev/null +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Dsp/KiwiApp_MeterTildeView.cpp @@ -0,0 +1,185 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +#include + +#include + +#include + +#include + +namespace kiwi +{ + // ================================================================================ // + // METER~ VIEW // + // ================================================================================ // + + class MeterTildeView::Task : public engine::Scheduler<>::Task + { + public: // methods + + Task(MeterTildeView & meter, float peak_value): + m_meter(meter), + m_peak_value(peak_value) + { + } + + ~Task() + { + } + + void execute() override final + { + float peak_db = 20 * log10(m_peak_value); + m_meter.computeActiveLed(peak_db); + m_meter.repaint(); + } + + private: // members + + MeterTildeView & m_meter; + float m_peak_value; + }; + + MeterTildeView::MeterTildeView(model::Object & object_model): + ObjectView(object_model), + m_leds(), + m_active_led(-1), + m_cold_colour(juce::Colour(0xff04047f)), + m_hot_colour(juce::Colour(0xffca2423)), + m_border(5), + m_padding(1), + m_connection(object_model.getSignal(model::MeterTilde::Signal::PeakChanged) + .connect(std::bind(&MeterTildeView::peakChanged, this, std::placeholders::_1))), + m_tasks(10) + { + size_t num_leds = 12; + + for(int i = 0; i < num_leds; ++i) + { + float min_db = - 3. * (num_leds - (i + 1)); + + m_leds.push_back({min_db, + computeGradientColour(( static_cast(i) / (num_leds - 1))), + juce::Rectangle()}); + } + } + + MeterTildeView::~MeterTildeView() + { + while(m_tasks.load_size() > 0) + { + std::shared_ptr task; + m_tasks.pop(task); + KiwiApp::useInstance().useScheduler().unschedule(task); + } + } + + void MeterTildeView::resized() + { + juce::AffineTransform transform; + + if (getHeight() > getWidth()) + { + transform = juce::AffineTransform::translation(-getLocalBounds().getCentre()); + transform = transform.followedBy(juce::AffineTransform(0, -1, 0, 1, 0, 0)); + transform = transform.followedBy(juce::AffineTransform::translation(getLocalBounds().getCentre())); + } + + juce::Rectangle bounds = getLocalBounds().transformedBy(transform); + + float led_width = (bounds.getWidth() - (m_leds.size() - 1.) * m_padding - 2. * m_border) / m_leds.size(); + + int led_height = bounds.getHeight() - 2 * m_border; + + int led_y = bounds.getY() + (bounds.getHeight() / 2.) - (led_height / 2.); + + for(int i = 0; i < m_leds.size(); ++i) + { + juce::Rectangle led_bounds(bounds.getX() + m_border + (i + 1) * m_padding + i * led_width, + led_y, + led_width, + led_height); + + m_leds[i].m_bounds = led_bounds.transformedBy(transform.inverted()); + } + } + + juce::Colour MeterTildeView::computeGradientColour(float delta) const + { + assert((delta >= 0 && delta <= 1.) && "meter wrong index for gradient"); + + float hue = m_cold_colour.getHue() + + delta * (m_hot_colour.getHue() - m_cold_colour.getHue()); + + float saturation = m_cold_colour.getSaturation() + + delta * (m_hot_colour.getSaturation() - m_cold_colour.getSaturation()); + + float brightness = m_cold_colour.getBrightness() + + delta * (m_hot_colour.getBrightness() - m_cold_colour.getBrightness()); + + float alpha = 1; + + return juce::Colour(hue, saturation, brightness, alpha); + } + + void MeterTildeView::computeActiveLed(float peak_db) + { + auto it = std::find_if(m_leds.rbegin(), m_leds.rend(), [peak_db](Led const& led) + { + return peak_db >= led.m_min_db; + }); + + m_active_led = it != m_leds.rend() ? m_leds.rend() - (it + 1) : -1; + } + + void MeterTildeView::peakChanged(float new_peak) + { + std::shared_ptr task(new Task(*this, new_peak)); + m_tasks.push(task); + KiwiApp::useInstance().useScheduler().schedule(task); + } + + void MeterTildeView::paint(juce::Graphics & g) + { + g.fillAll(findColour(ObjectView::ColourIds::Background)); + + for(int i = 0; i < m_leds.size(); ++i) + { + g.setColour(findColour(ObjectView::ColourIds::Outline)); + g.drawRect(m_leds[i].m_bounds.toFloat(), 1); + + if (i <= m_active_led) + { + g.setColour(m_leds[i].m_colour); + g.fillRect(m_leds[i].m_bounds.reduced(1).toFloat()); + } + } + + g.setColour(findColour(ObjectView::ColourIds::Outline)); + + drawOutline(g); + } +} diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Dsp/KiwiApp_MeterTildeView.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Dsp/KiwiApp_MeterTildeView.h new file mode 100644 index 00000000..d297cc3b --- /dev/null +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Dsp/KiwiApp_MeterTildeView.h @@ -0,0 +1,102 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +#include + +#include + +#include + +#include + +#include + +namespace kiwi +{ + // ================================================================================ // + // METER~ VIEW // + // ================================================================================ // + + class MeterTildeView : public ObjectView + { + private: // classes + + class Task; + + struct Led + { + float m_min_db; + juce::Colour m_colour; + juce::Rectangle m_bounds; + }; + + public: // methods + + //! @brief Constructor. + MeterTildeView(model::Object & object_model); + + //! @brief Destructor. + ~MeterTildeView(); + + private: // methods + + //! @brief Recomputes leds bounds + void resized() override final; + + //! @brief The graphical rendering methods + void paint(juce::Graphics & g) override final; + + //! @brief The reaction to a change of peak value. + //! @details Update the display value and call repaint. + void peakChanged(float new_peak); + + //! @brief Computes the interpolation between the cold and warm colour. + //! @details Interpolation value must be between 0 and 1. + juce::Colour computeGradientColour(float delta) const; + + //! @brief Computes and updates the active led. + //! @details Peak value is given in db. + void computeActiveLed(float peak_db); + + private: // members + + std::vector m_leds; + int m_active_led; + juce::Colour m_cold_colour; + juce::Colour m_hot_colour; + int m_border; + int m_padding; + flip::SignalConnection m_connection; + engine::ConcurrentQueue> m_tasks; + + private: // deleted methods + + MeterTildeView() = delete; + MeterTildeView(MeterTildeView const& other) = delete; + MeterTildeView(MeterTildeView && other) = delete; + MeterTildeView& operator=(MeterTildeView const& other) = delete; + MeterTildeView& operator=(MeterTildeView && other) = delete; + }; +} diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Objects.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Objects.h index c958de12..12fe0fc9 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Objects.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Objects.h @@ -34,3 +34,9 @@ #include #include #include + +// ================================================================================ // +// DSP OBJECTS // +// ================================================================================ // + +#include diff --git a/Modules/KiwiEngine/KiwiEngine_Instance.cpp b/Modules/KiwiEngine/KiwiEngine_Instance.cpp index 6bce0620..e6de6eb6 100644 --- a/Modules/KiwiEngine/KiwiEngine_Instance.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Instance.cpp @@ -102,6 +102,7 @@ namespace kiwi engine::Factory::add("bang"); engine::Factory::add("toggle"); engine::Factory::add("slider"); + engine::Factory::add("meter~"); } // ================================================================================ // diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_MeterTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_MeterTilde.cpp new file mode 100644 index 00000000..a0abf677 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_MeterTilde.cpp @@ -0,0 +1,98 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include + +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // METER~ // + // ================================================================================ // + + MeterTilde::MeterTilde(model::Object const& model, Patcher& patcher, std::vector const& atom): + engine::AudioObject(model, patcher), + Scheduler<>::Timer(patcher.getScheduler()), + m_interval(50), + m_current_peak(0), + m_sample_index(0), + m_target_sample_index(0), + m_last_peak(0), + m_uptodate(true), + m_signal(model.getSignal(model::MeterTilde::Signal::PeakChanged)) + { + } + + void MeterTilde::receive(size_t index, std::vector const& args) + { + } + + void MeterTilde::perform(dsp::Buffer const& input, dsp::Buffer& output) + { + dsp::sample_t const* const input_data = input[0ul].data(); + size_t sample_index = input[0].size(); + + while(sample_index--) + { + m_current_peak = std::max(m_current_peak, std::abs(input_data[sample_index])); + + if (m_sample_index++ == m_target_sample_index) + { + m_last_peak.store(m_current_peak); + m_uptodate.store(false); + m_sample_index = 0; + m_current_peak = 0; + } + } + } + + void MeterTilde::timerCallBack() + { + bool expected = false; + + if (m_uptodate.compare_exchange_strong(expected, true)) + { + float last_peak = m_last_peak.load(); + send(0, {last_peak}); + m_signal(last_peak); + } + } + + void MeterTilde::release() + { + stopTimer(); + } + + void MeterTilde::prepare(dsp::Processor::PrepareInfo const& infos) + { + m_target_sample_index = static_cast(infos.sample_rate * (m_interval / 1000.)); + m_sample_index = 0; + m_current_peak = 0; + + setPerformCallBack(this, &MeterTilde::perform); + + startTimer(std::chrono::milliseconds(m_interval)); + } +} +} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_MeterTilde.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_MeterTilde.h new file mode 100644 index 00000000..45a746c7 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_MeterTilde.h @@ -0,0 +1,77 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include +#include + +#include +#include + +#include + +namespace kiwi { namespace engine { + + /// ================================================================================ // + // METER~ // + // ================================================================================ // + + class MeterTilde : public engine::AudioObject, Scheduler<>::Timer + { + public: // usings + + using clock_t = std::chrono::high_resolution_clock; + + public: // methods + + //! @brief Constructor + MeterTilde(model::Object const& model, Patcher& patcher, std::vector const& atom); + + //! @brief The engine's receive method. + //! @details Does nothing as no control inlets exists. + void receive(size_t index, std::vector const& args) override final; + + //! @brief The dsp perform method called. + void perform(dsp::Buffer const& intput, dsp::Buffer& output); + + //! @brief Called to prepare dsp processing. + void prepare(dsp::Processor::PrepareInfo const& infos) override final; + + //! @brief Stops the timer callback method. + void release() override final; + + //! @brief The timer callback method. + //! @details Sends last peak and trigger signal. + void timerCallBack() override final; + + private: // members + + size_t m_interval; + dsp::sample_t m_current_peak; + size_t m_sample_index; + size_t m_target_sample_index; + std::atomic m_last_peak; + std::atomic m_uptodate; + flip::Signal & m_signal; + }; +} +} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h index eaf551b3..754cf17f 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h @@ -39,6 +39,7 @@ #include #include #include +#include // ================================================================================ // // MATH OBJECTS // diff --git a/Modules/KiwiModel/KiwiModel_DataModel.cpp b/Modules/KiwiModel/KiwiModel_DataModel.cpp index 9fba2827..caaaa8b8 100644 --- a/Modules/KiwiModel/KiwiModel_DataModel.cpp +++ b/Modules/KiwiModel/KiwiModel_DataModel.cpp @@ -81,6 +81,7 @@ namespace kiwi Bang::declare(); Toggle::declare(); Slider::declare(); + MeterTilde::declare(); } } } diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_MeterTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_MeterTilde.cpp new file mode 100755 index 00000000..91e9e164 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_MeterTilde.cpp @@ -0,0 +1,79 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT METER~ // + // ================================================================================ // + + MeterTilde::MeterTilde(flip::Default& d): + model::Object(d) + { + addSignal(Signal::PeakChanged, *this); + } + + MeterTilde::MeterTilde(std::string const& name, std::vector const& args): + model::Object() + { + if (!args.empty()) + { + throw std::runtime_error("wrong arguments for object meter"); + } + + setFlag(Flag::IFlag::DefinedSize); + setFlag(Flag::IFlag::ResizeWidth); + setFlag(Flag::IFlag::ResizeHeight); + setMinWidth(20); + setMinHeight(20); + setWidth(100); + setHeight(20); + pushInlet({PinType::IType::Signal}); + pushOutlet(PinType::IType::Control); + addSignal(Signal::PeakChanged, *this); + } + + std::string MeterTilde::getIODescription(bool is_inlet , size_t index) const + { + std::string description; + + if (is_inlet && index == 0) + { + description = "input monitored signal"; + } + else if (!is_inlet && index == 0) + { + description = "sends peak value each metering intervall"; + } + + return description; + } + + void MeterTilde::declare() + { + Factory::add("meter~"); + } +} +} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_MeterTilde.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_MeterTilde.h new file mode 100755 index 00000000..c613e0e8 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_MeterTilde.h @@ -0,0 +1,57 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // METER~ // + // ================================================================================ // + + class MeterTilde : public model::Object + { + public: // enum + + enum Signal : SignalKey + { + PeakChanged + }; + + //! @brief flip Default Constructor + MeterTilde(flip::Default& d); + + //! @brief Constructor + MeterTilde(std::string const& name, std::vector const& args); + + //! @brief Returns the descriptions of an inlet/outlet. + std::string getIODescription(bool is_inlet, size_t index) const override final; + + //! @internal flip static declare method. + static void declare(); + + private: // members + + }; +} +} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h index ed6b6a12..83a6e2ba 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h @@ -39,6 +39,7 @@ #include #include #include +#include // ================================================================================ // // MATH OBJECTS // From c295e8988ff42f52adc9f162984e9f37a566cc38 Mon Sep 17 00:00:00 2001 From: jean-millot Date: Tue, 24 Oct 2017 20:54:06 +0200 Subject: [PATCH 063/148] Moving DocumentManager into model. --- .../KiwiApp_Application/KiwiApp_Instance.cpp | 12 +- .../KiwiApp_PatcherManager.cpp | 211 ++++++++++++------ .../KiwiApp_Patcher/KiwiApp_PatcherManager.h | 49 ++-- .../KiwiApp_Patcher/KiwiApp_PatcherView.cpp | 74 +++--- .../KiwiApp_PatcherViewMouseHandler.cpp | 18 +- .../KiwiModel/KiwiModel_DocumentManager.cpp | 176 +-------------- .../KiwiModel/KiwiModel_DocumentManager.h | 108 ++------- 7 files changed, 253 insertions(+), 395 deletions(-) rename Client/Source/KiwiApp_Network/KiwiApp_DocumentManager.cpp => Modules/KiwiModel/KiwiModel_DocumentManager.cpp (51%) rename Client/Source/KiwiApp_Network/KiwiApp_DocumentManager.h => Modules/KiwiModel/KiwiModel_DocumentManager.h (54%) diff --git a/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp b/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp index 1420a4c1..7360c022 100644 --- a/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp +++ b/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp @@ -21,11 +21,12 @@ #include +#include + #include "KiwiApp_Instance.h" #include "KiwiApp_AboutWindow.h" #include "../KiwiApp.h" -#include "../KiwiApp_Network/KiwiApp_DocumentManager.h" #include "../KiwiApp_Components/KiwiApp_Window.h" #include "../KiwiApp_Patcher/KiwiApp_PatcherView.h" #include "../KiwiApp_Patcher/KiwiApp_PatcherComponent.h" @@ -67,6 +68,13 @@ namespace kiwi void Instance::timerCallback() { m_scheduler.process(); + + for(auto patcher_manager = m_patcher_managers.begin(); + patcher_manager != m_patcher_managers.end(); + ++patcher_manager) + { + (*patcher_manager)->pull(); + } } uint64_t Instance::getUserId() const noexcept @@ -143,7 +151,7 @@ namespace kiwi manager.newView(); } - DocumentManager::commit(patcher); + model::DocumentManager::commit(patcher); } bool Instance::openFile(juce::File const& file) diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.cpp index c0c4c7c2..ec39e751 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.cpp @@ -19,18 +19,25 @@ ============================================================================== */ +#include + +#include +#include +#include +#include + #include #include #include -#include "KiwiApp_PatcherManager.h" +#include -#include "../KiwiApp.h" -#include "../KiwiApp_Application/KiwiApp_Instance.h" -#include "../KiwiApp_Network/KiwiApp_DocumentManager.h" -#include "KiwiApp_PatcherView.h" -#include "KiwiApp_PatcherComponent.h" +#include +#include +#include +#include +#include namespace kiwi { @@ -43,18 +50,17 @@ namespace kiwi m_validator(), m_document(model::DataModel::use(), *this, m_validator, m_instance.getUserId(), 'cicm', 'kpat'), + m_file(), + m_socket(), m_need_saving_flag(false), - m_is_remote(false) + m_session(nullptr) { ; } PatcherManager::~PatcherManager() { - if(m_session) - { - m_session->useDrive().removeListener(*this); - } + disconnect(); } void PatcherManager::addListener(Listener& listener) @@ -67,18 +73,28 @@ namespace kiwi m_listeners.remove(listener); } - void PatcherManager::connect(DocumentBrowser::Drive::DocumentSession& session) + void PatcherManager::pull() + { + if (isRemote()) + { + m_socket->process(); + model::DocumentManager::pull(getPatcher()); + } + } + + void PatcherManager::disconnect() { - if(m_session) + if (isRemote()) { + m_socket.reset(); m_session->useDrive().removeListener(*this); m_session = nullptr; } - - m_is_remote = true; - m_session = &session; - - m_session->useDrive().addListener(*this); + } + + void PatcherManager::connect(DocumentBrowser::Drive::DocumentSession& session) + { + disconnect(); model::Patcher& patcher = getPatcher(); @@ -110,28 +126,82 @@ namespace kiwi const auto& network_settings = getAppSettings().network(); - DocumentManager::connect(patcher, - network_settings.getHost(), - network_settings.getSessionPort(), - session.getSessionId()); + std::unique_ptr socket(new CarrierSocket(m_document, + network_settings.getHost(), + network_settings.getSessionPort(), + session.getSessionId())); + + const auto init_time = std::chrono::steady_clock::now(); + + const std::chrono::duration time_out(2); + + while(!socket->isConnected() && std::chrono::steady_clock::now() - init_time < time_out) + { + socket->process(); + } + + if (socket->isConnected()) + { + bool loaded = false; + + socket->listenLoaded([&loaded](){loaded = true;}); + + while(!loaded) + { + socket->process(); + } + + socket->listenLoaded(std::function()); + } + else + { + throw std::runtime_error("Failed to connect to the document"); + } + + m_socket = std::move(socket); + + m_session = &session; + + m_session->useDrive().addListener(*this); + + model::DocumentManager::pull(patcher); patcher.useSelfUser(); - DocumentManager::commit(patcher); + model::DocumentManager::commit(patcher); patcher.entity().use().sendLoadbang(); } - void PatcherManager::loadFromFile(juce::File const& file) + void PatcherManager::readDocument() { - model::Patcher& patcher = getPatcher(); - DocumentManager::load(patcher, file); - patcher.useSelfUser(); - patcher.setName(file.getFileNameWithoutExtension().toStdString()); + flip::DataProviderFile provider(m_file.getFullPathName().toStdString().c_str()); + flip::BackEndIR back_end; - DocumentManager::commit(patcher); - m_need_saving_flag = false; + back_end.register_backend(); + back_end.read(provider); - patcher.entity().use().sendLoadbang(); + m_document.read(back_end); + + m_need_saving_flag = false; + } + + void PatcherManager::loadFromFile(juce::File const& file) + { + if (file.hasFileExtension("kiwi")) + { + m_file = file; + + readDocument(); + + model::Patcher& patcher = getPatcher(); + + patcher.useSelfUser(); + patcher.setName(file.getFileNameWithoutExtension().toStdString()); + + model::DocumentManager::commit(patcher); + + patcher.entity().use().sendLoadbang(); + } } model::Patcher& PatcherManager::getPatcher() @@ -146,7 +216,7 @@ namespace kiwi bool PatcherManager::isRemote() const noexcept { - return m_is_remote; + return m_socket != nullptr; } uint64_t PatcherManager::getSessionId() const noexcept @@ -162,10 +232,10 @@ namespace kiwi void PatcherManager::newView() { auto& patcher = getPatcher(); - if(!DocumentManager::isInCommitGesture(patcher)) + if(!model::DocumentManager::isInCommitGesture(patcher)) { patcher.useSelfUser().addView(); - DocumentManager::commit(patcher); + model::DocumentManager::commit(patcher); } } @@ -190,41 +260,52 @@ namespace kiwi }); } + juce::File const& PatcherManager::getSelectedFile() const + { + return m_file; + } + bool PatcherManager::needsSaving() const noexcept { - return (!m_is_remote) && m_need_saving_flag; + return !isRemote() && m_need_saving_flag; + } + + void PatcherManager::writeDocument() + { + flip::BackEndIR back_end = m_document.write(); + flip::DataConsumerFile consumer(m_file.getFullPathName().toStdString().c_str()); + back_end.write(consumer); + m_need_saving_flag = false; } bool PatcherManager::saveDocument() { - auto& patcher = getPatcher(); - juce::File const& current_save_file = DocumentManager::getSelectedFile(patcher); - - if (current_save_file.existsAsFile()) + if (needsSaving()) { - DocumentManager::save(patcher, current_save_file); - m_need_saving_flag = false; - DocumentManager::commit(patcher); - return true; - } - else - { - auto directory = juce::File::getSpecialLocation(juce::File::userHomeDirectory); - juce::FileChooser saveFileChooser("Save file", directory, "*.kiwi"); - - if(saveFileChooser.browseForFileToSave(true)) + if (m_file.existsAsFile()) + { + writeDocument(); + } + else { - juce::File save_file(saveFileChooser.getResult().getFullPathName()); - DocumentManager::save(patcher, save_file); - m_need_saving_flag = false; + auto directory = juce::File::getSpecialLocation(juce::File::userHomeDirectory); + + juce::FileChooser saveFileChooser("Save file", directory, "*.kiwi"); - patcher.setName(save_file.getFileNameWithoutExtension().toStdString()); - DocumentManager::commit(patcher); - return true; + if (saveFileChooser.browseForFileToSave(true)) + { + m_file = saveFileChooser.getResult(); + + writeDocument(); + + model::Patcher& patcher = getPatcher(); + patcher.setName(m_file.getFileNameWithoutExtension().toStdString()); + model::DocumentManager::commit(patcher); + } } } - return false; + return !m_need_saving_flag; } juce::FileBasedDocument::SaveResult PatcherManager::saveIfNeededAndUserAgrees() @@ -272,7 +353,7 @@ namespace kiwi it = user.removeView(*it); } - DocumentManager::commit(patcher); + model::DocumentManager::commit(patcher); } bool PatcherManager::askAllWindowsToClose() @@ -294,7 +375,7 @@ namespace kiwi if(!need_saving || (need_saving && saveIfNeededAndUserAgrees() == juce::FileBasedDocument::savedOk)) { it = user.removeView(*it); - DocumentManager::commit(patcher); + model::DocumentManager::commit(patcher); } else { @@ -328,7 +409,7 @@ namespace kiwi if(!need_saving || saveIfNeededAndUserAgrees() == juce::FileBasedDocument::savedOk) { user.removeView(patcher_view_m); - DocumentManager::commit(patcher); + model::DocumentManager::commit(patcher); return true; } } @@ -377,17 +458,13 @@ namespace kiwi { if(m_session && (m_session == &doc)) { - m_session->useDrive().removeListener(*this); - m_session = nullptr; - m_is_remote = false; + disconnect(); for(auto& view : getPatcher().useSelfUser().getViews()) { auto& patcherview = view.entity().use(); patcherview.updateWindowTitle(); } - // disconnect - // propose document fork ? } } @@ -397,7 +474,7 @@ namespace kiwi { std::unique_lock lock(m_instance.useEngineInstance().getScheduler().lock()); - patcher.entity().emplace(patcher.document()); + patcher.entity().emplace(patcher.document()); patcher.entity().emplace(m_instance.useEngineInstance()); } @@ -414,7 +491,7 @@ namespace kiwi std::unique_lock lock(m_instance.useEngineInstance().getScheduler().lock()); patcher.entity().erase(); - patcher.entity().erase(); + patcher.entity().erase(); } if(patcher.resident() && (patcher.objectsChanged() || patcher.linksChanged())) diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.h b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.h index 0ddc5a7e..6dd34a4b 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.h @@ -21,17 +21,19 @@ #pragma once -#include "flip/Document.h" -#include "flip/DocumentObserver.h" - -#include -#include +#include +#include #include -#include "../KiwiApp_Network/KiwiApp_DocumentBrowser.h" +#include +#include -#include +#include +#include + +#include +#include namespace kiwi { @@ -62,9 +64,22 @@ namespace kiwi //! @brief Try to connect this patcher to a remote server. void connect(DocumentBrowser::Drive::DocumentSession& session); + //! @brief Pull changes from server if it is remote. + void pull(); + //! @brief Load patcher datas from file. void loadFromFile(juce::File const& file); + //! @brief Save the document. + //! @details Returns true if saving document succeeded false otherwise. + bool saveDocument(); + + //! @brief Returns true if the patcher needs to be saved. + bool needsSaving() const noexcept; + + //! @brief Returns the file currently used to save document. + juce::File const& getSelectedFile() const; + //! @brief Returns the Patcher model model::Patcher& getPatcher(); @@ -110,12 +125,6 @@ namespace kiwi //! @details if it's the last patcher view, it will ask the user the save the document before closing if needed. bool closePatcherViewWindow(PatcherView& patcherview); - //! @brief Save the document. - bool saveDocument(); - - //! @brief Returns true if the patcher needs to be saved. - bool needsSaving() const noexcept; - //! @brief Add a listener. void addListener(Listener& listener); @@ -133,6 +142,15 @@ namespace kiwi private: + //! @internal Write data into file. + void writeDocument(); + + //! @internal Reads data from file. + void readDocument(); + + //! @internal If the patcher is remote, tries to disconnect it. + void disconnect(); + //! @internal flip::DocumentObserver::document_changed void document_changed(model::Patcher& patcher) override final; @@ -163,9 +181,10 @@ namespace kiwi Instance& m_instance; model::PatcherValidator m_validator; flip::Document m_document; + juce::File m_file; + std::unique_ptr m_socket; bool m_need_saving_flag; - bool m_is_remote; - DocumentBrowser::Drive::DocumentSession* m_session {nullptr}; + DocumentBrowser::Drive::DocumentSession* m_session; flip::SignalConnection m_user_connected_signal_cnx; flip::SignalConnection m_user_disconnected_signal_cnx; diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp index 55fb0db0..73a0720f 100755 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp @@ -31,7 +31,7 @@ #include "../KiwiApp.h" #include "../KiwiApp_General/KiwiApp_CommandIDs.h" -#include "../KiwiApp_Network/KiwiApp_DocumentManager.h" +#include #include "KiwiApp_LinkView.h" #include "KiwiApp_PatcherComponent.h" @@ -265,11 +265,11 @@ namespace kiwi { if(commit_gesture) { - DocumentManager::commitGesture(m_patcher_model, "Move selected objects"); + model::DocumentManager::commitGesture(m_patcher_model, "Move selected objects"); } else { - DocumentManager::commit(m_patcher_model, "Move selected objects"); + model::DocumentManager::commit(m_patcher_model, "Move selected objects"); } } } @@ -286,7 +286,7 @@ namespace kiwi void PatcherView::copySelectionToClipboard() { - auto& document = m_patcher_model.entity().use(); + auto& document = m_patcher_model.entity().use(); auto& clipboard = m_instance.getPatcherClipboardData(); clipboard.clear(); @@ -424,7 +424,7 @@ namespace kiwi } } - DocumentManager::commit(m_patcher_model, "paste objects"); + model::DocumentManager::commit(m_patcher_model, "paste objects"); } } @@ -502,7 +502,7 @@ namespace kiwi { flip::Mold mold(model::DataModel::use(), sbi); - auto& document = m_patcher_model.entity().use(); + auto& document = m_patcher_model.entity().use(); std::string new_object_name; sbi >> new_object_name; @@ -528,7 +528,7 @@ namespace kiwi } } - DocumentManager::commit(m_patcher_model, "paste-replace objects"); + model::DocumentManager::commit(m_patcher_model, "paste-replace objects"); } } } @@ -660,7 +660,7 @@ namespace kiwi { if(m_local_objects_selection.size() == 1) { - auto& doc = m_patcher_model.entity().use(); + auto& doc = m_patcher_model.entity().use(); model::Object* object_m = doc.get(*m_local_objects_selection.begin()); if(object_m) @@ -729,7 +729,7 @@ namespace kiwi } m_view_model.setLock(locked); - DocumentManager::commit(m_patcher_model, "Edit mode switch"); + model::DocumentManager::commit(m_patcher_model, "Edit mode switch"); } bool PatcherView::isLocked() const @@ -923,7 +923,7 @@ namespace kiwi void PatcherView::zoomIn() { m_view_model.setZoomFactor(m_view_model.getZoomFactor() + 0.25); - DocumentManager::commit(m_patcher_model); + model::DocumentManager::commit(m_patcher_model); if(isAnyObjectSelected()) { @@ -934,7 +934,7 @@ namespace kiwi void PatcherView::zoomNormal() { m_view_model.setZoomFactor(1.); - DocumentManager::commit(m_patcher_model); + model::DocumentManager::commit(m_patcher_model); if(isAnyObjectSelected()) { @@ -948,7 +948,7 @@ namespace kiwi if(zoom > 0.25) { m_view_model.setZoomFactor(zoom - 0.25); - DocumentManager::commit(m_patcher_model); + model::DocumentManager::commit(m_patcher_model); if(isAnyObjectSelected()) { @@ -1091,7 +1091,7 @@ namespace kiwi title = m_patcher_model.getName(); const bool edited = m_manager.needsSaving(); - juce::File kiwi_file = DocumentManager::getSelectedFile(m_patcher_model); + juce::File kiwi_file = m_manager.getSelectedFile(); if(juce::ComponentPeer* peer = window->getPeer()) { @@ -1585,12 +1585,12 @@ namespace kiwi m_view_model.selectObject(new_object); } - DocumentManager::commit(m_patcher_model, "Edit Object"); + model::DocumentManager::commit(m_patcher_model, "Edit Object"); } void PatcherView::createObjectModel(std::string const& text, bool give_focus) { - if(! DocumentManager::isInCommitGesture(m_patcher_model)) + if(! model::DocumentManager::isInCommitGesture(m_patcher_model)) { bool linked_newbox = m_local_objects_selection.size() == 1; @@ -1598,7 +1598,7 @@ namespace kiwi juce::Point pos = getMouseXYRelative() - getOriginPosition(); - auto& doc = m_patcher_model.entity().use(); + auto& doc = m_patcher_model.entity().use(); if(linked_newbox) { @@ -1622,7 +1622,7 @@ namespace kiwi m_view_model.selectObject(m_patcher_model.addObject(std::move(new_object))); - DocumentManager::commit(m_patcher_model, "Insert New Empty Box"); + model::DocumentManager::commit(m_patcher_model, "Insert New Empty Box"); if(give_focus && m_local_objects_selection.size() == 1) { @@ -1645,7 +1645,7 @@ namespace kiwi void PatcherView::undo() { - auto& doc = m_patcher_model.entity().use(); + auto& doc = m_patcher_model.entity().use(); if(doc.canUndo()) { doc.undo(); @@ -1655,18 +1655,18 @@ namespace kiwi bool PatcherView::canUndo() { - return m_patcher_model.entity().use().canUndo(); + return m_patcher_model.entity().use().canUndo(); } std::string PatcherView::getUndoLabel() { - auto& doc = m_patcher_model.entity().use(); + auto& doc = m_patcher_model.entity().use(); return doc.canUndo() ? doc.getUndoLabel() : ""; } void PatcherView::redo() { - auto& doc = m_patcher_model.entity().use(); + auto& doc = m_patcher_model.entity().use(); if(doc.canRedo()) { doc.redo(); @@ -1676,12 +1676,12 @@ namespace kiwi bool PatcherView::canRedo() { - return m_patcher_model.entity().use().canRedo(); + return m_patcher_model.entity().use().canRedo(); } std::string PatcherView::getRedoLabel() { - auto& doc = m_patcher_model.entity().use(); + auto& doc = m_patcher_model.entity().use(); return doc.canRedo() ? doc.getRedoLabel() : ""; } @@ -1707,7 +1707,7 @@ namespace kiwi void PatcherView::selectObject(ObjectFrame& object) { m_view_model.selectObject(object.getModel()); - DocumentManager::commit(m_patcher_model); + model::DocumentManager::commit(m_patcher_model); } void PatcherView::selectObjects(std::vector const& objects) @@ -1725,14 +1725,14 @@ namespace kiwi if(should_commit) { - DocumentManager::commit(m_patcher_model); + model::DocumentManager::commit(m_patcher_model); } } void PatcherView::selectLink(LinkView& link) { m_view_model.selectLink(link.getModel()); - DocumentManager::commit(m_patcher_model); + model::DocumentManager::commit(m_patcher_model); } void PatcherView::selectLinks(std::vector const& links) @@ -1750,48 +1750,48 @@ namespace kiwi if(should_commit) { - DocumentManager::commit(m_patcher_model); + model::DocumentManager::commit(m_patcher_model); } } void PatcherView::unselectObject(ObjectFrame& object) { m_view_model.unselectObject(object.getModel()); - DocumentManager::commit(m_patcher_model); + model::DocumentManager::commit(m_patcher_model); } void PatcherView::unselectLink(LinkView& link) { m_view_model.unselectLink(link.getModel()); - DocumentManager::commit(m_patcher_model); + model::DocumentManager::commit(m_patcher_model); } void PatcherView::selectObjectOnly(ObjectFrame& object) { unselectAll(); selectObject(object); - DocumentManager::commit(m_patcher_model); + model::DocumentManager::commit(m_patcher_model); } void PatcherView::selectLinkOnly(LinkView& link) { unselectAll(); selectLink(link); - DocumentManager::commit(m_patcher_model); + model::DocumentManager::commit(m_patcher_model); } void PatcherView::selectAllObjects() { m_view_model.selectAll(); - DocumentManager::commit(m_patcher_model); + model::DocumentManager::commit(m_patcher_model); } void PatcherView::unselectAll() { - if(!DocumentManager::isInCommitGesture(m_patcher_model)) + if(!model::DocumentManager::isInCommitGesture(m_patcher_model)) { m_view_model.unselectAll(); - DocumentManager::commit(m_patcher_model); + model::DocumentManager::commit(m_patcher_model); } } @@ -1813,7 +1813,7 @@ namespace kiwi } } - DocumentManager::commit(m_patcher_model, "Delete objects and links"); + model::DocumentManager::commit(m_patcher_model, "Delete objects and links"); m_viewport.updatePatcherArea(false); } @@ -1861,7 +1861,7 @@ namespace kiwi void PatcherView::getCommandInfo(const juce::CommandID commandID, juce::ApplicationCommandInfo& result) { - const bool is_not_in_gesture = !DocumentManager::isInCommitGesture(m_patcher_model); + const bool is_not_in_gesture = !model::DocumentManager::isInCommitGesture(m_patcher_model); switch(commandID) { @@ -2037,7 +2037,7 @@ namespace kiwi { // most of the commands below generate conflicts when they are being executed // in a commit gesture or when a box is being edited, so simply not execute them. - if(DocumentManager::isInCommitGesture(m_patcher_model) || isEditingObject()) + if(model::DocumentManager::isInCommitGesture(m_patcher_model) || isEditingObject()) { return true; } diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewMouseHandler.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewMouseHandler.cpp index f0057f15..3f31829e 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewMouseHandler.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewMouseHandler.cpp @@ -22,13 +22,13 @@ #include #include +#include #include #include #include #include #include -#include namespace kiwi { @@ -108,7 +108,7 @@ namespace kiwi { KiwiApp::commandStatusChanged(); - DocumentManager::startCommitGesture(m_patcher_view.m_patcher_model); + model::DocumentManager::startCommitGesture(m_patcher_view.m_patcher_model); break; } @@ -193,7 +193,7 @@ namespace kiwi { m_direction = getResizeDirection(hit_tester); - auto& document = m_patcher_view.m_patcher_model.entity().use(); + auto& document = m_patcher_view.m_patcher_model.entity().use(); for (flip::Ref const& ref : m_patcher_view.getSelectedObjects()) { @@ -205,7 +205,7 @@ namespace kiwi object.getHeight()); } - DocumentManager::startCommitGesture(m_patcher_view.m_patcher_model); + model::DocumentManager::startCommitGesture(m_patcher_view.m_patcher_model); break; } @@ -418,12 +418,12 @@ namespace kiwi new_bounds.setBottom(std::max(new_bounds.getBottom() + delta.getY(), new_bounds.getY())); } - auto& document = m_patcher_view.m_patcher_model.entity().use(); + auto& document = m_patcher_view.m_patcher_model.entity().use(); applyNewBounds(*document.get(bounds_it.first), new_bounds, ratio); } - DocumentManager::commitGesture(m_patcher_view.m_patcher_model, "Resize object"); + model::DocumentManager::commitGesture(m_patcher_view.m_patcher_model, "Resize object"); break; } @@ -472,7 +472,7 @@ namespace kiwi if(link != nullptr) { m_patcher_view.m_view_model.selectLink(*link); - DocumentManager::commit(m_patcher_view.m_patcher_model, "Add link"); + model::DocumentManager::commit(m_patcher_view.m_patcher_model, "Add link"); } } @@ -490,7 +490,7 @@ namespace kiwi } case Action::MoveObject: { - DocumentManager::endCommitGesture(m_patcher_view.m_patcher_model); + model::DocumentManager::endCommitGesture(m_patcher_view.m_patcher_model); KiwiApp::commandStatusChanged(); @@ -511,7 +511,7 @@ namespace kiwi m_direction = Direction::None; m_mousedown_bounds.clear(); - DocumentManager::endCommitGesture(m_patcher_view.m_patcher_model); + model::DocumentManager::endCommitGesture(m_patcher_view.m_patcher_model); m_patcher_view.m_viewport.updatePatcherArea(true); diff --git a/Client/Source/KiwiApp_Network/KiwiApp_DocumentManager.cpp b/Modules/KiwiModel/KiwiModel_DocumentManager.cpp similarity index 51% rename from Client/Source/KiwiApp_Network/KiwiApp_DocumentManager.cpp rename to Modules/KiwiModel/KiwiModel_DocumentManager.cpp index 2563f2c8..5395395a 100755 --- a/Client/Source/KiwiApp_Network/KiwiApp_DocumentManager.cpp +++ b/Modules/KiwiModel/KiwiModel_DocumentManager.cpp @@ -19,17 +19,11 @@ ============================================================================== */ -#include "flip/BackEndIR.h" -#include "flip/BackEndBinary.h" -#include "flip/contrib/DataConsumerFile.h" -#include "flip/contrib/DataProviderFile.h" - +#include #include -#include "KiwiApp_DocumentManager.h" +namespace kiwi { namespace model { -namespace kiwi -{ // ================================================================================ // // DOCUMENT MANAGER // // ================================================================================ // @@ -37,14 +31,14 @@ namespace kiwi DocumentManager::DocumentManager(flip::DocumentBase& document) : m_document(document), m_history(document), - m_file_handler(m_document) + m_gesture_flag(false), + m_gesture_cnt(0) { ; } DocumentManager::~DocumentManager() { - disconnect(); } void DocumentManager::commit(flip::Type& type, std::string action) @@ -53,13 +47,6 @@ namespace kiwi patcher.entity().use().commit(action); } - void DocumentManager::connect(flip::Type& type, - const std::string host, uint16_t port, uint64_t session_id) - { - model::Patcher& patcher = type.ancestor(); - patcher.entity().use().connect(host, port, session_id); - } - void DocumentManager::pull(flip::Type& type) { model::Patcher& patcher = type.ancestor(); @@ -90,24 +77,6 @@ namespace kiwi return patcher.entity().use().m_gesture_flag; } - void DocumentManager::save(flip::Type& type, juce::File const& file) - { - model::Patcher& patcher = type.ancestor(); - patcher.entity().use().save(file); - } - - void DocumentManager::load(flip::Type& type, juce::File const& file) - { - model::Patcher& patcher = type.ancestor(); - patcher.entity().use().load(file); - } - - juce::File const& DocumentManager::getSelectedFile(flip::Type& type) - { - model::Patcher& patcher = type.ancestor(); - return patcher.entity().use().getSelectedFile(); - } - bool DocumentManager::canUndo() { return m_history.last_undo() != m_history.end(); @@ -176,65 +145,7 @@ namespace kiwi m_document.push(); } - void DocumentManager::connect(std::string const host, uint16_t port, uint64_t session_id) - { - disconnect(); - - m_socket.reset(new CarrierSocket(m_document, host, port, session_id)); - - m_socket->listenDisconnected(std::bind(&DocumentManager::onDisconnected, this)); - - const auto init_time = std::chrono::steady_clock::now(); - const std::chrono::duration time_out(2); - - while(!m_socket->isConnected() && std::chrono::steady_clock::now() - init_time < time_out) - { - m_socket->process(); - } - - if (m_socket->isConnected()) - { - bool loaded = false; - - m_socket->listenLoaded([&loaded](){loaded = true;}); - - while(!loaded) - { - m_socket->process(); - } - - m_socket->listenLoaded(std::function()); - - pull(); - - startTimer(20); - } - else - { - throw std::runtime_error("Failed to connect to the document"); - } - } - - void DocumentManager::disconnect() - { - m_socket.reset(); - } - - bool DocumentManager::isConnected() - { - return (m_socket && m_socket->isConnected()); - } - - void DocumentManager::timerCallback() - { - m_socket->process(); - pull(); - } - void DocumentManager::onDisconnected() - { - stopTimer(); - } void DocumentManager::startCommitGesture() { assert(!m_gesture_flag); @@ -279,81 +190,4 @@ namespace kiwi m_document.push(); } } - - void DocumentManager::save(juce::File const& file) - { - m_file_handler.save(file); - } - - void DocumentManager::load(juce::File const& file) - { - m_file_handler.load(file); - } - - juce::File const& DocumentManager::getSelectedFile() const - { - return m_file_handler.getFile(); - } - - // ================================================================================ // - // FILE HANDLER // - // ================================================================================ // - - FileHandler::FileHandler(flip::DocumentBase & document): - m_document(document), - m_file() - { - } - - juce::File const& FileHandler::getFile() const - { - return m_file; - } - - void FileHandler::setFile(juce::File const& file) - { - m_file = file; - } - - bool FileHandler::hasValidExtension(juce::File const& file) - { - return file.hasFileExtension("kiwi"); - } - - void FileHandler::load(juce::File const& file) - { - if (hasValidExtension(file)) - { - setFile(file); - load(); - } - } - - void FileHandler::load() - { - flip::DataProviderFile provider(m_file.getFullPathName().toStdString().c_str()); - flip::BackEndIR back_end; - - back_end.register_backend(); - back_end.read(provider); - - m_document.read(back_end); - } - - void FileHandler::save(juce::File const& file) - { - if (hasValidExtension(file)) - { - setFile(file); - save(); - } - } - - void FileHandler::save() - { - flip::DataConsumerFile consumer(m_file.getFullPathName().toStdString().c_str()); - - flip::BackEndIR back_end = m_document.write(); - back_end.write(consumer); - } -} +}} diff --git a/Client/Source/KiwiApp_Network/KiwiApp_DocumentManager.h b/Modules/KiwiModel/KiwiModel_DocumentManager.h similarity index 54% rename from Client/Source/KiwiApp_Network/KiwiApp_DocumentManager.h rename to Modules/KiwiModel/KiwiModel_DocumentManager.h index ea31e6db..a135c95f 100755 --- a/Client/Source/KiwiApp_Network/KiwiApp_DocumentManager.h +++ b/Modules/KiwiModel/KiwiModel_DocumentManager.h @@ -21,68 +21,20 @@ #pragma once -#include -#include +#include +#include -#include "flip/History.h" -#include "flip/HistoryStoreMemory.h" - -#include "KiwiApp_CarrierSocket.h" - -namespace kiwi -{ - // ================================================================================ // - // FILE HANDLER // - // ================================================================================ // - - //! @brief Class that enable saving and loading the document from a kiwi file - class FileHandler final - { - public: // methods - - //! @brief Constructs the FileHandler referencing document and pointing to a non-existing file. - FileHandler(flip::DocumentBase & document); - - //! @brief Destructor. - ~FileHandler() = default; - - //! @brief Loads the document from file and sets the pointed file. - void load(juce::File const& file); - - //! @brief Saves the document from file and sets the pointed file. - void save(juce::File const& file); - - //! @brief Get the pointed file. - juce::File const& getFile() const; - - private: // internal methods - - void setFile(juce::File const& file); - void load(); - void save(); - bool hasValidExtension(juce::File const& file); - - private: // members - - flip::DocumentBase& m_document; - juce::File m_file; - - private: // deleted methods - - FileHandler(FileHandler const& other) = delete; - FileHandler(FileHandler && other) = delete; - FileHandler& operator=(FileHandler const& other) = delete; - FileHandler& operator=(FileHandler && other) = delete; - }; +namespace kiwi { namespace model { // ================================================================================ // // DOCUMENT MANAGER // // ================================================================================ // - class DocumentManager : public juce::Timer + class DocumentManager { public: + //! @brief Constructor. DocumentManager(flip::DocumentBase & document); //! @brief Destructor. @@ -112,22 +64,10 @@ namespace kiwi //! @details Each call to this function must be preceded by a call to startCommitGesture. //! @see startCommitGesture. static void endCommitGesture(flip::Type& type); - + //! @brief Returns true if the document is currently commiting a gesture. static bool isInCommitGesture(flip::Type& type); - //! @brief Saves the patch into the designated file - //! @details Doesn't save if not kiwi file. Sets the currently pointed file. - static void save(flip::Type& type, juce::File const& file); - - //! @brief Loads the patch from the designated file - //! @details Doesn't load if not kiwi file. Sets the currently pointed file. - static void load(flip::Type& type, juce::File const& file); - - //! @brief Returns the file that is currently pointed to by the DocumentManager. - //! @details If neither save or load was called return a non existing file (file.exist() == false). - static juce::File const& getSelectedFile(flip::Type& type); - //! @brief Returns true if there is an action to undo. bool canUndo(); @@ -163,41 +103,21 @@ namespace kiwi //! @brief Pushes a trasactions stacked by a socket's process void push(); - //! @brief Connects the document manager and download the patcher's initial state - void connect(std::string const host, uint16_t port, uint64_t session_id); - - //! @brief Returns true if the document manager is connected false otherwise - bool isConnected(); - - //! @brief Disconnects the document manager from the server - void disconnect(); - - //! @brief Called once document manager is disconnected and stops pulling - void onDisconnected(); - - //! @brief Called once the initial load happened - void onLoaded(); - - //! @brief Called at a regular frequency to pull document - void timerCallback() override; - + //! @brief Starts a commit gesture. void startCommitGesture(); + + //! @brief Commit a gesture. void commitGesture(std::string action); + + //! @brief Ends a commit gesture. void endCommitGesture(); - void save(juce::File const& file); - void load(juce::File const& file); - juce::File const& getSelectedFile() const; private: flip::DocumentBase& m_document; flip::History m_history; - FileHandler m_file_handler; - - std::unique_ptr m_socket = nullptr; - - bool m_gesture_flag = false; - size_t m_gesture_cnt = 0; + bool m_gesture_flag; + size_t m_gesture_cnt; private: @@ -209,4 +129,4 @@ namespace kiwi bool operator ==(DocumentManager const& rhs) const = delete; bool operator !=(DocumentManager const& rhs) const = delete; }; -} +}} From f8a81c1bd15d45bc4c3231cd6142824b317b940c Mon Sep 17 00:00:00 2001 From: jean-millot Date: Thu, 26 Oct 2017 16:44:50 +0200 Subject: [PATCH 064/148] Creating module KiwiTool. --- CMakeLists.txt | 34 +- .../KiwiApp_BeaconDispatcher.cpp | 8 +- .../KiwiApp_BeaconDispatcher.h | 5 +- .../KiwiApp_Application/KiwiApp_Console.cpp | 2 +- .../KiwiApp_ConsoleHistory.h | 2 +- .../KiwiApp_DocumentBrowserView.h | 2 +- .../KiwiApp_Application/KiwiApp_Instance.cpp | 2 +- .../KiwiApp_Application/KiwiApp_Instance.h | 6 +- .../KiwiApp_SuggestEditor.h | 2 +- .../KiwiApp_General/KiwiApp_StoredSettings.h | 4 +- .../KiwiApp_Network/KiwiApp_ApiController.h | 4 +- .../KiwiApp_Network/KiwiApp_DocumentBrowser.h | 6 +- .../KiwiApp_Basic/KiwiApp_ClassicView.h | 4 +- .../KiwiApp_Controller/KiwiApp_BangView.cpp | 4 +- .../KiwiApp_Controller/KiwiApp_BangView.h | 4 +- .../KiwiApp_Controller/KiwiApp_SliderView.cpp | 6 +- .../KiwiApp_Controller/KiwiApp_SliderView.h | 4 +- .../KiwiApp_Controller/KiwiApp_ToggleView.cpp | 4 +- .../KiwiApp_Controller/KiwiApp_ToggleView.h | 6 +- .../KiwiApp_Dsp/KiwiApp_MeterTildeView.cpp | 4 +- .../KiwiApp_Dsp/KiwiApp_MeterTildeView.h | 4 +- .../KiwiApp_Patcher/KiwiApp_PatcherManager.h | 2 +- .../KiwiApp_Patcher/KiwiApp_PatcherView.cpp | 4 +- Modules/KiwiEngine/KiwiEngine_Beacon.cpp | 75 ---- Modules/KiwiEngine/KiwiEngine_Beacon.h | 113 ----- .../KiwiEngine/KiwiEngine_CircularBuffer.h | 166 -------- .../KiwiEngine/KiwiEngine_ConcurrentQueue.h | 125 ------ Modules/KiwiEngine/KiwiEngine_Console.h | 6 +- Modules/KiwiEngine/KiwiEngine_Def.h | 5 +- Modules/KiwiEngine/KiwiEngine_Factory.cpp | 4 +- Modules/KiwiEngine/KiwiEngine_Factory.h | 6 +- Modules/KiwiEngine/KiwiEngine_Instance.cpp | 2 +- Modules/KiwiEngine/KiwiEngine_Instance.h | 9 +- Modules/KiwiEngine/KiwiEngine_Listeners.h | 144 ------- Modules/KiwiEngine/KiwiEngine_Object.cpp | 6 +- Modules/KiwiEngine/KiwiEngine_Object.h | 11 +- .../KiwiEngine_Basic/KiwiEngine_ErrorBox.cpp | 4 +- .../KiwiEngine_Basic/KiwiEngine_ErrorBox.h | 4 +- .../KiwiEngine_Basic/KiwiEngine_NewBox.cpp | 4 +- .../KiwiEngine_Basic/KiwiEngine_NewBox.h | 4 +- .../KiwiEngine_Controller/KiwiEngine_Bang.cpp | 8 +- .../KiwiEngine_Controller/KiwiEngine_Bang.h | 6 +- .../KiwiEngine_Slider.cpp | 8 +- .../KiwiEngine_Controller/KiwiEngine_Slider.h | 8 +- .../KiwiEngine_Toggle.cpp | 8 +- .../KiwiEngine_Controller/KiwiEngine_Toggle.h | 10 +- .../KiwiEngine_Dsp/KiwiEngine_AdcTilde.cpp | 2 +- .../KiwiEngine_Dsp/KiwiEngine_AdcTilde.h | 2 +- .../KiwiEngine_Dsp/KiwiEngine_DacTilde.cpp | 2 +- .../KiwiEngine_Dsp/KiwiEngine_DacTilde.h | 2 +- .../KiwiEngine_DelaySimpleTilde.cpp | 6 +- .../KiwiEngine_DelaySimpleTilde.h | 22 +- .../KiwiEngine_Dsp/KiwiEngine_MeterTilde.cpp | 6 +- .../KiwiEngine_Dsp/KiwiEngine_MeterTilde.h | 8 +- .../KiwiEngine_Dsp/KiwiEngine_OscTilde.cpp | 4 +- .../KiwiEngine_Dsp/KiwiEngine_OscTilde.h | 4 +- .../KiwiEngine_Dsp/KiwiEngine_PlusTilde.cpp | 4 +- .../KiwiEngine_Dsp/KiwiEngine_PlusTilde.h | 4 +- .../KiwiEngine_Dsp/KiwiEngine_SigTilde.cpp | 4 +- .../KiwiEngine_Dsp/KiwiEngine_SigTilde.h | 4 +- .../KiwiEngine_Dsp/KiwiEngine_TimesTilde.cpp | 4 +- .../KiwiEngine_Dsp/KiwiEngine_TimesTilde.h | 4 +- .../KiwiEngine_Math/KiwiEngine_Plus.cpp | 4 +- .../KiwiEngine_Math/KiwiEngine_Plus.h | 4 +- .../KiwiEngine_Math/KiwiEngine_Times.cpp | 4 +- .../KiwiEngine_Math/KiwiEngine_Times.h | 4 +- .../KiwiEngine_Loadmess.cpp | 4 +- .../KiwiEngine_Message/KiwiEngine_Loadmess.h | 6 +- .../KiwiEngine_Message/KiwiEngine_Print.cpp | 6 +- .../KiwiEngine_Message/KiwiEngine_Print.h | 4 +- .../KiwiEngine_Message/KiwiEngine_Receive.cpp | 18 +- .../KiwiEngine_Message/KiwiEngine_Receive.h | 8 +- .../KiwiEngine_Time/KiwiEngine_Delay.cpp | 6 +- .../KiwiEngine_Time/KiwiEngine_Delay.h | 10 +- .../KiwiEngine_Time/KiwiEngine_Metro.cpp | 6 +- .../KiwiEngine_Time/KiwiEngine_Metro.h | 8 +- .../KiwiEngine_Time/KiwiEngine_Pipe.cpp | 14 +- .../KiwiEngine_Time/KiwiEngine_Pipe.h | 8 +- .../KiwiEngine_AudioInterface.cpp | 8 +- .../KiwiEngine_AudioInterface.h | 6 +- Modules/KiwiEngine/KiwiEngine_Patcher.cpp | 6 +- Modules/KiwiEngine/KiwiEngine_Patcher.h | 7 +- Modules/KiwiEngine/KiwiEngine_Scheduler.h | 380 ----------------- Modules/KiwiEngine/KiwiEngine_Scheduler.hpp | 399 ------------------ Modules/KiwiModel/KiwiModel_Factory.cpp | 10 +- Modules/KiwiModel/KiwiModel_Factory.h | 10 +- Modules/KiwiModel/KiwiModel_Object.h | 2 +- .../KiwiModel_Basic/KiwiModel_ErrorBox.cpp | 2 +- .../KiwiModel_Basic/KiwiModel_ErrorBox.h | 2 +- .../KiwiModel_Basic/KiwiModel_NewBox.cpp | 2 +- .../KiwiModel_Basic/KiwiModel_NewBox.h | 2 +- .../KiwiModel_Controller/KiwiModel_Bang.cpp | 2 +- .../KiwiModel_Controller/KiwiModel_Bang.h | 2 +- .../KiwiModel_Controller/KiwiModel_Slider.cpp | 2 +- .../KiwiModel_Controller/KiwiModel_Slider.h | 4 +- .../KiwiModel_Controller/KiwiModel_Toggle.cpp | 2 +- .../KiwiModel_Controller/KiwiModel_Toggle.h | 2 +- .../KiwiModel_Dsp/KiwiModel_AdcTilde.cpp | 8 +- .../KiwiModel_Dsp/KiwiModel_AdcTilde.h | 4 +- .../KiwiModel_Dsp/KiwiModel_DacTilde.cpp | 8 +- .../KiwiModel_Dsp/KiwiModel_DacTilde.h | 4 +- .../KiwiModel_DelaySimpleTilde.cpp | 2 +- .../KiwiModel_DelaySimpleTilde.h | 2 +- .../KiwiModel_Dsp/KiwiModel_MeterTilde.cpp | 2 +- .../KiwiModel_Dsp/KiwiModel_MeterTilde.h | 2 +- .../KiwiModel_Dsp/KiwiModel_OscTilde.cpp | 2 +- .../KiwiModel_Dsp/KiwiModel_OscTilde.h | 2 +- .../KiwiModel_Dsp/KiwiModel_PlusTilde.cpp | 2 +- .../KiwiModel_Dsp/KiwiModel_PlusTilde.h | 2 +- .../KiwiModel_Dsp/KiwiModel_SigTilde.cpp | 2 +- .../KiwiModel_Dsp/KiwiModel_SigTilde.h | 2 +- .../KiwiModel_Dsp/KiwiModel_TimesTilde.cpp | 2 +- .../KiwiModel_Dsp/KiwiModel_TimesTilde.h | 2 +- .../KiwiModel_Math/KiwiModel_Plus.cpp | 2 +- .../KiwiModel_Math/KiwiModel_Plus.h | 2 +- .../KiwiModel_Math/KiwiModel_Times.cpp | 2 +- .../KiwiModel_Math/KiwiModel_Times.h | 2 +- .../KiwiModel_Message/KiwiModel_Loadmess.cpp | 2 +- .../KiwiModel_Message/KiwiModel_Loadmess.h | 2 +- .../KiwiModel_Message/KiwiModel_Print.cpp | 2 +- .../KiwiModel_Message/KiwiModel_Print.h | 2 +- .../KiwiModel_Message/KiwiModel_Receive.cpp | 2 +- .../KiwiModel_Message/KiwiModel_Receive.h | 2 +- .../KiwiModel_Time/KiwiModel_Delay.cpp | 2 +- .../KiwiModel_Time/KiwiModel_Delay.h | 2 +- .../KiwiModel_Time/KiwiModel_Metro.cpp | 2 +- .../KiwiModel_Time/KiwiModel_Metro.h | 2 +- .../KiwiModel_Time/KiwiModel_Pipe.cpp | 2 +- .../KiwiModel_Time/KiwiModel_Pipe.h | 2 +- .../KiwiTool_Atom.h} | 7 +- Modules/KiwiTool/KiwiTool_Beacon.cpp | 73 ++++ Modules/KiwiTool/KiwiTool_Beacon.h | 115 +++++ Modules/KiwiTool/KiwiTool_CircularBuffer.h | 164 +++++++ Modules/KiwiTool/KiwiTool_ConcurrentQueue.h | 123 ++++++ Modules/KiwiTool/KiwiTool_Listeners.h | 142 +++++++ Modules/KiwiTool/KiwiTool_Scheduler.h | 378 +++++++++++++++++ Modules/KiwiTool/KiwiTool_Scheduler.hpp | 396 +++++++++++++++++ Test/Model/test_PatcherValidator.cpp | 11 +- Test/{Model => Tool}/test_Atom.cpp | 4 +- Test/Tool/test_KiwiTool.cpp | 33 ++ Test/{Engine => Tool}/test_Scheduler.cpp | 7 +- 141 files changed, 1744 insertions(+), 1694 deletions(-) delete mode 100644 Modules/KiwiEngine/KiwiEngine_Beacon.cpp delete mode 100644 Modules/KiwiEngine/KiwiEngine_Beacon.h delete mode 100644 Modules/KiwiEngine/KiwiEngine_CircularBuffer.h delete mode 100644 Modules/KiwiEngine/KiwiEngine_ConcurrentQueue.h delete mode 100644 Modules/KiwiEngine/KiwiEngine_Listeners.h delete mode 100644 Modules/KiwiEngine/KiwiEngine_Scheduler.h delete mode 100644 Modules/KiwiEngine/KiwiEngine_Scheduler.hpp rename Modules/{KiwiModel/KiwiModel_Atom.h => KiwiTool/KiwiTool_Atom.h} (97%) create mode 100644 Modules/KiwiTool/KiwiTool_Beacon.cpp create mode 100644 Modules/KiwiTool/KiwiTool_Beacon.h create mode 100644 Modules/KiwiTool/KiwiTool_CircularBuffer.h create mode 100644 Modules/KiwiTool/KiwiTool_ConcurrentQueue.h create mode 100644 Modules/KiwiTool/KiwiTool_Listeners.h create mode 100644 Modules/KiwiTool/KiwiTool_Scheduler.h create mode 100644 Modules/KiwiTool/KiwiTool_Scheduler.hpp rename Test/{Model => Tool}/test_Atom.cpp (99%) create mode 100755 Test/Tool/test_KiwiTool.cpp rename Test/{Engine => Tool}/test_Scheduler.cpp (98%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 78f5912e..e19c49ec 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -326,6 +326,17 @@ endif() set(JSON_INCLUDE_DIRS ${ROOT_DIR}/ThirdParty/json) +#---------------------------------- +# KiwiTool +#---------------------------------- + +file(GLOB_RECURSE KIWI_TOOL_SRC ${ROOT_DIR}/Modules/KiwiTool/*.[c|h]pp + ${ROOT_DIR}/Modules/KiwiTool/*.h) +add_library(KiwiTool STATIC ${KIWI_TOOL_SRC}) +target_include_directories(KiwiTool PUBLIC ${ROOT_DIR}/Modules ${ROOT_DIR}/ThirdParty/concurrentqueue) +set_target_properties(KiwiTool PROPERTIES FOLDER Modules) +source_group_rec("${KIWI_TOOL_SRC}" ${ROOT_DIR}/Modules/KiwiTool) + #---------------------------------- # Model #---------------------------------- @@ -333,8 +344,9 @@ set(JSON_INCLUDE_DIRS ${ROOT_DIR}/ThirdParty/json) file(GLOB_RECURSE KIWI_MODEL_SRC ${ROOT_DIR}/Modules/KiwiModel/*.[c|h]pp ${ROOT_DIR}/Modules/KiwiModel/*.h) add_library(KiwiModel STATIC ${KIWI_MODEL_SRC}) +target_add_dependency(KiwiModel KiwiTool) target_include_directories(KiwiModel PUBLIC ${ROOT_DIR}/Modules ${FLIP_INCLUDE_DIRS}) -target_link_libraries(KiwiModel ${FLIP_LIBRARIES}) +target_link_libraries(KiwiModel PUBLIC ${FLIP_LIBRARIES}) target_compile_definitions(KiwiModel PUBLIC ${FLIP_COMPILE_DEFINITIONS}) set_target_properties(KiwiModel PROPERTIES FOLDER Modules) source_group_rec("${KIWI_MODEL_SRC}" ${ROOT_DIR}/Modules/KiwiModel) @@ -380,7 +392,6 @@ source_group_rec("${KIWI_NETWORK_SRC}" ${ROOT_DIR}/Modules/KiwiNetwork) file(GLOB_RECURSE KIWI_ENGINE_SRC ${ROOT_DIR}/Modules/KiwiEngine/*.[c|h]pp ${ROOT_DIR}/Modules/KiwiEngine/*.h) add_library(KiwiEngine STATIC ${KIWI_ENGINE_SRC}) -target_include_directories(KiwiEngine PUBLIC ${ROOT_DIR}/ThirdParty/concurrentqueue) target_include_directories(KiwiEngine PUBLIC ${ROOT_DIR}/Modules) target_add_dependency(KiwiEngine KiwiModel) target_add_dependency(KiwiEngine KiwiDsp) @@ -445,6 +456,18 @@ source_group_rec("${KIWI_CLIENT_SRC}" ${ROOT_DIR}/Client/Source) # Tests #---------------------------------- +# Test Tool + +file(GLOB TEST_TOOL_SRC ${ROOT_DIR}/Test/Tool/*.[c|h]pp + ${ROOT_DIR}/Test/Tool/*.h) +add_executable(test_tool ${TEST_TOOL_SRC}) +target_add_dependency(test_tool KiwiTool) +set_target_properties(test_tool PROPERTIES FOLDER Test) +if (LINUX) + target_link_libraries(test_tool PUBLIC ${PTHREAD}) +endif() +source_group_rec("${TEST_TOOL_SRC}" ${ROOT_DIR}/Test/Tool) + # Test Dsp file(GLOB TEST_DSP_SRC ${ROOT_DIR}/Test/Dsp/*.[c|h]pp @@ -478,9 +501,6 @@ file(GLOB TEST_ENGINE_SRC ${ROOT_DIR}/Test/Engine/*.[c|h]pp ${ROOT_DIR}/Test/Engine/*.h) add_executable(test_engine ${TEST_ENGINE_SRC}) target_add_dependency(test_engine KiwiEngine) -if (LINUX) - target_link_libraries(test_engine PUBLIC ${PTHREAD}) -endif() set_target_properties(test_engine PROPERTIES FOLDER Test) source_group_rec("${TEST_ENGINE_SRC}" ${ROOT_DIR}/Test/Engine) @@ -506,17 +526,19 @@ if(${GCOV_SUPPORT} STREQUAL "On" AND DEBUG) target_link_libraries(test_engine PUBLIC gcov) target_link_libraries(test_server PUBLIC gcov) target_link_libraries(test_network PUBLIC gcov) + target_link_libraries(test_tool PUBLIC gcov) endif() # Tests Target -add_custom_target(Tests ALL DEPENDS test_dsp test_model test_engine test_network) +add_custom_target(Tests ALL DEPENDS test_dsp test_model test_engine test_network test_tool) set_target_properties(Tests PROPERTIES FOLDER Test) add_custom_command(TARGET Tests POST_BUILD COMMAND test_dsp COMMAND test_model COMMAND test_engine + COMMAND test_tool COMMAND test_server COMMAND test_network USES_TERMINAL) diff --git a/Client/Source/KiwiApp_Application/KiwiApp_BeaconDispatcher.cpp b/Client/Source/KiwiApp_Application/KiwiApp_BeaconDispatcher.cpp index 017eab66..ce8ed25a 100644 --- a/Client/Source/KiwiApp_Application/KiwiApp_BeaconDispatcher.cpp +++ b/Client/Source/KiwiApp_Application/KiwiApp_BeaconDispatcher.cpp @@ -57,7 +57,7 @@ namespace kiwi if(btn == &m_send_button) { std::string args = m_message_editor.getText().toStdString(); - m_owner.sendValue(AtomHelper::parse(args)); + m_owner.sendValue(tool::AtomHelper::parse(args)); } } @@ -195,16 +195,16 @@ namespace kiwi } } - void BeaconDispatcherElem::sendValue(std::vector const& args) const + void BeaconDispatcherElem::sendValue(std::vector const& args) const { send(m_beacon_name_editor.getText().toStdString(), args); } - void BeaconDispatcherElem::send(std::string const& name, std::vector const& args) const + void BeaconDispatcherElem::send(std::string const& name, std::vector const& args) const { if(!name.empty() && !args.empty()) { - engine::Beacon& beacon = m_instance.getBeacon(name); + tool::Beacon& beacon = m_instance.getBeacon(name); beacon.dispatch(args); } } diff --git a/Client/Source/KiwiApp_Application/KiwiApp_BeaconDispatcher.h b/Client/Source/KiwiApp_Application/KiwiApp_BeaconDispatcher.h index 02900529..666250c1 100644 --- a/Client/Source/KiwiApp_Application/KiwiApp_BeaconDispatcher.h +++ b/Client/Source/KiwiApp_Application/KiwiApp_BeaconDispatcher.h @@ -21,6 +21,7 @@ #pragma once +#include #include #include "../KiwiApp_Components/KiwiApp_Window.h" @@ -78,10 +79,10 @@ namespace kiwi }; //! @brief dispatch message to castaways - void sendValue(std::vector const& args) const; + void sendValue(std::vector const& args) const; //! @brief dispatch message to castaways - void send(std::string const& name, std::vector const& args) const; + void send(std::string const& name, std::vector const& args) const; //! @brief Called when a slider value changed. void sliderValueChanged(juce::Slider* slider) override; diff --git a/Client/Source/KiwiApp_Application/KiwiApp_Console.cpp b/Client/Source/KiwiApp_Application/KiwiApp_Console.cpp index 57863e0a..38121fd6 100644 --- a/Client/Source/KiwiApp_Application/KiwiApp_Console.cpp +++ b/Client/Source/KiwiApp_Application/KiwiApp_Console.cpp @@ -140,7 +140,7 @@ namespace kiwi void ConsoleContent::consoleHistoryChanged(ConsoleHistory const&) { - engine::Scheduler<> &scheduler = KiwiApp::useInstance().useScheduler(); + tool::Scheduler<> &scheduler = KiwiApp::useInstance().useScheduler(); scheduler.defer([this]() { diff --git a/Client/Source/KiwiApp_Application/KiwiApp_ConsoleHistory.h b/Client/Source/KiwiApp_Application/KiwiApp_ConsoleHistory.h index ac279b32..548d7136 100644 --- a/Client/Source/KiwiApp_Application/KiwiApp_ConsoleHistory.h +++ b/Client/Source/KiwiApp_Application/KiwiApp_ConsoleHistory.h @@ -107,7 +107,7 @@ namespace kiwi std::mutex m_message_mutex; std::vector m_messages; Sort m_sort; - engine::Listeners m_listeners; + tool::Listeners m_listeners; }; // ================================================================================ // diff --git a/Client/Source/KiwiApp_Application/KiwiApp_DocumentBrowserView.h b/Client/Source/KiwiApp_Application/KiwiApp_DocumentBrowserView.h index 5191b109..5cb23d1c 100644 --- a/Client/Source/KiwiApp_Application/KiwiApp_DocumentBrowserView.h +++ b/Client/Source/KiwiApp_Application/KiwiApp_DocumentBrowserView.h @@ -21,7 +21,7 @@ #pragma once -#include +#include #include "../KiwiApp_Network/KiwiApp_DocumentBrowser.h" #include "../KiwiApp_Components/KiwiApp_ImageButton.h" diff --git a/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp b/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp index 7360c022..54823b14 100644 --- a/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp +++ b/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp @@ -124,7 +124,7 @@ namespace kiwi return m_instance; } - engine::Scheduler<> & Instance::useScheduler() + tool::Scheduler<> & Instance::useScheduler() { return m_scheduler; } diff --git a/Client/Source/KiwiApp_Application/KiwiApp_Instance.h b/Client/Source/KiwiApp_Application/KiwiApp_Instance.h index ba497ec9..0294623f 100644 --- a/Client/Source/KiwiApp_Application/KiwiApp_Instance.h +++ b/Client/Source/KiwiApp_Application/KiwiApp_Instance.h @@ -22,7 +22,7 @@ #pragma once #include -#include +#include #include @@ -76,7 +76,7 @@ namespace kiwi engine::Instance const& useEngineInstance() const; //! @brief Returns the instance's scheduler - engine::Scheduler<> & useScheduler(); + tool::Scheduler<> & useScheduler(); //! @brief Open a File. bool openFile(juce::File const& file); @@ -146,7 +146,7 @@ namespace kiwi private: // variables - engine::Scheduler<> m_scheduler; + tool::Scheduler<> m_scheduler; engine::Instance m_instance; diff --git a/Client/Source/KiwiApp_Components/KiwiApp_SuggestEditor.h b/Client/Source/KiwiApp_Components/KiwiApp_SuggestEditor.h index ab164cd5..a982d40d 100644 --- a/Client/Source/KiwiApp_Components/KiwiApp_SuggestEditor.h +++ b/Client/Source/KiwiApp_Components/KiwiApp_SuggestEditor.h @@ -21,7 +21,7 @@ #pragma once -#include +#include #include #include diff --git a/Client/Source/KiwiApp_General/KiwiApp_StoredSettings.h b/Client/Source/KiwiApp_General/KiwiApp_StoredSettings.h index fc22a5fc..e325f6b1 100644 --- a/Client/Source/KiwiApp_General/KiwiApp_StoredSettings.h +++ b/Client/Source/KiwiApp_General/KiwiApp_StoredSettings.h @@ -22,7 +22,7 @@ #pragma once #include -#include +#include #include namespace kiwi @@ -109,7 +109,7 @@ namespace kiwi private: // variables juce::ValueTree m_settings; - engine::Listeners m_listeners; + tool::Listeners m_listeners; friend StoredSettings; }; diff --git a/Client/Source/KiwiApp_Network/KiwiApp_ApiController.h b/Client/Source/KiwiApp_Network/KiwiApp_ApiController.h index 44fe92b4..45cf205b 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_ApiController.h +++ b/Client/Source/KiwiApp_Network/KiwiApp_ApiController.h @@ -21,7 +21,7 @@ #pragma once -#include +#include #include "../KiwiApp_Network/KiwiApp_Api.h" #include "../KiwiApp_General/KiwiApp_StoredSettings.h" @@ -90,6 +90,6 @@ namespace kiwi private: // variables - engine::Listeners m_listeners; + tool::Listeners m_listeners; }; } diff --git a/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.h b/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.h index cad0cd6a..c78a66e7 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.h +++ b/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.h @@ -21,7 +21,7 @@ #pragma once -#include +#include #include #include @@ -89,7 +89,7 @@ namespace kiwi private: // variables std::unique_ptr m_distant_drive; - engine::Listeners m_listeners = {}; + tool::Listeners m_listeners = {}; }; // ================================================================================ // @@ -173,7 +173,7 @@ namespace kiwi uint16_t m_session_port = 9090; std::string m_name = "Drive"; DocumentSessions m_documents; - engine::Listeners m_listeners; + tool::Listeners m_listeners; friend class DocumentBrowser; }; diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.h index 05002c61..08ddbd85 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.h @@ -27,7 +27,7 @@ #include -#include +#include #include @@ -121,7 +121,7 @@ namespace kiwi private: // members Label m_label; - engine::Listeners m_listeners; + tool::Listeners m_listeners; private: // deleted methods diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_BangView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_BangView.cpp index 225d2c20..98c169c0 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_BangView.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_BangView.cpp @@ -23,7 +23,7 @@ #include -#include +#include #include #include @@ -36,7 +36,7 @@ namespace kiwi m_connection(m_signal.connect(std::bind(&BangView::signalTriggered, this))), m_active(false), m_mouse_down(false), - m_switch_off(std::make_shared::CallBack>(std::bind(&BangView::switchOff, this))) + m_switch_off(std::make_shared::CallBack>(std::bind(&BangView::switchOff, this))) { } diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_BangView.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_BangView.h index d6896c21..e8c40585 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_BangView.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_BangView.h @@ -27,7 +27,7 @@ #include -#include +#include #include @@ -76,7 +76,7 @@ namespace kiwi flip::SignalConnection m_connection; bool m_active; bool m_mouse_down; - std::shared_ptr::CallBack> m_switch_off; + std::shared_ptr::CallBack> m_switch_off; private: // deleted methods diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_SliderView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_SliderView.cpp index 7456a2ba..0559adf3 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_SliderView.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_SliderView.cpp @@ -25,7 +25,7 @@ #include -#include +#include #include #include @@ -36,12 +36,12 @@ namespace kiwi // SLIDER VIEW // // ================================================================================ // - class SliderView::Task final : public engine::Scheduler<>::Task + class SliderView::Task final : public tool::Scheduler<>::Task { public: // methods Task(SliderView & object, double new_value): - engine::Scheduler<>::Task(), + tool::Scheduler<>::Task(), m_object(object), m_new_value(new_value) { diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_SliderView.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_SliderView.h index 7aa50234..dfa6b315 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_SliderView.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_SliderView.h @@ -23,7 +23,7 @@ #include -#include +#include #include @@ -66,7 +66,7 @@ namespace kiwi juce::Slider m_slider; flip::Signal & m_signal; flip::SignalConnection m_connection; - engine::ConcurrentQueue> m_tasks; + tool::ConcurrentQueue> m_tasks; private: // delted methods diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_ToggleView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_ToggleView.cpp index 0a44f7a0..7fa610d6 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_ToggleView.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_ToggleView.cpp @@ -34,12 +34,12 @@ namespace kiwi // TOGGLE VIEW // // ================================================================================ // - class ToggleView::Task final : public engine::Scheduler<>::Task + class ToggleView::Task final : public tool::Scheduler<>::Task { public: // methods Task(ToggleView & object, model::Toggle::Request request): - engine::Scheduler<>::Task(), + tool::Scheduler<>::Task(), m_object(object), m_request(request) { diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_ToggleView.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_ToggleView.h index 8db6c717..135a2cbf 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_ToggleView.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_ToggleView.h @@ -26,8 +26,8 @@ #include -#include -#include +#include +#include #include #include @@ -71,7 +71,7 @@ namespace kiwi flip::Signal & m_signal; flip::SignalConnection m_connection; bool m_is_on; - engine::ConcurrentQueue> m_tasks; + tool::ConcurrentQueue> m_tasks; private: // deleted methods diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Dsp/KiwiApp_MeterTildeView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Dsp/KiwiApp_MeterTildeView.cpp index cf755cc7..6535bfcd 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Dsp/KiwiApp_MeterTildeView.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Dsp/KiwiApp_MeterTildeView.cpp @@ -24,7 +24,7 @@ #include -#include +#include #include @@ -36,7 +36,7 @@ namespace kiwi // METER~ VIEW // // ================================================================================ // - class MeterTildeView::Task : public engine::Scheduler<>::Task + class MeterTildeView::Task : public tool::Scheduler<>::Task { public: // methods diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Dsp/KiwiApp_MeterTildeView.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Dsp/KiwiApp_MeterTildeView.h index d297cc3b..1a89a0f7 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Dsp/KiwiApp_MeterTildeView.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Dsp/KiwiApp_MeterTildeView.h @@ -29,7 +29,7 @@ #include -#include +#include #include @@ -89,7 +89,7 @@ namespace kiwi int m_border; int m_padding; flip::SignalConnection m_connection; - engine::ConcurrentQueue> m_tasks; + tool::ConcurrentQueue> m_tasks; private: // deleted methods diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.h b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.h index 6dd34a4b..44da8a96 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.h @@ -192,7 +192,7 @@ namespace kiwi std::unordered_set m_connected_users; - engine::Listeners m_listeners; + tool::Listeners m_listeners; }; // ================================================================================ // diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp index 73a0720f..0c150091 100755 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp @@ -1548,7 +1548,7 @@ namespace kiwi { model::Object & old_model = object_frame.getModel(); - std::vector atoms = AtomHelper::parse(new_text); + std::vector atoms = tool::AtomHelper::parse(new_text); std::unique_ptr object_model = model::Factory::create(atoms); @@ -1594,7 +1594,7 @@ namespace kiwi { bool linked_newbox = m_local_objects_selection.size() == 1; - std::unique_ptr new_object = model::Factory::create(AtomHelper::parse(text)); + std::unique_ptr new_object = model::Factory::create(tool::AtomHelper::parse(text)); juce::Point pos = getMouseXYRelative() - getOriginPosition(); diff --git a/Modules/KiwiEngine/KiwiEngine_Beacon.cpp b/Modules/KiwiEngine/KiwiEngine_Beacon.cpp deleted file mode 100644 index 3cd28282..00000000 --- a/Modules/KiwiEngine/KiwiEngine_Beacon.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#include "KiwiEngine_Beacon.h" - -namespace kiwi -{ - namespace engine - { - // ================================================================================ // - // BEACON // - // ================================================================================ // - - Beacon::Beacon(std::string const& name) : m_name(name) - { - ; - } - - void Beacon::bind(Castaway& castaway) - { - m_castaways.insert(&castaway); - } - - void Beacon::unbind(Castaway& castaway) - { - m_castaways.erase(&castaway); - } - - void Beacon::dispatch(std::vector const& args) - { - for(auto* castaway : m_castaways) - { - castaway->receive(args); - } - } - - // ================================================================================ // - // BEACON FACTORY // - // ================================================================================ // - - Beacon& Beacon::Factory::getBeacon(std::string const& name) - { - auto it = m_beacons.find(name); - if(it != m_beacons.end()) - { - return *it->second.get(); - } - - Beacon* beacon = new Beacon(name); - if(beacon) - { - m_beacons[name] = std::unique_ptr(beacon); - } - return *beacon; - } - }; -}; diff --git a/Modules/KiwiEngine/KiwiEngine_Beacon.h b/Modules/KiwiEngine/KiwiEngine_Beacon.h deleted file mode 100644 index 9a7c764f..00000000 --- a/Modules/KiwiEngine/KiwiEngine_Beacon.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#pragma once - -#include "KiwiEngine_Def.h" - -namespace kiwi -{ - namespace engine - { - // ================================================================================ // - // BEACON // - // ================================================================================ // - - //! @brief The beacon is unique and matchs to a "unique" string in the scope of a beacon factory and can be used to bind beacon's castaways. - //! @details The beacon are uniques in the scope of a beacon factory and matchs to a string. - //! If you create a beacon with a string that already matchs to a beacon of the beacon factory, - //! it will return this beacon otherwise it will create a new beacon. - //! Thus, the beacons can be used to bind, unbind and retrieve castways. - //! After recovering a castaway, you should dynamically cast it to the class you expect. - //! More often, this will be a kiwi Object. - //! @see Beacon::Factory - //! @see Beacon::Castaway - class Beacon - { - public: // methods - - class Castaway; - - //! @brief Gets the name of the beacon. - inline std::string getName() const {return m_name;} - - //! @brief Destructor. - ~Beacon() = default; - - //! @brief Adds a castaway in the binding list of the beacon. - void bind(Castaway& castaway); - - //! @brief Removes a castaways from the binding list of the beacon. - void unbind(Castaway& castaway); - - //! @brief Dispatch message to beacon castaways. - void dispatch(std::vector const& args); - - public: // nested classes - - // ================================================================================ // - // BEACON CASTAWAY // - // ================================================================================ // - - //! @brief The beacon castaway can be binded to a beacon. - class Castaway - { - public: - virtual ~Castaway() {} - virtual void receive(std::vector const& args) = 0; - }; - - // ================================================================================ // - // BEACON FACTORY // - // ================================================================================ // - - //! @brief The beacon factory is used to create beacons. - class Factory - { - public: - Factory() = default; - ~Factory() = default; - Beacon& getBeacon(std::string const& name); - - private: - std::map> m_beacons; - }; - - private: // methods - - //! @internal Constructor. - Beacon(std::string const& name); - friend class Beacon::Factory; - - private: // members - - const std::string m_name; - std::set m_castaways; - - private: // deleted methods - - Beacon(Beacon const&) = delete; - Beacon(Beacon&&) = delete; - Beacon& operator=(Beacon const&) = delete; - Beacon& operator=(Beacon&&) = delete; - }; - }; -}; diff --git a/Modules/KiwiEngine/KiwiEngine_CircularBuffer.h b/Modules/KiwiEngine/KiwiEngine_CircularBuffer.h deleted file mode 100644 index 2ccdaea8..00000000 --- a/Modules/KiwiEngine/KiwiEngine_CircularBuffer.h +++ /dev/null @@ -1,166 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#pragma once - -#include -#include -#include - -namespace kiwi -{ - namespace engine - { - // ================================================================================ // - // CIRCULAR BUFFER // - // ================================================================================ // - - //! @todo documentation inspired from boost circular buffer - //! @see http://www.boost.org/doc/libs/1_59_0/doc/html/boost/circular_buffer.html#idp23975984-bb - template - class CircularBuffer final - { - public: // methods - - CircularBuffer(size_t capacity): - m_buffer((T*) std::malloc(capacity * sizeof(T))), - m_head(0), - m_tail(0), - m_size(0), - m_capacity(capacity) - { - } - - CircularBuffer(size_t capacity, size_t size, T const& value): - m_buffer((T*) std::malloc(capacity * sizeof(T))), - m_head(0), - m_tail(0), - m_size(0), - m_capacity(capacity) - { - assert(m_capacity >= m_size); - - for (int i = 0; i < size; ++i) - { - push_back(value); - } - } - - ~CircularBuffer() - { - for (int i = std::min(m_head, m_tail); i < std::max(m_head, m_tail); ++i) - { - (m_buffer + i)->~T(); - } - - std::free(m_buffer); - } - - void assign(size_t nb_elements, const T& value) - { - clear(); - - for(int i = 0; i < nb_elements; ++i) - { - push_back(value); - } - } - - void clear() - { - size_t init_size = m_size; - - for (int i = 0; i < init_size; ++i) - { - pop_front(); - } - } - - size_t size() const - { - return m_size; - } - - T const& operator[](size_t index) const noexcept - { - return *(m_buffer + ((m_head + index) % m_size)); - } - - T& operator[](size_t index) noexcept - { - return *(m_buffer + ((m_head + index) % m_size)); - } - - void push_back(T const& value) - { - if (m_size == m_capacity) - { - (m_buffer + m_tail)->~T(); - increment_head(); - } - - new (m_buffer + m_tail) T(value); - - increment_tail(); - } - - void pop_front() - { - if (m_size != 0) - { - (m_buffer + m_head)->~T(); - increment_head(); - } - } - - private: // methods - - void increment_head() - { - m_head = (m_head + 1) == m_capacity ? 0 : m_head + 1; - --m_size; - } - - void increment_tail() - { - m_tail = (m_tail + 1) == m_capacity ? 0 : m_tail + 1; - ++m_size; - } - - private: // members - - T* m_buffer; - size_t m_head; - size_t m_tail; - size_t m_size; - size_t m_capacity; - - private: // deleted methods - - CircularBuffer() = delete; - CircularBuffer(CircularBuffer const& other) = delete; - CircularBuffer(CircularBuffer && other) = delete; - CircularBuffer& operator=(CircularBuffer const& other) = delete; - CircularBuffer& operator=(CircularBuffer && other) = delete; - - }; - } -} diff --git a/Modules/KiwiEngine/KiwiEngine_ConcurrentQueue.h b/Modules/KiwiEngine/KiwiEngine_ConcurrentQueue.h deleted file mode 100644 index 20f5f0b1..00000000 --- a/Modules/KiwiEngine/KiwiEngine_ConcurrentQueue.h +++ /dev/null @@ -1,125 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#pragma once - -#include -#include - -#include - -namespace kiwi -{ - namespace engine - { - // ==================================================================================== // - // CONCURRENTQUEUE // - // ==================================================================================== // - - namespace mc = moodycamel; - - //! @brief A mono producer, mono consumer FIFO lock free queue. - //! @details Wrapper around a thirdparty concurrent queue. - //! @see https://github.com/cameron314/readerwriterqueue - template - class ConcurrentQueue final - { - public: // methods - - //! @brief Constructor. - //! @details Reserves memory space for at least capcity elements. - ConcurrentQueue(size_t capacity): - m_queue(capacity), - m_size(0) - { - } - - //! @brief Destructor. - ~ConcurrentQueue() = default; - - //! @brief Pushes element at end of queue (by copy). - //! @details If number of elements exceeds capacity allocation will occur. - //! Increments element counter. - void push(T const& value) - { - if(m_queue.enqueue(value)) - { - m_size++; - } - } - - //! @brief Pushes element at end of queue (by move). - //! @details If number of elements exceeds capacity allocation will occur. - //! Increments element counter. - void push(T&& value) - { - if(m_queue.enqueue(std::forward(value))) - { - m_size++; - } - } - - //! @brief Pops first element in the queue. - //! @details Returns false if the queue was empty and pop failed, true otherwise. - bool pop(T & value) - { - if(m_queue.try_dequeue(value)) - { - m_size--; - return true; - } - - return false; - } - - //! @brief Returns an approximative size for the queue. - //! @details Since size is increased and decreased after elements are effectively pushed or poped, - //! for the consumer the returned size is guaranteed to be lower or equal - //! to the effective size of the queue, for the producer the returned size is guaranteed to be - //! greater or equal than the effective size of the queue. - size_t load_size() const - { - return m_size.load(); - } - - private: // classes - - struct Trait : public moodycamel::ConcurrentQueueDefaultTraits - { - static const size_t BLOCK_SIZE = 1024; - }; - - private: // members - - mc::ConcurrentQueue m_queue; - std::atomic m_size; - - private: // deleted methods - - ConcurrentQueue() = delete; - ConcurrentQueue(ConcurrentQueue const& other) = delete; - ConcurrentQueue(ConcurrentQueue && other) = delete; - ConcurrentQueue& operator=(ConcurrentQueue const& other) = delete; - ConcurrentQueue& operator=(ConcurrentQueue && other) = delete; - - }; - } -} diff --git a/Modules/KiwiEngine/KiwiEngine_Console.h b/Modules/KiwiEngine/KiwiEngine_Console.h index b334b6c9..e7661931 100644 --- a/Modules/KiwiEngine/KiwiEngine_Console.h +++ b/Modules/KiwiEngine/KiwiEngine_Console.h @@ -21,8 +21,8 @@ #pragma once -#include -#include "KiwiEngine_Listeners.h" +#include +#include namespace kiwi { @@ -86,7 +86,7 @@ namespace kiwi private: // members - Listeners m_listeners; + tool::Listeners m_listeners; }; } } diff --git a/Modules/KiwiEngine/KiwiEngine_Def.h b/Modules/KiwiEngine/KiwiEngine_Def.h index 0a9ee524..29e92c5b 100644 --- a/Modules/KiwiEngine/KiwiEngine_Def.h +++ b/Modules/KiwiEngine/KiwiEngine_Def.h @@ -29,9 +29,9 @@ #include #include -#include +#include -#include "KiwiEngine_Scheduler.h" +#include namespace kiwi { @@ -44,7 +44,6 @@ namespace kiwi namespace engine { - class Beacon; class Link; class Object; class Patcher; diff --git a/Modules/KiwiEngine/KiwiEngine_Factory.cpp b/Modules/KiwiEngine/KiwiEngine_Factory.cpp index d600d756..7ec0d666 100644 --- a/Modules/KiwiEngine/KiwiEngine_Factory.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Factory.cpp @@ -34,11 +34,11 @@ namespace kiwi std::unique_ptr Factory::create(Patcher& patcher, model::Object const& model) { - std::vector args; + std::vector args; if (!model.getText().empty()) { - std::vector parsed_text = AtomHelper::parse(model.getText()); + std::vector parsed_text = tool::AtomHelper::parse(model.getText()); args.insert(args.begin(), parsed_text.begin() + 1, parsed_text.end()); } diff --git a/Modules/KiwiEngine/KiwiEngine_Factory.h b/Modules/KiwiEngine/KiwiEngine_Factory.h index 1f896cfb..9d60393b 100644 --- a/Modules/KiwiEngine/KiwiEngine_Factory.h +++ b/Modules/KiwiEngine/KiwiEngine_Factory.h @@ -50,7 +50,7 @@ namespace kiwi "The engine object must not be abstract."); static_assert(std::is_constructible const&>::value, + model::Object const&, Patcher&, std::vector const&>::value, "The engine object must have a valid constructor."); assert(!name.empty()); @@ -61,7 +61,7 @@ namespace kiwi creators[name] = [](model::Object const& model, Patcher& patcher, - std::vector const& args) -> TEngine* + std::vector const& args) -> TEngine* { return new TEngine(model, patcher, args); }; @@ -83,7 +83,7 @@ namespace kiwi using ctor_fn_t = std::function const&)>; + std::vector const&)>; using creator_map_t = std::map; diff --git a/Modules/KiwiEngine/KiwiEngine_Instance.cpp b/Modules/KiwiEngine/KiwiEngine_Instance.cpp index e6de6eb6..0e11583d 100644 --- a/Modules/KiwiEngine/KiwiEngine_Instance.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Instance.cpp @@ -118,7 +118,7 @@ namespace kiwi // SCHEDULER // // ================================================================================ // - Scheduler<> & Instance::getScheduler() + tool::Scheduler<> & Instance::getScheduler() { return m_scheduler; } diff --git a/Modules/KiwiEngine/KiwiEngine_Instance.h b/Modules/KiwiEngine/KiwiEngine_Instance.h index e8fd4ffd..4d8c890a 100644 --- a/Modules/KiwiEngine/KiwiEngine_Instance.h +++ b/Modules/KiwiEngine/KiwiEngine_Instance.h @@ -26,9 +26,10 @@ #include "flip/Document.h" +#include + #include "KiwiEngine_Console.h" #include "KiwiEngine_Patcher.h" -#include "KiwiEngine_Beacon.h" #include "KiwiEngine_AudioControler.h" namespace kiwi @@ -42,7 +43,7 @@ namespace kiwi //! @brief The Instance adds the engine objects to the engine::Factory //! @details The patcher document model must be initialised before creating the Instance //! The Instance is also the entry point to retrieve beacons and output messages to the console. - class Instance : public Beacon::Factory + class Instance : public tool::Beacon::Factory { public: // methods @@ -85,7 +86,7 @@ namespace kiwi // ================================================================================ // //! @brief Returns the engine's scheduler. - Scheduler<> & getScheduler(); + tool::Scheduler<> & getScheduler(); private: // methods @@ -100,7 +101,7 @@ namespace kiwi Console m_console; std::unique_ptr m_audio_controler; - Scheduler<> m_scheduler; + tool::Scheduler<> m_scheduler; std::atomic m_quit; std::thread m_engine_thread; diff --git a/Modules/KiwiEngine/KiwiEngine_Listeners.h b/Modules/KiwiEngine/KiwiEngine_Listeners.h deleted file mode 100644 index ec57811b..00000000 --- a/Modules/KiwiEngine/KiwiEngine_Listeners.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#pragma once - -#include -#include -#include -#include - -namespace kiwi -{ - namespace engine - { - // ================================================================================ // - // LISTENERS // - // ================================================================================ // - - //! @brief The listener set is a class that manages a list of listeners. - //! @details Manages a list of listeners and allows to retrieve them easily and thread-safely. - template - class Listeners - { - public: - - struct is_valid_listener : std::integral_constant::value && - !std::is_reference::value - > {}; - - using listener_t = typename std::remove_pointer::type>::type; - using listener_ref_t = listener_t&; - using listener_ptr_t = listener_t*; - - //! @brief Creates an empty listener set. - Listeners() - { - static_assert(is_valid_listener::value, - "Template parameter must not be a pointer or a reference"); - } - - //! @brief Destructor. - ~Listeners() noexcept { m_listeners.clear(); } - - //! @brief Add a listener. - //! @details If the listener was allready present in the set, the function does nothing. - //! @param listener The new listener to be added. - //! @return True if success, otherwise false. - bool add(listener_ref_t listener) noexcept - { - std::lock_guard guard(m_mutex); - bool insert_success = m_listeners.insert(&listener).second; - return insert_success; - } - - //! @brief Remove a listener. - //! @details If the listener wasn't in the set, the function does nothing. - //! @param listener The listener to be removed. - //! @return True if success, false otherwise. - bool remove(listener_ref_t listener) noexcept - { - std::lock_guard guard(m_mutex); - bool erase_success = m_listeners.erase(&listener); - return erase_success; - } - - //! @brief Returns the number of listeners. - size_t size() const noexcept - { - std::lock_guard guard(m_mutex); - return m_listeners.size(); - } - - //! @brief Returns true if there is no listener. - bool empty() const noexcept - { - std::lock_guard guard(m_mutex); - return m_listeners.empty(); - } - - //! @brief Remove all listeners. - void clear() noexcept - { - std::lock_guard guard(m_mutex); - m_listeners.clear(); - } - - //! @brief Returns true if the set contains a given listener. - bool contains(listener_ref_t listener) const noexcept - { - return (m_listeners.find(&listener) != m_listeners.end()); - } - - //! @brief Get the listeners. - std::vector getListeners() - { - std::lock_guard guard(m_mutex); - return {m_listeners.begin(), m_listeners.end()}; - } - - //! @brief Retrieve the listeners. - std::vector getListeners() const - { - std::lock_guard guard(m_mutex); - return {m_listeners.begin(), m_listeners.end()}; - } - - //! @brief Calls a given method for each listener of the set. - //! @param fun The listener's method to call. - //! @param arguments optional arguments. - template - void call(T fun, Args&& ...arguments) const - { - for(auto* listener : getListeners()) - { - (listener->*(fun))(arguments...); - } - } - - private: - - std::set m_listeners; - mutable std::mutex m_mutex; - }; - } -} diff --git a/Modules/KiwiEngine/KiwiEngine_Object.cpp b/Modules/KiwiEngine/KiwiEngine_Object.cpp index a11a94ba..9ad5ed88 100644 --- a/Modules/KiwiEngine/KiwiEngine_Object.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Object.cpp @@ -81,7 +81,7 @@ namespace kiwi m_patcher.error(text); } - Scheduler<> & Object::getScheduler() const + tool::Scheduler<> & Object::getScheduler() const { return m_patcher.getScheduler(); } @@ -90,14 +90,14 @@ namespace kiwi // BEACON // // ================================================================================ // - Beacon& Object::getBeacon(std::string const& name) const + tool::Beacon& Object::getBeacon(std::string const& name) const { return m_patcher.getBeacon(name); } #define KIWI_ENGINE_STACKOVERFLOW_MAX 256 - void Object::send(const size_t index, std::vector const& args) + void Object::send(const size_t index, std::vector const& args) { assert(getScheduler().isThisConsumerThread()); diff --git a/Modules/KiwiEngine/KiwiEngine_Object.h b/Modules/KiwiEngine/KiwiEngine_Object.h index 06990f99..759a80c1 100644 --- a/Modules/KiwiEngine/KiwiEngine_Object.h +++ b/Modules/KiwiEngine/KiwiEngine_Object.h @@ -22,7 +22,8 @@ #pragma once #include "KiwiEngine_Def.h" -#include "KiwiEngine_Scheduler.h" + +#include #include @@ -50,7 +51,7 @@ namespace kiwi //! @brief Receives a set of arguments via an inlet. //! @details This method must be overriden by object's subclasses. //! @todo see if the method must be noexcept. - virtual void receive(size_t index, std::vector const& args) = 0; + virtual void receive(size_t index, std::vector const& args) = 0; //! @brief Called when the Patcher is loaded. virtual void loadbang() {}; @@ -84,14 +85,14 @@ namespace kiwi // ================================================================================ // //! @biref Returns the engine's scheduler. - Scheduler<> & getScheduler() const; + tool::Scheduler<> & getScheduler() const; // ================================================================================ // // BEACON // // ================================================================================ // //! @brief Gets or creates a Beacon with a given name. - Beacon& getBeacon(std::string const& name) const; + tool::Beacon& getBeacon(std::string const& name) const; // ================================================================================ // // SEND // @@ -100,7 +101,7 @@ namespace kiwi //! @brief Sends a vector of Atom via an outlet. //! @todo Improve the stack overflow system. //! @todo See if the method must be noexcept. - void send(const size_t index, std::vector const& args); + void send(const size_t index, std::vector const& args); private: // members diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Basic/KiwiEngine_ErrorBox.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Basic/KiwiEngine_ErrorBox.cpp index 74b04849..ef5a0755 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Basic/KiwiEngine_ErrorBox.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Basic/KiwiEngine_ErrorBox.cpp @@ -29,13 +29,13 @@ namespace kiwi // ERRORBOX // // ================================================================================ // - ErrorBox::ErrorBox(model::Object const& model, Patcher& patcher, std::vector const& args) + ErrorBox::ErrorBox(model::Object const& model, Patcher& patcher, std::vector const& args) : AudioObject(model, patcher) { ; } - void ErrorBox::receive(size_t index, std::vector const& args) + void ErrorBox::receive(size_t index, std::vector const& args) { ; } diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Basic/KiwiEngine_ErrorBox.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Basic/KiwiEngine_ErrorBox.h index 65e7bc22..b90a9218 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Basic/KiwiEngine_ErrorBox.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Basic/KiwiEngine_ErrorBox.h @@ -34,9 +34,9 @@ namespace kiwi class ErrorBox : public AudioObject { public: - ErrorBox(model::Object const& model, Patcher& patcher, std::vector const& args); + ErrorBox(model::Object const& model, Patcher& patcher, std::vector const& args); - void receive(size_t index, std::vector const& args) override; + void receive(size_t index, std::vector const& args) override; void prepare(dsp::Processor::PrepareInfo const& infos) override final; }; diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Basic/KiwiEngine_NewBox.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Basic/KiwiEngine_NewBox.cpp index a7c37b0a..7420243e 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Basic/KiwiEngine_NewBox.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Basic/KiwiEngine_NewBox.cpp @@ -29,13 +29,13 @@ namespace kiwi // NEWBOX // // ================================================================================ // - NewBox::NewBox(model::Object const& model, Patcher& patcher, std::vector const& args) + NewBox::NewBox(model::Object const& model, Patcher& patcher, std::vector const& args) : Object(model, patcher) { ; } - void NewBox::receive(size_t index, std::vector const& args) + void NewBox::receive(size_t index, std::vector const& args) { ; } diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Basic/KiwiEngine_NewBox.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Basic/KiwiEngine_NewBox.h index 27e9af27..349f7710 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Basic/KiwiEngine_NewBox.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Basic/KiwiEngine_NewBox.h @@ -34,9 +34,9 @@ namespace kiwi class NewBox : public engine::Object { public: - NewBox(model::Object const& model, Patcher& patcher, std::vector const& args); + NewBox(model::Object const& model, Patcher& patcher, std::vector const& args); - void receive(size_t index, std::vector const& args) override; + void receive(size_t index, std::vector const& args) override; }; } } diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Bang.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Bang.cpp index d54d28ef..9c4e7c3b 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Bang.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Bang.cpp @@ -21,7 +21,7 @@ #include -#include +#include #include namespace kiwi @@ -32,7 +32,7 @@ namespace kiwi // OBJECT BANG // // ================================================================================ // - class Bang::Task : public Scheduler<>::Task + class Bang::Task : public tool::Scheduler<>::Task { public: // methods @@ -55,7 +55,7 @@ namespace kiwi Bang & m_object; }; - Bang::Bang(model::Object const& model, Patcher& patcher, std::vector const& args): + Bang::Bang(model::Object const& model, Patcher& patcher, std::vector const& args): Object(model, patcher), m_task(new Task(*this)), m_signal(model.getSignal<>(model::Bang::Signal::TriggerBang)), @@ -73,7 +73,7 @@ namespace kiwi getScheduler().defer(m_task); } - void Bang::receive(size_t index, std::vector const& args) + void Bang::receive(size_t index, std::vector const& args) { if (index == 0) { diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Bang.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Bang.h index d4de7ca6..fbf165eb 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Bang.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Bang.h @@ -25,7 +25,7 @@ #include #include -#include +#include #include @@ -45,13 +45,13 @@ namespace kiwi public: // methods - Bang(model::Object const& model, Patcher& patcher, std::vector const& args); + Bang(model::Object const& model, Patcher& patcher, std::vector const& args); ~Bang(); void signalTriggered(); - void receive(size_t index, std::vector const& args) override final; + void receive(size_t index, std::vector const& args) override final; private: // members diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Slider.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Slider.cpp index b528163e..6feee12b 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Slider.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Slider.cpp @@ -24,12 +24,12 @@ #include -#include +#include #include namespace kiwi { namespace engine { - class Slider::Task final : public Scheduler<>::Task + class Slider::Task final : public tool::Scheduler<>::Task { public: // methods @@ -59,7 +59,7 @@ namespace kiwi { namespace engine { // OBJECT SLIDER // // ================================================================================ // - Slider::Slider(model::Object const& object_model, Patcher& patcher, std::vector const& args): + Slider::Slider(model::Object const& object_model, Patcher& patcher, std::vector const& args): Object(object_model, patcher), m_signal(object_model.getSignal(model::Slider::Signal::ValueChanged)), m_connection(m_signal.connect(std::bind(&Slider::valueChanged, this, std::placeholders::_1))), @@ -86,7 +86,7 @@ namespace kiwi { namespace engine { getScheduler().schedule(task); } - void Slider::receive(size_t index, std::vector const& args) + void Slider::receive(size_t index, std::vector const& args) { if (index == 0 && !args.empty()) { diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Slider.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Slider.h index 11ddbe23..f5a2dce8 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Slider.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Slider.h @@ -26,7 +26,7 @@ #include -#include +#include #include #include @@ -45,19 +45,19 @@ namespace kiwi { namespace engine { public: // methods - Slider(model::Object const& model, Patcher& patcher, std::vector const& args); + Slider(model::Object const& model, Patcher& patcher, std::vector const& args); ~Slider(); void valueChanged(double new_value); - void receive(size_t index, std::vector const& args) override final; + void receive(size_t index, std::vector const& args) override final; private: // members flip::Signal & m_signal; flip::SignalConnection m_connection; - engine::ConcurrentQueue> m_tasks; + tool::ConcurrentQueue> m_tasks; double m_value; }; diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Toggle.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Toggle.cpp index 1140f314..6213130d 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Toggle.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Toggle.cpp @@ -33,12 +33,12 @@ namespace kiwi // OBJECT BANG // // ================================================================================ // - class Toggle::Task final : public Scheduler<>::Task + class Toggle::Task final : public tool::Scheduler<>::Task { public: // methods Task(Toggle & object, model::Toggle::Request request, bool shall_output): - Scheduler<>::Task(), + tool::Scheduler<>::Task(), m_object(object), m_request(request), m_shall_output(shall_output) @@ -93,7 +93,7 @@ namespace kiwi bool m_shall_output; }; - Toggle::Toggle(model::Object const& model, Patcher& patcher, std::vector const& args): + Toggle::Toggle(model::Object const& model, Patcher& patcher, std::vector const& args): Object(model, patcher), m_signal(model.getSignal(model::Toggle::Signal::Switch)), m_connection(m_signal.connect(std::bind(&Toggle::toggleSwitched, @@ -122,7 +122,7 @@ namespace kiwi getScheduler().schedule(task); } - void Toggle::receive(size_t index, std::vector const& args) + void Toggle::receive(size_t index, std::vector const& args) { if (!args.empty()) { diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Toggle.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Toggle.h index 81567bf6..3261c4a2 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Toggle.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Toggle.h @@ -28,8 +28,8 @@ #include -#include -#include +#include +#include #include @@ -49,11 +49,11 @@ namespace kiwi public: // methods - Toggle(model::Object const& model, Patcher& patcher, std::vector const& args); + Toggle(model::Object const& model, Patcher& patcher, std::vector const& args); ~Toggle(); - void receive(size_t index, std::vector const& args) override final; + void receive(size_t index, std::vector const& args) override final; private: // methods @@ -64,7 +64,7 @@ namespace kiwi flip::Signal & m_signal; flip::SignalConnection m_connection; bool m_is_on; - engine::ConcurrentQueue> m_tasks; + tool::ConcurrentQueue> m_tasks; }; } } diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_AdcTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_AdcTilde.cpp index 55030efb..761bc2cf 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_AdcTilde.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_AdcTilde.cpp @@ -29,7 +29,7 @@ namespace kiwi // ADC~ // // ================================================================================ // - AdcTilde::AdcTilde(model::Object const& model, Patcher& patcher, std::vector const& args): + AdcTilde::AdcTilde(model::Object const& model, Patcher& patcher, std::vector const& args): AudioInterfaceObject(model, patcher, args) { std::vector routes = parseArgs(args); diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_AdcTilde.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_AdcTilde.h index 2e84c98a..b8da5325 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_AdcTilde.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_AdcTilde.h @@ -36,7 +36,7 @@ namespace kiwi { public: // methods - AdcTilde(model::Object const& model, Patcher& patcher, std::vector const& args); + AdcTilde(model::Object const& model, Patcher& patcher, std::vector const& args); void perform(dsp::Buffer const& input, dsp::Buffer& output) noexcept; diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_DacTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_DacTilde.cpp index d6b04812..576474fd 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_DacTilde.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_DacTilde.cpp @@ -29,7 +29,7 @@ namespace kiwi // DAC~ // // ================================================================================ // - DacTilde::DacTilde(model::Object const& model, Patcher& patcher, std::vector const& args): + DacTilde::DacTilde(model::Object const& model, Patcher& patcher, std::vector const& args): AudioInterfaceObject(model, patcher, args) { std::vector routes = parseArgs(args); diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_DacTilde.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_DacTilde.h index 136b8f36..d1e6add3 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_DacTilde.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_DacTilde.h @@ -35,7 +35,7 @@ namespace kiwi { public: // methods - DacTilde(model::Object const& model, Patcher& patcher, std::vector const& args); + DacTilde(model::Object const& model, Patcher& patcher, std::vector const& args); void perform(dsp::Buffer const& input, dsp::Buffer& output) noexcept; diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_DelaySimpleTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_DelaySimpleTilde.cpp index 86d9a5af..18e5a30a 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_DelaySimpleTilde.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_DelaySimpleTilde.cpp @@ -29,7 +29,7 @@ namespace kiwi // DELAYSIMPLETILDE // // ================================================================================ // - DelaySimpleTilde::DelaySimpleTilde(model::Object const& model, Patcher& patcher, std::vector const& args): + DelaySimpleTilde::DelaySimpleTilde(model::Object const& model, Patcher& patcher, std::vector const& args): AudioObject(model, patcher), m_circular_buffer(), m_reinject_signal(), @@ -42,7 +42,7 @@ namespace kiwi { } - void DelaySimpleTilde::receive(size_t index, std::vector const& args) + void DelaySimpleTilde::receive(size_t index, std::vector const& args) { if (index == 0 && args[0].isString()) { @@ -138,7 +138,7 @@ namespace kiwi size_t buffer_size = std::ceil(m_max_delay * m_sr) + 1 + m_vector_size; - m_circular_buffer.reset(new CircularBuffer(buffer_size, buffer_size, 0.)); + m_circular_buffer.reset(new tool::CircularBuffer(buffer_size, buffer_size, 0.)); m_reinject_signal.reset(new dsp::Signal(m_vector_size)); } diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_DelaySimpleTilde.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_DelaySimpleTilde.h index d168789b..0eb1f1a3 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_DelaySimpleTilde.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_DelaySimpleTilde.h @@ -21,7 +21,7 @@ #pragma once -#include +#include #include @@ -37,9 +37,9 @@ namespace kiwi { public: // methods - DelaySimpleTilde(model::Object const& model, Patcher& patcher, std::vector const& args); + DelaySimpleTilde(model::Object const& model, Patcher& patcher, std::vector const& args); - void receive(size_t index, std::vector const& args) override final; + void receive(size_t index, std::vector const& args) override final; void perform(dsp::Buffer const& input, dsp::Buffer& output) noexcept; @@ -57,14 +57,14 @@ namespace kiwi private: // members - std::unique_ptr> m_circular_buffer; - std::unique_ptr m_reinject_signal; - float m_max_delay; - std::atomic m_delay; - std::atomic m_reinject_level; - dsp::sample_t m_sr; - size_t m_vector_size; - mutable std::mutex m_mutex; + std::unique_ptr> m_circular_buffer; + std::unique_ptr m_reinject_signal; + float m_max_delay; + std::atomic m_delay; + std::atomic m_reinject_level; + dsp::sample_t m_sr; + size_t m_vector_size; + mutable std::mutex m_mutex; }; } } diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_MeterTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_MeterTilde.cpp index a0abf677..09066365 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_MeterTilde.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_MeterTilde.cpp @@ -31,9 +31,9 @@ namespace kiwi { namespace engine { // METER~ // // ================================================================================ // - MeterTilde::MeterTilde(model::Object const& model, Patcher& patcher, std::vector const& atom): + MeterTilde::MeterTilde(model::Object const& model, Patcher& patcher, std::vector const& atom): engine::AudioObject(model, patcher), - Scheduler<>::Timer(patcher.getScheduler()), + tool::Scheduler<>::Timer(patcher.getScheduler()), m_interval(50), m_current_peak(0), m_sample_index(0), @@ -44,7 +44,7 @@ namespace kiwi { namespace engine { { } - void MeterTilde::receive(size_t index, std::vector const& args) + void MeterTilde::receive(size_t index, std::vector const& args) { } diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_MeterTilde.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_MeterTilde.h index 45a746c7..ee0b00c5 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_MeterTilde.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_MeterTilde.h @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include @@ -35,7 +35,7 @@ namespace kiwi { namespace engine { // METER~ // // ================================================================================ // - class MeterTilde : public engine::AudioObject, Scheduler<>::Timer + class MeterTilde : public engine::AudioObject, tool::Scheduler<>::Timer { public: // usings @@ -44,11 +44,11 @@ namespace kiwi { namespace engine { public: // methods //! @brief Constructor - MeterTilde(model::Object const& model, Patcher& patcher, std::vector const& atom); + MeterTilde(model::Object const& model, Patcher& patcher, std::vector const& atom); //! @brief The engine's receive method. //! @details Does nothing as no control inlets exists. - void receive(size_t index, std::vector const& args) override final; + void receive(size_t index, std::vector const& args) override final; //! @brief The dsp perform method called. void perform(dsp::Buffer const& intput, dsp::Buffer& output); diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_OscTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_OscTilde.cpp index 29b96195..f6d53636 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_OscTilde.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_OscTilde.cpp @@ -29,7 +29,7 @@ namespace kiwi // OSC~ // // ================================================================================ // - OscTilde::OscTilde(model::Object const& model, Patcher& patcher, std::vector const& args) + OscTilde::OscTilde(model::Object const& model, Patcher& patcher, std::vector const& args) : AudioObject(model, patcher) { if (!args.empty() && args[0].isNumber()) @@ -53,7 +53,7 @@ namespace kiwi m_offset = fmodf(offset, 1.f); } - void OscTilde::receive(size_t index, std::vector const& args) + void OscTilde::receive(size_t index, std::vector const& args) { if (index == 0 && args[0].isNumber()) { diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_OscTilde.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_OscTilde.h index e3bffeea..78a377a7 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_OscTilde.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_OscTilde.h @@ -35,9 +35,9 @@ namespace kiwi { public: // methods - OscTilde(model::Object const& model, Patcher& patcher, std::vector const& args); + OscTilde(model::Object const& model, Patcher& patcher, std::vector const& args); - void receive(size_t index, std::vector const& args) override; + void receive(size_t index, std::vector const& args) override; void performValue(dsp::Buffer const& input, dsp::Buffer& output) noexcept; diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_PlusTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_PlusTilde.cpp index 73011fb4..891fbfbe 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_PlusTilde.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_PlusTilde.cpp @@ -29,7 +29,7 @@ namespace kiwi // PLUS~ // // ================================================================================ // - PlusTilde::PlusTilde(model::Object const& model, Patcher& patcher, std::vector const& args) + PlusTilde::PlusTilde(model::Object const& model, Patcher& patcher, std::vector const& args) : AudioObject(model, patcher) { if (!args.empty() && args[0].isNumber()) @@ -38,7 +38,7 @@ namespace kiwi } } - void PlusTilde::receive(size_t index, std::vector const& args) + void PlusTilde::receive(size_t index, std::vector const& args) { if(index == 1 && args[0].isNumber()) { diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_PlusTilde.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_PlusTilde.h index faf62cbe..14345342 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_PlusTilde.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_PlusTilde.h @@ -36,9 +36,9 @@ namespace kiwi { public: // methods - PlusTilde(model::Object const& model, Patcher& patcher, std::vector const& args); + PlusTilde(model::Object const& model, Patcher& patcher, std::vector const& args); - void receive(size_t index, std::vector const& args) override; + void receive(size_t index, std::vector const& args) override; void performValue(dsp::Buffer const& input, dsp::Buffer& output) noexcept; diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_SigTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_SigTilde.cpp index e89a50aa..a850aea9 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_SigTilde.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_SigTilde.cpp @@ -29,7 +29,7 @@ namespace kiwi // SIG~ // // ================================================================================ // - SigTilde::SigTilde(model::Object const& model, Patcher& patcher, std::vector const& args): + SigTilde::SigTilde(model::Object const& model, Patcher& patcher, std::vector const& args): AudioObject(model, patcher) { if (!args.empty() && args[0].isNumber()) @@ -38,7 +38,7 @@ namespace kiwi } } - void SigTilde::receive(size_t index, std::vector const& args) + void SigTilde::receive(size_t index, std::vector const& args) { if (index == 0 && args[0].isNumber()) { diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_SigTilde.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_SigTilde.h index 6dd42e66..02dc9967 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_SigTilde.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_SigTilde.h @@ -35,9 +35,9 @@ namespace kiwi { public: // methods - SigTilde(model::Object const& model, Patcher& patcher, std::vector const& args); + SigTilde(model::Object const& model, Patcher& patcher, std::vector const& args); - void receive(size_t index, std::vector const& args) override final; + void receive(size_t index, std::vector const& args) override final; void perform(dsp::Buffer const& input, dsp::Buffer& output) noexcept; diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_TimesTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_TimesTilde.cpp index 751bb93b..d60e863a 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_TimesTilde.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_TimesTilde.cpp @@ -29,7 +29,7 @@ namespace kiwi // TIMES~ // // ================================================================================ // - TimesTilde::TimesTilde(model::Object const& model, Patcher& patcher, std::vector const& args) + TimesTilde::TimesTilde(model::Object const& model, Patcher& patcher, std::vector const& args) : AudioObject(model, patcher) { if (!args.empty() && args[0].isNumber()) @@ -38,7 +38,7 @@ namespace kiwi } } - void TimesTilde::receive(size_t index, std::vector const& args) + void TimesTilde::receive(size_t index, std::vector const& args) { if(index == 1 && args[0].isNumber()) { diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_TimesTilde.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_TimesTilde.h index b3c18f7d..6e3a8160 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_TimesTilde.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_TimesTilde.h @@ -36,9 +36,9 @@ namespace kiwi { public: // methods - TimesTilde(model::Object const& model, Patcher& patcher, std::vector const& args); + TimesTilde(model::Object const& model, Patcher& patcher, std::vector const& args); - void receive(size_t index, std::vector const& args) override; + void receive(size_t index, std::vector const& args) override; void performValue(dsp::Buffer const& input, dsp::Buffer& output) noexcept; diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Math/KiwiEngine_Plus.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Math/KiwiEngine_Plus.cpp index f987c58e..1d2a8cdd 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Math/KiwiEngine_Plus.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Math/KiwiEngine_Plus.cpp @@ -30,7 +30,7 @@ namespace kiwi // OBJECT PLUS // // ================================================================================ // - Plus::Plus(model::Object const& model, Patcher& patcher, std::vector const& args) + Plus::Plus(model::Object const& model, Patcher& patcher, std::vector const& args) : Object(model, patcher) { m_lhs = 0.; @@ -40,7 +40,7 @@ namespace kiwi } } - void Plus::receive(size_t index, std::vector const& args) + void Plus::receive(size_t index, std::vector const& args) { if(!args.empty()) { diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Math/KiwiEngine_Plus.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Math/KiwiEngine_Plus.h index 392984eb..7dfa1bfc 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Math/KiwiEngine_Plus.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Math/KiwiEngine_Plus.h @@ -35,9 +35,9 @@ namespace kiwi { public: - Plus(model::Object const& model, Patcher& patcher, std::vector const& args); + Plus(model::Object const& model, Patcher& patcher, std::vector const& args); - void receive(size_t index, std::vector const& args) override; + void receive(size_t index, std::vector const& args) override; void bang(); diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Math/KiwiEngine_Times.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Math/KiwiEngine_Times.cpp index 4c801f7d..8a6747fc 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Math/KiwiEngine_Times.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Math/KiwiEngine_Times.cpp @@ -29,7 +29,7 @@ namespace kiwi // OBJECT TIMES // // ================================================================================ // - Times::Times(model::Object const& model, Patcher& patcher, std::vector const& args) + Times::Times(model::Object const& model, Patcher& patcher, std::vector const& args) : Object(model, patcher) { m_lhs = 0.; @@ -39,7 +39,7 @@ namespace kiwi } } - void Times::receive(size_t index, std::vector const& args) + void Times::receive(size_t index, std::vector const& args) { if(!args.empty()) { diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Math/KiwiEngine_Times.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Math/KiwiEngine_Times.h index 6a385251..07057731 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Math/KiwiEngine_Times.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Math/KiwiEngine_Times.h @@ -35,9 +35,9 @@ namespace kiwi { public: - Times(model::Object const& model, Patcher& patcher, std::vector const& args); + Times(model::Object const& model, Patcher& patcher, std::vector const& args); - void receive(size_t index, std::vector const& args) override; + void receive(size_t index, std::vector const& args) override; void bang(); diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Loadmess.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Loadmess.cpp index 8df96d8e..9bafc5cb 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Loadmess.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Loadmess.cpp @@ -29,14 +29,14 @@ namespace kiwi // OBJECT LOADMESS // // ================================================================================ // - Loadmess::Loadmess(model::Object const& model, Patcher& patcher, std::vector const& args) + Loadmess::Loadmess(model::Object const& model, Patcher& patcher, std::vector const& args) : Object(model, patcher), m_args(args) { ; } - void Loadmess::receive(size_t, std::vector const& args) + void Loadmess::receive(size_t, std::vector const& args) { send(0ul, m_args); } diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Loadmess.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Loadmess.h index 23b2321a..d7f79e3f 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Loadmess.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Loadmess.h @@ -35,17 +35,17 @@ namespace kiwi { public: - Loadmess(model::Object const& model, Patcher& patcher, std::vector const& args); + Loadmess(model::Object const& model, Patcher& patcher, std::vector const& args); ~Loadmess() = default; - void receive(size_t, std::vector const& args) override; + void receive(size_t, std::vector const& args) override; void loadbang() override; private: - const std::vector m_args; + const std::vector m_args; }; } } diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Print.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Print.cpp index 0d546ca6..b6cffe7d 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Print.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Print.cpp @@ -29,17 +29,17 @@ namespace kiwi // OBJECT PRINT // // ================================================================================ // - Print::Print(model::Object const& model, Patcher& patcher, std::vector const& args) + Print::Print(model::Object const& model, Patcher& patcher, std::vector const& args) : Object(model, patcher) { m_name = !args.empty() ? args[0].getString() : "print"; } - void Print::receive(size_t, std::vector const& args) + void Print::receive(size_t, std::vector const& args) { if(!args.empty()) { - post(m_name + " \xe2\x80\xa2 " + AtomHelper::toString(args)); + post(m_name + " \xe2\x80\xa2 " + tool::AtomHelper::toString(args)); } } } diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Print.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Print.h index bde76681..7864f923 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Print.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Print.h @@ -35,9 +35,9 @@ namespace kiwi { public: - Print(model::Object const& model, Patcher& patcher, std::vector const& args); + Print(model::Object const& model, Patcher& patcher, std::vector const& args); - void receive(size_t, std::vector const& args) override; + void receive(size_t, std::vector const& args) override; private: std::string m_name; diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Receive.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Receive.cpp index 26248e25..8f8ee143 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Receive.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Receive.cpp @@ -29,12 +29,12 @@ namespace kiwi // OBJECT RECEIVE // // ================================================================================ // - class Receive::Task final : public Scheduler<>::Task + class Receive::Task final : public tool::Scheduler<>::Task { public: // methods - Task(Receive& object, std::vector const& atoms): - Scheduler<>::Task(), + Task(Receive& object, std::vector const& atoms): + tool::Scheduler<>::Task(), m_object(object), m_atoms(atoms) { @@ -59,10 +59,10 @@ namespace kiwi private: // members Receive& m_object; - std::vector m_atoms; + std::vector m_atoms; }; - Receive::Receive(model::Object const& model, Patcher& patcher, std::vector const& args): + Receive::Receive(model::Object const& model, Patcher& patcher, std::vector const& args): Object(model, patcher), m_name(), m_tasks() @@ -71,7 +71,7 @@ namespace kiwi if(!m_name.empty()) { - Beacon& beacon = getBeacon(m_name); + tool::Beacon& beacon = getBeacon(m_name); beacon.bind(*this); } } @@ -85,17 +85,17 @@ namespace kiwi if(!m_name.empty()) { - Beacon& beacon = getBeacon(m_name); + tool::Beacon& beacon = getBeacon(m_name); beacon.unbind(*this); } } - void Receive::receive(size_t, std::vector const& args) + void Receive::receive(size_t, std::vector const& args) { } - void Receive::receive(std::vector const& args) + void Receive::receive(std::vector const& args) { if (!args.empty()) { diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Receive.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Receive.h index ed06fab9..b990a504 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Receive.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Receive.h @@ -31,7 +31,7 @@ namespace kiwi // OBJECT RECEIVE // // ================================================================================ // - class Receive : public engine::Object, public Beacon::Castaway + class Receive : public engine::Object, public tool::Beacon::Castaway { private: // classes @@ -39,13 +39,13 @@ namespace kiwi public: // methods - Receive(model::Object const& model, Patcher& patcher, std::vector const& args); + Receive(model::Object const& model, Patcher& patcher, std::vector const& args); ~Receive(); - void receive(size_t, std::vector const& args) override; + void receive(size_t, std::vector const& args) override; - void receive(std::vector const& args) override; + void receive(std::vector const& args) override; private: // members diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Delay.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Delay.cpp index fc9fff0f..1ec7ffea 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Delay.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Delay.cpp @@ -30,7 +30,7 @@ namespace kiwi // ================================================================================ // Delay::Task::Task(Delay& object): - Scheduler<>::Task(), + tool::Scheduler<>::Task(), m_object(object) { } @@ -40,7 +40,7 @@ namespace kiwi m_object.send(0, {"bang"}); } - Delay::Delay(model::Object const& model, Patcher& patcher, std::vector const& args): + Delay::Delay(model::Object const& model, Patcher& patcher, std::vector const& args): Object(model, patcher), m_task(new Task(*this)), m_delay(std::chrono::milliseconds(0)) @@ -56,7 +56,7 @@ namespace kiwi getScheduler().unschedule(m_task); } - void Delay::receive(size_t index, std::vector const& args) + void Delay::receive(size_t index, std::vector const& args) { if (!args.empty()) { diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Delay.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Delay.h index 12d214bd..9fad2de9 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Delay.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Delay.h @@ -35,15 +35,15 @@ namespace kiwi { public: // methods - Delay(model::Object const& model, Patcher& patcher, std::vector const& args); + Delay(model::Object const& model, Patcher& patcher, std::vector const& args); ~Delay(); - void receive(size_t index, std::vector const& args) override; + void receive(size_t index, std::vector const& args) override; private: // members - struct Task final : public Scheduler<>::Task + struct Task final : public tool::Scheduler<>::Task { Task(Delay & object); ~Task() = default; @@ -53,8 +53,8 @@ namespace kiwi Delay& m_object; }; - std::shared_ptr m_task; - Scheduler<>::clock_t::duration m_delay; + std::shared_ptr m_task; + tool::Scheduler<>::clock_t::duration m_delay; }; } } diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Metro.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Metro.cpp index 721a26bc..4d395c2c 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Metro.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Metro.cpp @@ -29,9 +29,9 @@ namespace kiwi // OBJECT METRO // // ================================================================================ // - Metro::Metro(model::Object const& model, Patcher& patcher, std::vector const& args): + Metro::Metro(model::Object const& model, Patcher& patcher, std::vector const& args): engine::Object(model, patcher), - Scheduler<>::Timer(patcher.getScheduler()), + tool::Scheduler<>::Timer(patcher.getScheduler()), m_period(std::chrono::milliseconds(0)) { if(!args.empty()) @@ -44,7 +44,7 @@ namespace kiwi { } - void Metro::receive(size_t index, std::vector const& args) + void Metro::receive(size_t index, std::vector const& args) { if (!args.empty()) { diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Metro.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Metro.h index 2148d000..07441d3c 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Metro.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Metro.h @@ -31,21 +31,21 @@ namespace kiwi // OBJECT METRO // // ================================================================================ // - class Metro final : public engine::Object, Scheduler<>::Timer + class Metro final : public engine::Object, tool::Scheduler<>::Timer { public: // methods - Metro(model::Object const& model, Patcher& patcher, std::vector const& args); + Metro(model::Object const& model, Patcher& patcher, std::vector const& args); ~Metro(); - void receive(size_t index, std::vector const& args) override; + void receive(size_t index, std::vector const& args) override; void timerCallBack() override; private: // members - Scheduler<>::duration_t m_period; + tool::Scheduler<>::duration_t m_period; }; } } diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Pipe.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Pipe.cpp index 8682afb8..8dbeff95 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Pipe.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Pipe.cpp @@ -29,12 +29,12 @@ namespace kiwi // OBJECT PIPE // // ================================================================================ // - class Pipe::Task final : public Scheduler<>::Task + class Pipe::Task final : public tool::Scheduler<>::Task { public: // methods - Task(Pipe & object, std::vector const& atoms): - Scheduler<>::Task(), + Task(Pipe & object, std::vector const& atoms): + tool::Scheduler<>::Task(), m_object(object), m_atoms(atoms) { @@ -58,11 +58,11 @@ namespace kiwi private: // members - Pipe& m_object; - std::vector m_atoms; + Pipe& m_object; + std::vector m_atoms; }; - Pipe::Pipe(model::Object const& model, Patcher& patcher, std::vector const& args): + Pipe::Pipe(model::Object const& model, Patcher& patcher, std::vector const& args): Object(model, patcher), m_tasks(), m_delay(std::chrono::milliseconds(0)) @@ -81,7 +81,7 @@ namespace kiwi } } - void Pipe::receive(size_t index, std::vector const& args) + void Pipe::receive(size_t index, std::vector const& args) { if (!args.empty()) { diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Pipe.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Pipe.h index e76037a6..a0c2e53c 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Pipe.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Pipe.h @@ -39,16 +39,16 @@ namespace kiwi public: // methods - Pipe(model::Object const& model, Patcher& patcher, std::vector const& args); + Pipe(model::Object const& model, Patcher& patcher, std::vector const& args); ~Pipe(); - void receive(size_t index, std::vector const& args) override; + void receive(size_t index, std::vector const& args) override; private: // members - std::set> m_tasks; - Scheduler<>::clock_t::duration m_delay; + std::set> m_tasks; + tool::Scheduler<>::clock_t::duration m_delay; }; } } diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Utils/KiwiEngine_AudioInterface.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Utils/KiwiEngine_AudioInterface.cpp index d01343d9..bb3dee25 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Utils/KiwiEngine_AudioInterface.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Utils/KiwiEngine_AudioInterface.cpp @@ -31,18 +31,18 @@ namespace kiwi AudioInterfaceObject::AudioInterfaceObject(model::Object const& model, Patcher& patcher, - std::vector const& args): + std::vector const& args): AudioObject(model, patcher), m_router(), m_audio_controler(patcher.getAudioControler()) { } - std::vector AudioInterfaceObject::parseArgs(std::vector const& args) const + std::vector AudioInterfaceObject::parseArgs(std::vector const& args) const { std::vector routes; - for(Atom const& arg : args) + for(tool::Atom const& arg : args) { if (arg.isNumber()) { @@ -72,7 +72,7 @@ namespace kiwi return routes; } - void AudioInterfaceObject::receive(size_t index, std::vector const & args) + void AudioInterfaceObject::receive(size_t index, std::vector const & args) { if(!args.empty()) { diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Utils/KiwiEngine_AudioInterface.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Utils/KiwiEngine_AudioInterface.h index 6ea23c27..939662b3 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Utils/KiwiEngine_AudioInterface.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Utils/KiwiEngine_AudioInterface.h @@ -38,11 +38,11 @@ namespace kiwi { public: // methods - AudioInterfaceObject(model::Object const& model, Patcher& patcher, std::vector const& args); + AudioInterfaceObject(model::Object const& model, Patcher& patcher, std::vector const& args); - void receive(size_t index, std::vector const & args) override final; + void receive(size_t index, std::vector const & args) override final; - std::vector parseArgs(std::vector const& args) const; + std::vector parseArgs(std::vector const& args) const; virtual ~AudioInterfaceObject() = default; diff --git a/Modules/KiwiEngine/KiwiEngine_Patcher.cpp b/Modules/KiwiEngine/KiwiEngine_Patcher.cpp index 69edfd25..d1a6f161 100644 --- a/Modules/KiwiEngine/KiwiEngine_Patcher.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Patcher.cpp @@ -24,7 +24,7 @@ #include "KiwiEngine_Link.h" #include "KiwiEngine_Factory.h" #include "KiwiEngine_Instance.h" -#include "KiwiEngine_Scheduler.h" +#include #include @@ -191,7 +191,7 @@ namespace kiwi // SCHEDULER // // ================================================================================ // - Scheduler<> & Patcher::getScheduler() const + tool::Scheduler<> & Patcher::getScheduler() const { return m_instance.getScheduler(); } @@ -200,7 +200,7 @@ namespace kiwi // BEACON // // ================================================================================ // - Beacon& Patcher::getBeacon(std::string const& name) const + tool::Beacon& Patcher::getBeacon(std::string const& name) const { return m_instance.getBeacon(name); } diff --git a/Modules/KiwiEngine/KiwiEngine_Patcher.h b/Modules/KiwiEngine/KiwiEngine_Patcher.h index 5bca9176..73d9d078 100644 --- a/Modules/KiwiEngine/KiwiEngine_Patcher.h +++ b/Modules/KiwiEngine/KiwiEngine_Patcher.h @@ -24,8 +24,9 @@ #include #include +#include + #include "KiwiEngine_Def.h" -#include "KiwiEngine_Beacon.h" #include "KiwiEngine_AudioControler.h" #include @@ -112,14 +113,14 @@ namespace kiwi // ================================================================================ // //! @brief Returns the engine's scheduler. - Scheduler<> & getScheduler() const; + tool::Scheduler<> & getScheduler() const; // ================================================================================ // // BEACON // // ================================================================================ // //! @brief Gets or creates a Beacon with a given name. - Beacon& getBeacon(std::string const& name) const; + tool::Beacon& getBeacon(std::string const& name) const; private: // methods diff --git a/Modules/KiwiEngine/KiwiEngine_Scheduler.h b/Modules/KiwiEngine/KiwiEngine_Scheduler.h deleted file mode 100644 index 9e3a8bb1..00000000 --- a/Modules/KiwiEngine/KiwiEngine_Scheduler.h +++ /dev/null @@ -1,380 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "KiwiEngine_ConcurrentQueue.h" - -namespace kiwi -{ - namespace engine - { - // ==================================================================================== // - // SCHEDULER // - // ==================================================================================== // - - //! @brief A class designed to delay tasks' execution between threads that where previously declared. - //! @details The scheduler is designed as a singleton that uses multiple event lists. - //! Before processing the scheduler one should create an instance and register all threads that will - //! use the scheduler. One can override the clock used by the scheduler to get time. - template - class Scheduler final - { - public: // classes - - using clock_t = Clock; - - using time_point_t = typename Clock::time_point; - - using duration_t = typename Clock::duration; - - class Task; - - class CallBack; - - class Timer; - - private: // classes - - class Queue; - - class Event; - - public: // methods - - //! @brief Constructor - //! @details Sets current thread as the consumer thread. - Scheduler(); - - //! @brief Desctructor. - ~Scheduler(); - - //! @brief Sets the current thread as the consumer thread. - //! @details This method can be called for instance if the scheduler's constructor - //! is called on another thread than desired consumer. - void setThreadAsConsumer(); - - //! @brief Check wehter or not this thread is the consumer. - //! @details This method can be usefull to help decide if a direct call can be made - //! or if the scheduler shall be used. - bool isThisConsumerThread() const; - - //! @brief Delays execution of a task. Shared ownership. - //! @details Calling twice this method with same task will cancel the previous scheduled execution - //! and add a new one at specified time. - void schedule(std::shared_ptr const& task, duration_t delay = std::chrono::milliseconds(0)); - - //! @brief Delays execution of a task. Transfer ownership. - //! @details Calling twice this method with same task will cancel the previous scheduled execution - //! and add a new one at specified time. - void schedule(std::shared_ptr && task, duration_t delay = std::chrono::milliseconds(0)); - - //! @brief Delays execution of a function by the scheduler. - //! @details Internally create a callback that will be executed and destroyed by the scheduler. - void schedule(std::function && func, duration_t delay = std::chrono::milliseconds(0)); - - //! @brief Conditionally schedule a task in the consumer thread. - //! @details The task is scheduled only if the calling thread is not the consumer thread. Otherwise - //! it is executed right away. - void defer(std::shared_ptr const& task); - - //! @brief Conditionally schedule a task in the consumer thread. - //! @details The task is scheduled only if the calling thread is not the consumer thread. - //! Otherwise it is executed right away. Task is destroyed when executed. - void defer(std::shared_ptr && task); - - //! @brief Conditionally schedule a function in the consumer thread. - //! @details The function is scheduled only if the calling thread is not the consumer thread. - //! Otherwise it is executed right away. - void defer(std::function && func); - - //! @brief Used to cancel the execution of a previously scheduled task. - //! @details If the task is currently being processed by the scheduler, this method does't - //! wait for the execution to finish but only guarantee that further execution will no occur. - void unschedule(std::shared_ptr const& task); - - //! @brief Processes events of the consumer that have reached exeuction time. - void process(); - - //! @brief Lock the process until the returned lock is out of scope. - std::unique_lock lock() const; - - private: // members - - Queue m_queue; - mutable std::mutex m_mutex; - std::thread::id m_consumer_id; - - private: // deleted methods - - Scheduler(Scheduler const& other) = delete; - Scheduler(Scheduler && other) = delete; - Scheduler& operator=(Scheduler const& other) = delete; - Scheduler& operator=(Scheduler && other) = delete; - }; - - // ==================================================================================== // - // QUEUE // - // ==================================================================================== // - - //! @brief A class that holds a list of scheduled events. - //! @details Implementation countains a list of events sorted by execution time that is updated - //! before processing using commands. A queue is created for each consumer. - template - class Scheduler::Queue final - { - public: // classes - - struct Command - { - std::shared_ptr m_task; - time_point_t m_time; - }; - - public: // methods - - //! @brief Constructor. - Queue(); - - //! @brief Destructor - ~Queue(); - - //! @brief Delays the execution of a task. Shared ownership. - void schedule(std::shared_ptr const& task, duration_t delay); - - //! @brief Delays the execution of a task. Transfer ownership. - void schedule(std::shared_ptr && task, duration_t delay); - - //! @brief Cancels the execution of a task. - void unschedule(std::shared_ptr const& task); - - //! @brief Processes all events that have reached execution time. - void process(time_point_t process_time); - - private: // methods - - //! @internal - void emplace(Event && event); - - //! @internal - void remove(Event const& event); - - private: // members - - std::vector m_events; - ConcurrentQueue m_commands; - - private: // friend classes - - friend class Scheduler; - - private: // deleted methods - - Queue(Queue const& other) = delete; - Queue(Queue && other) = delete; - Queue& operator=(Queue const& other) = delete; - Queue& operator=(Queue && other) = delete; - }; - - // ==================================================================================== // - // TASK // - // ==================================================================================== // - - //! @brief The abstract class that the scheduler executes. Caller must override execute function - //! to specify the callback behavior. - template - class Scheduler::Task - { - public: // methods - - //! @brief Constructor. - //! @details A certain task is designed to be scheduled on only one consumer. - Task(); - - //! @brief Destructor. - //! @details It is not safe to destroy a task from another thread than the consumer because it can be - //! concurrent to its execution. One can create a task that deletes itself at exeuction time or lock - //! a consumer using Scheduler::Lock before deleting the task. - virtual ~Task(); - - private: // methods - - //! @brief The pure virtual execution method. Called by the scheduler when execution time - //! is reached. - virtual void execute() = 0; - - private: // friends - - friend class Scheduler; - - private: // deleted methods - - Task(Task const& other) = delete; - Task(Task && other) = delete; - Task& operator=(Task const& other) = delete; - Task& operator=(Task && other) = delete; - }; - - // ==================================================================================== // - // CALLBACK // - // ==================================================================================== // - - //! @brief The scheduler's callback is a task that uses an std::function for - //! conveniency. - template - class Scheduler::CallBack : public Scheduler::Task - { - public: // methods - - //! @brief Constructor, initializes function. - CallBack(std::function func); - - //! @brief Destructor. - ~CallBack(); - - //! @brief Executes the given functions. - void execute() override final; - - private: // members - - std::function m_func; - - private: // deleted methods - - CallBack() = delete; - CallBack(CallBack const& other) = delete; - CallBack(CallBack && other) = delete; - CallBack& operator=(CallBack const& other) = delete; - CallBack& operator=(CallBack && other) = delete; - }; - - - // ==================================================================================== // - // TIMER // - // ==================================================================================== // - - //! @brief An abstract class designed to repetedly call a method at a specified intervall of time. - //! Overriding timerCallBack and calling startTimer will start repetdly calling method. - template - class Scheduler::Timer - { - private: // classes - - class Task; - - public: // methods - - //! @brief Constructor. - //! @details A timer can only be created for a certain consumer. - Timer(Scheduler & scheduler); - - //! @brief Destructor. - //! @details It is not safe to destroy a timer in another thread than the consumer. If intended - //! one shall lock the consumer before destroying the timer. - ~Timer(); - - //! @brief Starts the timer. - //! @details Will cause timerCallBack to be called at a specified rate by the right consumer. - void startTimer(duration_t period); - - //! @brief Stops the timer. - //! @details If called when timerCallBack is being processed, stopTimer will not wait for the execution - //! to finish but will only guarantee that further execution will not occur. - void stopTimer(); - - private: // methods - - //! @brief The pure virtual call back function. - virtual void timerCallBack() = 0; - - //! @brief Reschedule task before calling virtual method timerCallBack. - void callBackInternal(); - - private: // members - - Scheduler & m_scheduler; - std::shared_ptr m_task; - duration_t m_period; - - private: // deleted methods - - Timer() = delete; - Timer(Timer const& other) = delete; - Timer(Timer && other) = delete; - Timer& operator=(Timer const& other) = delete; - Timer& operator=(Timer && other) = delete; - }; - - // ==================================================================================== // - // EVENT // - // ==================================================================================== // - - //! @brief An event that associates a task and a execution time. - template - class Scheduler::Event final - { - public: // methods - - //! @brief Constructor. - Event(std::shared_ptr && task, time_point_t time); - - //! @brief Moove constructor - Event(Event && other); - - //! @brief Moove assignment operator. - Event& operator=(Event && other); - - //! @brief Destructor. - ~Event(); - - //! @brief Called by the scheduler to execute a the task. - void execute(); - - private: // friends - - friend class Scheduler; - - private: // members - - std::shared_ptr m_task; - time_point_t m_time; - - private: // deleted methods - - Event() = delete; - Event(Event const& other) = delete; - Event& operator=(Event const& other) = delete; - }; - } -} - -#include "KiwiEngine_Scheduler.hpp" diff --git a/Modules/KiwiEngine/KiwiEngine_Scheduler.hpp b/Modules/KiwiEngine/KiwiEngine_Scheduler.hpp deleted file mode 100644 index 3b85e9bf..00000000 --- a/Modules/KiwiEngine/KiwiEngine_Scheduler.hpp +++ /dev/null @@ -1,399 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#pragma once - -#include - -namespace kiwi -{ - namespace engine - { - // ==================================================================================== // - // SCHEDULER // - // ==================================================================================== // - - template - Scheduler::Scheduler(): - m_queue(), - m_mutex(), - m_consumer_id(std::this_thread::get_id()) - { - } - - template - Scheduler::~Scheduler() - { - } - - template - void Scheduler::setThreadAsConsumer() - { - m_consumer_id = std::this_thread::get_id(); - } - - template - bool Scheduler::isThisConsumerThread() const - { - return m_consumer_id == std::this_thread::get_id(); - } - - template - void Scheduler::schedule(std::shared_ptr const& task, duration_t delay) - { - assert(task); - m_queue.schedule(task, delay); - } - - template - void Scheduler::schedule(std::shared_ptr && task, duration_t delay) - { - assert(task); - m_queue.schedule(std::move(task), delay); - } - - template - void Scheduler::schedule(std::function && func, duration_t delay) - { - schedule(std::make_shared(func), delay); - } - - template - void Scheduler::defer(std::shared_ptr const& task) - { - assert(task); - - if (!isThisConsumerThread()) - { - schedule(task); - } - else - { - task->execute(); - } - } - - template - void Scheduler::defer(std::shared_ptr && task) - { - assert(task); - - if (!isThisConsumerThread()) - { - schedule(std::move(task)); - } - else - { - task->execute(); - task.reset(); - } - } - - template - void Scheduler::defer(std::function && func) - { - if (!isThisConsumerThread()) - { - schedule(std::move(func)); - } - else - { - func(); - } - } - - template - void Scheduler::unschedule(std::shared_ptr const& task) - { - assert(task); - m_queue.unschedule(task); - } - - template - void Scheduler::process() - { - assert(std::this_thread::get_id() == m_consumer_id); - - std::lock_guard lock(m_mutex); - - time_point_t process_time = clock_t::now(); - - m_queue.process(process_time); - } - - template - std::unique_lock Scheduler::lock() const - { - std::unique_lock head_lock(m_mutex); - - return std::move(head_lock); - } - - // ==================================================================================== // - // QUEUE // - // ==================================================================================== // - - template - Scheduler::Queue::Queue(): - m_events(), - m_commands(1024) - { - } - - template - Scheduler::Queue::~Queue() - { - } - - template - void Scheduler::Queue::schedule(std::shared_ptr const& task, duration_t delay) - { - assert(task); - m_commands.push({task, clock_t::now() + delay }); - } - - template - void Scheduler::Queue::schedule(std::shared_ptr && task, duration_t delay) - { - assert(task); - m_commands.push({std::move(task), clock_t::now() + delay}); - } - - template - void Scheduler::Queue::unschedule(std::shared_ptr const& task) - { - m_commands.push({task, clock_t::time_point::max()}); - } - - template - void Scheduler::Queue::remove(Event const& event) - { - m_events.erase(std::remove_if(m_events.begin(), m_events.end(), [&event](Event const& e) { - - return e.m_task == event.m_task; - - }), m_events.end()); - } - - template - void Scheduler::Queue::emplace(Event && event) - { - remove(event); - - auto event_it = m_events.begin(); - - while(event_it != m_events.end()) - { - if (event.m_time < event_it->m_time) - { - m_events.insert(event_it, std::move(event)); - break; - } - - ++event_it; - } - - if (event_it == m_events.end()) - { - m_events.emplace_back(std::move(event)); - } - } - - template - void Scheduler::Queue::process(time_point_t process_time) - { - size_t command_size = m_commands.load_size(); - - for (size_t i = 0; i < command_size; ++i) - { - Command command; - - if (m_commands.pop(command)) - { - Event event(std::move(command.m_task), command.m_time); - - if (event.m_time != clock_t::time_point::max()) - { - emplace(std::move(event)); - } - else - { - remove(event); - } - } - } - - m_events.erase(std::remove_if(m_events.begin(), m_events.end(), [&process_time](auto& event) { - - if (event.m_time <= process_time) - { - event.execute(); - return true; - } - - return false; - - }), m_events.end()); - } - - // ==================================================================================== // - // TASK // - // ==================================================================================== // - - template - Scheduler::Task::Task() - { - } - - template - Scheduler::Task::~Task() - { - } - - // ==================================================================================== // - // CALLBACK // - // ==================================================================================== // - - template - Scheduler::CallBack::CallBack(std::function func): - Task(), - m_func(func) - { - } - - template - Scheduler::CallBack::~CallBack() - { - } - - template - void Scheduler::CallBack::execute() - { - m_func(); - } - - // ==================================================================================== // - // TIMER // - // ==================================================================================== // - - template - class Scheduler::Timer::Task final : public Scheduler::Task - { - public: // methods - - Task(Timer& timer): - m_timer(timer) - { - } - - ~Task() - { - } - - void execute() override - { - m_timer.callBackInternal(); - } - - private: // members - - Timer& m_timer; - - }; - - template - Scheduler::Timer::Timer(Scheduler & scheduler): - m_scheduler(scheduler), - m_task(new Task(*this)), - m_period() - { - } - - template - Scheduler::Timer::~Timer() - { - stopTimer(); - } - - template - void Scheduler::Timer::startTimer(duration_t period) - { - stopTimer(); - - m_period = period; - - m_scheduler.schedule(m_task, m_period); - } - - template - void Scheduler::Timer::callBackInternal() - { - timerCallBack(); - - m_scheduler.schedule(m_task, m_period); - } - - template - void Scheduler::Timer::stopTimer() - { - m_scheduler.unschedule(m_task); - } - - // ==================================================================================== // - // EVENT // - // ==================================================================================== // - - template - Scheduler::Event::Event(std::shared_ptr && task, time_point_t time): - m_task(std::move(task)), - m_time(time) - { - } - - template - Scheduler::Event::Event(Event && other): - m_task(std::move(other.m_task)), - m_time(std::move(other.m_time)) - { - } - - template - typename Scheduler::Event& Scheduler::Event::operator=(Event && other) - { - m_task = std::move(other.m_task); - m_time = std::move(other.m_time); - - return *this; - } - - - template - Scheduler::Event::~Event() - { - } - - template - void Scheduler::Event::execute() - { - if (m_task){m_task->execute();} - } - } -} diff --git a/Modules/KiwiModel/KiwiModel_Factory.cpp b/Modules/KiwiModel/KiwiModel_Factory.cpp index 37517119..7abd7cd0 100644 --- a/Modules/KiwiModel/KiwiModel_Factory.cpp +++ b/Modules/KiwiModel/KiwiModel_Factory.cpp @@ -31,7 +31,7 @@ namespace kiwi // FACTORY // // ================================================================================ // - std::unique_ptr Factory::create(std::vector const& atoms) + std::unique_ptr Factory::create(std::vector const& atoms) { std::unique_ptr object; @@ -41,27 +41,27 @@ namespace kiwi { object_class = getClassByName("errorbox"); - object = object_class->create(std::vector()); + object = object_class->create(std::vector()); dynamic_cast(object.get())->setError("object \"" + atoms[0].getString() + "\" not found"); } else { try { - std::vector args(atoms.empty() ? atoms.begin() : atoms.begin() + 1, atoms.end()); + std::vector args(atoms.empty() ? atoms.begin() : atoms.begin() + 1, atoms.end()); object = object_class->create(args); } catch(std::runtime_error & e) { object_class = getClassByName("errorbox"); - object = object_class->create(std::vector()); + object = object_class->create(std::vector()); dynamic_cast(object.get())->setError(e.what()); } } object->m_name = object_class->getName(); - object->m_text = AtomHelper::toString(atoms); + object->m_text = tool::AtomHelper::toString(atoms); return object; } diff --git a/Modules/KiwiModel/KiwiModel_Factory.h b/Modules/KiwiModel/KiwiModel_Factory.h index e7eded48..e1240879 100644 --- a/Modules/KiwiModel/KiwiModel_Factory.h +++ b/Modules/KiwiModel/KiwiModel_Factory.h @@ -54,7 +54,7 @@ namespace kiwi { value = std::is_base_of::value && !std::is_abstract::value - && std::is_constructible>::value + && std::is_constructible>::value && std::is_constructible::value }; }; @@ -90,7 +90,7 @@ namespace kiwi //! @param name The name of the Object. //! @param args A list of arguments as a vector of Atom. //! @return A ptr to a model::Object. - static std::unique_ptr create(std::vector const& args); + static std::unique_ptr create(std::vector const& args); //! @brief Creates a new Object from a flip::Mold. //! @details This function will throw if the object name does not exist. @@ -131,7 +131,7 @@ namespace kiwi using object_classes_t = std::vector>; - using ctor_fn_t = std::function(std::vector)>; + using ctor_fn_t = std::function(std::vector)>; using mold_maker_fn_t = std::function; using mold_caster_fn_t = std::function(flip::Mold const&)>; @@ -139,7 +139,7 @@ namespace kiwi template static ctor_fn_t getCtor(std::string const& name) { - return [name](std::vector const& args) + return [name](std::vector const& args) { return std::make_unique(name, args); }; @@ -239,7 +239,7 @@ namespace kiwi //! @brief Creates and returns a new Object with a vector of Atom as parameter. //! @param args A vector of Atom. //! @return A new model::Object. - std::unique_ptr create(std::vector const& args) const + std::unique_ptr create(std::vector const& args) const { return m_ctor(args); } //! @brief Copy the content an object instance into a flip::Mold. diff --git a/Modules/KiwiModel/KiwiModel_Object.h b/Modules/KiwiModel/KiwiModel_Object.h index 367a8185..453fa2c0 100755 --- a/Modules/KiwiModel/KiwiModel_Object.h +++ b/Modules/KiwiModel/KiwiModel_Object.h @@ -35,7 +35,7 @@ #include "flip/Enum.h" #include "flip/Signal.h" -#include "KiwiModel_Atom.h" +#include #include #include diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_ErrorBox.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_ErrorBox.cpp index 791801f5..a4f7cfed 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_ErrorBox.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_ErrorBox.cpp @@ -36,7 +36,7 @@ namespace kiwi Factory::add("errorbox").setInternal(true); } - ErrorBox::ErrorBox(std::string const& name, std::vector const& args) + ErrorBox::ErrorBox(std::string const& name, std::vector const& args) { } diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_ErrorBox.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_ErrorBox.h index e3485c5a..7f47f06c 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_ErrorBox.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_ErrorBox.h @@ -39,7 +39,7 @@ namespace kiwi ErrorBox(flip::Default& d) : model::Object(d) {} //! @brief Constructor - ErrorBox(std::string const& name, std::vector const& args); + ErrorBox(std::string const& name, std::vector const& args); //! @brief Set the number of inlets. //! @param inlets The number of inlets. diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_NewBox.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_NewBox.cpp index 6e874973..909c36ac 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_NewBox.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_NewBox.cpp @@ -37,7 +37,7 @@ namespace kiwi } - NewBox::NewBox(std::string const& name, std::vector const& args) + NewBox::NewBox(std::string const& name, std::vector const& args) { setFlag(Flag::IFlag::DefinedSize); setWidth(80); diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_NewBox.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_NewBox.h index abcd4f7f..06c3d288 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_NewBox.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_NewBox.h @@ -39,7 +39,7 @@ namespace kiwi NewBox(flip::Default& d) : model::Object(d) {} //! @brief Constructor - NewBox(std::string const& name, std::vector const& args); + NewBox(std::string const& name, std::vector const& args); std::string getIODescription(bool is_inlet, size_t index) const override; diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Bang.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Bang.cpp index d337e6d0..d29b73c0 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Bang.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Bang.cpp @@ -31,7 +31,7 @@ namespace kiwi // OBJECT BANG // // ================================================================================ // - Bang::Bang(std::string const& name, std::vector const& args): + Bang::Bang(std::string const& name, std::vector const& args): Object() { if (!args.empty()) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Bang.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Bang.h index 77eab576..ef61b69c 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Bang.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Bang.h @@ -47,7 +47,7 @@ namespace kiwi Bang(flip::Default& d); - Bang(std::string const& name, std::vector const& args); + Bang(std::string const& name, std::vector const& args); std::string getIODescription(bool is_inlet, size_t index) const override; diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Slider.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Slider.cpp index bd3f34ff..dc2fc0f7 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Slider.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Slider.cpp @@ -28,7 +28,7 @@ namespace kiwi { namespace model { // OBJECT SLIDER // // ================================================================================ // - Slider::Slider(std::string const& name, std::vector const& args): + Slider::Slider(std::string const& name, std::vector const& args): Object() { if (!args.empty()) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Slider.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Slider.h index 3110f466..7f222151 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Slider.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Slider.h @@ -27,7 +27,7 @@ #include #include -#include +#include namespace kiwi { namespace model { @@ -48,7 +48,7 @@ namespace kiwi { namespace model { Slider(flip::Default& d); - Slider(std::string const& name, std::vector const& args); + Slider(std::string const& name, std::vector const& args); std::string getIODescription(bool is_inlet, size_t index) const override; diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Toggle.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Toggle.cpp index db287f74..4f6d5527 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Toggle.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Toggle.cpp @@ -31,7 +31,7 @@ namespace kiwi // OBJECT TOGGLE // // ================================================================================ // - Toggle::Toggle(std::string const& name, std::vector const& args): + Toggle::Toggle(std::string const& name, std::vector const& args): Object() { if (!args.empty()) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Toggle.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Toggle.h index ecc7fb80..ea431f6b 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Toggle.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Toggle.h @@ -52,7 +52,7 @@ namespace kiwi Toggle(flip::Default& d); - Toggle(std::string const& name, std::vector const& args); + Toggle(std::string const& name, std::vector const& args); std::string getIODescription(bool is_inlet, size_t index) const override; diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_AdcTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_AdcTilde.cpp index 5cfbc08b..e098ec02 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_AdcTilde.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_AdcTilde.cpp @@ -31,7 +31,7 @@ namespace kiwi // OBJECT ADC~ // // ================================================================================ // - AdcTilde::AdcTilde(std::string const& name, std::vector const& args) + AdcTilde::AdcTilde(std::string const& name, std::vector const& args) { size_t channels = parseArgsAsChannelRoutes(args).size(); @@ -43,11 +43,11 @@ namespace kiwi } } - std::vector AdcTilde::parseArgsAsChannelRoutes(std::vector const& args) const + std::vector AdcTilde::parseArgsAsChannelRoutes(std::vector const& args) const { std::vector routes; - for(Atom const& arg : args) + for(tool::Atom const& arg : args) { if (arg.isNumber()) { @@ -111,7 +111,7 @@ namespace kiwi { if(index < getNumberOfOutlets()) { - auto text_atoms = AtomHelper::parse(getText()); + auto text_atoms = tool::AtomHelper::parse(getText()); text_atoms.erase(text_atoms.cbegin()); const auto routes = parseArgsAsChannelRoutes(text_atoms); diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_AdcTilde.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_AdcTilde.h index 349d1607..9b41a66d 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_AdcTilde.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_AdcTilde.h @@ -40,10 +40,10 @@ namespace kiwi //! @brief Parses args to construct routes //! @todo Mutualize with adc tilde object. - std::vector parseArgsAsChannelRoutes(std::vector const& args) const; + std::vector parseArgsAsChannelRoutes(std::vector const& args) const; //! @brief Constructor - AdcTilde(std::string const& name, std::vector const& args); + AdcTilde(std::string const& name, std::vector const& args); std::string getIODescription(bool is_inlet, size_t index) const override; diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_DacTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_DacTilde.cpp index 7774c500..3ac749c1 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_DacTilde.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_DacTilde.cpp @@ -31,7 +31,7 @@ namespace kiwi // OBJECT DAC~ // // ================================================================================ // - DacTilde::DacTilde(std::string const& name, std::vector const& args) + DacTilde::DacTilde(std::string const& name, std::vector const& args) { size_t channels = parseArgsAsChannelRoutes(args).size(); @@ -43,11 +43,11 @@ namespace kiwi } } - std::vector DacTilde::parseArgsAsChannelRoutes(std::vector const& args) const + std::vector DacTilde::parseArgsAsChannelRoutes(std::vector const& args) const { std::vector routes; - for(Atom const& arg : args) + for(tool::Atom const& arg : args) { if (arg.isNumber()) { @@ -107,7 +107,7 @@ namespace kiwi { if(index < getNumberOfInlets()) { - auto text_atoms = AtomHelper::parse(getText()); + auto text_atoms = tool::AtomHelper::parse(getText()); text_atoms.erase(text_atoms.cbegin()); const auto routes = parseArgsAsChannelRoutes(text_atoms); diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_DacTilde.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_DacTilde.h index 683aed03..d4cf4df3 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_DacTilde.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_DacTilde.h @@ -39,10 +39,10 @@ namespace kiwi DacTilde(flip::Default& d): model::Object(d){} //! @brief Parses args to construct routes - std::vector parseArgsAsChannelRoutes(std::vector const& args) const; + std::vector parseArgsAsChannelRoutes(std::vector const& args) const; //! @brief Constructor - DacTilde(std::string const& name, std::vector const& args); + DacTilde(std::string const& name, std::vector const& args); std::string getIODescription(bool is_inlet, size_t index) const override; diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_DelaySimpleTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_DelaySimpleTilde.cpp index 8b768692..6aaa273a 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_DelaySimpleTilde.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_DelaySimpleTilde.cpp @@ -31,7 +31,7 @@ namespace kiwi // OBJECT DELAYSIMPLE~ // // ================================================================================ // - DelaySimpleTilde::DelaySimpleTilde(std::string const& name, std::vector const& args) + DelaySimpleTilde::DelaySimpleTilde(std::string const& name, std::vector const& args) { if (args.size() > 0) { diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_DelaySimpleTilde.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_DelaySimpleTilde.h index 65300540..98517c85 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_DelaySimpleTilde.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_DelaySimpleTilde.h @@ -39,7 +39,7 @@ namespace kiwi DelaySimpleTilde(flip::Default& d): model::Object(d){}; //! @brief Constructor - DelaySimpleTilde(std::string const& name, std::vector const& args); + DelaySimpleTilde(std::string const& name, std::vector const& args); std::string getIODescription(bool is_inlet, size_t index) const override; diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_MeterTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_MeterTilde.cpp index 91e9e164..7cffd6b5 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_MeterTilde.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_MeterTilde.cpp @@ -35,7 +35,7 @@ namespace kiwi { namespace model { addSignal(Signal::PeakChanged, *this); } - MeterTilde::MeterTilde(std::string const& name, std::vector const& args): + MeterTilde::MeterTilde(std::string const& name, std::vector const& args): model::Object() { if (!args.empty()) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_MeterTilde.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_MeterTilde.h index c613e0e8..9bb220d8 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_MeterTilde.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_MeterTilde.h @@ -42,7 +42,7 @@ namespace kiwi { namespace model { MeterTilde(flip::Default& d); //! @brief Constructor - MeterTilde(std::string const& name, std::vector const& args); + MeterTilde(std::string const& name, std::vector const& args); //! @brief Returns the descriptions of an inlet/outlet. std::string getIODescription(bool is_inlet, size_t index) const override final; diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_OscTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_OscTilde.cpp index 9667ec1a..70e15974 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_OscTilde.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_OscTilde.cpp @@ -31,7 +31,7 @@ namespace kiwi // OBJECT OSC~ // // ================================================================================ // - OscTilde::OscTilde(std::string const& name, std::vector const& args) + OscTilde::OscTilde(std::string const& name, std::vector const& args) { pushInlet({PinType::IType::Control, PinType::IType::Signal}); pushInlet({PinType::IType::Control, PinType::IType::Signal}); diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_OscTilde.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_OscTilde.h index f7f4b3c5..45371202 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_OscTilde.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_OscTilde.h @@ -38,7 +38,7 @@ namespace kiwi OscTilde(flip::Default& d): model::Object(d){}; //! @brief Constructor - OscTilde(std::string const& name, std::vector const& args); + OscTilde(std::string const& name, std::vector const& args); std::string getIODescription(bool is_inlet, size_t index) const override; diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_PlusTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_PlusTilde.cpp index ae1ddd54..fedeb623 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_PlusTilde.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_PlusTilde.cpp @@ -31,7 +31,7 @@ namespace kiwi // OBJECT PLUS~ // // ================================================================================ // - PlusTilde::PlusTilde(std::string const& name, std::vector const& args) + PlusTilde::PlusTilde(std::string const& name, std::vector const& args) { pushInlet({PinType::IType::Signal}); diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_PlusTilde.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_PlusTilde.h index 0751c617..d16aa0c0 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_PlusTilde.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_PlusTilde.h @@ -39,7 +39,7 @@ namespace kiwi PlusTilde(flip::Default& d): model::Object(d){}; //! @brief Constructor - PlusTilde(std::string const& name, std::vector const& args); + PlusTilde(std::string const& name, std::vector const& args); std::string getIODescription(bool is_inlet, size_t index) const override; diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_SigTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_SigTilde.cpp index 746e5fad..4fe9e3fa 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_SigTilde.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_SigTilde.cpp @@ -31,7 +31,7 @@ namespace kiwi // OBJECT SIG~ // // ================================================================================ // - SigTilde::SigTilde(std::string const& name, std::vector const& args) + SigTilde::SigTilde(std::string const& name, std::vector const& args) { if (args.empty() || !args[0].isNumber()) { diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_SigTilde.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_SigTilde.h index 550dc8f0..680911ea 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_SigTilde.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_SigTilde.h @@ -39,7 +39,7 @@ namespace kiwi SigTilde(flip::Default& d): model::Object(d){}; //! @brief Constructor - SigTilde(std::string const& name, std::vector const& args); + SigTilde(std::string const& name, std::vector const& args); std::string getIODescription(bool is_inlet, size_t index) const override; diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_TimesTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_TimesTilde.cpp index dce92da7..b0598808 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_TimesTilde.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_TimesTilde.cpp @@ -31,7 +31,7 @@ namespace kiwi // OBJECT TIMES~ // // ================================================================================ // - TimesTilde::TimesTilde(std::string const& name, std::vector const& args) + TimesTilde::TimesTilde(std::string const& name, std::vector const& args) { pushInlet({PinType::IType::Signal}); diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_TimesTilde.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_TimesTilde.h index ec49d732..0a73d071 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_TimesTilde.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_TimesTilde.h @@ -39,7 +39,7 @@ namespace kiwi TimesTilde(flip::Default& d): model::Object(d){}; //! @brief Constructor - TimesTilde(std::string const& name, std::vector const& args); + TimesTilde(std::string const& name, std::vector const& args); std::string getIODescription(bool is_inlet, size_t index) const override; diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Math/KiwiModel_Plus.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Math/KiwiModel_Plus.cpp index cb18194a..bf7a6169 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Math/KiwiModel_Plus.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Math/KiwiModel_Plus.cpp @@ -36,7 +36,7 @@ namespace kiwi Factory::add("plus").addAlias("+"); } - Plus::Plus(std::string const& name, std::vector const& args) + Plus::Plus(std::string const& name, std::vector const& args) { pushInlet({PinType::IType::Control}); diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Math/KiwiModel_Plus.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Math/KiwiModel_Plus.h index 27c4f78e..f9047096 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Math/KiwiModel_Plus.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Math/KiwiModel_Plus.h @@ -39,7 +39,7 @@ namespace kiwi Plus(flip::Default& d) : model::Object(d) {} //! @brief Constructor - Plus(std::string const& name, std::vector const& args); + Plus(std::string const& name, std::vector const& args); std::string getIODescription(bool is_inlet, size_t index) const override; diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Math/KiwiModel_Times.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Math/KiwiModel_Times.cpp index b0b64ea8..06e513f5 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Math/KiwiModel_Times.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Math/KiwiModel_Times.cpp @@ -36,7 +36,7 @@ namespace kiwi Factory::add("times").addAlias("*"); } - Times::Times(std::string const& name, std::vector const& args) + Times::Times(std::string const& name, std::vector const& args) { pushInlet({PinType::IType::Control}); diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Math/KiwiModel_Times.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Math/KiwiModel_Times.h index a1877bc0..c5aaf1d1 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Math/KiwiModel_Times.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Math/KiwiModel_Times.h @@ -39,7 +39,7 @@ namespace kiwi Times(flip::Default& d) : model::Object(d) {} //! @brief Constructor - Times(std::string const& name, std::vector const& args); + Times(std::string const& name, std::vector const& args); std::string getIODescription(bool is_inlet, size_t index) const override; diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Loadmess.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Loadmess.cpp index 7ea67911..c8c9adb9 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Loadmess.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Loadmess.cpp @@ -31,7 +31,7 @@ namespace kiwi // OBJECT LOADMESS // // ================================================================================ // - Loadmess::Loadmess(std::string const& name, std::vector const& args) + Loadmess::Loadmess(std::string const& name, std::vector const& args) { pushOutlet(PinType::IType::Control); } diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Loadmess.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Loadmess.h index 7fb63dc0..9405393c 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Loadmess.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Loadmess.h @@ -39,7 +39,7 @@ namespace kiwi Loadmess(flip::Default& d) : model::Object(d) {} //! @brief Constructor - Loadmess(std::string const& name, std::vector const& args); + Loadmess(std::string const& name, std::vector const& args); std::string getIODescription(bool is_inlet, size_t index) const override; diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Print.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Print.cpp index 40f8ece3..548b56a8 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Print.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Print.cpp @@ -31,7 +31,7 @@ namespace kiwi // OBJECT PRINT // // ================================================================================ // - Print::Print(std::string const& name, std::vector const& args) + Print::Print(std::string const& name, std::vector const& args) { pushInlet({PinType::IType::Control}); } diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Print.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Print.h index 75e338a3..adcb7a55 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Print.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Print.h @@ -39,7 +39,7 @@ namespace kiwi Print(flip::Default& d) : model::Object(d) {} //! @brief Constructor - Print(std::string const& name, std::vector const& args); + Print(std::string const& name, std::vector const& args); std::string getIODescription(bool is_inlet, size_t index) const override; diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Receive.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Receive.cpp index 696aa413..fd9a1af5 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Receive.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Receive.cpp @@ -31,7 +31,7 @@ namespace kiwi // OBJECT RECEIVE // // ================================================================================ // - Receive::Receive(std::string const& name, std::vector const& args) + Receive::Receive(std::string const& name, std::vector const& args) { pushOutlet(PinType::IType::Control); } diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Receive.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Receive.h index a1593170..d97620f9 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Receive.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Receive.h @@ -39,7 +39,7 @@ namespace kiwi Receive(flip::Default& d) : model::Object(d) {} //! @brief Constructor - Receive(std::string const& name, std::vector const& args); + Receive(std::string const& name, std::vector const& args); std::string getIODescription(bool is_inlet, size_t index) const override; diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Delay.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Delay.cpp index b8bf4da5..9dc2d3ca 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Delay.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Delay.cpp @@ -31,7 +31,7 @@ namespace kiwi // OBJECT DELAY // // ================================================================================ // - Delay::Delay(std::string const& name, std::vector const& args) + Delay::Delay(std::string const& name, std::vector const& args) { if (args.size() > 1 || (args.size() == 1 && !args[0].isNumber())) { diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Delay.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Delay.h index 303e489b..ad755b69 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Delay.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Delay.h @@ -39,7 +39,7 @@ namespace kiwi Delay(flip::Default& d) : model::Object(d) {}; //! @brief Constructor - Delay(std::string const& name, std::vector const& args); + Delay(std::string const& name, std::vector const& args); std::string getIODescription(bool is_inlet, size_t index) const override; diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Metro.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Metro.cpp index 084893ed..6778096b 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Metro.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Metro.cpp @@ -31,7 +31,7 @@ namespace kiwi // OBJECT METRO // // ================================================================================ // - Metro::Metro(std::string const& name, std::vector const& args) + Metro::Metro(std::string const& name, std::vector const& args) { if (args.size() < 1 || (args.size() == 1 && !args[0].isNumber())) { diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Metro.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Metro.h index ea7bfc0c..3632eb6d 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Metro.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Metro.h @@ -39,7 +39,7 @@ namespace kiwi Metro(flip::Default& d) : model::Object(d) {}; //! @brief Constructor - Metro(std::string const& name, std::vector const& args); + Metro(std::string const& name, std::vector const& args); std::string getIODescription(bool is_inlet, size_t index) const override; diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Pipe.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Pipe.cpp index eded951e..35e76979 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Pipe.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Pipe.cpp @@ -31,7 +31,7 @@ namespace kiwi // OBJECT PIPE // // ================================================================================ // - Pipe::Pipe(std::string const& name, std::vector const& args) + Pipe::Pipe(std::string const& name, std::vector const& args) { if (args.size() > 1 || (args.size() == 1 && !args[0].isNumber())) { diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Pipe.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Pipe.h index e62ccb0c..f1b14ce5 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Pipe.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Pipe.h @@ -39,7 +39,7 @@ namespace kiwi Pipe(flip::Default& d) : model::Object(d) {}; //! @brief Constructor - Pipe(std::string const& name, std::vector const& args); + Pipe(std::string const& name, std::vector const& args); std::string getIODescription(bool is_inlet, size_t index) const override; diff --git a/Modules/KiwiModel/KiwiModel_Atom.h b/Modules/KiwiTool/KiwiTool_Atom.h similarity index 97% rename from Modules/KiwiModel/KiwiModel_Atom.h rename to Modules/KiwiTool/KiwiTool_Atom.h index cbe4a9ef..64b03c5f 100644 --- a/Modules/KiwiModel/KiwiModel_Atom.h +++ b/Modules/KiwiTool/KiwiTool_Atom.h @@ -28,8 +28,8 @@ #include #include -namespace kiwi -{ +namespace kiwi { namespace tool { + // ================================================================================ // // ATOM // // ================================================================================ // @@ -653,4 +653,5 @@ namespace kiwi return output; } }; -} + +}} diff --git a/Modules/KiwiTool/KiwiTool_Beacon.cpp b/Modules/KiwiTool/KiwiTool_Beacon.cpp new file mode 100644 index 00000000..0bbe2711 --- /dev/null +++ b/Modules/KiwiTool/KiwiTool_Beacon.cpp @@ -0,0 +1,73 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +namespace kiwi { namespace tool { + + // ================================================================================ // + // BEACON // + // ================================================================================ // + + Beacon::Beacon(std::string const& name) : m_name(name) + { + ; + } + + void Beacon::bind(Castaway& castaway) + { + m_castaways.insert(&castaway); + } + + void Beacon::unbind(Castaway& castaway) + { + m_castaways.erase(&castaway); + } + + void Beacon::dispatch(std::vector const& args) + { + for(auto* castaway : m_castaways) + { + castaway->receive(args); + } + } + + // ================================================================================ // + // BEACON FACTORY // + // ================================================================================ // + + Beacon& Beacon::Factory::getBeacon(std::string const& name) + { + auto it = m_beacons.find(name); + if(it != m_beacons.end()) + { + return *it->second.get(); + } + + Beacon* beacon = new Beacon(name); + if(beacon) + { + m_beacons[name] = std::unique_ptr(beacon); + } + return *beacon; + } + +}} diff --git a/Modules/KiwiTool/KiwiTool_Beacon.h b/Modules/KiwiTool/KiwiTool_Beacon.h new file mode 100644 index 00000000..464c9bcf --- /dev/null +++ b/Modules/KiwiTool/KiwiTool_Beacon.h @@ -0,0 +1,115 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include +#include +#include + +#include + +namespace kiwi { namespace tool { + + // ================================================================================ // + // BEACON // + // ================================================================================ // + + //! @brief The beacon is unique and matchs to a "unique" string in the scope of a beacon factory and can be used to bind beacon's castaways. + //! @details The beacon are uniques in the scope of a beacon factory and matchs to a string. + //! If you create a beacon with a string that already matchs to a beacon of the beacon factory, + //! it will return this beacon otherwise it will create a new beacon. + //! Thus, the beacons can be used to bind, unbind and retrieve castways. + //! After recovering a castaway, you should dynamically cast it to the class you expect. + //! More often, this will be a kiwi Object. + //! @see Beacon::Factory + //! @see Beacon::Castaway + class Beacon + { + public: // methods + + class Castaway; + + //! @brief Gets the name of the beacon. + inline std::string getName() const {return m_name;} + + //! @brief Destructor. + ~Beacon() = default; + + //! @brief Adds a castaway in the binding list of the beacon. + void bind(Castaway& castaway); + + //! @brief Removes a castaways from the binding list of the beacon. + void unbind(Castaway& castaway); + + //! @brief Dispatch message to beacon castaways. + void dispatch(std::vector const& args); + + public: // nested classes + + // ================================================================================ // + // BEACON CASTAWAY // + // ================================================================================ // + + //! @brief The beacon castaway can be binded to a beacon. + class Castaway + { + public: + virtual ~Castaway() {} + virtual void receive(std::vector const& args) = 0; + }; + + // ================================================================================ // + // BEACON FACTORY // + // ================================================================================ // + + //! @brief The beacon factory is used to create beacons. + class Factory + { + public: + Factory() = default; + ~Factory() = default; + Beacon& getBeacon(std::string const& name); + + private: + std::map> m_beacons; + }; + + private: // methods + + //! @internal Constructor. + Beacon(std::string const& name); + friend class Beacon::Factory; + + private: // members + + const std::string m_name; + std::set m_castaways; + + private: // deleted methods + + Beacon(Beacon const&) = delete; + Beacon(Beacon&&) = delete; + Beacon& operator=(Beacon const&) = delete; + Beacon& operator=(Beacon&&) = delete; + }; + +}} diff --git a/Modules/KiwiTool/KiwiTool_CircularBuffer.h b/Modules/KiwiTool/KiwiTool_CircularBuffer.h new file mode 100644 index 00000000..0ec91eb0 --- /dev/null +++ b/Modules/KiwiTool/KiwiTool_CircularBuffer.h @@ -0,0 +1,164 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include +#include +#include + +namespace kiwi { namespace tool { + + // ================================================================================ // + // CIRCULAR BUFFER // + // ================================================================================ // + + //! @todo documentation inspired from boost circular buffer + //! @see http://www.boost.org/doc/libs/1_59_0/doc/html/boost/circular_buffer.html#idp23975984-bb + template + class CircularBuffer final + { + public: // methods + + CircularBuffer(size_t capacity): + m_buffer((T*) std::malloc(capacity * sizeof(T))), + m_head(0), + m_tail(0), + m_size(0), + m_capacity(capacity) + { + } + + CircularBuffer(size_t capacity, size_t size, T const& value): + m_buffer((T*) std::malloc(capacity * sizeof(T))), + m_head(0), + m_tail(0), + m_size(0), + m_capacity(capacity) + { + assert(m_capacity >= m_size); + + for (int i = 0; i < size; ++i) + { + push_back(value); + } + } + + ~CircularBuffer() + { + for (int i = std::min(m_head, m_tail); i < std::max(m_head, m_tail); ++i) + { + (m_buffer + i)->~T(); + } + + std::free(m_buffer); + } + + void assign(size_t nb_elements, const T& value) + { + clear(); + + for(int i = 0; i < nb_elements; ++i) + { + push_back(value); + } + } + + void clear() + { + size_t init_size = m_size; + + for (int i = 0; i < init_size; ++i) + { + pop_front(); + } + } + + size_t size() const + { + return m_size; + } + + T const& operator[](size_t index) const noexcept + { + return *(m_buffer + ((m_head + index) % m_size)); + } + + T& operator[](size_t index) noexcept + { + return *(m_buffer + ((m_head + index) % m_size)); + } + + void push_back(T const& value) + { + if (m_size == m_capacity) + { + (m_buffer + m_tail)->~T(); + increment_head(); + } + + new (m_buffer + m_tail) T(value); + + increment_tail(); + } + + void pop_front() + { + if (m_size != 0) + { + (m_buffer + m_head)->~T(); + increment_head(); + } + } + + private: // methods + + void increment_head() + { + m_head = (m_head + 1) == m_capacity ? 0 : m_head + 1; + --m_size; + } + + void increment_tail() + { + m_tail = (m_tail + 1) == m_capacity ? 0 : m_tail + 1; + ++m_size; + } + + private: // members + + T* m_buffer; + size_t m_head; + size_t m_tail; + size_t m_size; + size_t m_capacity; + + private: // deleted methods + + CircularBuffer() = delete; + CircularBuffer(CircularBuffer const& other) = delete; + CircularBuffer(CircularBuffer && other) = delete; + CircularBuffer& operator=(CircularBuffer const& other) = delete; + CircularBuffer& operator=(CircularBuffer && other) = delete; + + }; + +}} diff --git a/Modules/KiwiTool/KiwiTool_ConcurrentQueue.h b/Modules/KiwiTool/KiwiTool_ConcurrentQueue.h new file mode 100644 index 00000000..8ed11d89 --- /dev/null +++ b/Modules/KiwiTool/KiwiTool_ConcurrentQueue.h @@ -0,0 +1,123 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include +#include + +#include + +namespace kiwi { namespace tool { + + // ==================================================================================== // + // CONCURRENTQUEUE // + // ==================================================================================== // + + namespace mc = moodycamel; + + //! @brief A mono producer, mono consumer FIFO lock free queue. + //! @details Wrapper around a thirdparty concurrent queue. + //! @see https://github.com/cameron314/readerwriterqueue + template + class ConcurrentQueue final + { + public: // methods + + //! @brief Constructor. + //! @details Reserves memory space for at least capcity elements. + ConcurrentQueue(size_t capacity): + m_queue(capacity), + m_size(0) + { + } + + //! @brief Destructor. + ~ConcurrentQueue() = default; + + //! @brief Pushes element at end of queue (by copy). + //! @details If number of elements exceeds capacity allocation will occur. + //! Increments element counter. + void push(T const& value) + { + if(m_queue.enqueue(value)) + { + m_size++; + } + } + + //! @brief Pushes element at end of queue (by move). + //! @details If number of elements exceeds capacity allocation will occur. + //! Increments element counter. + void push(T&& value) + { + if(m_queue.enqueue(std::forward(value))) + { + m_size++; + } + } + + //! @brief Pops first element in the queue. + //! @details Returns false if the queue was empty and pop failed, true otherwise. + bool pop(T & value) + { + if(m_queue.try_dequeue(value)) + { + m_size--; + return true; + } + + return false; + } + + //! @brief Returns an approximative size for the queue. + //! @details Since size is increased and decreased after elements are effectively pushed or poped, + //! for the consumer the returned size is guaranteed to be lower or equal + //! to the effective size of the queue, for the producer the returned size is guaranteed to be + //! greater or equal than the effective size of the queue. + size_t load_size() const + { + return m_size.load(); + } + + private: // classes + + struct Trait : public moodycamel::ConcurrentQueueDefaultTraits + { + static const size_t BLOCK_SIZE = 1024; + }; + + private: // members + + mc::ConcurrentQueue m_queue; + std::atomic m_size; + + private: // deleted methods + + ConcurrentQueue() = delete; + ConcurrentQueue(ConcurrentQueue const& other) = delete; + ConcurrentQueue(ConcurrentQueue && other) = delete; + ConcurrentQueue& operator=(ConcurrentQueue const& other) = delete; + ConcurrentQueue& operator=(ConcurrentQueue && other) = delete; + + }; + +}} diff --git a/Modules/KiwiTool/KiwiTool_Listeners.h b/Modules/KiwiTool/KiwiTool_Listeners.h new file mode 100644 index 00000000..0800d97b --- /dev/null +++ b/Modules/KiwiTool/KiwiTool_Listeners.h @@ -0,0 +1,142 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include +#include +#include +#include + +namespace kiwi { namespace tool { + + // ================================================================================ // + // LISTENERS // + // ================================================================================ // + + //! @brief The listener set is a class that manages a list of listeners. + //! @details Manages a list of listeners and allows to retrieve them easily and thread-safely. + template + class Listeners + { + public: + + struct is_valid_listener : std::integral_constant::value && + !std::is_reference::value + > {}; + + using listener_t = typename std::remove_pointer::type>::type; + using listener_ref_t = listener_t&; + using listener_ptr_t = listener_t*; + + //! @brief Creates an empty listener set. + Listeners() + { + static_assert(is_valid_listener::value, + "Template parameter must not be a pointer or a reference"); + } + + //! @brief Destructor. + ~Listeners() noexcept { m_listeners.clear(); } + + //! @brief Add a listener. + //! @details If the listener was allready present in the set, the function does nothing. + //! @param listener The new listener to be added. + //! @return True if success, otherwise false. + bool add(listener_ref_t listener) noexcept + { + std::lock_guard guard(m_mutex); + bool insert_success = m_listeners.insert(&listener).second; + return insert_success; + } + + //! @brief Remove a listener. + //! @details If the listener wasn't in the set, the function does nothing. + //! @param listener The listener to be removed. + //! @return True if success, false otherwise. + bool remove(listener_ref_t listener) noexcept + { + std::lock_guard guard(m_mutex); + bool erase_success = m_listeners.erase(&listener); + return erase_success; + } + + //! @brief Returns the number of listeners. + size_t size() const noexcept + { + std::lock_guard guard(m_mutex); + return m_listeners.size(); + } + + //! @brief Returns true if there is no listener. + bool empty() const noexcept + { + std::lock_guard guard(m_mutex); + return m_listeners.empty(); + } + + //! @brief Remove all listeners. + void clear() noexcept + { + std::lock_guard guard(m_mutex); + m_listeners.clear(); + } + + //! @brief Returns true if the set contains a given listener. + bool contains(listener_ref_t listener) const noexcept + { + return (m_listeners.find(&listener) != m_listeners.end()); + } + + //! @brief Get the listeners. + std::vector getListeners() + { + std::lock_guard guard(m_mutex); + return {m_listeners.begin(), m_listeners.end()}; + } + + //! @brief Retrieve the listeners. + std::vector getListeners() const + { + std::lock_guard guard(m_mutex); + return {m_listeners.begin(), m_listeners.end()}; + } + + //! @brief Calls a given method for each listener of the set. + //! @param fun The listener's method to call. + //! @param arguments optional arguments. + template + void call(T fun, Args&& ...arguments) const + { + for(auto* listener : getListeners()) + { + (listener->*(fun))(arguments...); + } + } + + private: + + std::set m_listeners; + mutable std::mutex m_mutex; + }; + +}} diff --git a/Modules/KiwiTool/KiwiTool_Scheduler.h b/Modules/KiwiTool/KiwiTool_Scheduler.h new file mode 100644 index 00000000..fe4339a3 --- /dev/null +++ b/Modules/KiwiTool/KiwiTool_Scheduler.h @@ -0,0 +1,378 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace kiwi { namespace tool { + + // ==================================================================================== // + // SCHEDULER // + // ==================================================================================== // + + //! @brief A class designed to delay tasks' execution between threads that where previously declared. + //! @details The scheduler is designed as a singleton that uses multiple event lists. + //! Before processing the scheduler one should create an instance and register all threads that will + //! use the scheduler. One can override the clock used by the scheduler to get time. + template + class Scheduler final + { + public: // classes + + using clock_t = Clock; + + using time_point_t = typename Clock::time_point; + + using duration_t = typename Clock::duration; + + class Task; + + class CallBack; + + class Timer; + + private: // classes + + class Queue; + + class Event; + + public: // methods + + //! @brief Constructor + //! @details Sets current thread as the consumer thread. + Scheduler(); + + //! @brief Desctructor. + ~Scheduler(); + + //! @brief Sets the current thread as the consumer thread. + //! @details This method can be called for instance if the scheduler's constructor + //! is called on another thread than desired consumer. + void setThreadAsConsumer(); + + //! @brief Check wehter or not this thread is the consumer. + //! @details This method can be usefull to help decide if a direct call can be made + //! or if the scheduler shall be used. + bool isThisConsumerThread() const; + + //! @brief Delays execution of a task. Shared ownership. + //! @details Calling twice this method with same task will cancel the previous scheduled execution + //! and add a new one at specified time. + void schedule(std::shared_ptr const& task, duration_t delay = std::chrono::milliseconds(0)); + + //! @brief Delays execution of a task. Transfer ownership. + //! @details Calling twice this method with same task will cancel the previous scheduled execution + //! and add a new one at specified time. + void schedule(std::shared_ptr && task, duration_t delay = std::chrono::milliseconds(0)); + + //! @brief Delays execution of a function by the scheduler. + //! @details Internally create a callback that will be executed and destroyed by the scheduler. + void schedule(std::function && func, duration_t delay = std::chrono::milliseconds(0)); + + //! @brief Conditionally schedule a task in the consumer thread. + //! @details The task is scheduled only if the calling thread is not the consumer thread. Otherwise + //! it is executed right away. + void defer(std::shared_ptr const& task); + + //! @brief Conditionally schedule a task in the consumer thread. + //! @details The task is scheduled only if the calling thread is not the consumer thread. + //! Otherwise it is executed right away. Task is destroyed when executed. + void defer(std::shared_ptr && task); + + //! @brief Conditionally schedule a function in the consumer thread. + //! @details The function is scheduled only if the calling thread is not the consumer thread. + //! Otherwise it is executed right away. + void defer(std::function && func); + + //! @brief Used to cancel the execution of a previously scheduled task. + //! @details If the task is currently being processed by the scheduler, this method does't + //! wait for the execution to finish but only guarantee that further execution will no occur. + void unschedule(std::shared_ptr const& task); + + //! @brief Processes events of the consumer that have reached exeuction time. + void process(); + + //! @brief Lock the process until the returned lock is out of scope. + std::unique_lock lock() const; + + private: // members + + Queue m_queue; + mutable std::mutex m_mutex; + std::thread::id m_consumer_id; + + private: // deleted methods + + Scheduler(Scheduler const& other) = delete; + Scheduler(Scheduler && other) = delete; + Scheduler& operator=(Scheduler const& other) = delete; + Scheduler& operator=(Scheduler && other) = delete; + }; + + // ==================================================================================== // + // QUEUE // + // ==================================================================================== // + + //! @brief A class that holds a list of scheduled events. + //! @details Implementation countains a list of events sorted by execution time that is updated + //! before processing using commands. A queue is created for each consumer. + template + class Scheduler::Queue final + { + public: // classes + + struct Command + { + std::shared_ptr m_task; + time_point_t m_time; + }; + + public: // methods + + //! @brief Constructor. + Queue(); + + //! @brief Destructor + ~Queue(); + + //! @brief Delays the execution of a task. Shared ownership. + void schedule(std::shared_ptr const& task, duration_t delay); + + //! @brief Delays the execution of a task. Transfer ownership. + void schedule(std::shared_ptr && task, duration_t delay); + + //! @brief Cancels the execution of a task. + void unschedule(std::shared_ptr const& task); + + //! @brief Processes all events that have reached execution time. + void process(time_point_t process_time); + + private: // methods + + //! @internal + void emplace(Event && event); + + //! @internal + void remove(Event const& event); + + private: // members + + std::vector m_events; + ConcurrentQueue m_commands; + + private: // friend classes + + friend class Scheduler; + + private: // deleted methods + + Queue(Queue const& other) = delete; + Queue(Queue && other) = delete; + Queue& operator=(Queue const& other) = delete; + Queue& operator=(Queue && other) = delete; + }; + + // ==================================================================================== // + // TASK // + // ==================================================================================== // + + //! @brief The abstract class that the scheduler executes. Caller must override execute function + //! to specify the callback behavior. + template + class Scheduler::Task + { + public: // methods + + //! @brief Constructor. + //! @details A certain task is designed to be scheduled on only one consumer. + Task(); + + //! @brief Destructor. + //! @details It is not safe to destroy a task from another thread than the consumer because it can be + //! concurrent to its execution. One can create a task that deletes itself at exeuction time or lock + //! a consumer using Scheduler::Lock before deleting the task. + virtual ~Task(); + + private: // methods + + //! @brief The pure virtual execution method. Called by the scheduler when execution time + //! is reached. + virtual void execute() = 0; + + private: // friends + + friend class Scheduler; + + private: // deleted methods + + Task(Task const& other) = delete; + Task(Task && other) = delete; + Task& operator=(Task const& other) = delete; + Task& operator=(Task && other) = delete; + }; + + // ==================================================================================== // + // CALLBACK // + // ==================================================================================== // + + //! @brief The scheduler's callback is a task that uses an std::function for + //! conveniency. + template + class Scheduler::CallBack : public Scheduler::Task + { + public: // methods + + //! @brief Constructor, initializes function. + CallBack(std::function func); + + //! @brief Destructor. + ~CallBack(); + + //! @brief Executes the given functions. + void execute() override final; + + private: // members + + std::function m_func; + + private: // deleted methods + + CallBack() = delete; + CallBack(CallBack const& other) = delete; + CallBack(CallBack && other) = delete; + CallBack& operator=(CallBack const& other) = delete; + CallBack& operator=(CallBack && other) = delete; + }; + + + // ==================================================================================== // + // TIMER // + // ==================================================================================== // + + //! @brief An abstract class designed to repetedly call a method at a specified intervall of time. + //! Overriding timerCallBack and calling startTimer will start repetdly calling method. + template + class Scheduler::Timer + { + private: // classes + + class Task; + + public: // methods + + //! @brief Constructor. + //! @details A timer can only be created for a certain consumer. + Timer(Scheduler & scheduler); + + //! @brief Destructor. + //! @details It is not safe to destroy a timer in another thread than the consumer. If intended + //! one shall lock the consumer before destroying the timer. + ~Timer(); + + //! @brief Starts the timer. + //! @details Will cause timerCallBack to be called at a specified rate by the right consumer. + void startTimer(duration_t period); + + //! @brief Stops the timer. + //! @details If called when timerCallBack is being processed, stopTimer will not wait for the execution + //! to finish but will only guarantee that further execution will not occur. + void stopTimer(); + + private: // methods + + //! @brief The pure virtual call back function. + virtual void timerCallBack() = 0; + + //! @brief Reschedule task before calling virtual method timerCallBack. + void callBackInternal(); + + private: // members + + Scheduler & m_scheduler; + std::shared_ptr m_task; + duration_t m_period; + + private: // deleted methods + + Timer() = delete; + Timer(Timer const& other) = delete; + Timer(Timer && other) = delete; + Timer& operator=(Timer const& other) = delete; + Timer& operator=(Timer && other) = delete; + }; + + // ==================================================================================== // + // EVENT // + // ==================================================================================== // + + //! @brief An event that associates a task and a execution time. + template + class Scheduler::Event final + { + public: // methods + + //! @brief Constructor. + Event(std::shared_ptr && task, time_point_t time); + + //! @brief Moove constructor + Event(Event && other); + + //! @brief Moove assignment operator. + Event& operator=(Event && other); + + //! @brief Destructor. + ~Event(); + + //! @brief Called by the scheduler to execute a the task. + void execute(); + + private: // friends + + friend class Scheduler; + + private: // members + + std::shared_ptr m_task; + time_point_t m_time; + + private: // deleted methods + + Event() = delete; + Event(Event const& other) = delete; + Event& operator=(Event const& other) = delete; + }; + +}} + +#include diff --git a/Modules/KiwiTool/KiwiTool_Scheduler.hpp b/Modules/KiwiTool/KiwiTool_Scheduler.hpp new file mode 100644 index 00000000..8744f109 --- /dev/null +++ b/Modules/KiwiTool/KiwiTool_Scheduler.hpp @@ -0,0 +1,396 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace tool { + + // ==================================================================================== // + // SCHEDULER // + // ==================================================================================== // + + template + Scheduler::Scheduler(): + m_queue(), + m_mutex(), + m_consumer_id(std::this_thread::get_id()) + { + } + + template + Scheduler::~Scheduler() + { + } + + template + void Scheduler::setThreadAsConsumer() + { + m_consumer_id = std::this_thread::get_id(); + } + + template + bool Scheduler::isThisConsumerThread() const + { + return m_consumer_id == std::this_thread::get_id(); + } + + template + void Scheduler::schedule(std::shared_ptr const& task, duration_t delay) + { + assert(task); + m_queue.schedule(task, delay); + } + + template + void Scheduler::schedule(std::shared_ptr && task, duration_t delay) + { + assert(task); + m_queue.schedule(std::move(task), delay); + } + + template + void Scheduler::schedule(std::function && func, duration_t delay) + { + schedule(std::make_shared(func), delay); + } + + template + void Scheduler::defer(std::shared_ptr const& task) + { + assert(task); + + if (!isThisConsumerThread()) + { + schedule(task); + } + else + { + task->execute(); + } + } + + template + void Scheduler::defer(std::shared_ptr && task) + { + assert(task); + + if (!isThisConsumerThread()) + { + schedule(std::move(task)); + } + else + { + task->execute(); + task.reset(); + } + } + + template + void Scheduler::defer(std::function && func) + { + if (!isThisConsumerThread()) + { + schedule(std::move(func)); + } + else + { + func(); + } + } + + template + void Scheduler::unschedule(std::shared_ptr const& task) + { + assert(task); + m_queue.unschedule(task); + } + + template + void Scheduler::process() + { + assert(std::this_thread::get_id() == m_consumer_id); + + std::lock_guard lock(m_mutex); + + time_point_t process_time = clock_t::now(); + + m_queue.process(process_time); + } + + template + std::unique_lock Scheduler::lock() const + { + std::unique_lock head_lock(m_mutex); + + return std::move(head_lock); + } + + // ==================================================================================== // + // QUEUE // + // ==================================================================================== // + + template + Scheduler::Queue::Queue(): + m_events(), + m_commands(1024) + { + } + + template + Scheduler::Queue::~Queue() + { + } + + template + void Scheduler::Queue::schedule(std::shared_ptr const& task, duration_t delay) + { + assert(task); + m_commands.push({task, clock_t::now() + delay }); + } + + template + void Scheduler::Queue::schedule(std::shared_ptr && task, duration_t delay) + { + assert(task); + m_commands.push({std::move(task), clock_t::now() + delay}); + } + + template + void Scheduler::Queue::unschedule(std::shared_ptr const& task) + { + m_commands.push({task, clock_t::time_point::max()}); + } + + template + void Scheduler::Queue::remove(Event const& event) + { + m_events.erase(std::remove_if(m_events.begin(), m_events.end(), [&event](Event const& e) { + + return e.m_task == event.m_task; + + }), m_events.end()); + } + + template + void Scheduler::Queue::emplace(Event && event) + { + remove(event); + + auto event_it = m_events.begin(); + + while(event_it != m_events.end()) + { + if (event.m_time < event_it->m_time) + { + m_events.insert(event_it, std::move(event)); + break; + } + + ++event_it; + } + + if (event_it == m_events.end()) + { + m_events.emplace_back(std::move(event)); + } + } + + template + void Scheduler::Queue::process(time_point_t process_time) + { + size_t command_size = m_commands.load_size(); + + for (size_t i = 0; i < command_size; ++i) + { + Command command; + + if (m_commands.pop(command)) + { + Event event(std::move(command.m_task), command.m_time); + + if (event.m_time != clock_t::time_point::max()) + { + emplace(std::move(event)); + } + else + { + remove(event); + } + } + } + + m_events.erase(std::remove_if(m_events.begin(), m_events.end(), [&process_time](auto& event) { + + if (event.m_time <= process_time) + { + event.execute(); + return true; + } + + return false; + + }), m_events.end()); + } + + // ==================================================================================== // + // TASK // + // ==================================================================================== // + + template + Scheduler::Task::Task() + { + } + + template + Scheduler::Task::~Task() + { + } + + // ==================================================================================== // + // CALLBACK // + // ==================================================================================== // + + template + Scheduler::CallBack::CallBack(std::function func): + Task(), + m_func(func) + { + } + + template + Scheduler::CallBack::~CallBack() + { + } + + template + void Scheduler::CallBack::execute() + { + m_func(); + } + + // ==================================================================================== // + // TIMER // + // ==================================================================================== // + + template + class Scheduler::Timer::Task final : public Scheduler::Task + { + public: // methods + + Task(Timer& timer): + m_timer(timer) + { + } + + ~Task() + { + } + + void execute() override + { + m_timer.callBackInternal(); + } + + private: // members + + Timer& m_timer; + + }; + + template + Scheduler::Timer::Timer(Scheduler & scheduler): + m_scheduler(scheduler), + m_task(new Task(*this)), + m_period() + { + } + + template + Scheduler::Timer::~Timer() + { + stopTimer(); + } + + template + void Scheduler::Timer::startTimer(duration_t period) + { + stopTimer(); + + m_period = period; + + m_scheduler.schedule(m_task, m_period); + } + + template + void Scheduler::Timer::callBackInternal() + { + timerCallBack(); + + m_scheduler.schedule(m_task, m_period); + } + + template + void Scheduler::Timer::stopTimer() + { + m_scheduler.unschedule(m_task); + } + + // ==================================================================================== // + // EVENT // + // ==================================================================================== // + + template + Scheduler::Event::Event(std::shared_ptr && task, time_point_t time): + m_task(std::move(task)), + m_time(time) + { + } + + template + Scheduler::Event::Event(Event && other): + m_task(std::move(other.m_task)), + m_time(std::move(other.m_time)) + { + } + + template + typename Scheduler::Event& Scheduler::Event::operator=(Event && other) + { + m_task = std::move(other.m_task); + m_time = std::move(other.m_time); + + return *this; + } + + + template + Scheduler::Event::~Event() + { + } + + template + void Scheduler::Event::execute() + { + if (m_task){m_task->execute();} + } +}} diff --git a/Test/Model/test_PatcherValidator.cpp b/Test/Model/test_PatcherValidator.cpp index 1dab72d6..973cbbd0 100755 --- a/Test/Model/test_PatcherValidator.cpp +++ b/Test/Model/test_PatcherValidator.cpp @@ -26,9 +26,10 @@ #include "flip/PortDirect.h" #include "flip/CarrierDirect.h" +#include + #include #include -#include #include #include @@ -45,8 +46,8 @@ TEST_CASE("Model Validator", "[Validator]") model::PatcherValidator validator; flip::DocumentServer server (model::DataModel::use(), validator, 123456789ULL); - server.root().addObject(model::Factory::create(AtomHelper::parse("+"))); - server.root().addObject(model::Factory::create(AtomHelper::parse("+"))); + server.root().addObject(model::Factory::create(tool::AtomHelper::parse("+"))); + server.root().addObject(model::Factory::create(tool::AtomHelper::parse("+"))); server.commit(); @@ -108,8 +109,8 @@ TEST_CASE("Model Validator", "[Validator]") model::PatcherValidator validator; flip::DocumentServer server (model::DataModel::use(), validator, 123456789ULL); - server.root().addObject(model::Factory::create(AtomHelper::parse("+"))); - server.root().addObject(model::Factory::create(AtomHelper::parse("+"))); + server.root().addObject(model::Factory::create(tool::AtomHelper::parse("+"))); + server.root().addObject(model::Factory::create(tool::AtomHelper::parse("+"))); server.commit(); diff --git a/Test/Model/test_Atom.cpp b/Test/Tool/test_Atom.cpp similarity index 99% rename from Test/Model/test_Atom.cpp rename to Test/Tool/test_Atom.cpp index 5b033778..36c1d30a 100755 --- a/Test/Model/test_Atom.cpp +++ b/Test/Tool/test_Atom.cpp @@ -23,9 +23,9 @@ #include "../catch.hpp" -#include +#include -using namespace kiwi; +using namespace kiwi::tool; //! @brief kiwi::Atom unit test //! @todo : diff --git a/Test/Tool/test_KiwiTool.cpp b/Test/Tool/test_KiwiTool.cpp new file mode 100755 index 00000000..ef911aff --- /dev/null +++ b/Test/Tool/test_KiwiTool.cpp @@ -0,0 +1,33 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#define CATCH_CONFIG_RUNNER + +#include "../catch.hpp" + +int main( int argc, char* const argv[] ) +{ + std::cout << "running Unit-Tests - KiwiTool ..." << '\n' << '\n'; + + int result = Catch::Session().run( argc, argv ); + + return result; +} diff --git a/Test/Engine/test_Scheduler.cpp b/Test/Tool/test_Scheduler.cpp similarity index 98% rename from Test/Engine/test_Scheduler.cpp rename to Test/Tool/test_Scheduler.cpp index cbd67271..8039eff0 100644 --- a/Test/Engine/test_Scheduler.cpp +++ b/Test/Tool/test_Scheduler.cpp @@ -28,10 +28,11 @@ #include "../catch.hpp" -#include +#include using namespace kiwi; -using Scheduler = engine::Scheduler; +; +using Scheduler = tool::Scheduler; using Task = Scheduler::Task; using CallBack = Scheduler::CallBack; @@ -473,7 +474,7 @@ TickClock::time_point TickClock::current_time = TickClock::clock_t::now(); TEST_CASE("Scheduler - custom clock", "[Scheduler]") { - using TickScheduler = engine::Scheduler; + using TickScheduler = tool::Scheduler; SECTION("Execution order and custom clock") { From 56c6d344028d751f760ebf973b7355095038c492 Mon Sep 17 00:00:00 2001 From: jmillot Date: Mon, 20 Nov 2017 22:25:33 +0100 Subject: [PATCH 065/148] Object refactoring. --- Client/Source/KiwiApp.cpp | 45 ++- Client/Source/KiwiApp.h | 6 + .../KiwiApp_Application/KiwiApp_Instance.cpp | 2 +- .../KiwiApp_Patcher/KiwiApp_Factory.cpp | 17 +- .../Source/KiwiApp_Patcher/KiwiApp_Factory.h | 23 +- .../KiwiApp_BangView.cpp | 35 ++- .../KiwiApp_BangView.h | 22 +- .../KiwiApp_ClassicView.cpp | 87 ++---- .../KiwiApp_Objects/KiwiApp_ClassicView.h | 80 +++++ .../KiwiApp_EditableObjectView.cpp | 103 +++++++ ...sicView.h => KiwiApp_EditableObjectView.h} | 92 +++--- .../KiwiApp_MeterTildeView.cpp | 60 ++-- .../KiwiApp_MeterTildeView.h | 27 +- .../KiwiApp_Objects/KiwiApp_ObjectFrame.cpp | 31 +- .../KiwiApp_Objects/KiwiApp_ObjectFrame.h | 10 +- .../KiwiApp_Objects/KiwiApp_ObjectView.cpp | 118 +++++++- .../KiwiApp_Objects/KiwiApp_ObjectView.h | 64 +++- .../KiwiApp_Objects/KiwiApp_Objects.h | 24 +- .../KiwiApp_SliderView.cpp | 74 ++--- .../KiwiApp_SliderView.h | 15 +- .../KiwiApp_ToggleView.cpp | 96 ++---- .../KiwiApp_ToggleView.h | 35 +-- .../KiwiApp_PatcherManager.cpp | 6 +- .../KiwiApp_Patcher/KiwiApp_PatcherView.cpp | 27 +- .../KiwiApp_Patcher/KiwiApp_PatcherView.h | 3 + .../KiwiApp_PatcherViewMouseHandler.cpp | 12 +- Modules/KiwiEngine/KiwiEngine_Factory.cpp | 23 +- Modules/KiwiEngine/KiwiEngine_Factory.h | 32 +- Modules/KiwiEngine/KiwiEngine_Instance.cpp | 35 +-- Modules/KiwiEngine/KiwiEngine_Instance.h | 9 +- Modules/KiwiEngine/KiwiEngine_Object.cpp | 170 ++++++++++- Modules/KiwiEngine/KiwiEngine_Object.h | 96 +++++- .../KiwiEngine_AdcTilde.cpp | 59 ++++ ...ine_Loadmess.cpp => KiwiEngine_AdcTilde.h} | 44 ++- .../KiwiEngine_AudioInterface.cpp | 92 ++++++ .../KiwiEngine_AudioInterface.h | 51 ++++ .../KiwiEngine_Objects/KiwiEngine_Bang.cpp | 71 +++++ .../KiwiEngine_Objects/KiwiEngine_Bang.h | 54 ++++ .../KiwiEngine_Basic/KiwiEngine_NewBox.cpp | 43 --- .../KiwiEngine_Controller/KiwiEngine_Bang.cpp | 85 ------ .../KiwiEngine_Controller/KiwiEngine_Bang.h | 63 ---- .../KiwiEngine_Toggle.cpp | 165 ----------- .../KiwiEngine_Controller/KiwiEngine_Toggle.h | 70 ----- .../KiwiEngine_DacTilde.cpp | 59 ++++ .../KiwiEngine_Objects/KiwiEngine_DacTilde.h | 46 +++ .../KiwiEngine_Delay.cpp | 27 +- .../KiwiEngine_Objects/KiwiEngine_Delay.h | 54 ++++ .../KiwiEngine_DelaySimpleTilde.cpp | 274 ++++++++++++++++++ .../KiwiEngine_DelaySimpleTilde.h | 106 +++++++ .../KiwiEngine_Dsp/KiwiEngine_AdcTilde.cpp | 58 ---- .../KiwiEngine_Dsp/KiwiEngine_DacTilde.cpp | 58 ---- .../KiwiEngine_Dsp/KiwiEngine_DacTilde.h | 45 --- .../KiwiEngine_DelaySimpleTilde.cpp | 155 ---------- .../KiwiEngine_DelaySimpleTilde.h | 70 ----- .../KiwiEngine_Dsp/KiwiEngine_OscTilde.cpp | 154 ---------- .../KiwiEngine_Dsp/KiwiEngine_OscTilde.h | 68 ----- .../KiwiEngine_Dsp/KiwiEngine_PlusTilde.cpp | 104 ------- .../KiwiEngine_Dsp/KiwiEngine_PlusTilde.h | 54 ---- .../KiwiEngine_Dsp/KiwiEngine_SigTilde.cpp | 66 ----- .../KiwiEngine_Dsp/KiwiEngine_SigTilde.h | 51 ---- .../KiwiEngine_Dsp/KiwiEngine_TimesTilde.cpp | 102 ------- .../KiwiEngine_Dsp/KiwiEngine_TimesTilde.h | 54 ---- .../KiwiEngine_ErrorBox.cpp | 58 ++++ ...iwiEngine_Plus.h => KiwiEngine_ErrorBox.h} | 43 ++- .../KiwiEngine_Loadmess.cpp | 68 +++++ .../KiwiEngine_Loadmess.h | 52 ++-- .../KiwiEngine_Math/KiwiEngine_Plus.cpp | 71 ----- .../KiwiEngine_Math/KiwiEngine_Times.cpp | 70 ----- .../KiwiEngine_Message/KiwiEngine_Print.cpp | 47 --- .../KiwiEngine_Message/KiwiEngine_Receive.cpp | 111 ------- .../KiwiEngine_Message/KiwiEngine_Receive.h | 56 ---- .../KiwiEngine_MeterTilde.cpp | 19 +- .../KiwiEngine_MeterTilde.h | 17 +- .../KiwiEngine_Objects/KiwiEngine_Metro.cpp | 98 +++++++ .../KiwiEngine_Objects/KiwiEngine_Metro.h | 54 ++++ .../KiwiEngine_Objects/KiwiEngine_NewBox.cpp | 52 ++++ .../KiwiEngine_NewBox.h | 33 ++- .../KiwiEngine_Objects/KiwiEngine_Objects.h | 71 ++--- .../KiwiEngine_Operator.cpp | 74 +++++ ...wiEngine_Times.h => KiwiEngine_Operator.h} | 24 +- .../KiwiEngine_OperatorTilde.cpp | 117 ++++++++ .../KiwiEngine_OperatorTilde.h | 53 ++++ .../KiwiEngine_OscTilde.cpp | 179 ++++++++++++ .../KiwiEngine_Objects/KiwiEngine_OscTilde.h | 70 +++++ .../KiwiEngine_Objects/KiwiEngine_Pipe.cpp | 80 +++++ .../KiwiEngine_Objects/KiwiEngine_Pipe.h | 51 ++++ .../KiwiEngine_Objects/KiwiEngine_Plus.cpp | 52 ++++ ...iwiEngine_ErrorBox.h => KiwiEngine_Plus.h} | 34 +-- .../KiwiEngine_PlusTilde.cpp | 51 ++++ .../KiwiEngine_Objects/KiwiEngine_PlusTilde.h | 45 +++ .../KiwiEngine_Objects/KiwiEngine_Print.cpp | 61 ++++ .../KiwiEngine_Objects/KiwiEngine_Print.h | 48 +++ .../KiwiEngine_Objects/KiwiEngine_Receive.cpp | 82 ++++++ .../KiwiEngine_Objects/KiwiEngine_Receive.h | 57 ++++ .../KiwiEngine_SigTilde.cpp | 77 +++++ .../KiwiEngine_Objects/KiwiEngine_SigTilde.h | 53 ++++ .../KiwiEngine_Slider.cpp | 71 ++--- .../KiwiEngine_Slider.h | 25 +- .../KiwiEngine_Time/KiwiEngine_Delay.h | 60 ---- .../KiwiEngine_Time/KiwiEngine_Metro.cpp | 81 ------ .../KiwiEngine_Time/KiwiEngine_Metro.h | 51 ---- .../KiwiEngine_Time/KiwiEngine_Pipe.cpp | 102 ------- .../KiwiEngine_Time/KiwiEngine_Pipe.h | 54 ---- .../KiwiEngine_Objects/KiwiEngine_Times.cpp | 51 ++++ .../KiwiEngine_Print.h => KiwiEngine_Times.h} | 38 +-- .../KiwiEngine_TimesTilde.cpp | 51 ++++ .../KiwiEngine_TimesTilde.h | 45 +++ .../KiwiEngine_Objects/KiwiEngine_Toggle.cpp | 125 ++++++++ .../KiwiEngine_Objects/KiwiEngine_Toggle.h | 61 ++++ .../KiwiEngine_AudioInterface.cpp | 95 ------ .../KiwiEngine_AudioInterface.h | 55 ---- .../KiwiEngine_Utils/KiwiEngine_Router.cpp | 64 ---- .../KiwiEngine_Utils/KiwiEngine_Router.h | 68 ----- Modules/KiwiEngine/KiwiEngine_Patcher.cpp | 114 ++++++-- Modules/KiwiEngine/KiwiEngine_Patcher.h | 18 +- Modules/KiwiModel/KiwiModel_DataModel.cpp | 65 ++--- Modules/KiwiModel/KiwiModel_DataModel.h | 19 +- .../KiwiModel_Error.h} | 93 +++--- Modules/KiwiModel/KiwiModel_Factory.cpp | 43 +-- Modules/KiwiModel/KiwiModel_Factory.h | 244 ++++------------ Modules/KiwiModel/KiwiModel_Object.cpp | 203 +++++++++---- Modules/KiwiModel/KiwiModel_Object.h | 153 ++++++---- Modules/KiwiModel/KiwiModel_ObjectClass.cpp | 197 +++++++++++++ Modules/KiwiModel/KiwiModel_ObjectClass.h | 225 ++++++++++++++ .../KiwiModel_Objects/KiwiModel_AdcTilde.cpp | 134 +++++++++ ...iModel_NewBox.cpp => KiwiModel_AdcTilde.h} | 103 ++++--- .../KiwiModel_Objects/KiwiModel_Bang.cpp | 88 ++++++ .../KiwiModel_OscTilde.h => KiwiModel_Bang.h} | 45 +-- .../KiwiModel_Basic/KiwiModel_ErrorBox.cpp | 68 ----- .../KiwiModel_Basic/KiwiModel_ErrorBox.h | 68 ----- .../KiwiModel_Basic/KiwiModel_NewBox.h | 50 ---- .../KiwiModel_Controller/KiwiModel_Bang.cpp | 80 ----- .../KiwiModel_Controller/KiwiModel_Toggle.cpp | 80 ----- .../KiwiModel_Controller/KiwiModel_Toggle.h | 62 ---- .../KiwiModel_DacTilde.cpp | 33 ++- .../KiwiModel_Bang.h => KiwiModel_DacTilde.h} | 51 ++-- .../{KiwiModel_Time => }/KiwiModel_Delay.cpp | 38 ++- .../KiwiModel_Objects/KiwiModel_Delay.h | 47 +++ .../KiwiModel_DelaySimpleTilde.cpp | 98 +++++++ .../KiwiModel_DelaySimpleTilde.h | 21 +- .../KiwiModel_Dsp/KiwiModel_AdcTilde.cpp | 125 -------- .../KiwiModel_Dsp/KiwiModel_AdcTilde.h | 54 ---- .../KiwiModel_Dsp/KiwiModel_DacTilde.h | 53 ---- .../KiwiModel_DelaySimpleTilde.cpp | 78 ----- .../KiwiModel_Dsp/KiwiModel_OscTilde.cpp | 68 ----- .../KiwiModel_Dsp/KiwiModel_PlusTilde.cpp | 56 ---- .../KiwiModel_Dsp/KiwiModel_PlusTilde.h | 50 ---- .../KiwiModel_Dsp/KiwiModel_SigTilde.cpp | 54 ---- .../KiwiModel_Dsp/KiwiModel_TimesTilde.cpp | 56 ---- .../KiwiModel_Dsp/KiwiModel_TimesTilde.h | 50 ---- .../KiwiModel_Objects/KiwiModel_ErrorBox.cpp | 84 ++++++ .../KiwiModel_Objects/KiwiModel_ErrorBox.h | 69 +++++ .../KiwiModel_Objects/KiwiModel_Loadmess.cpp | 71 +++++ .../KiwiModel_Objects/KiwiModel_Loadmess.h} | 95 +++--- .../KiwiModel_Math/KiwiModel_Plus.cpp | 56 ---- .../KiwiModel_Math/KiwiModel_Plus.h | 50 ---- .../KiwiModel_Math/KiwiModel_Times.cpp | 56 ---- .../KiwiModel_Math/KiwiModel_Times.h | 50 ---- .../KiwiModel_Message/KiwiModel_Loadmess.cpp | 54 ---- .../KiwiModel_Message/KiwiModel_Print.h | 50 ---- .../KiwiModel_Message/KiwiModel_Receive.cpp | 54 ---- .../KiwiModel_Message/KiwiModel_Receive.h | 50 ---- .../KiwiModel_MeterTilde.cpp | 36 ++- .../KiwiModel_MeterTilde.h | 16 +- .../KiwiModel_Objects/KiwiModel_Metro.cpp | 87 ++++++ .../KiwiModel_Objects/KiwiModel_Metro.h | 47 +++ .../KiwiModel_Objects/KiwiModel_NewBox.cpp | 65 +++++ ...iwiModel_Loadmess.h => KiwiModel_NewBox.h} | 47 +-- .../KiwiModel_Objects/KiwiModel_Objects.h | 72 ++--- .../KiwiModel_Objects/KiwiModel_Operator.cpp | 56 ++++ .../KiwiModel_Objects/KiwiModel_Operator.h | 45 +++ .../KiwiModel_OperatorTilde.cpp | 56 ++++ .../KiwiModel_OperatorTilde.h | 45 +++ .../KiwiModel_Objects/KiwiModel_OscTilde.cpp | 84 ++++++ .../KiwiModel_Objects/KiwiModel_OscTilde.h | 47 +++ .../KiwiModel_Objects/KiwiModel_Pipe.cpp | 87 ++++++ .../KiwiModel_Objects/KiwiModel_Pipe.h | 47 +++ .../KiwiModel_Objects/KiwiModel_Plus.cpp | 61 ++++ .../KiwiModel_Objects/KiwiModel_Plus.h | 46 +++ .../KiwiModel_Objects/KiwiModel_PlusTilde.cpp | 60 ++++ .../KiwiModel_Objects/KiwiModel_PlusTilde.h | 45 +++ .../KiwiModel_Print.cpp | 25 +- .../KiwiModel_Objects/KiwiModel_Print.h | 48 +++ .../KiwiModel_Objects/KiwiModel_Receive.cpp | 70 +++++ .../KiwiModel_Objects/KiwiModel_Receive.h | 47 +++ .../KiwiModel_Objects/KiwiModel_SigTilde.cpp | 64 ++++ .../KiwiModel_Objects/KiwiModel_SigTilde.h | 47 +++ .../KiwiModel_Slider.cpp | 51 +++- .../KiwiModel_Slider.h | 12 +- .../KiwiModel_Time/KiwiModel_Delay.h | 50 ---- .../KiwiModel_Time/KiwiModel_Metro.cpp | 76 ----- .../KiwiModel_Time/KiwiModel_Metro.h | 50 ---- .../KiwiModel_Time/KiwiModel_Pipe.cpp | 77 ----- .../KiwiModel_Time/KiwiModel_Pipe.h | 50 ---- .../KiwiModel_Objects/KiwiModel_Times.cpp | 61 ++++ .../KiwiModel_Objects/KiwiModel_Times.h | 46 +++ .../KiwiModel_TimesTilde.cpp | 60 ++++ .../KiwiModel_Objects/KiwiModel_TimesTilde.h | 45 +++ .../KiwiModel_Objects/KiwiModel_Toggle.cpp | 94 ++++++ ...iwiModel_SigTilde.h => KiwiModel_Toggle.h} | 47 +-- Modules/KiwiTool/KiwiTool_Parameter.cpp | 110 +++++++ Modules/KiwiTool/KiwiTool_Parameter.h | 79 +++++ Test/Model/test_KiwiModel.cpp | 2 + 203 files changed, 7402 insertions(+), 5787 deletions(-) rename Client/Source/KiwiApp_Patcher/KiwiApp_Objects/{KiwiApp_Controller => }/KiwiApp_BangView.cpp (73%) rename Client/Source/KiwiApp_Patcher/KiwiApp_Objects/{KiwiApp_Controller => }/KiwiApp_BangView.h (79%) rename Client/Source/KiwiApp_Patcher/KiwiApp_Objects/{KiwiApp_Basic => }/KiwiApp_ClassicView.cpp (52%) create mode 100644 Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ClassicView.h create mode 100644 Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_EditableObjectView.cpp rename Client/Source/KiwiApp_Patcher/KiwiApp_Objects/{KiwiApp_Basic/KiwiApp_ClassicView.h => KiwiApp_EditableObjectView.h} (65%) rename Client/Source/KiwiApp_Patcher/KiwiApp_Objects/{KiwiApp_Dsp => }/KiwiApp_MeterTildeView.cpp (80%) rename Client/Source/KiwiApp_Patcher/KiwiApp_Objects/{KiwiApp_Dsp => }/KiwiApp_MeterTildeView.h (79%) rename Client/Source/KiwiApp_Patcher/KiwiApp_Objects/{KiwiApp_Controller => }/KiwiApp_SliderView.cpp (66%) rename Client/Source/KiwiApp_Patcher/KiwiApp_Objects/{KiwiApp_Controller => }/KiwiApp_SliderView.h (86%) rename Client/Source/KiwiApp_Patcher/KiwiApp_Objects/{KiwiApp_Controller => }/KiwiApp_ToggleView.cpp (51%) rename Client/Source/KiwiApp_Patcher/KiwiApp_Objects/{KiwiApp_Controller => }/KiwiApp_ToggleView.h (64%) create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_AdcTilde.cpp rename Modules/KiwiEngine/KiwiEngine_Objects/{KiwiEngine_Message/KiwiEngine_Loadmess.cpp => KiwiEngine_AdcTilde.h} (51%) create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_AudioInterface.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_AudioInterface.h create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Bang.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Bang.h delete mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Basic/KiwiEngine_NewBox.cpp delete mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Bang.cpp delete mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Bang.h delete mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Toggle.cpp delete mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Toggle.h create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_DacTilde.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_DacTilde.h rename Modules/KiwiEngine/KiwiEngine_Objects/{KiwiEngine_Time => }/KiwiEngine_Delay.cpp (76%) create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Delay.h create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_DelaySimpleTilde.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_DelaySimpleTilde.h delete mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_AdcTilde.cpp delete mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_DacTilde.cpp delete mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_DacTilde.h delete mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_DelaySimpleTilde.cpp delete mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_DelaySimpleTilde.h delete mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_OscTilde.cpp delete mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_OscTilde.h delete mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_PlusTilde.cpp delete mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_PlusTilde.h delete mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_SigTilde.cpp delete mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_SigTilde.h delete mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_TimesTilde.cpp delete mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_TimesTilde.h create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_ErrorBox.cpp rename Modules/KiwiEngine/KiwiEngine_Objects/{KiwiEngine_Math/KiwiEngine_Plus.h => KiwiEngine_ErrorBox.h} (54%) create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Loadmess.cpp rename Modules/KiwiEngine/KiwiEngine_Objects/{KiwiEngine_Message => }/KiwiEngine_Loadmess.h (52%) delete mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Math/KiwiEngine_Plus.cpp delete mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Math/KiwiEngine_Times.cpp delete mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Print.cpp delete mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Receive.cpp delete mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Receive.h rename Modules/KiwiEngine/KiwiEngine_Objects/{KiwiEngine_Dsp => }/KiwiEngine_MeterTilde.cpp (86%) rename Modules/KiwiEngine/KiwiEngine_Objects/{KiwiEngine_Dsp => }/KiwiEngine_MeterTilde.h (79%) create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Metro.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Metro.h create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_NewBox.cpp rename Modules/KiwiEngine/KiwiEngine_Objects/{KiwiEngine_Basic => }/KiwiEngine_NewBox.h (57%) create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Operator.cpp rename Modules/KiwiEngine/KiwiEngine_Objects/{KiwiEngine_Math/KiwiEngine_Times.h => KiwiEngine_Operator.h} (77%) create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_OperatorTilde.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_OperatorTilde.h create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_OscTilde.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_OscTilde.h create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Pipe.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Pipe.h create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Plus.cpp rename Modules/KiwiEngine/KiwiEngine_Objects/{KiwiEngine_Basic/KiwiEngine_ErrorBox.h => KiwiEngine_Plus.h} (56%) create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_PlusTilde.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_PlusTilde.h create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Print.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Print.h create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Receive.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Receive.h create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_SigTilde.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_SigTilde.h rename Modules/KiwiEngine/KiwiEngine_Objects/{KiwiEngine_Controller => }/KiwiEngine_Slider.cpp (55%) rename Modules/KiwiEngine/KiwiEngine_Objects/{KiwiEngine_Controller => }/KiwiEngine_Slider.h (73%) delete mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Delay.h delete mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Metro.cpp delete mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Metro.h delete mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Pipe.cpp delete mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Pipe.h create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Times.cpp rename Modules/KiwiEngine/KiwiEngine_Objects/{KiwiEngine_Message/KiwiEngine_Print.h => KiwiEngine_Times.h} (56%) create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_TimesTilde.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_TimesTilde.h create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Toggle.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Toggle.h delete mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Utils/KiwiEngine_AudioInterface.cpp delete mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Utils/KiwiEngine_AudioInterface.h delete mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Utils/KiwiEngine_Router.cpp delete mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Utils/KiwiEngine_Router.h rename Modules/{KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_AdcTilde.h => KiwiModel/KiwiModel_Error.h} (53%) create mode 100755 Modules/KiwiModel/KiwiModel_ObjectClass.cpp create mode 100755 Modules/KiwiModel/KiwiModel_ObjectClass.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_AdcTilde.cpp rename Modules/KiwiModel/KiwiModel_Objects/{KiwiModel_Basic/KiwiModel_NewBox.cpp => KiwiModel_AdcTilde.h} (51%) create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Bang.cpp rename Modules/KiwiModel/KiwiModel_Objects/{KiwiModel_Dsp/KiwiModel_OscTilde.h => KiwiModel_Bang.h} (53%) delete mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_ErrorBox.cpp delete mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_ErrorBox.h delete mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_NewBox.h delete mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Bang.cpp delete mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Toggle.cpp delete mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Toggle.h rename Modules/KiwiModel/KiwiModel_Objects/{KiwiModel_Dsp => }/KiwiModel_DacTilde.cpp (83%) rename Modules/KiwiModel/KiwiModel_Objects/{KiwiModel_Controller/KiwiModel_Bang.h => KiwiModel_DacTilde.h} (50%) rename Modules/KiwiModel/KiwiModel_Objects/{KiwiModel_Time => }/KiwiModel_Delay.cpp (68%) create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Delay.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_DelaySimpleTilde.cpp rename Modules/KiwiModel/KiwiModel_Objects/{KiwiModel_Dsp => }/KiwiModel_DelaySimpleTilde.h (82%) delete mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_AdcTilde.cpp delete mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_AdcTilde.h delete mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_DacTilde.h delete mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_DelaySimpleTilde.cpp delete mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_OscTilde.cpp delete mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_PlusTilde.cpp delete mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_PlusTilde.h delete mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_SigTilde.cpp delete mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_TimesTilde.cpp delete mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_TimesTilde.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_ErrorBox.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_ErrorBox.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Loadmess.cpp rename Modules/{KiwiEngine/KiwiEngine_Objects/KiwiEngine_Basic/KiwiEngine_ErrorBox.cpp => KiwiModel/KiwiModel_Objects/KiwiModel_Loadmess.h} (52%) mode change 100644 => 100755 delete mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Math/KiwiModel_Plus.cpp delete mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Math/KiwiModel_Plus.h delete mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Math/KiwiModel_Times.cpp delete mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Math/KiwiModel_Times.h delete mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Loadmess.cpp delete mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Print.h delete mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Receive.cpp delete mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Receive.h rename Modules/KiwiModel/KiwiModel_Objects/{KiwiModel_Dsp => }/KiwiModel_MeterTilde.cpp (67%) rename Modules/KiwiModel/KiwiModel_Objects/{KiwiModel_Dsp => }/KiwiModel_MeterTilde.h (84%) create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Metro.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Metro.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_NewBox.cpp rename Modules/KiwiModel/KiwiModel_Objects/{KiwiModel_Message/KiwiModel_Loadmess.h => KiwiModel_NewBox.h} (51%) create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Operator.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Operator.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_OperatorTilde.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_OperatorTilde.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_OscTilde.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_OscTilde.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Pipe.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Pipe.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Plus.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Plus.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_PlusTilde.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_PlusTilde.h rename Modules/KiwiModel/KiwiModel_Objects/{KiwiModel_Message => }/KiwiModel_Print.cpp (67%) create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Print.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Receive.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Receive.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_SigTilde.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_SigTilde.h rename Modules/KiwiModel/KiwiModel_Objects/{KiwiModel_Controller => }/KiwiModel_Slider.cpp (61%) rename Modules/KiwiModel/KiwiModel_Objects/{KiwiModel_Controller => }/KiwiModel_Slider.h (86%) delete mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Delay.h delete mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Metro.cpp delete mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Metro.h delete mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Pipe.cpp delete mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Pipe.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Times.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Times.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_TimesTilde.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_TimesTilde.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Toggle.cpp rename Modules/KiwiModel/KiwiModel_Objects/{KiwiModel_Dsp/KiwiModel_SigTilde.h => KiwiModel_Toggle.h} (52%) create mode 100644 Modules/KiwiTool/KiwiTool_Parameter.cpp create mode 100644 Modules/KiwiTool/KiwiTool_Parameter.h diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index e04e61e8..cbdf53aa 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -20,10 +20,14 @@ */ #include +#include + +#include #include -#include "KiwiApp.h" -#include "KiwiApp_General/KiwiApp_CommandIDs.h" +#include +#include +#include namespace kiwi { @@ -93,7 +97,9 @@ namespace kiwi model::DataModel::init(); - Factory::initialise(); + declareEngineObjects(); + + declareObjectViews(); juce::Desktop::getInstance().setGlobalScaleFactor(1.); @@ -128,6 +134,39 @@ namespace kiwi } } + void KiwiApp::declareEngineObjects() + { + engine::NewBox::declare(); + engine::ErrorBox::declare(); + engine::Slider::declare(); + engine::Print::declare(); + engine::Receive::declare(); + engine::Plus::declare(); + engine::Times::declare(); + engine::Delay::declare(); + engine::Metro::declare(); + engine::Pipe::declare(); + engine::Bang::declare(); + engine::Toggle::declare(); + engine::AdcTilde::declare(); + engine::DacTilde::declare(); + engine::OscTilde::declare(); + engine::Loadmess::declare(); + engine::SigTilde::declare(); + engine::TimesTilde::declare(); + engine::PlusTilde::declare(); + engine::MeterTilde::declare(); + engine::DelaySimpleTilde::declare(); + } + + void KiwiApp::declareObjectViews() + { + SliderView::declare(); + BangView::declare(); + ToggleView::declare(); + MeterTildeView::declare(); + } + void KiwiApp::shutdown() { #if JUCE_MAC diff --git a/Client/Source/KiwiApp.h b/Client/Source/KiwiApp.h index 15454755..25808887 100644 --- a/Client/Source/KiwiApp.h +++ b/Client/Source/KiwiApp.h @@ -241,6 +241,12 @@ namespace kiwi //! @internal Utility to quit the app asynchronously. class AsyncQuitRetrier; + //! @internal Initializes engine's factory declaring engine objects + void declareEngineObjects(); + + //! @internal Initializes gui specific objects. + void declareObjectViews(); + private: // members std::unique_ptr m_api_controller; diff --git a/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp b/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp index 54823b14..f7c1dc6a 100644 --- a/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp +++ b/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp @@ -43,7 +43,7 @@ namespace kiwi Instance::Instance() : m_scheduler(), - m_instance(std::make_unique()), + m_instance(std::make_unique(), m_scheduler), m_browser(), m_console_history(std::make_shared(m_instance)), m_last_opened_file(juce::File::getSpecialLocation(juce::File::userHomeDirectory)) diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Factory.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Factory.cpp index bc4e393b..08f7822f 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Factory.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Factory.cpp @@ -21,12 +21,13 @@ #include -#include #include +#include + namespace kiwi { - std::map Factory::m_creator_map; + std::map Factory::m_creators; std::unique_ptr Factory::createObjectView(model::Object & object_model) { @@ -34,9 +35,9 @@ namespace kiwi std::string object_name = object_model.getName(); - if (m_creator_map.find(object_name) != m_creator_map.end()) + if (m_creators.find(object_name) != m_creators.end()) { - object_view = std::move(m_creator_map[object_name](object_model)); + object_view = std::move(m_creators[object_name](object_model)); } else { @@ -45,12 +46,4 @@ namespace kiwi return object_view; } - - void Factory::initialise() - { - add("bang"); - add("toggle"); - add("slider"); - add("meter~"); - } } diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Factory.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Factory.h index 6df41eb2..cbdcec07 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Factory.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Factory.h @@ -41,7 +41,7 @@ namespace kiwi { public: // definitions - using factory_func = std::function(model::Object & model)>; + using ctor_fn_t = std::function(model::Object & model)>; public: // methods @@ -49,24 +49,23 @@ namespace kiwi //! @details Returns an object corresponding to a certain object's model. static std::unique_ptr createObjectView(model::Object & object_model); - //! @brief Initializes the list of creators adding a function for each type of objects. - static void initialise(); - - private: // members - //! @brief Adds a object to the factory. template - static void add(std::string const& name) + static void add(std::string const& name, ctor_fn_t create_method) { + static_assert(std::is_base_of::value, + "object's view doesn't inherit from class ObjectView"); + + static_assert(!std::is_abstract::value, + "The object's view must not be abstract."); + assert(model::Factory::has(name) && "Adding an engine object that has no corresponding model"); + assert(m_creators.count(name) == 0 && "The object already exists"); - m_creator_map[name] = [](model::Object & object_model) - { - return std::make_unique(object_model); - }; + m_creators[name] = create_method; }; - static std::map m_creator_map; + static std::map m_creators; private: // deleted methods diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_BangView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_BangView.cpp similarity index 73% rename from Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_BangView.cpp rename to Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_BangView.cpp index 98c169c0..beba0e8c 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_BangView.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_BangView.cpp @@ -21,15 +21,25 @@ #include -#include +#include +#include -#include - -#include -#include - -namespace kiwi -{ +namespace kiwi { + + // ================================================================================ // + // BANG VIEW // + // ================================================================================ // + + void BangView::declare() + { + Factory::add("bang", &BangView::create); + } + + std::unique_ptr BangView::create(model::Object & model) + { + return std::make_unique(model); + } + BangView::BangView(model::Object & model): ObjectView(model), m_signal(model.getSignal<>(model::Bang::Signal::TriggerBang)), @@ -42,7 +52,7 @@ namespace kiwi BangView::~BangView() { - KiwiApp::useInstance().useScheduler().unschedule(m_switch_off); + getScheduler().unschedule(m_switch_off); } void BangView::paint(juce::Graphics & g) @@ -90,7 +100,7 @@ namespace kiwi repaint(); } - KiwiApp::useInstance().useScheduler().schedule(m_switch_off, std::chrono::milliseconds(150)); + getScheduler().schedule(m_switch_off, std::chrono::milliseconds(150)); } void BangView::switchOff() @@ -101,6 +111,9 @@ namespace kiwi void BangView::signalTriggered() { - KiwiApp::useInstance().useScheduler().defer(std::bind(&BangView::flash, this)); + getScheduler().defer([this]() + { + flash(); + }); } } diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_BangView.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_BangView.h similarity index 79% rename from Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_BangView.h rename to Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_BangView.h index e8c40585..7685382a 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_BangView.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_BangView.h @@ -23,18 +23,14 @@ #include -#include - #include -#include - #include #include -namespace kiwi -{ +namespace kiwi { + // ================================================================================ // // BANG VIEW // // ================================================================================ // @@ -43,30 +39,26 @@ namespace kiwi { public: // methods - //! @brief Constructor. + static void declare(); + + static std::unique_ptr create(model::Object & model); + BangView(model::Object & object_model); - //! @brief Destructor. ~BangView(); private: // methods - //! @brief The graphical rendering method. void paint(juce::Graphics & g) override final; - //! @brief Called when the bang is clicked. void mouseDown(juce::MouseEvent const& e) override final; - //! @brief Called when the bang is unclicked. void mouseUp(juce::MouseEvent const& e) override final; - //! @brief Switches the bang view on and schedules to switch it off. void flash(); - //! @brief Switches the bang view off. void switchOff(); - //! @brief Called whenever bang is trigerred. void signalTriggered(); private: // members @@ -76,7 +68,7 @@ namespace kiwi flip::SignalConnection m_connection; bool m_active; bool m_mouse_down; - std::shared_ptr::CallBack> m_switch_off; + std::shared_ptr::CallBack> m_switch_off; private: // deleted methods diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ClassicView.cpp similarity index 52% rename from Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.cpp rename to Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ClassicView.cpp index 8e71530d..bfa6e72c 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ClassicView.cpp @@ -21,7 +21,7 @@ #include -#include +#include #include @@ -32,42 +32,29 @@ namespace kiwi // ================================================================================ // ClassicView::ClassicView(model::Object & object_model) : - ObjectView(object_model), - m_label(*this, object_model.getText()), - m_listeners() + EditableObjectView(object_model) { + juce::Label & label = getLabel(); + + label.setText(object_model.getText(), juce::NotificationType::dontSendNotification); + juce::Colour bg_colour = object_model.getName() == "errorbox" ? findColour(ObjectView::ColourIds::Error).withAlpha(0.4f) : findColour(ObjectView::ColourIds::Background); - m_label.setColour(juce::Label::backgroundColourId, bg_colour); - m_label.setColour(juce::Label::backgroundWhenEditingColourId, bg_colour); - m_label.setColour(juce::Label::textColourId, findColour(ObjectView::ColourIds::Text)); - m_label.setColour(juce::Label::textWhenEditingColourId, findColour(ObjectView::ColourIds::Text)); + label.setColour(juce::Label::backgroundColourId, bg_colour); + label.setColour(juce::Label::backgroundWhenEditingColourId, bg_colour); + label.setColour(juce::Label::textColourId, findColour(ObjectView::ColourIds::Text)); + label.setColour(juce::Label::textWhenEditingColourId, findColour(ObjectView::ColourIds::Text)); - addAndMakeVisible(m_label); + addAndMakeVisible(label); } ClassicView::~ClassicView() { } - void ClassicView::addListener(Listener& listener) - { - m_listeners.add(listener); - } - - void ClassicView::removeListener(Listener& listener) - { - m_listeners.remove(listener); - } - - void ClassicView::edit() - { - m_label.showEditor(); - } - void ClassicView::paintOverChildren (juce::Graphics& g) { g.setColour (findColour (ObjectView::ColourIds::Outline)); @@ -77,12 +64,11 @@ namespace kiwi void ClassicView::resized() { - m_label.setBounds(getLocalBounds()); + getLabel().setBounds(getLocalBounds()); } - bool ClassicView::isEditing() const + void ClassicView::textChanged() { - return m_label.isBeingEdited(); } void ClassicView::textEditorTextChanged(juce::TextEditor& editor) @@ -95,67 +81,36 @@ namespace kiwi } } - void ClassicView::labelTextChanged (juce::Label* labelThatHasChanged) - { - m_listeners.call(&ClassicView::Listener::textChanged, m_label.getText().toStdString()); - } - - void ClassicView::editorHidden (juce::Label* label, juce::TextEditor& text_editor) - { - m_listeners.call(&ClassicView::Listener::editorHidden); - } - - void ClassicView::editorShown (juce::Label* label, juce::TextEditor& text_editor) - { - m_listeners.call(&ClassicView::Listener::editorShown); - } - - // ================================================================================ // - // LABEL // - // ================================================================================ // - - ClassicView::Label::Label(ClassicView & classic_view, std::string const& label): - juce::Label("object name", label), - m_classic_view(classic_view) - { - addListener(&classic_view); - } - - ClassicView::Label::~Label() - { - removeListener(&m_classic_view); - } - - juce::TextEditor* ClassicView::Label::createEditorComponent() + juce::TextEditor* ClassicView::createdTextEditor() { juce::TextEditor * editor = new SuggestEditor(model::Factory::getNames()); editor->setBounds(getLocalBounds()); editor->setBorder(juce::BorderSize(0)); - + editor->setColour(juce::TextEditor::ColourIds::textColourId, - findColour(juce::Label::textWhenEditingColourId)); + getLabel().findColour(juce::Label::textWhenEditingColourId)); editor->setColour(juce::TextEditor::backgroundColourId, - findColour(juce::Label::backgroundWhenEditingColourId)); + getLabel().findColour(juce::Label::backgroundWhenEditingColourId)); editor->setColour(juce::TextEditor::highlightColourId, - findColour(ObjectView::ColourIds::Highlight, true).withAlpha(0.4f)); + findColour(ObjectView::ColourIds::Highlight, true).withAlpha(0.4f)); editor->setColour(juce::TextEditor::outlineColourId, - juce::Colours::transparentWhite); + juce::Colours::transparentWhite); editor->setColour(juce::TextEditor::focusedOutlineColourId, - juce::Colours::transparentWhite); + juce::Colours::transparentWhite); editor->setScrollbarsShown(false); editor->setScrollToShowCursor(true); editor->setReturnKeyStartsNewLine(false); editor->setMultiLine(true, false); - editor->addListener(&m_classic_view); + editor->addListener(this); return editor; } diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ClassicView.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ClassicView.h new file mode 100644 index 00000000..de30f197 --- /dev/null +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ClassicView.h @@ -0,0 +1,80 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +#include + +#include + +#include + +#include + +namespace kiwi +{ + // ================================================================================ // + // CLASSIC VIEW // + // ================================================================================ // + + //! @brief The view of any textual kiwi object. + class ClassicView : public EditableObjectView, + public juce::TextEditor::Listener + { + public: // methods + + //! @brief Constructor. + ClassicView(model::Object & object_model); + + //! @brief Destructor. + ~ClassicView(); + + private: // methods + + //! @brief Constructs the label's text editor. + //! @brief Overrides EditableObjectView::createTextEditor. + juce::TextEditor* createdTextEditor() override final; + + //! @brief Called when label text changed. + //! @details Overrides EditableObjectView::textChanged. + void textChanged() override final; + + //! @brief Called when the object is resized. + void resized() override final; + + //! @brief Called when the text is being typed. + //! @details Used to resize in order to keep text visible. + void textEditorTextChanged(juce::TextEditor& editor) override final; + + //! @brief Paints elements over the text editor. + void paintOverChildren (juce::Graphics& g) override final; + + private: // deleted methods + + ClassicView() = delete; + ClassicView(ClassicView const& other) = delete; + ClassicView(ClassicView && other) = delete; + ClassicView& operator=(ClassicView const& other) = delete; + ClassicView& operator=(ClassicView && other) = delete; + }; +} diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_EditableObjectView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_EditableObjectView.cpp new file mode 100644 index 00000000..b3887573 --- /dev/null +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_EditableObjectView.cpp @@ -0,0 +1,103 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +namespace kiwi { + + // ================================================================================ // + // EDITABLE OBJECT VIEW // + // ================================================================================ // + + EditableObjectView::EditableObjectView(model::Object & object_model) : + ObjectView(object_model), + m_label(*this), + m_listeners() + { + } + + EditableObjectView::~EditableObjectView() + { + } + + void EditableObjectView::edit() + { + m_label.showEditor(); + } + + void EditableObjectView::labelTextChanged (juce::Label* label) + { + textChanged(); + + m_listeners.call(&EditableObjectView::Listener::textChanged, m_label.getText().toStdString()); + } + + juce::Label & EditableObjectView::getLabel() + { + return m_label; + } + + void EditableObjectView::editorHidden (juce::Label* label, juce::TextEditor& text_editor) + { + m_label.setInterceptsMouseClicks(false, false); + + m_listeners.call(&EditableObjectView::Listener::editorHidden); + } + + void EditableObjectView::editorShown(juce::Label* label, juce::TextEditor& text_editor) + { + m_label.setInterceptsMouseClicks(true, true); + + m_listeners.call(&EditableObjectView::Listener::editorShown); + } + + void EditableObjectView::addListener(Listener& listener) + { + m_listeners.add(listener); + } + + void EditableObjectView::removeListener(Listener& listener) + { + m_listeners.remove(listener); + } + + // ================================================================================ // + // LABEL // + // ================================================================================ // + + EditableObjectView::Label::Label(EditableObjectView & object_view): + juce::Label(), + m_object_view(object_view) + { + addListener(&m_object_view); + } + + EditableObjectView::Label::~Label() + { + removeListener(&m_object_view); + } + + juce::TextEditor * EditableObjectView::Label::createEditorComponent() + { + return m_object_view.createdTextEditor(); + } + +} diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_EditableObjectView.h similarity index 65% rename from Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.h rename to Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_EditableObjectView.h index 08ddbd85..e2601c93 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Basic/KiwiApp_ClassicView.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_EditableObjectView.h @@ -21,12 +21,6 @@ #pragma once -#include - -#include - -#include - #include #include @@ -34,22 +28,37 @@ namespace kiwi { // ================================================================================ // - // CLASSIC VIEW // + // EDITABLE OBJECT VIEW // // ================================================================================ // - //! @brief The view of any textual kiwi object. - class ClassicView : public ObjectView, - public juce::TextEditor::Listener, - public juce::Label::Listener + //! @brief Abstract class for object's views that can be edited in mode unlock. + class EditableObjectView : public ObjectView, public juce::Label::Listener { public: // classes + struct Listener + { + //! @brief Destructor. + virtual ~Listener() = default; + + //! @brief Called when the text has been edited and return key was pressed. + virtual void textChanged(std::string const& new_text) = 0; + + //! @brief Called when the classic view ends its edition. + virtual void editorHidden() = 0; + + //! @brief Called when the classic view enters its edition mode. + virtual void editorShown() = 0; + }; + + private: // classes + class Label : public juce::Label { public: // methods //! @brief Constructor. - Label(ClassicView & classic_view, std::string const& label); + Label(EditableObjectView & object_view); //! @brief Destructor. ~Label(); @@ -59,31 +68,17 @@ namespace kiwi private: // members - ClassicView & m_classic_view; - }; - - struct Listener - { - //! @brief Destructor. - virtual ~Listener() = default; - - //! @brief Called when the text has been edited and return key was pressed. - virtual void textChanged(std::string const& new_text) = 0; - - //! @brief Called when the classic view ends its edition. - virtual void editorHidden() = 0; - - //! @brief Called when the classic view enters its edition mode. - virtual void editorShown() = 0; + EditableObjectView & m_object_view; }; public: // methods //! @brief Constructor. - ClassicView(model::Object & object_model); + //! @details The label is not a child component by default, initialised with not text. + EditableObjectView(model::Object & object_model); //! @brief Destructor. - ~ClassicView(); + ~EditableObjectView(); //! @brief Add a listener. void addListener(Listener& listener); @@ -91,44 +86,45 @@ namespace kiwi //! @brief Remove a listener. void removeListener(Listener& listener); - //! @brief Lets the user edit the text of the box. + //! @brief Edits the label. void edit(); - //! @brief Returns true if the classic view is currently in edition mode. - bool isEditing() const; + protected: // methods - private: // methods + //! @brief Returns the label created by the editable object. + juce::Label & getLabel(); - //! @brief Called when the object is resized. - void resized() override final; + private: // methods - //! @brief Called when the text is being typed. - //! @details Used to resize in order to keep text visible. - void textEditorTextChanged(juce::TextEditor& editor) override final; + //! @brief Creates the text editor used by label when it's edited. + virtual juce::TextEditor* createdTextEditor() = 0; - //! @brief Paints elements over the text editor. - void paintOverChildren (juce::Graphics& g) override final; + //! @brief Called when the label text has changed before calling observers. + virtual void textChanged() = 0; //! @brief Called when the label text has changed. + //! @details Overrides juce::Label::labelTextChanged. void labelTextChanged (juce::Label* label) override final; //! @brief Called when edition ends. + //! @details Overrides juce::Label::editorHidden. void editorHidden (juce::Label* label, juce::TextEditor& text_editor) override final; //! @brief Called when edition begins. + //! @details Overrides juce::Label::editorShown. void editorShown(juce::Label* label, juce::TextEditor& text_editor) override final; private: // members - Label m_label; - tool::Listeners m_listeners; + Label m_label; + tool::Listeners m_listeners; private: // deleted methods - ClassicView() = delete; - ClassicView(ClassicView const& other) = delete; - ClassicView(ClassicView && other) = delete; - ClassicView& operator=(ClassicView const& other) = delete; - ClassicView& operator=(ClassicView && other) = delete; + EditableObjectView() = delete; + EditableObjectView(EditableObjectView const& other) = delete; + EditableObjectView(EditableObjectView && other) = delete; + EditableObjectView& operator=(EditableObjectView const& other) = delete; + EditableObjectView& operator=(EditableObjectView && other) = delete; }; } diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Dsp/KiwiApp_MeterTildeView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_MeterTildeView.cpp similarity index 80% rename from Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Dsp/KiwiApp_MeterTildeView.cpp rename to Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_MeterTildeView.cpp index 6535bfcd..f08342af 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Dsp/KiwiApp_MeterTildeView.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_MeterTildeView.cpp @@ -22,13 +22,10 @@ #include #include -#include +#include -#include - -#include - -#include +#include +#include namespace kiwi { @@ -36,32 +33,15 @@ namespace kiwi // METER~ VIEW // // ================================================================================ // - class MeterTildeView::Task : public tool::Scheduler<>::Task + void MeterTildeView::declare() { - public: // methods - - Task(MeterTildeView & meter, float peak_value): - m_meter(meter), - m_peak_value(peak_value) - { - } - - ~Task() - { - } - - void execute() override final - { - float peak_db = 20 * log10(m_peak_value); - m_meter.computeActiveLed(peak_db); - m_meter.repaint(); - } - - private: // members - - MeterTildeView & m_meter; - float m_peak_value; - }; + Factory::add("meter~", &MeterTildeView::create); + } + + std::unique_ptr MeterTildeView::create(model::Object & model) + { + return std::make_unique(model); + } MeterTildeView::MeterTildeView(model::Object & object_model): ObjectView(object_model), @@ -72,8 +52,7 @@ namespace kiwi m_border(5), m_padding(1), m_connection(object_model.getSignal(model::MeterTilde::Signal::PeakChanged) - .connect(std::bind(&MeterTildeView::peakChanged, this, std::placeholders::_1))), - m_tasks(10) + .connect(std::bind(&MeterTildeView::peakChanged, this, std::placeholders::_1))) { size_t num_leds = 12; @@ -89,12 +68,6 @@ namespace kiwi MeterTildeView::~MeterTildeView() { - while(m_tasks.load_size() > 0) - { - std::shared_ptr task; - m_tasks.pop(task); - KiwiApp::useInstance().useScheduler().unschedule(task); - } } void MeterTildeView::resized() @@ -157,9 +130,12 @@ namespace kiwi void MeterTildeView::peakChanged(float new_peak) { - std::shared_ptr task(new Task(*this, new_peak)); - m_tasks.push(task); - KiwiApp::useInstance().useScheduler().schedule(task); + defer([this, new_peak]() + { + float peak_db = 20 * log10(new_peak); + computeActiveLed(peak_db); + repaint(); + }); } void MeterTildeView::paint(juce::Graphics & g) diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Dsp/KiwiApp_MeterTildeView.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_MeterTildeView.h similarity index 79% rename from Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Dsp/KiwiApp_MeterTildeView.h rename to Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_MeterTildeView.h index 1a89a0f7..30cc5294 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Dsp/KiwiApp_MeterTildeView.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_MeterTildeView.h @@ -23,18 +23,12 @@ #include -#include - #include -#include - -#include - #include -namespace kiwi -{ +namespace kiwi { + // ================================================================================ // // METER~ VIEW // // ================================================================================ // @@ -43,8 +37,6 @@ namespace kiwi { private: // classes - class Task; - struct Led { float m_min_db; @@ -54,30 +46,24 @@ namespace kiwi public: // methods - //! @brief Constructor. + static void declare(); + + static std::unique_ptr create(model::Object & model); + MeterTildeView(model::Object & object_model); - //! @brief Destructor. ~MeterTildeView(); private: // methods - //! @brief Recomputes leds bounds void resized() override final; - //! @brief The graphical rendering methods void paint(juce::Graphics & g) override final; - //! @brief The reaction to a change of peak value. - //! @details Update the display value and call repaint. void peakChanged(float new_peak); - //! @brief Computes the interpolation between the cold and warm colour. - //! @details Interpolation value must be between 0 and 1. juce::Colour computeGradientColour(float delta) const; - //! @brief Computes and updates the active led. - //! @details Peak value is given in db. void computeActiveLed(float peak_db); private: // members @@ -89,7 +75,6 @@ namespace kiwi int m_border; int m_padding; flip::SignalConnection m_connection; - tool::ConcurrentQueue> m_tasks; private: // deleted methods diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.cpp index 033bd511..09663d7e 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.cpp @@ -24,6 +24,7 @@ #include #include +#include namespace kiwi { @@ -228,20 +229,6 @@ namespace kiwi return getPatcherView().isSelected(*this); } - bool ObjectFrame::isEditing() const - { - bool is_editing = false; - - ClassicView * classic_view = dynamic_cast(m_object_view.get()); - - if (classic_view != nullptr) - { - is_editing = classic_view->isEditing(); - } - - return is_editing; - } - std::set ObjectFrame::getDistantSelection() const { return getPatcherView().getDistantSelection(*this); @@ -278,11 +265,21 @@ namespace kiwi } } + void ObjectFrame::attributeChanged(std::string const& name, tool::Parameter const& parameter) + { + m_object_view->modelAttributeChanged(name, parameter); + } + void ObjectFrame::textChanged(std::string const& new_text) { - dynamic_cast(m_object_view.get())->removeListener(*this); + dynamic_cast(m_object_view.get())->removeListener(*this); + + ClassicView * object_view = dynamic_cast(m_object_view.get()); - getPatcherView().objectTextChanged(*this, new_text); + if (object_view) + { + getPatcherView().objectTextChanged(*this, new_text); + } } void ObjectFrame::editorHidden() @@ -301,7 +298,7 @@ namespace kiwi void ObjectFrame::editObject() { - ClassicView * object_view = dynamic_cast(m_object_view.get()); + EditableObjectView * object_view = dynamic_cast(m_object_view.get()); if (object_view != nullptr) { diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.h index 892df45e..fd34e2b7 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectFrame.h @@ -28,7 +28,7 @@ #include -#include +#include #include namespace kiwi @@ -41,7 +41,7 @@ namespace kiwi //! @details ObjectFrame is implemented as a wrapper around an object view that displays //! selections and outlet and handle certain interactions. class ObjectFrame : public juce::Component, - public ClassicView::Listener + public EditableObjectView::Listener { public: // classes @@ -133,6 +133,9 @@ namespace kiwi //! @brief Called whenever an object's model has changed. void objectChanged(model::Patcher::View& view, model::Object& object); + + //! @brief Updates the inner object's view attributes. + void attributeChanged(std::string const& name, tool::Parameter const& parameter); //! @brief Called whenever the client wants to edit an object. //! @details Will only edit the object if its a textual object. @@ -172,9 +175,6 @@ namespace kiwi //! @brief Returns true if the object is selected. bool isSelected() const; - //! @brief Returns true if the underlying object is currently being edited. - bool isEditing() const; - //! @brief Called when object's frame is clicked. void mouseDown(juce::MouseEvent const& e) override final; diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectView.cpp index 0edbd442..7bb3b490 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectView.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectView.cpp @@ -21,9 +21,12 @@ #include +#include #include #include +#include + namespace kiwi { // ================================================================================ // @@ -32,8 +35,11 @@ namespace kiwi ObjectView::ObjectView(model::Object & object_model): m_model(object_model), - m_border_size(1.5) + m_border_size(1.5), + m_tasks() { + object_model.addListener(*this); + setColour(ObjectView::ColourIds::Error, juce::Colour::fromFloatRGBA(0.6, 0.1, 0.1, 0.)); setColour(ObjectView::ColourIds::Background, juce::Colours::white); setColour(ObjectView::ColourIds::Text, juce::Colours::black); @@ -43,6 +49,44 @@ namespace kiwi } ObjectView::~ObjectView() + { + for (auto task : m_tasks) + { + getScheduler().unschedule(task); + } + + getModel().removeListener(*this); + } + + void ObjectView::setAttribute(std::string const& name, tool::Parameter const& parameter) + { + model::Object & object_model = getModel(); + + object_model.setAttribute(name, parameter); + + model::DocumentManager::commit(object_model); + } + + void ObjectView::setParameter(std::string const& name, tool::Parameter const& parameter) + { + getModel().setParameter(name, parameter); + } + + void ObjectView::modelAttributeChanged(std::string const& name, tool::Parameter const& param) + { + attributeChanged(name, param); + } + + void ObjectView::modelParameterChanged(std::string const& name, tool::Parameter const& param) + { + parameterChanged(name, param); + } + + void ObjectView::attributeChanged(std::string const& name, tool::Parameter const& param) + { + } + + void ObjectView::parameterChanged(std::string const& name, tool::Parameter const& param) { } @@ -62,4 +106,76 @@ namespace kiwi g.drawRect(getOutline(), m_border_size); } + + // ================================================================================ // + // SCHEDULER // + // ================================================================================ // + + tool::Scheduler<> & ObjectView::getScheduler() const + { + return KiwiApp::useInstance().useScheduler(); + } + + void ObjectView::defer(std::function call_back) + { + removeTasks(m_tasks); + + std::shared_ptr task(new Task(call_back)); + + m_tasks.insert(task); + + getScheduler().defer(task); + } + + void ObjectView::schedule(std::function call_back, tool::Scheduler<>::duration_t delay) + { + removeTasks(m_tasks); + + std::shared_ptr task(new Task(call_back)); + + m_tasks.insert(task); + + getScheduler().schedule(task, delay); + } + + void ObjectView::removeTasks(std::set> & tasks) + { + for (auto task_it = m_tasks.begin(); task_it != m_tasks.end(); ) + { + if ((*task_it)->executed() == true) + { + task_it = m_tasks.erase(task_it); + } + else + { + ++task_it; + } + } + } + + // ================================================================================ // + // TASK // + // ================================================================================ // + + ObjectView::Task::Task(std::function callback): + m_callback(callback), + m_executed(false) + { + } + + ObjectView::Task::~Task() + { + } + + void ObjectView::Task::execute() + { + m_callback(); + + m_executed.store(true); + } + + bool ObjectView::Task::executed() const + { + return m_executed.load(); + } } diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectView.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectView.h index 217c381b..467b4914 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectView.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectView.h @@ -21,8 +21,13 @@ #pragma once +#include + #include +#include +#include + #include namespace kiwi @@ -34,7 +39,7 @@ namespace kiwi // ================================================================================ // //! @brief Abstract for objects graphical representation. - class ObjectView : public juce::Component + class ObjectView : public juce::Component, public model::Object::Listener { public: // classes @@ -48,6 +53,27 @@ namespace kiwi Active = 0x1100009 }; + private: // classes + + //! @brief A generic task that call an std::function. + class Task : public tool::Scheduler<>::Task + { + public: // methods + + Task(std::function callback); + + ~Task(); + + void execute() override final; + + bool executed() const; + + private: // members + + std::function m_callback; + std::atomic m_executed; + }; + public: // methods //! @brief Constructor. @@ -59,22 +85,54 @@ namespace kiwi //! @brief Returns the model represented by the graphical object. model::Object& getModel() const; + //! @brief Called when one of the model's attributes has changed. + void modelAttributeChanged(std::string const& name, tool::Parameter const& param) override final; + + //! @brief Called when a parameter has changed. + void modelParameterChanged(std::string const& name, tool::Parameter const& param) override final; + protected: // methods + //! @biref Returns the main scheduler. + tool::Scheduler<> & getScheduler() const; + + //! @brief Defers a task on the main thread. + //! @details The task is automatically unscheduled when object is destroyed. + void defer(std::function call_back); + + //! @brief Schedules a task on the main thread. + //! @details The tasks is automatically unscheduled when object is destroyed. + void schedule(std::function call_back, tool::Scheduler<>::duration_t delay); + //! @brief Draws the outlines of the object. void drawOutline(juce::Graphics & g); + //! @brief Changes one of the data model's attribute. + void setAttribute(std::string const& name, tool::Parameter const& param); + + //! @brief Changes one of the data model's parameter. + void setParameter(std::string const& name, tool::Parameter const& param); + private: // methods + void removeTasks(std::set> & tasks); + //! @brief Override this function if you want it to have a customied outline. //! @details Used to draw the object's outline. Returns the object's bounds by default. //! @todo May make it return path instead. virtual juce::Rectangle getOutline() const; + //! @brief Called once one of the data model's attributes has changed. + virtual void attributeChanged(std::string const& name, tool::Parameter const& param); + + //! @brief Called once the data model's parameters has changed. + virtual void parameterChanged(std::string const& name, tool::Parameter const& param); + private: // members - model::Object& m_model; - int m_border_size; + model::Object& m_model; + int m_border_size; + std::set> m_tasks; private: // deleted methods diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Objects.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Objects.h index 12fe0fc9..17abea8c 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Objects.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Objects.h @@ -21,22 +21,8 @@ #pragma once -// ================================================================================ // -// BASIC OBJECTS // -// ================================================================================ // - -#include - -// ================================================================================ // -// CONTROLLER OBJECTS // -// ================================================================================ // - -#include -#include -#include - -// ================================================================================ // -// DSP OBJECTS // -// ================================================================================ // - -#include +#include +#include +#include +#include +#include diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_SliderView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_SliderView.cpp similarity index 66% rename from Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_SliderView.cpp rename to Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_SliderView.cpp index 0559adf3..77125229 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_SliderView.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_SliderView.cpp @@ -23,12 +23,11 @@ #include -#include - #include #include -#include +#include +#include namespace kiwi { @@ -36,43 +35,10 @@ namespace kiwi // SLIDER VIEW // // ================================================================================ // - class SliderView::Task final : public tool::Scheduler<>::Task - { - public: // methods - - Task(SliderView & object, double new_value): - tool::Scheduler<>::Task(), - m_object(object), - m_new_value(new_value) - { - } - - ~Task() - { - } - - void execute() - { - m_object.m_slider.setValue(m_new_value, juce::NotificationType::dontSendNotification); - m_object.repaint(); - - std::shared_ptr task; - m_object.m_tasks.pop(task); - } - - private: // members - - SliderView & m_object; - double m_new_value; - }; - SliderView::SliderView(model::Object & object_model): ObjectView(object_model), - m_slider(juce::Slider::SliderStyle::LinearVertical, juce::Slider::TextEntryBoxPosition::NoTextBox), - m_signal(object_model.getSignal(model::Slider::Signal::ValueChanged)), - m_connection(m_signal.connect(std::bind(&SliderView::valueChanged, this, std::placeholders::_1))), - m_tasks(100) - { + m_slider(juce::Slider::SliderStyle::LinearVertical, juce::Slider::TextEntryBoxPosition::NoTextBox) + { m_slider.setColour(juce::Slider::ColourIds::backgroundColourId, findColour(ObjectView::ColourIds::Outline)); @@ -93,16 +59,19 @@ namespace kiwi SliderView::~SliderView() { - while(m_tasks.load_size() > 0) - { - std::shared_ptr task; - m_tasks.pop(task); - KiwiApp::useInstance().useScheduler().unschedule(task); - } - m_slider.removeListener(this); } + void SliderView::declare() + { + Factory::add("slider", &SliderView::create); + } + + std::unique_ptr SliderView::create(model::Object & object_model) + { + return std::make_unique(object_model); + } + void SliderView::paint(juce::Graphics & g) { g.setColour(findColour(ObjectView::ColourIds::Background)); @@ -129,7 +98,7 @@ namespace kiwi void SliderView::sliderValueChanged(juce::Slider * slider) { - m_signal(slider->getValue()); + setParameter("value", tool::Parameter(tool::Parameter::Type::Float, {slider->getValue()})); } void SliderView::resized() @@ -143,14 +112,17 @@ namespace kiwi { m_slider.setSliderStyle(juce::Slider::SliderStyle::LinearVertical); } - + m_slider.setBounds(getLocalBounds()); } - void SliderView::valueChanged(double new_value) + void SliderView::parameterChanged(std::string const& name, tool::Parameter const& parameter) { - std::shared_ptr task(new Task(*this, new_value)); - m_tasks.push(task); - KiwiApp::useInstance().useScheduler().schedule(task); + if (name == "value") + { + m_slider.setValue(parameter[0].getFloat(), + juce::NotificationType::dontSendNotification); + repaint(); + } } } diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_SliderView.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_SliderView.h similarity index 86% rename from Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_SliderView.h rename to Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_SliderView.h index dfa6b315..931cbeb8 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_SliderView.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_SliderView.h @@ -21,9 +21,9 @@ #pragma once -#include +#include -#include +#include #include @@ -45,6 +45,10 @@ namespace kiwi ~SliderView(); + static void declare(); + + static std::unique_ptr create(model::Object & object); + private: // methods void sliderValueChanged(juce::Slider * slider) override final; @@ -59,14 +63,13 @@ namespace kiwi void resized() override final; + void parameterChanged(std::string const& name, tool::Parameter const& parameter) override final; + void valueChanged(double new_value); private: // members - juce::Slider m_slider; - flip::Signal & m_signal; - flip::SignalConnection m_connection; - tool::ConcurrentQueue> m_tasks; + juce::Slider m_slider; private: // delted methods diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_ToggleView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ToggleView.cpp similarity index 51% rename from Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_ToggleView.cpp rename to Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ToggleView.cpp index 7fa610d6..7ceac3bf 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_ToggleView.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ToggleView.cpp @@ -19,101 +19,49 @@ ============================================================================== */ -#include -#include +#include +#include -#include - -#include - -#include - -namespace kiwi -{ +namespace kiwi { + // ================================================================================ // // TOGGLE VIEW // // ================================================================================ // - class ToggleView::Task final : public tool::Scheduler<>::Task + void ToggleView::declare() { - public: // methods - - Task(ToggleView & object, model::Toggle::Request request): - tool::Scheduler<>::Task(), - m_object(object), - m_request(request) - { - } - - ~Task() - { - } - - void execute() - { - switch(m_request) - { - case model::Toggle::Request::Switch: - { - m_object.m_is_on = !m_object.m_is_on; - break; - } - case model::Toggle::Request::SwitchOn: - { - m_object.m_is_on = true; - break; - } - case model::Toggle::Request::SwitchOff: - { - m_object.m_is_on = false; - break; - } - } - - m_object.repaint(); - - std::shared_ptr task; - m_object.m_tasks.pop(task); - } - - private: // members - - ToggleView & m_object; - model::Toggle::Request m_request; - }; + Factory::add("toggle", &ToggleView::create); + } + + std::unique_ptr ToggleView::create(model::Object & model) + { + return std::make_unique(model); + } ToggleView::ToggleView(model::Object & model): ObjectView(model), - m_signal(model.getSignal(model::Toggle::Signal::Switch)), - m_connection(m_signal.connect(std::bind(&ToggleView::toggleSwitched, - this, - std::placeholders::_1, - std::placeholders::_2))), - m_is_on(false), - m_tasks(10) + m_signal(model.getSignal<>(model::Toggle::Signal::OutputValue)), + m_is_on(false) { } ToggleView::~ToggleView() { - while(m_tasks.load_size() > 0) - { - std::shared_ptr task; - m_tasks.pop(task); - KiwiApp::useInstance().useScheduler().unschedule(task); - } } void ToggleView::mouseDown(juce::MouseEvent const& e) { - m_signal(model::Toggle::Request::Switch, true); + setParameter("value", tool::Parameter(tool::Parameter::Type::Int, {!m_is_on})); + m_signal(); } - void ToggleView::toggleSwitched(model::Toggle::Request request, bool shall_request) + void ToggleView::parameterChanged(std::string const& name, tool::Parameter const& param) { - std::shared_ptr task(new Task(*this, request)); - m_tasks.push(task); - KiwiApp::useInstance().useScheduler().schedule(task); + if (name == "value") + { + m_is_on = static_cast(param[0].getInt()); + repaint(); + } } void ToggleView::paint(juce::Graphics & g) diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_ToggleView.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ToggleView.h similarity index 64% rename from Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_ToggleView.h rename to Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ToggleView.h index 135a2cbf..8b03c1b6 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Controller/KiwiApp_ToggleView.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ToggleView.h @@ -21,57 +21,38 @@ #pragma once -#include -#include - -#include - -#include -#include - -#include -#include - #include -namespace kiwi -{ +namespace kiwi { + // ================================================================================ // // TOGGLE VIEW // // ================================================================================ // class ToggleView : public ObjectView { - private: // classes + public: // methods - class Task; + static void declare(); - public: // methods + static std::unique_ptr create(model::Object & model); - //! @brief Constructor. ToggleView(model::Object & object_model); - //! @brief Destructor. ~ToggleView(); private: // methods - //! @brief The graphical rendering method. void paint(juce::Graphics & g) override final; - //! @brief Called when the bang is clicked. void mouseDown(juce::MouseEvent const& e) override final; - //! @brief Called whenever the toggle is switched on or off. - //! @details Can ba called on the engine thread or the gui thread. - void toggleSwitched(model::Toggle::Request request, bool shall_ouptut); + void parameterChanged(std::string const& name, tool::Parameter const& param) override final; private: // members - flip::Signal & m_signal; - flip::SignalConnection m_connection; - bool m_is_on; - tool::ConcurrentQueue> m_tasks; + flip::Signal<> & m_signal; + bool m_is_on; private: // deleted methods diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.cpp index ec39e751..7884c7f1 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.cpp @@ -475,12 +475,10 @@ namespace kiwi std::unique_lock lock(m_instance.useEngineInstance().getScheduler().lock()); patcher.entity().emplace(patcher.document()); - patcher.entity().emplace(m_instance.useEngineInstance()); + patcher.entity().emplace(m_instance.useEngineInstance(), patcher); } - { - std::unique_lock lock(m_instance.useEngineInstance().getScheduler().lock()); - + { patcher.entity().use().modelChanged(patcher); } diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp index 0c150091..8ccc4eb0 100755 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp @@ -19,7 +19,6 @@ ============================================================================== */ -#include #include #include @@ -1071,6 +1070,8 @@ namespace kiwi } } + updateParameters(patcher); + if(view.removed()) {} if(patcher.resident() && (patcher.objectsChanged() || patcher.linksChanged())) @@ -1079,6 +1080,28 @@ namespace kiwi } } + void PatcherView::updateParameters(model::Patcher const& patcher_model) + { + if (patcher_model.objectsChanged()) + { + for(auto const & object : patcher_model.getObjects()) + { + if (!object.removed() && !object.added()) + { + std::set changed_params = object.getChangedAttributes(); + + auto object_frame = findObject(object); + + for (std::string const& param_name : changed_params) + { + (*object_frame)->attributeChanged(param_name, + object.getAttribute(param_name)); + } + } + } + } + } + void PatcherView::updateWindowTitle() const { PatcherViewWindow* window = findParentComponentOfClass(); @@ -1566,7 +1589,7 @@ namespace kiwi KiwiApp::error(error_box.getError()); } - if (!object_model->hasFlag(model::Flag::IFlag::DefinedSize)) + if (!object_model->hasFlag(model::ObjectClass::Flag::DefinedSize)) { const int text_width = juce::Font().getStringWidth(new_text) + 12; const int max_io = std::max(object_model->getNumberOfInlets(), diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.h b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.h index a0f4a28c..cac8e7c6 100755 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.h @@ -185,6 +185,9 @@ namespace kiwi //! @internal Object model is resident and internal value changed. void objectChanged(model::Patcher::View& view, model::Object& object); + //! @internal Updates the object's view parameters. + void updateParameters(model::Patcher const& patcher); + //! @internal Object model will be removed from the document. void removeObjectView(model::Object& object); diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewMouseHandler.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewMouseHandler.cpp index 3f31829e..3f74ffbd 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewMouseHandler.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewMouseHandler.cpp @@ -220,7 +220,7 @@ namespace kiwi { juce::ComponentBoundsConstrainer bounds_constrainer; - if (!object_model.hasFlag(model::Flag::IFlag::ResizeWidth)) + if (!object_model.hasFlag(model::ObjectClass::Flag::ResizeWidth)) { bounds_constrainer.setMinimumWidth(object_model.getWidth()); bounds_constrainer.setMaximumWidth(object_model.getWidth()); @@ -230,7 +230,7 @@ namespace kiwi bounds_constrainer.setMinimumWidth(object_model.getMinWidth()); } - if (!object_model.hasFlag(model::Flag::IFlag::ResizeHeight)) + if (!object_model.hasFlag(model::ObjectClass::Flag::ResizeHeight)) { bounds_constrainer.setMinimumHeight(object_model.getHeight()); bounds_constrainer.setMaximumHeight(object_model.getHeight()); @@ -678,22 +678,22 @@ namespace kiwi model::Object const& object_model = hit_tester.getObject()->getModel(); - if ((border & HitTester::Border::Top) && object_model.hasFlag(model::Flag::IFlag::ResizeHeight)) + if ((border & HitTester::Border::Top) && object_model.hasFlag(model::ObjectClass::Flag::ResizeHeight)) { direction |= Direction::Up; } - if ((border & HitTester::Border::Right) && object_model.hasFlag(model::Flag::IFlag::ResizeWidth)) + if ((border & HitTester::Border::Right) && object_model.hasFlag(model::ObjectClass::Flag::ResizeWidth)) { direction |= Direction::Right; } - if ((border & HitTester::Border::Bottom) && object_model.hasFlag(model::Flag::IFlag::ResizeHeight)) + if ((border & HitTester::Border::Bottom) && object_model.hasFlag(model::ObjectClass::Flag::ResizeHeight)) { direction |= Direction::Down; } - if ((border & HitTester::Border::Left) && object_model.hasFlag(model::Flag::IFlag::ResizeWidth)) + if ((border & HitTester::Border::Left) && object_model.hasFlag(model::ObjectClass::Flag::ResizeWidth)) { direction |= Direction::Left; } diff --git a/Modules/KiwiEngine/KiwiEngine_Factory.cpp b/Modules/KiwiEngine/KiwiEngine_Factory.cpp index 7ec0d666..cfe9d548 100644 --- a/Modules/KiwiEngine/KiwiEngine_Factory.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Factory.cpp @@ -32,30 +32,17 @@ namespace kiwi // FACTORY // // ================================================================================ // + std::map Factory::m_creators; + std::unique_ptr Factory::create(Patcher& patcher, model::Object const& model) { - std::vector args; - - if (!model.getText().empty()) - { - std::vector parsed_text = tool::AtomHelper::parse(model.getText()); - args.insert(args.begin(), parsed_text.begin() + 1, parsed_text.end()); - } - - auto& creators = getCreators(); - assert(creators.count(model.getName()) != 0 && "The object has not been registered."); - return std::unique_ptr(creators[model.getName()](model, patcher, args)); + assert(m_creators.count(model.getName()) != 0 && "The object has not been registered."); + return m_creators[model.getName()](model, patcher); } bool Factory::has(std::string const& name) { - return static_cast(getCreators().count(name)); - } - - auto Factory::getCreators() -> creator_map_t& - { - static creator_map_t static_creators; - return static_creators; + return static_cast(m_creators.count(name)); } bool Factory::modelHasObject(std::string const& name) diff --git a/Modules/KiwiEngine/KiwiEngine_Factory.h b/Modules/KiwiEngine/KiwiEngine_Factory.h index 9d60393b..ceeb684c 100644 --- a/Modules/KiwiEngine/KiwiEngine_Factory.h +++ b/Modules/KiwiEngine/KiwiEngine_Factory.h @@ -21,6 +21,11 @@ #pragma once +#include +#include +#include +#include + #include namespace kiwi @@ -34,6 +39,10 @@ namespace kiwi //! @brief The engine Object's factory class Factory { + public: // classes + + using ctor_fn_t = std::function(model::Object const& model, Patcher& patcher)>; + public: // methods //! @brief Adds an object engine into the Factory. @@ -44,27 +53,21 @@ namespace kiwi template ::value, Object>::type* = nullptr> - static void add(std::string const& name) + static void add(std::string const& name, ctor_fn_t create_method) { static_assert(!std::is_abstract::value, "The engine object must not be abstract."); static_assert(std::is_constructible const&>::value, + model::Object const&, Patcher&>::value, "The engine object must have a valid constructor."); assert(!name.empty()); assert(modelHasObject(name) && "The model counterpart does not exist"); - auto& creators = getCreators(); - assert(creators.count(name) == 0 && "The object already exists"); + assert(m_creators.count(name) == 0 && "The object already exists"); - creators[name] = [](model::Object const& model, - Patcher& patcher, - std::vector const& args) -> TEngine* - { - return new TEngine(model, patcher, args); - }; + m_creators[name] = create_method; } //! @brief Creates a new engine Object. @@ -80,15 +83,8 @@ namespace kiwi private: // methods static bool modelHasObject(std::string const& name); - - using ctor_fn_t = std::function const&)>; - - using creator_map_t = std::map; - //! @internal Returns the static map of creators. - static creator_map_t& getCreators(); + static std::map m_creators; private: // deleted methods diff --git a/Modules/KiwiEngine/KiwiEngine_Instance.cpp b/Modules/KiwiEngine/KiwiEngine_Instance.cpp index 0e11583d..080b7bc3 100644 --- a/Modules/KiwiEngine/KiwiEngine_Instance.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Instance.cpp @@ -20,7 +20,6 @@ */ #include "KiwiEngine_Factory.h" -#include #include "KiwiEngine_Instance.h" namespace kiwi @@ -31,13 +30,13 @@ namespace kiwi // INSTANCE // // ================================================================================ // - Instance::Instance(std::unique_ptr audio_controler): + Instance::Instance(std::unique_ptr audio_controler, tool::Scheduler<> & main_scheduler): m_audio_controler(std::move(audio_controler)), m_scheduler(), + m_main_scheduler(main_scheduler), m_quit(false), m_engine_thread(std::bind(&Instance::processScheduler, this)) { - addObjectsToFactory(); } Instance::~Instance() @@ -80,31 +79,6 @@ namespace kiwi m_console.removeListener(listener); } - void Instance::addObjectsToFactory() - { - engine::Factory::add("newbox"); - engine::Factory::add("errorbox"); - engine::Factory::add("plus"); - engine::Factory::add("times"); - engine::Factory::add("print"); - engine::Factory::add("receive"); - engine::Factory::add("loadmess"); - engine::Factory::add("delay"); - engine::Factory::add("pipe"); - engine::Factory::add("metro"); - engine::Factory::add("osc~"); - engine::Factory::add("adc~"); - engine::Factory::add("dac~"); - engine::Factory::add("times~"); - engine::Factory::add("plus~"); - engine::Factory::add("sig~"); - engine::Factory::add("delaysimple~"); - engine::Factory::add("bang"); - engine::Factory::add("toggle"); - engine::Factory::add("slider"); - engine::Factory::add("meter~"); - } - // ================================================================================ // // AUDIO CONTROLER // // ================================================================================ // @@ -123,6 +97,11 @@ namespace kiwi return m_scheduler; } + tool::Scheduler<> & Instance::getMainScheduler() + { + return m_main_scheduler; + } + void Instance::processScheduler() { m_scheduler.setThreadAsConsumer(); diff --git a/Modules/KiwiEngine/KiwiEngine_Instance.h b/Modules/KiwiEngine/KiwiEngine_Instance.h index 4d8c890a..97d4fd6d 100644 --- a/Modules/KiwiEngine/KiwiEngine_Instance.h +++ b/Modules/KiwiEngine/KiwiEngine_Instance.h @@ -48,7 +48,7 @@ namespace kiwi public: // methods //! @brief Constructs an Instance and adds the engine objects to the engine::Factory. - Instance(std::unique_ptr audio_controler); + Instance(std::unique_ptr audio_controler, tool::Scheduler<> & main_scheduler); //! @brief Destructor. ~Instance(); @@ -88,10 +88,10 @@ namespace kiwi //! @brief Returns the engine's scheduler. tool::Scheduler<> & getScheduler(); - private: // methods + //! @brief Returns the main's scheduler. + tool::Scheduler<> & getMainScheduler(); - //! @internal Adds the engine objects to the engine::Factory - void addObjectsToFactory(); + private: // methods //! @internal Processes the scheduler to check if new messages have been added. void processScheduler(); @@ -102,6 +102,7 @@ namespace kiwi std::unique_ptr m_audio_controler; tool::Scheduler<> m_scheduler; + tool::Scheduler<>& m_main_scheduler; std::atomic m_quit; std::thread m_engine_thread; diff --git a/Modules/KiwiEngine/KiwiEngine_Object.cpp b/Modules/KiwiEngine/KiwiEngine_Object.cpp index 9ad5ed88..74da9d62 100644 --- a/Modules/KiwiEngine/KiwiEngine_Object.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Object.cpp @@ -23,28 +23,38 @@ #include "KiwiEngine_Link.h" #include "KiwiEngine_Patcher.h" +#include #include namespace kiwi { namespace engine { + // ================================================================================ // // OBJECT // // ================================================================================ // Object::Object(model::Object const& model, Patcher& patcher) noexcept : m_patcher(patcher), + m_ref(model.ref()), m_inlets(model.getNumberOfInlets()), m_outlets(model.getNumberOfOutlets()), + m_tasks(), + m_main_tasks(), m_stack_count(0ul) { - ; + getObjectModel().addListener(*this); } Object::~Object() noexcept { - m_outlets.clear(); + for (auto task : m_tasks) + { + getScheduler().unschedule(task); + } + + getObjectModel().removeListener(*this); } void Object::addOutputLink(size_t outlet_index, Object & receiver, size_t inlet_index) @@ -57,6 +67,109 @@ namespace kiwi m_outlets[outlet_index].erase(Link(receiver, inlet_index)); } + // ================================================================================ // + // TASK // + // ================================================================================ // + + Object::Task::Task(std::function callback): + m_callback(callback), + m_executed(false) + { + } + + Object::Task::~Task() + { + } + + void Object::Task::execute() + { + m_callback(); + + m_executed.store(true); + } + + bool Object::Task::executed() const + { + return m_executed.load(); + } + + // ================================================================================ // + // PARMETERS // + // ================================================================================ // + + void Object::removeTasks(std::set> & tasks) + { + for (auto task_it = m_tasks.begin(); task_it != m_tasks.end(); ) + { + if ((*task_it)->executed() == true) + { + task_it = m_tasks.erase(task_it); + } + else + { + ++task_it; + } + } + } + + void Object::modelParameterChanged(std::string const& name, tool::Parameter const& parameter) + { + defer([this, name, parameter]() + { + parameterChanged(name, parameter); + }); + } + + void Object::modelAttributeChanged(std::string const& name, tool::Parameter const& parameter) + { + defer([this, name, parameter]() + { + attributeChanged(name, parameter); + }); + } + + model::Object & Object::getObjectModel() + { + flip::Array & objects = m_patcher.getPatcherModel().getObjects(); + + return *std::find_if(objects.begin(), objects.end(), [this](model::Object const & object_model) + { + return object_model.ref() == m_ref; + }); + } + + void Object::parameterChanged(std::string const& param_name, tool::Parameter const& param) + { + } + + void Object::attributeChanged(std::string const& name, tool::Parameter const& attribute) + { + } + + void Object::setAttribute(std::string const& name, tool::Parameter const& param) + { + deferMain([this, name, param]() + { + getObjectModel().setAttribute(name, param); + + model::DocumentManager::commit(getObjectModel()); + }); + } + + void Object::setParameter(std::string const& name, tool::Parameter const& param) + { + removeTasks(m_main_tasks); + + std::shared_ptr task(new Task([this, name, param]() + { + getObjectModel().setParameter(name, param); + })); + + m_main_tasks.insert(task); + + getMainScheduler().defer(task); + } + // ================================================================================ // // CONSOLE // // ================================================================================ // @@ -81,11 +194,64 @@ namespace kiwi m_patcher.error(text); } + // ================================================================================ // + // SCHEDULER // + // ================================================================================ // + tool::Scheduler<> & Object::getScheduler() const { return m_patcher.getScheduler(); } + tool::Scheduler<> & Object::getMainScheduler() const + { + return m_patcher.getMainScheduler(); + } + + void Object::defer(std::function call_back) + { + removeTasks(m_tasks); + + std::shared_ptr task(new Task(call_back)); + + m_tasks.insert(task); + + getScheduler().defer(task); + } + + void Object::deferMain(std::function call_back) + { + removeTasks(m_main_tasks); + + std::shared_ptr task(new Task(call_back)); + + m_main_tasks.insert(task); + + getMainScheduler().defer(task); + } + + void Object::schedule(std::function call_back, tool::Scheduler<>::duration_t delay) + { + removeTasks(m_tasks); + + std::shared_ptr task(new Task(call_back)); + + m_tasks.insert(task); + + getScheduler().schedule(task, delay); + } + + void Object::scheduleMain(std::function call_back, tool::Scheduler<>::duration_t delay) + { + removeTasks(m_main_tasks); + + std::shared_ptr task(new Task(call_back)); + + m_main_tasks.insert(task); + + getMainScheduler().schedule(task, delay); + } + // ================================================================================ // // BEACON // // ================================================================================ // diff --git a/Modules/KiwiEngine/KiwiEngine_Object.h b/Modules/KiwiEngine/KiwiEngine_Object.h index 759a80c1..d1af4ff4 100644 --- a/Modules/KiwiEngine/KiwiEngine_Object.h +++ b/Modules/KiwiEngine/KiwiEngine_Object.h @@ -21,14 +21,24 @@ #pragma once -#include "KiwiEngine_Def.h" +#include +#include +#include +#include + +#include + +#include #include +#include #include #include +#include + namespace kiwi { namespace engine @@ -38,8 +48,30 @@ namespace kiwi // ================================================================================ // //! @brief The Object reacts and interacts with other ones by sending and receiving messages via its inlets and outlets. - class Object + class Object : public model::Object::Listener { + private: // classes + + //! @brief A generic task that call an std::function. + //! @details When executed + class Task : public tool::Scheduler<>::Task + { + public: // methods + + Task(std::function callback); + + ~Task(); + + void execute() override final; + + bool executed() const; + + private: // members + + std::function m_callback; + std::atomic m_executed; + }; + public: // methods //! @brief Constructor. @@ -62,6 +94,12 @@ namespace kiwi //! @internal Removes a Link from an outlet. void removeOutputLink(size_t outlet_index, Object & receiver, size_t inlet_index); + //! @brief Called when a parameter has changed. + void modelParameterChanged(std::string const& name, tool::Parameter const& parameter) override final; + + //! @brief Called when an attribute has changed. + void modelAttributeChanged(std::string const& name, tool::Parameter const& parameter) override final; + protected: // methods // ================================================================================ // @@ -87,6 +125,25 @@ namespace kiwi //! @biref Returns the engine's scheduler. tool::Scheduler<> & getScheduler() const; + //! @biref Returns the main scheduler. + tool::Scheduler<> & getMainScheduler() const; + + //! @brief Defers a task on the engine thread. + //! @details The task is automatically unscheduled when object is destroyed. + void defer(std::function call_back); + + //! @brief Defers a task on the main thread. + //! @details The tasks is automatically unscheduled when object is destroyed. + void deferMain(std::function call_back); + + //! @brief Schedules a task on the engine thread. + //! @details The tasks is automatically unscheduled when object is destroyed. + void schedule(std::function call_back, tool::Scheduler<>::duration_t delay); + + //! @brief Schedules a task on the main thread. + //! @details The tasks is automatically unscheduled when object is destroyed. + void scheduleMain(std::function call_back, tool::Scheduler<>::duration_t delay); + // ================================================================================ // // BEACON // // ================================================================================ // @@ -103,14 +160,41 @@ namespace kiwi //! @todo See if the method must be noexcept. void send(const size_t index, std::vector const& args); + //! @brief Changes one of the data model's attributes. + //! @details For thread safety actual model's modification is called on the main thread. + void setAttribute(std::string const& name, tool::Parameter const& parameter); + + //! @brief Changes one of the data model's parameter. + //! @details For thread safety actual model's modification is called on the main thread. + void setParameter(std::string const& name, tool::Parameter const& parameter); + + private: // methods + + //! @brief Returns the object's data model. + model::Object & getObjectModel(); + + //! @brief Called once the data model's parameters has changed. + //! @details Automatically called on the engine's thread. + virtual void parameterChanged(std::string const& param_name, tool::Parameter const& param); + + //! @brief Called once one of the data model's attributes has changed. + //! @brief Automatically called on the engine's thread. + virtual void attributeChanged(std::string const& name, tool::Parameter const& attribute); + + //! @brief Call this function to remove tasks already executed. + void removeTasks(std::set> & tasks); + private: // members using Outlet = std::set; - Patcher& m_patcher; - size_t m_inlets; - std::vector m_outlets; - size_t m_stack_count = 0ul; + Patcher& m_patcher; + flip::Ref const m_ref; + size_t m_inlets; + std::vector m_outlets; + std::set> m_tasks; + std::set> m_main_tasks; + size_t m_stack_count; private: // deleted methods diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_AdcTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_AdcTilde.cpp new file mode 100644 index 00000000..4b30ca6b --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_AdcTilde.cpp @@ -0,0 +1,59 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // ADC~ // + // ================================================================================ // + + void AdcTilde::declare() + { + Factory::add("adc~", &AdcTilde::create); + } + + std::unique_ptr AdcTilde::create(model::Object const& model, Patcher & patcher) + { + return std::make_unique(model, patcher); + } + + AdcTilde::AdcTilde(model::Object const& model, Patcher& patcher): + AudioInterfaceObject(model, patcher) + { + } + + void AdcTilde::perform(dsp::Buffer const& input, dsp::Buffer& output) noexcept + { + for (size_t outlet = 0; outlet < m_routes.size(); ++outlet) + { + m_audio_controler.getFromChannel(m_routes[outlet], output[outlet]); + } + } + + void AdcTilde::prepare(dsp::Processor::PrepareInfo const& infos) + { + setPerformCallBack(this, &AdcTilde::perform); + } + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Loadmess.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_AdcTilde.h similarity index 51% rename from Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Loadmess.cpp rename to Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_AdcTilde.h index 9bafc5cb..33227bb5 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Loadmess.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_AdcTilde.h @@ -19,32 +19,28 @@ ============================================================================== */ -#include +#pragma once -namespace kiwi -{ - namespace engine +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // ADC~ // + // ================================================================================ // + + class AdcTilde : public AudioInterfaceObject { - // ================================================================================ // - // OBJECT LOADMESS // - // ================================================================================ // + public: // methods - Loadmess::Loadmess(model::Object const& model, Patcher& patcher, std::vector const& args) - : Object(model, patcher), - m_args(args) - { - ; - } + static void declare(); - void Loadmess::receive(size_t, std::vector const& args) - { - send(0ul, m_args); - } + static std::unique_ptr create(model::Object const& model, Patcher & patcher); - void Loadmess::loadbang() - { - send(0ul, m_args); - } - } -} - + AdcTilde(model::Object const& model, Patcher& patcher); + + void perform(dsp::Buffer const& input, dsp::Buffer& output) noexcept; + + void prepare(dsp::Processor::PrepareInfo const& infos) override final; + }; +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_AudioInterface.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_AudioInterface.cpp new file mode 100644 index 00000000..c1c83b30 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_AudioInterface.cpp @@ -0,0 +1,92 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // AUDIOINTERFACE // + // ================================================================================ // + + AudioInterfaceObject::AudioInterfaceObject(model::Object const& model, + Patcher& patcher): + AudioObject(model, patcher), + m_audio_controler(patcher.getAudioControler()), + m_routes(parseArgs(model.getArguments())) + { + } + + std::vector AudioInterfaceObject::parseArgs(std::vector const& args) const + { + std::vector routes; + + for(tool::Atom const& arg : args) + { + if (arg.isNumber()) + { + routes.push_back(arg.getInt() - 1); + } + else if(arg.isString()) + { + std::string inputs(arg.getString()); + + int left_input = std::stoi(inputs.substr(0, inputs.find(":"))) - 1; + int right_input = std::stoi(inputs.substr(inputs.find(":") + 1)) - 1; + + bool rev = left_input > right_input; + + for (int channel = left_input; rev ? channel >= right_input : channel <= right_input; rev ? --channel : ++channel) + { + routes.push_back(channel); + } + } + } + + if (routes.empty()) + { + routes = {0, 1}; + } + + return routes; + } + + void AudioInterfaceObject::receive(size_t index, std::vector const & args) + { + if(!args.empty()) + { + if(args[0].isString()) + { + const std::string sym = args[0].getString(); + + if(sym == "start") + { + m_audio_controler.startAudio(); + } + else if(sym == "stop") + { + m_audio_controler.stopAudio(); + } + } + } + } + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_AudioInterface.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_AudioInterface.h new file mode 100644 index 00000000..de54d814 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_AudioInterface.h @@ -0,0 +1,51 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // AUDIO_INTERFACE // + // ================================================================================ // + + class AudioInterfaceObject : public AudioObject + { + public: // methods + + AudioInterfaceObject(model::Object const& model, Patcher& patcher); + + void receive(size_t index, std::vector const & args) override final; + + std::vector parseArgs(std::vector const& args) const; + + virtual ~AudioInterfaceObject() = default; + + protected: // members + + engine::AudioControler& m_audio_controler; + std::vector m_routes; + }; + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Bang.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Bang.cpp new file mode 100644 index 00000000..a0a98733 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Bang.cpp @@ -0,0 +1,71 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OBJECT BANG // + // ================================================================================ // + + void Bang::declare() + { + Factory::add("bang", &Bang::create); + } + + std::unique_ptr Bang::create(model::Object const& model, Patcher & patcher) + { + return std::make_unique(model, patcher); + } + + Bang::Bang(model::Object const& model, Patcher & patcher): + Object(model, patcher), + m_signal(model.getSignal<>(model::Bang::Signal::TriggerBang)), + m_connection(m_signal.connect(std::bind(&Bang::signalTriggered, this))) + { + } + + Bang::~Bang() + { + } + + void Bang::signalTriggered() + { + defer([this]() + { + send(0, {"bang"}); + }); + } + + void Bang::receive(size_t index, std::vector const& args) + { + if (index == 0) + { + m_signal(); + } + } + +}} + diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Bang.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Bang.h new file mode 100644 index 00000000..b2112019 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Bang.h @@ -0,0 +1,54 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OBJECT BANG // + // ================================================================================ // + + class Bang : public engine::Object + { + public: // methods + + static void declare(); + + static std::unique_ptr create(model::Object const& object, Patcher & patcher); + + Bang(model::Object const& model, Patcher& patcher); + + ~Bang(); + + void signalTriggered(); + + void receive(size_t index, std::vector const& args) override final; + + private: // members + + flip::Signal<> & m_signal; + flip::SignalConnection m_connection; + }; + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Basic/KiwiEngine_NewBox.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Basic/KiwiEngine_NewBox.cpp deleted file mode 100644 index 7420243e..00000000 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Basic/KiwiEngine_NewBox.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#include - -namespace kiwi -{ - namespace engine - { - // ================================================================================ // - // NEWBOX // - // ================================================================================ // - - NewBox::NewBox(model::Object const& model, Patcher& patcher, std::vector const& args) - : Object(model, patcher) - { - ; - } - - void NewBox::receive(size_t index, std::vector const& args) - { - ; - } - } -} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Bang.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Bang.cpp deleted file mode 100644 index 9c4e7c3b..00000000 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Bang.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#include - -#include -#include - -namespace kiwi -{ - namespace engine - { - // ================================================================================ // - // OBJECT BANG // - // ================================================================================ // - - class Bang::Task : public tool::Scheduler<>::Task - { - public: // methods - - Task(Bang & object): - m_object(object) - { - } - - ~Task() - { - } - - void execute() override final - { - m_object.send(0, {"bang"}); - } - - private: // members - - Bang & m_object; - }; - - Bang::Bang(model::Object const& model, Patcher& patcher, std::vector const& args): - Object(model, patcher), - m_task(new Task(*this)), - m_signal(model.getSignal<>(model::Bang::Signal::TriggerBang)), - m_connection(m_signal.connect(std::bind(&Bang::signalTriggered, this))) - { - } - - Bang::~Bang() - { - getScheduler().unschedule(m_task); - } - - void Bang::signalTriggered() - { - getScheduler().defer(m_task); - } - - void Bang::receive(size_t index, std::vector const& args) - { - if (index == 0) - { - m_signal(); - } - } - } -} - diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Bang.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Bang.h deleted file mode 100644 index fbf165eb..00000000 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Bang.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#pragma once - -#include -#include - -#include -#include - -#include - -namespace kiwi -{ - namespace engine - { - // ================================================================================ // - // OBJECT BANG // - // ================================================================================ // - - class Bang : public engine::Object - { - private: // classes - - class Task; - - public: // methods - - Bang(model::Object const& model, Patcher& patcher, std::vector const& args); - - ~Bang(); - - void signalTriggered(); - - void receive(size_t index, std::vector const& args) override final; - - private: // members - - std::shared_ptr m_task; - flip::Signal<> & m_signal; - flip::SignalConnection m_connection; - }; - } -} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Toggle.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Toggle.cpp deleted file mode 100644 index 6213130d..00000000 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Toggle.cpp +++ /dev/null @@ -1,165 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#include - -#include - -#include - -namespace kiwi -{ - namespace engine - { - // ================================================================================ // - // OBJECT BANG // - // ================================================================================ // - - class Toggle::Task final : public tool::Scheduler<>::Task - { - public: // methods - - Task(Toggle & object, model::Toggle::Request request, bool shall_output): - tool::Scheduler<>::Task(), - m_object(object), - m_request(request), - m_shall_output(shall_output) - { - } - - ~Task() - { - } - - void execute() - { - switch(m_request) - { - case model::Toggle::Request::Switch: - { - m_object.m_is_on = !m_object.m_is_on; - break; - } - case model::Toggle::Request::SwitchOn: - { - m_object.m_is_on = true; - break; - } - case model::Toggle::Request::SwitchOff: - { - m_object.m_is_on = false; - break; - } - } - - if (m_shall_output) - { - if (m_object.m_is_on) - { - m_object.send(0, {1}); - } - else - { - m_object.send(0, {0}); - } - } - - std::shared_ptr task; - m_object.m_tasks.pop(task); - } - - private: // members - - Toggle& m_object; - model::Toggle::Request m_request; - bool m_shall_output; - }; - - Toggle::Toggle(model::Object const& model, Patcher& patcher, std::vector const& args): - Object(model, patcher), - m_signal(model.getSignal(model::Toggle::Signal::Switch)), - m_connection(m_signal.connect(std::bind(&Toggle::toggleSwitched, - this, - std::placeholders::_1, - std::placeholders::_2))), - m_is_on(false), - m_tasks(20) - { - } - - Toggle::~Toggle() - { - while(m_tasks.load_size() > 0) - { - std::shared_ptr task; - m_tasks.pop(task); - getScheduler().unschedule(task); - } - } - - void Toggle::toggleSwitched(model::Toggle::Request request, bool shall_output) - { - std::shared_ptr task(new Task(*this, request, shall_output)); - m_tasks.push(task); - getScheduler().schedule(task); - } - - void Toggle::receive(size_t index, std::vector const& args) - { - if (!args.empty()) - { - if (index == 0) - { - if(args[0].isString()) - { - if (args[0].getString() == "bang") - { - m_signal(model::Toggle::Request::Switch, true); - } - else if(args.size() == 2 && args[0].getString() == "set" && args[1].isNumber()) - { - if (args[1].getFloat() != 0) - { - m_signal(model::Toggle::Request::SwitchOn, false); - } - else - { - m_signal(model::Toggle::Request::SwitchOff, false); - } - } - } - else if(args[0].isNumber()) - { - if (args[0].getFloat() != 0) - { - m_signal(model::Toggle::Request::SwitchOn, true); - } - else - { - m_signal(model::Toggle::Request::SwitchOff, true); - } - } - } - } - } - } -} - diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Toggle.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Toggle.h deleted file mode 100644 index 3261c4a2..00000000 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Toggle.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#pragma once - -#include -#include - -#include - -#include - -#include -#include - -#include - -namespace kiwi -{ - namespace engine - { - // ================================================================================ // - // OBJECT TOGGLE // - // ================================================================================ // - - class Toggle : public engine::Object - { - private: // classes - - class Task; - - public: // methods - - Toggle(model::Object const& model, Patcher& patcher, std::vector const& args); - - ~Toggle(); - - void receive(size_t index, std::vector const& args) override final; - - private: // methods - - void toggleSwitched(model::Toggle::Request request, bool shall_output); - - private: // members - - flip::Signal & m_signal; - flip::SignalConnection m_connection; - bool m_is_on; - tool::ConcurrentQueue> m_tasks; - }; - } -} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_DacTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_DacTilde.cpp new file mode 100644 index 00000000..71cabf5a --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_DacTilde.cpp @@ -0,0 +1,59 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // DAC~ // + // ================================================================================ // + + void DacTilde::declare() + { + Factory::add("dac~", &DacTilde::create); + } + + std::unique_ptr DacTilde::create(model::Object const& model, Patcher & patcher) + { + return std::make_unique(model, patcher); + } + + DacTilde::DacTilde(model::Object const& model, Patcher& patcher): + AudioInterfaceObject(model, patcher) + { + } + + void DacTilde::perform(dsp::Buffer const& input, dsp::Buffer& output) noexcept + { + for (size_t inlet = 0; inlet < m_routes.size(); ++inlet) + { + m_audio_controler.addToChannel(m_routes[inlet], input[inlet]); + } + } + + void DacTilde::prepare(dsp::Processor::PrepareInfo const& infos) + { + setPerformCallBack(this, &DacTilde::perform); + } + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_DacTilde.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_DacTilde.h new file mode 100644 index 00000000..cba044c8 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_DacTilde.h @@ -0,0 +1,46 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // DAC~ // + // ================================================================================ // + + class DacTilde : public AudioInterfaceObject + { + public: // methods + + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher & patcher); + + DacTilde(model::Object const& model, Patcher& patcher); + + void perform(dsp::Buffer const& input, dsp::Buffer& output) noexcept; + + void prepare(dsp::Processor::PrepareInfo const& infos) override final; + }; +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Delay.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Delay.cpp similarity index 76% rename from Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Delay.cpp rename to Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Delay.cpp index 1ec7ffea..90dbed2a 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Delay.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Delay.cpp @@ -19,7 +19,8 @@ ============================================================================== */ -#include +#include +#include namespace kiwi { @@ -29,22 +30,23 @@ namespace kiwi // OBJECT DELAY // // ================================================================================ // - Delay::Task::Task(Delay& object): - tool::Scheduler<>::Task(), - m_object(object) + void Delay::declare() { + Factory::add("delay", &Delay::create); } - void Delay::Task::execute() + std::unique_ptr Delay::create(model::Object const& object, Patcher & patcher) { - m_object.send(0, {"bang"}); + return std::make_unique(object, patcher); } - Delay::Delay(model::Object const& model, Patcher& patcher, std::vector const& args): + Delay::Delay(model::Object const& model, Patcher& patcher): Object(model, patcher), - m_task(new Task(*this)), + m_task(new tool::Scheduler<>::CallBack(std::bind(&Delay::bang, this))), m_delay(std::chrono::milliseconds(0)) { + std::vector const& args = model.getArguments(); + if (!args.empty()) { m_delay = std::chrono::milliseconds(args[0].getInt()); @@ -56,6 +58,11 @@ namespace kiwi getScheduler().unschedule(m_task); } + void Delay::bang() + { + send(0, {"bang"}); + } + void Delay::receive(size_t index, std::vector const& args) { if (!args.empty()) @@ -77,6 +84,10 @@ namespace kiwi { m_delay = std::chrono::milliseconds(args[0].getInt()); } + else + { + warning("delay inlet 2 doesn't understand [" + args[0].getString() + "]"); + } } } } diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Delay.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Delay.h new file mode 100644 index 00000000..5df10a03 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Delay.h @@ -0,0 +1,54 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OBJECT DELAY // + // ================================================================================ // + + class Delay final : public engine::Object + { + public: // methods + + static void declare(); + + static std::unique_ptr create(model::Object const& object, Patcher & patcher); + + Delay(model::Object const& model, Patcher& patcher); + + ~Delay(); + + void receive(size_t index, std::vector const& args) override; + + void bang(); + + private: // members + + std::shared_ptr::CallBack> m_task; + tool::Scheduler<>::clock_t::duration m_delay; + }; + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_DelaySimpleTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_DelaySimpleTilde.cpp new file mode 100644 index 00000000..edaa57f8 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_DelaySimpleTilde.cpp @@ -0,0 +1,274 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // DELAYSIMPLETILDE // + // ================================================================================ // + + void DelaySimpleTilde::declare() + { + Factory::add("delaysimple~", &DelaySimpleTilde::create); + } + + std::unique_ptr DelaySimpleTilde::create(model::Object const& model, Patcher & patcher) + { + return std::make_unique(model, patcher); + } + + DelaySimpleTilde::DelaySimpleTilde(model::Object const& model, Patcher& patcher): + AudioObject(model, patcher), + tool::Scheduler<>::Timer(patcher.getScheduler()), + m_circular_buffer(), + m_reinject_signal(), + m_max_delay(60.), + m_delay(1.), + m_reinject_level(0.), + m_sr(0.), + m_pool() + { + std::vector const& args = model.getArguments(); + + if (args.size() > 0) + { + m_delay = (args[0].getFloat() / 1000.); + } + + if (args.size() > 1) + { + m_reinject_level = std::max(0., std::min(args[1].getFloat(), 1.)); + } + + std::shared_ptr buffer(new CircularBuffer(0., 0., 0.)); + m_pool.add(buffer); + store(buffer); + + startTimer(std::chrono::milliseconds(1000)); + } + + DelaySimpleTilde::~DelaySimpleTilde() + { + stopTimer(); + timerCallBack(); + } + + void DelaySimpleTilde::timerCallBack() + { + m_pool.clear(); + } + + std::shared_ptr DelaySimpleTilde::load() + { + std::shared_ptr load_buffer; + + { + std::lock_guard lock(m_mutex); + load_buffer = m_circular_buffer; + } + + return load_buffer; + } + + void DelaySimpleTilde::store(std::shared_ptr new_buffer) + { + std::lock_guard lock(m_mutex); + m_circular_buffer = new_buffer; + } + + void DelaySimpleTilde::receive(size_t index, std::vector const& args) + { + if (index == 0 && args[0].isString()) + { + if (args[0].isString() && args[0].getString() == "clear") + { + std::shared_ptr new_buffer(new CircularBuffer(m_circular_buffer->size(), + m_circular_buffer->size(), + 0.)); + m_pool.add(new_buffer); + store(new_buffer); + } + else + { + warning("delaysimple~ inlet 1 doesn't understand + [" + args[0].getString() + "]"); + } + } + if (index == 1) + { + if (args[0].isNumber()) + { + m_delay.store(args[0].getFloat() / 1000.); + } + else + { + warning("delaysimple~ inlet 2 requires a number"); + } + } + else if(index == 2) + { + if (args[0].isNumber()) + { + m_reinject_level.store(std::max(0., std::min(1., args[0].getFloat()))); + } + else + { + warning("delaysimple~ inlet 3 requires a number"); + } + } + } + + dsp::sample_t DelaySimpleTilde::cubicInterpolate(float const& x, + float const& y0, + float const& y1, + float const& y2, + float const& y3) + { + return y1 + 0.5 * x * (y2 - y0 + x * (2.0 * y0 - 5.0 * y1 + 4.0 * y2 - y3 + + x * (3.0 * (y1 - y2) + y3 - y0))); + } + + void DelaySimpleTilde::perform(dsp::Buffer const& input, dsp::Buffer& output) noexcept + { + std::shared_ptr buffer = load(); + + size_t buffer_size = input[0].size(); + + for (int i = 0; i < buffer_size; ++i) + { + buffer->push_back(input[0][i] + m_reinject_signal->operator[](i)); + } + + float delay = std::max(1. / m_sr, std::min(m_delay.load(), m_max_delay)); + float offset = buffer->size() - (delay * m_sr) - (buffer_size - 1); + size_t offset_floor = std::floor(offset); + float decimal_part = offset - offset_floor; + + for(int i = 0; i < buffer_size; ++i) + { + output[0][i] = cubicInterpolate(decimal_part, + m_circular_buffer->operator[](offset_floor - 1), + m_circular_buffer->operator[](offset_floor), + m_circular_buffer->operator[](offset_floor + 1), + m_circular_buffer->operator[](offset_floor + 2)); + + m_reinject_signal->operator[](i) = m_reinject_level.load() * output[0][i]; + ++offset_floor; + } + } + + void DelaySimpleTilde::performDelay(dsp::Buffer const& input, dsp::Buffer& output) noexcept + { + std::shared_ptr buffer = load(); + + size_t buffer_size = input[0].size(); + + for (int i = 0; i < buffer_size; ++i) + { + buffer->push_back(input[0][i] + m_reinject_signal->operator[](i)); + } + + for(int i = 0; i < buffer_size; ++i) + { + float delay = std::max(1. / m_sr, std::min(input[1][i] / 1000., m_max_delay)); + float offset = buffer->size() - (delay * m_sr) - (buffer_size - 1) + i; + size_t offset_floor = std::floor(offset); + + output[0][i] = cubicInterpolate(offset - offset_floor, + buffer->operator[](offset_floor - 1), + buffer->operator[](offset_floor), + buffer->operator[](offset_floor + 1), + buffer->operator[](offset_floor + 2)); + + m_reinject_signal->operator[](i) = m_reinject_level.load() * output[0][i]; + } + } + + void DelaySimpleTilde::prepare(dsp::Processor::PrepareInfo const& infos) + { + m_sr = infos.sample_rate; + size_t vector_size = infos.vector_size; + + size_t buffer_size = std::ceil(m_max_delay * m_sr) + 1 + vector_size; + + std::shared_ptr new_buffer(new CircularBuffer(buffer_size, buffer_size, 0.)); + m_pool.add(new_buffer); + store(new_buffer); + + m_reinject_signal.reset(new dsp::Signal(vector_size)); + + if (infos.inputs.size() > 1 && infos.inputs[1]) + { + setPerformCallBack(this, &DelaySimpleTilde::performDelay); + } + else + { + setPerformCallBack(this, &DelaySimpleTilde::perform); + } + } + + // ================================================================================ // + // RELEASEPOOL // + // ================================================================================ // + + DelaySimpleTilde::ReleasePool::ReleasePool(): + m_pool(), + m_mutex() + { + } + + DelaySimpleTilde::ReleasePool::~ReleasePool() + { + } + + void DelaySimpleTilde::ReleasePool::add(std::shared_ptr & buffer) + { + if (buffer != nullptr) + { + std::lock_guard lock(m_mutex); + + m_pool.emplace_back(buffer); + } + } + + void DelaySimpleTilde::ReleasePool::clear() + { + std::lock_guard lock(m_mutex); + + for (auto it = m_pool.begin(); it != m_pool.end();) + { + if (it->use_count() <= 1) + { + it = m_pool.erase(it); + } + else + { + ++it; + } + } + } + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_DelaySimpleTilde.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_DelaySimpleTilde.h new file mode 100644 index 00000000..82037b69 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_DelaySimpleTilde.h @@ -0,0 +1,106 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include +#include + +#include +#include + +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // DELAYSIMPLETILDE // + // ================================================================================ // + + class DelaySimpleTilde : public AudioObject, public tool::Scheduler<>::Timer + { + private: //classes + + using CircularBuffer = tool::CircularBuffer; + + class ReleasePool + { + public: // methods + + ReleasePool(); + + ~ReleasePool(); + + void add(std::shared_ptr & buffer); + + void clear(); + + private: // members + + std::vector> m_pool; + mutable std::mutex m_mutex; + }; + + public: // methods + + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher & patcher); + + DelaySimpleTilde(model::Object const& model, Patcher& patcher); + + ~DelaySimpleTilde(); + + void receive(size_t index, std::vector const& args) override final; + + void perform(dsp::Buffer const& input, dsp::Buffer& output) noexcept; + + void performDelay(dsp::Buffer const& input, dsp::Buffer& output) noexcept; + + void prepare(dsp::Processor::PrepareInfo const& infos) override final; + + void timerCallBack() override final; + + void store(std::shared_ptr new_buffer); + + std::shared_ptr load(); + + private: // methods + + dsp::sample_t cubicInterpolate(float const& x, + float const& y0, + float const& y1, + float const& y2, + float const& y3); + + private: // members + + std::shared_ptr m_circular_buffer; + std::unique_ptr m_reinject_signal; + float m_max_delay; + std::atomic m_delay; + std::atomic m_reinject_level; + dsp::sample_t m_sr; + ReleasePool m_pool; + mutable std::mutex m_mutex; + }; + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_AdcTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_AdcTilde.cpp deleted file mode 100644 index 761bc2cf..00000000 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_AdcTilde.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#include - -namespace kiwi -{ - namespace engine - { - // ================================================================================ // - // ADC~ // - // ================================================================================ // - - AdcTilde::AdcTilde(model::Object const& model, Patcher& patcher, std::vector const& args): - AudioInterfaceObject(model, patcher, args) - { - std::vector routes = parseArgs(args); - - for (size_t index = 0; index < routes.size(); ++index) - { - m_router.connect(routes[index], index); - } - } - - void AdcTilde::perform(dsp::Buffer const& input, dsp::Buffer& output) noexcept - { - std::set const& connections = m_router.getConnections(); - - for(Router::Cnx const& connection : connections) - { - m_audio_controler.getFromChannel(connection.m_input, output[connection.m_output]); - } - } - - void AdcTilde::prepare(dsp::Processor::PrepareInfo const& infos) - { - setPerformCallBack(this, &AdcTilde::perform); - } - } -} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_DacTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_DacTilde.cpp deleted file mode 100644 index 576474fd..00000000 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_DacTilde.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#include - -namespace kiwi -{ - namespace engine - { - // ================================================================================ // - // DAC~ // - // ================================================================================ // - - DacTilde::DacTilde(model::Object const& model, Patcher& patcher, std::vector const& args): - AudioInterfaceObject(model, patcher, args) - { - std::vector routes = parseArgs(args); - - for (size_t index = 0; index < routes.size(); ++index) - { - m_router.connect(index, routes[index]); - } - } - - void DacTilde::perform(dsp::Buffer const& input, dsp::Buffer& output) noexcept - { - std::set const& connections = m_router.getConnections(); - - for(Router::Cnx const& connection : connections) - { - m_audio_controler.addToChannel(connection.m_output, input[connection.m_input]); - } - } - - void DacTilde::prepare(dsp::Processor::PrepareInfo const& infos) - { - setPerformCallBack(this, &DacTilde::perform); - } - } -} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_DacTilde.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_DacTilde.h deleted file mode 100644 index d1e6add3..00000000 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_DacTilde.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#pragma once - -#include - -namespace kiwi -{ - namespace engine - { - // ================================================================================ // - // DAC~ // - // ================================================================================ // - - class DacTilde : public AudioInterfaceObject - { - public: // methods - - DacTilde(model::Object const& model, Patcher& patcher, std::vector const& args); - - void perform(dsp::Buffer const& input, dsp::Buffer& output) noexcept; - - void prepare(dsp::Processor::PrepareInfo const& infos) override final; - }; - } -} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_DelaySimpleTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_DelaySimpleTilde.cpp deleted file mode 100644 index 18e5a30a..00000000 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_DelaySimpleTilde.cpp +++ /dev/null @@ -1,155 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#include - -namespace kiwi -{ - namespace engine - { - // ================================================================================ // - // DELAYSIMPLETILDE // - // ================================================================================ // - - DelaySimpleTilde::DelaySimpleTilde(model::Object const& model, Patcher& patcher, std::vector const& args): - AudioObject(model, patcher), - m_circular_buffer(), - m_reinject_signal(), - m_max_delay(60.), - m_delay(1.), - m_reinject_level(0.), - m_sr(0.), - m_vector_size(0), - m_mutex() - { - } - - void DelaySimpleTilde::receive(size_t index, std::vector const& args) - { - if (index == 0 && args[0].isString()) - { - std::lock_guard lock(m_mutex); - - m_circular_buffer->assign(m_circular_buffer->size(), 0); - } - if (index == 1 && args[0].isNumber()) - { - m_delay.store(args[0].getFloat() / 1000.); - } - else if(index == 2 && args[0].isNumber()) - { - m_reinject_level.store(std::max(0., std::min(1., args[0].getFloat()))); - } - } - - dsp::sample_t DelaySimpleTilde::cubicInterpolate(float const& x, - float const& y0, - float const& y1, - float const& y2, - float const& y3) - { - return y1 + 0.5 * x * (y2 - y0 + x * (2.0 * y0 - 5.0 * y1 + 4.0 * y2 - y3 - + x * (3.0 * (y1 - y2) + y3 - y0))); - } - - void DelaySimpleTilde::perform(dsp::Buffer const& input, dsp::Buffer& output) noexcept - { - std::lock_guard lock(m_mutex); - - size_t buffer_size = input[0].size(); - - for (int i = 0; i < buffer_size; ++i) - { - m_circular_buffer->push_back(input[0][i] + m_reinject_signal->operator[](i)); - } - - float delay = std::max(1. / m_sr, std::min(m_delay.load(), m_max_delay)); - float offset = m_circular_buffer->size() - (delay * m_sr) - (buffer_size - 1); - size_t offset_floor = std::floor(offset); - float decimal_part = offset - offset_floor; - - for(int i = 0; i < buffer_size; ++i) - { - output[0][i] = cubicInterpolate(decimal_part, - m_circular_buffer->operator[](offset_floor - 1), - m_circular_buffer->operator[](offset_floor), - m_circular_buffer->operator[](offset_floor + 1), - m_circular_buffer->operator[](offset_floor + 2)); - - m_reinject_signal->operator[](i) = m_reinject_level.load() * output[0][i]; - ++offset_floor; - } - } - - void DelaySimpleTilde::performDelay(dsp::Buffer const& input, dsp::Buffer& output) noexcept - { - //! Durty solution to synchronize circular buffer. - //! Should be implemented as an atomic shared pointer and a release pool - //! https://www.youtube.com/watch?v=boPEO2auJj4 48' - std::lock_guard lock(m_mutex); - - size_t buffer_size = input[0].size(); - - for (int i = 0; i < buffer_size; ++i) - { - m_circular_buffer->push_back(input[0][i] + m_reinject_signal->operator[](i)); - } - - for(int i = 0; i < buffer_size; ++i) - { - float delay = std::max(1. / m_sr, std::min(input[1][i] / 1000., m_max_delay)); - float offset = m_circular_buffer->size() - (delay * m_sr) - (buffer_size - 1) + i; - size_t offset_floor = std::floor(offset); - - output[0][i] = cubicInterpolate(offset - offset_floor, - m_circular_buffer->operator[](offset_floor - 1), - m_circular_buffer->operator[](offset_floor), - m_circular_buffer->operator[](offset_floor + 1), - m_circular_buffer->operator[](offset_floor + 2)); - - m_reinject_signal->operator[](i) = m_reinject_level.load() * output[0][i]; - } - } - - void DelaySimpleTilde::prepare(dsp::Processor::PrepareInfo const& infos) - { - if (infos.sample_rate != m_sr || infos.vector_size != m_vector_size) - { - m_sr = infos.sample_rate; - m_vector_size = infos.vector_size; - - size_t buffer_size = std::ceil(m_max_delay * m_sr) + 1 + m_vector_size; - - m_circular_buffer.reset(new tool::CircularBuffer(buffer_size, buffer_size, 0.)); - m_reinject_signal.reset(new dsp::Signal(m_vector_size)); - } - - if (infos.inputs.size() > 1 && infos.inputs[1]) - { - setPerformCallBack(this, &DelaySimpleTilde::performDelay); - } - else - { - setPerformCallBack(this, &DelaySimpleTilde::perform); - } - } - } -} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_DelaySimpleTilde.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_DelaySimpleTilde.h deleted file mode 100644 index 0eb1f1a3..00000000 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_DelaySimpleTilde.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#pragma once - -#include - -#include - -namespace kiwi -{ - namespace engine - { - // ================================================================================ // - // DELAYSIMPLETILDE // - // ================================================================================ // - - class DelaySimpleTilde : public AudioObject - { - public: // methods - - DelaySimpleTilde(model::Object const& model, Patcher& patcher, std::vector const& args); - - void receive(size_t index, std::vector const& args) override final; - - void perform(dsp::Buffer const& input, dsp::Buffer& output) noexcept; - - void performDelay(dsp::Buffer const& input, dsp::Buffer& output) noexcept; - - void prepare(dsp::Processor::PrepareInfo const& infos) override final; - - private: // methods - - dsp::sample_t cubicInterpolate(float const& x, - float const& y0, - float const& y1, - float const& y2, - float const& y3); - - private: // members - - std::unique_ptr> m_circular_buffer; - std::unique_ptr m_reinject_signal; - float m_max_delay; - std::atomic m_delay; - std::atomic m_reinject_level; - dsp::sample_t m_sr; - size_t m_vector_size; - mutable std::mutex m_mutex; - }; - } -} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_OscTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_OscTilde.cpp deleted file mode 100644 index f6d53636..00000000 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_OscTilde.cpp +++ /dev/null @@ -1,154 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#include - -namespace kiwi -{ - namespace engine - { - // ================================================================================ // - // OSC~ // - // ================================================================================ // - - OscTilde::OscTilde(model::Object const& model, Patcher& patcher, std::vector const& args) - : AudioObject(model, patcher) - { - if (!args.empty() && args[0].isNumber()) - { - setFrequency(args[0].getFloat()); - } - } - - void OscTilde::setFrequency(dsp::sample_t const& freq) noexcept - { - m_freq = freq; - } - - void OscTilde::setSampleRate(dsp::sample_t const& sample_rate) - { - m_sr = sample_rate; - } - - void OscTilde::setOffset(dsp::sample_t const& offset) noexcept - { - m_offset = fmodf(offset, 1.f); - } - - void OscTilde::receive(size_t index, std::vector const& args) - { - if (index == 0 && args[0].isNumber()) - { - setFrequency(args[0].getFloat()); - } - else if(index == 1 && args[0].isNumber()) - { - setOffset(args[0].getFloat()); - } - } - - void OscTilde::prepare(PrepareInfo const& infos) - { - setSampleRate(static_cast(infos.sample_rate)); - - if (infos.inputs[0] && infos.inputs[1]) - { - setPerformCallBack(this, &OscTilde::performPhaseAndFreq); - } - else if(infos.inputs[0]) - { - setPerformCallBack(this, &OscTilde::performFreq); - } - else if(infos.inputs[1]) - { - setPerformCallBack(this, &OscTilde::performPhase); - } - else - { - setPerformCallBack(this, &OscTilde::performValue); - } - } - - void OscTilde::performValue(dsp::Buffer const& input, dsp::Buffer& output) noexcept - { - dsp::sample_t *sig_data = output[0ul].data(); - size_t sample_index = output[0ul].size(); - dsp::sample_t const time_inc = m_freq/m_sr; - dsp::sample_t const offset = m_offset; - - while(sample_index--) - { - *sig_data++ = std::cos(2.f * dsp::pi * (m_time + offset)); - m_time += time_inc; - } - - m_time = fmodf(m_time, 1.f); - } - - void OscTilde::performFreq(dsp::Buffer const& input, dsp::Buffer& output) noexcept - { - size_t sample_index = output[0ul].size(); - dsp::sample_t* output_sig = output[0ul].data(); - dsp::sample_t const* freq = input[0ul].data(); - dsp::sample_t const offset = m_offset; - - while(sample_index--) - { - *output_sig++ = std::cos(2.f *dsp::pi * (m_time + offset)); - m_time += (*freq++ / m_sr); - } - - m_time = fmodf(m_time, 1.f); - } - - void OscTilde::performPhase(dsp::Buffer const& input, dsp::Buffer& output) noexcept - { - dsp::sample_t* output_sig = output[0ul].data(); - size_t sample_index = output[0ul].size(); - dsp::sample_t const* phase = input[1ul].data(); - dsp::sample_t const time_inc = m_freq/m_sr; - - while(sample_index--) - { - *output_sig++ = std::cos(2.f * dsp::pi * (m_time + fmodf(*phase++, 1.f))); - m_time += time_inc; - } - - m_time = fmodf(m_time, 1.f); - } - - void OscTilde::performPhaseAndFreq(dsp::Buffer const& input, dsp::Buffer& output) noexcept - { - size_t sample_index = output[0].size(); - dsp::sample_t* output_sig = output[0].data(); - dsp::sample_t const* freq = input[0].data(); - dsp::sample_t const* phase = input[1].data(); - - while(sample_index--) - { - *output_sig++ = std::cos(2.f * dsp::pi * (m_time + fmodf(*phase++, 1.f))); - m_time += (*freq++ / m_sr); - } - - m_time = fmodf(m_time, 1.f); - } - } -} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_OscTilde.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_OscTilde.h deleted file mode 100644 index 78a377a7..00000000 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_OscTilde.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#pragma once - -#include - -namespace kiwi -{ - namespace engine - { - // ================================================================================ // - // OSC~ // - // ================================================================================ // - - class OscTilde : public AudioObject - { - public: // methods - - OscTilde(model::Object const& model, Patcher& patcher, std::vector const& args); - - void receive(size_t index, std::vector const& args) override; - - void performValue(dsp::Buffer const& input, dsp::Buffer& output) noexcept; - - void performFreq(dsp::Buffer const& input, dsp::Buffer& output) noexcept; - - void performPhase(dsp::Buffer const& input, dsp::Buffer& output) noexcept; - - void performPhaseAndFreq(dsp::Buffer const& input, dsp::Buffer& output) noexcept; - - void prepare(dsp::Processor::PrepareInfo const& infos) override final; - - private: // methods - - void setFrequency(dsp::sample_t const& freq) noexcept; - - void setOffset(dsp::sample_t const& offset) noexcept; - - void setSampleRate(dsp::sample_t const& sample_rate); - - private: // members - - dsp::sample_t m_sr = 0.f; - dsp::sample_t m_time = 0.f; - std::atomic m_freq{0.f}; - std::atomic m_offset{0.f}; - }; - } -} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_PlusTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_PlusTilde.cpp deleted file mode 100644 index 891fbfbe..00000000 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_PlusTilde.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#include - -namespace kiwi -{ - namespace engine - { - // ================================================================================ // - // PLUS~ // - // ================================================================================ // - - PlusTilde::PlusTilde(model::Object const& model, Patcher& patcher, std::vector const& args) - : AudioObject(model, patcher) - { - if (!args.empty() && args[0].isNumber()) - { - m_value = args[0].getFloat(); - } - } - - void PlusTilde::receive(size_t index, std::vector const& args) - { - if(index == 1 && args[0].isNumber()) - { - m_value = args[0].getFloat(); - } - } - - void PlusTilde::performValue(dsp::Buffer const& input, dsp::Buffer& output) noexcept - { - dsp::Signal const& in = input[0]; - const size_t size = in.size(); - dsp::sample_t const* in1 = in.data(); - dsp::sample_t* out = output[0].data(); - - dsp::sample_t const value = m_value; - - for(size_t i = size>>3; i; --i, in1 += 8, out += 8) - { - out[0] = in1[0] + value; out[1] = in1[1] + value; - out[2] = in1[2] + value; out[3] = in1[3] + value; - out[4] = in1[4] + value; out[5] = in1[5] + value; - out[6] = in1[6] + value; out[7] = in1[7] + value; - } - for(size_t i = size&7; i; --i, in1++, out++) - { - out[0] = in1[0] * value; - } - } - - void PlusTilde::performVec(dsp::Buffer const& input, dsp::Buffer& output) noexcept - { - dsp::Signal const& in = input[0]; - const size_t size = in.size(); - dsp::sample_t const* in1 = in.data(); - dsp::sample_t const* in2 = input[1].data(); - dsp::sample_t* out = output[0].data(); - - for(size_t i = size>>3; i; --i, in1 += 8, in2 += 8, out += 8) - { - out[0] = in1[0] + in2[0]; out[1] = in1[1] + in2[1]; - out[2] = in1[2] + in2[2]; out[3] = in1[3] + in2[3]; - out[4] = in1[4] + in2[4]; out[5] = in1[5] + in2[5]; - out[6] = in1[6] + in2[6]; out[7] = in1[7] + in2[7]; - } - for(size_t i = size&7; i; --i, in1++, in2++, out++) - { - out[0] = in1[0] * in2[0]; - } - } - - void PlusTilde::prepare(PrepareInfo const& infos) - { - if (infos.inputs.size() > 1 && infos.inputs[1]) - { - setPerformCallBack(this, &PlusTilde::performVec); - } - else - { - setPerformCallBack(this, &PlusTilde::performValue); - } - } - } -} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_PlusTilde.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_PlusTilde.h deleted file mode 100644 index 14345342..00000000 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_PlusTilde.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#pragma once - -#include - -namespace kiwi -{ - namespace engine - { - - // ================================================================================ // - // PLUS~ // - // ================================================================================ // - - class PlusTilde : public AudioObject - { - public: // methods - - PlusTilde(model::Object const& model, Patcher& patcher, std::vector const& args); - - void receive(size_t index, std::vector const& args) override; - - void performValue(dsp::Buffer const& input, dsp::Buffer& output) noexcept; - - void performVec(dsp::Buffer const& input, dsp::Buffer& output) noexcept; - - void prepare(dsp::Processor::PrepareInfo const& infos) override final; - - private: // members - - std::atomic m_value{0.f}; - }; - } -} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_SigTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_SigTilde.cpp deleted file mode 100644 index a850aea9..00000000 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_SigTilde.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#include - -namespace kiwi -{ - namespace engine - { - // ================================================================================ // - // SIG~ // - // ================================================================================ // - - SigTilde::SigTilde(model::Object const& model, Patcher& patcher, std::vector const& args): - AudioObject(model, patcher) - { - if (!args.empty() && args[0].isNumber()) - { - m_value = args[0].getFloat(); - } - } - - void SigTilde::receive(size_t index, std::vector const& args) - { - if (index == 0 && args[0].isNumber()) - { - m_value = args[0].getFloat(); - } - } - - void SigTilde::perform(dsp::Buffer const& input, dsp::Buffer& output) noexcept - { - size_t sample_index = output[0].size(); - dsp::sample_t* output_sig = output[0].data(); - dsp::sample_t const value = m_value; - - while(sample_index--) - { - *output_sig++ = value; - } - } - - void SigTilde::prepare(dsp::Processor::PrepareInfo const& infos) - { - setPerformCallBack(this, &SigTilde::perform); - } - } -} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_SigTilde.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_SigTilde.h deleted file mode 100644 index 02dc9967..00000000 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_SigTilde.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#pragma once - -#include - -namespace kiwi -{ - namespace engine - { - // ================================================================================ // - // SIG~ // - // ================================================================================ // - - class SigTilde : public AudioObject - { - public: // methods - - SigTilde(model::Object const& model, Patcher& patcher, std::vector const& args); - - void receive(size_t index, std::vector const& args) override final; - - void perform(dsp::Buffer const& input, dsp::Buffer& output) noexcept; - - void prepare(dsp::Processor::PrepareInfo const& infos) override final; - - private: // members - - std::atomic m_value{0.f}; - }; - } -} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_TimesTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_TimesTilde.cpp deleted file mode 100644 index d60e863a..00000000 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_TimesTilde.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#include - -namespace kiwi -{ - namespace engine - { - // ================================================================================ // - // TIMES~ // - // ================================================================================ // - - TimesTilde::TimesTilde(model::Object const& model, Patcher& patcher, std::vector const& args) - : AudioObject(model, patcher) - { - if (!args.empty() && args[0].isNumber()) - { - m_value = args[0].getFloat(); - } - } - - void TimesTilde::receive(size_t index, std::vector const& args) - { - if(index == 1 && args[0].isNumber()) - { - m_value = args[0].getFloat(); - } - } - - void TimesTilde::performValue(dsp::Buffer const& input, dsp::Buffer& output) noexcept - { - const size_t size = input[0ul].size(); - dsp::sample_t const* in1 = input[0ul].data(); - dsp::sample_t* out = output[0ul].data(); - - dsp::sample_t const value = m_value; - - for(size_t i = size>>3; i; --i, in1 += 8, out += 8) - { - out[0] = in1[0] * value; out[1] = in1[1] * value; - out[2] = in1[2] * value; out[3] = in1[3] * value; - out[4] = in1[4] * value; out[5] = in1[5] * value; - out[6] = in1[6] * value; out[7] = in1[7] * value; - } - for(size_t i = size&7; i; --i, in1++, out++) - { - out[0] = in1[0] * value; - } - } - - void TimesTilde::performVec(dsp::Buffer const& input, dsp::Buffer& output) noexcept - { - const size_t size = input[0ul].size(); - dsp::sample_t const* in1 = input[0ul].data(); - dsp::sample_t const* in2 = input[1ul].data(); - dsp::sample_t* out = output[0ul].data(); - - for(size_t i = size>>3; i; --i, in1 += 8, in2 += 8, out += 8) - { - out[0] = in1[0] * in2[0]; out[1] = in1[1] * in2[1]; - out[2] = in1[2] * in2[2]; out[3] = in1[3] * in2[3]; - out[4] = in1[4] * in2[4]; out[5] = in1[5] * in2[5]; - out[6] = in1[6] * in2[6]; out[7] = in1[7] * in2[7]; - } - for(size_t i = size&7; i; --i, in1++, in2++, out++) - { - out[0] = in1[0] * in2[0]; - } - } - - void TimesTilde::prepare(PrepareInfo const& infos) - { - if (infos.inputs.size() > 1 && infos.inputs[1]) - { - setPerformCallBack(this, &TimesTilde::performVec); - } - else - { - setPerformCallBack(this, &TimesTilde::performValue); - } - } - } -} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_TimesTilde.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_TimesTilde.h deleted file mode 100644 index 6e3a8160..00000000 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_TimesTilde.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#pragma once - -#include - -namespace kiwi -{ - namespace engine - { - - /// ================================================================================ // - // TIMES~ // - // ================================================================================ // - - class TimesTilde : public AudioObject - { - public: // methods - - TimesTilde(model::Object const& model, Patcher& patcher, std::vector const& args); - - void receive(size_t index, std::vector const& args) override; - - void performValue(dsp::Buffer const& input, dsp::Buffer& output) noexcept; - - void performVec(dsp::Buffer const& input, dsp::Buffer& output) noexcept; - - void prepare(dsp::Processor::PrepareInfo const& infos) override final; - - private: // members - - std::atomic m_value{0.f}; - }; - } -} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_ErrorBox.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_ErrorBox.cpp new file mode 100644 index 00000000..81f98190 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_ErrorBox.cpp @@ -0,0 +1,58 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // ERRORBOX // + // ================================================================================ // + + void ErrorBox::declare() + { + Factory::add("errorbox", &ErrorBox::create); + } + + std::unique_ptr ErrorBox::create(model::Object const& object, Patcher& patcher) + { + return std::make_unique(object, patcher); + } + + ErrorBox::ErrorBox(model::Object const& model, Patcher& patcher) + : AudioObject(model, patcher) + { + ; + } + + void ErrorBox::receive(size_t index, std::vector const& args) + { + ; + } + + void ErrorBox::prepare(dsp::Processor::PrepareInfo const& infos) + { + ; + } + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Math/KiwiEngine_Plus.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_ErrorBox.h similarity index 54% rename from Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Math/KiwiEngine_Plus.h rename to Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_ErrorBox.h index 7dfa1bfc..39e31414 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Math/KiwiEngine_Plus.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_ErrorBox.h @@ -23,28 +23,25 @@ #include -namespace kiwi -{ - namespace engine +namespace kiwi { namespace engine { + + // ================================================================================ // + // ERRORBOX // + // ================================================================================ // + + class ErrorBox : public AudioObject { - // ================================================================================ // - // OBJECT PLUS // - // ================================================================================ // + public: - class Plus : public engine::Object - { - public: - - Plus(model::Object const& model, Patcher& patcher, std::vector const& args); - - void receive(size_t index, std::vector const& args) override; - - void bang(); - - private: - - double m_lhs = 0.0; - double m_rhs = 0.0; - }; - } -} + ErrorBox(model::Object const& model, Patcher& patcher); + + void receive(size_t index, std::vector const& args) override; + + void prepare(dsp::Processor::PrepareInfo const& infos) override final; + + static void declare(); + + static std::unique_ptr create(model::Object const& object, Patcher& patcher); + }; + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Loadmess.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Loadmess.cpp new file mode 100644 index 00000000..ddd1db89 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Loadmess.cpp @@ -0,0 +1,68 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OBJECT LOADMESS // + // ================================================================================ // + + void Loadmess::declare() + { + Factory::add("loadmess", &Loadmess::create); + } + + std::unique_ptr Loadmess::create(model::Object const& model, Patcher & patcher) + { + return std::make_unique(model, patcher); + } + + Loadmess::Loadmess(model::Object const& model, Patcher& patcher): + Object(model, patcher), + m_args(model.getArguments()) + { + } + + void Loadmess::receive(size_t index, std::vector const& args) + { + if (!args.empty() && args[0].isString() && args[0].getString() == "bang") + { + send(0ul, m_args); + } + else + { + warning("loadmess inlet 1 doesn't understane [" + args[0].getString() + "]"); + } + } + + void Loadmess::loadbang() + { + defer([this]() + { + send(0, m_args); + }); + } + +}} + diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Loadmess.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Loadmess.h similarity index 52% rename from Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Loadmess.h rename to Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Loadmess.h index d7f79e3f..5e07e9b1 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Loadmess.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Loadmess.h @@ -23,29 +23,31 @@ #include -namespace kiwi -{ - namespace engine +namespace kiwi { namespace engine { + + // ================================================================================ // + // OBJECT LOADMESS // + // ================================================================================ // + + class Loadmess : public engine::Object { - // ================================================================================ // - // OBJECT LOADMESS // - // ================================================================================ // - - class Loadmess : public engine::Object - { - public: - - Loadmess(model::Object const& model, Patcher& patcher, std::vector const& args); - - ~Loadmess() = default; - - void receive(size_t, std::vector const& args) override; - - void loadbang() override; - - private: - - const std::vector m_args; - }; - } -} + public: + + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher & patcher); + + Loadmess(model::Object const& model, Patcher& patcher); + + ~Loadmess() = default; + + void receive(size_t index, std::vector const& args) override; + + void loadbang() override; + + private: + + const std::vector m_args; + }; + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Math/KiwiEngine_Plus.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Math/KiwiEngine_Plus.cpp deleted file mode 100644 index 1d2a8cdd..00000000 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Math/KiwiEngine_Plus.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#include - -namespace kiwi -{ - namespace engine - { - - // ================================================================================ // - // OBJECT PLUS // - // ================================================================================ // - - Plus::Plus(model::Object const& model, Patcher& patcher, std::vector const& args) - : Object(model, patcher) - { - m_lhs = 0.; - if(!args.empty() && args[0].isNumber()) - { - m_rhs = args[0].getFloat(); - } - } - - void Plus::receive(size_t index, std::vector const& args) - { - if(!args.empty()) - { - if(args[0].isNumber()) - { - if(index == 0) - { - m_lhs = args[0].getFloat(); - bang(); - } - else if(index == 1) - { - m_rhs = args[0].getFloat(); - } - } - else if(index == 0 && args[0].getString() == "bang") - { - bang(); - } - } - } - - void Plus::bang() - { - send(0, {m_rhs + m_lhs}); - } - } -} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Math/KiwiEngine_Times.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Math/KiwiEngine_Times.cpp deleted file mode 100644 index 8a6747fc..00000000 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Math/KiwiEngine_Times.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#include - -namespace kiwi -{ - namespace engine - { - // ================================================================================ // - // OBJECT TIMES // - // ================================================================================ // - - Times::Times(model::Object const& model, Patcher& patcher, std::vector const& args) - : Object(model, patcher) - { - m_lhs = 0.; - if(!args.empty() && args[0].isNumber()) - { - m_rhs = args[0].getFloat(); - } - } - - void Times::receive(size_t index, std::vector const& args) - { - if(!args.empty()) - { - if(args[0].isNumber()) - { - if(index == 0) - { - m_lhs = args[0].getFloat(); - bang(); - } - else if(index == 1) - { - m_rhs = args[0].getFloat(); - } - } - else if(index == 0 && args[0].getString() == "bang") - { - bang(); - } - } - } - - void Times::bang() - { - send(0, {m_rhs * m_lhs}); - } - } -} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Print.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Print.cpp deleted file mode 100644 index b6cffe7d..00000000 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Print.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#include - -namespace kiwi -{ - namespace engine - { - // ================================================================================ // - // OBJECT PRINT // - // ================================================================================ // - - Print::Print(model::Object const& model, Patcher& patcher, std::vector const& args) - : Object(model, patcher) - { - m_name = !args.empty() ? args[0].getString() : "print"; - } - - void Print::receive(size_t, std::vector const& args) - { - if(!args.empty()) - { - post(m_name + " \xe2\x80\xa2 " + tool::AtomHelper::toString(args)); - } - } - } -} - diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Receive.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Receive.cpp deleted file mode 100644 index 8f8ee143..00000000 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Receive.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#include - -namespace kiwi -{ - namespace engine - { - // ================================================================================ // - // OBJECT RECEIVE // - // ================================================================================ // - - class Receive::Task final : public tool::Scheduler<>::Task - { - public: // methods - - Task(Receive& object, std::vector const& atoms): - tool::Scheduler<>::Task(), - m_object(object), - m_atoms(atoms) - { - } - - ~Task() - { - } - - void execute() override - { - m_object.send(0, m_atoms); - - m_object.m_tasks.erase(std::find_if(m_object.m_tasks.begin(), - m_object.m_tasks.end(), - [this](std::shared_ptr const& task) - { - return task.get() == this; - })); - } - - private: // members - - Receive& m_object; - std::vector m_atoms; - }; - - Receive::Receive(model::Object const& model, Patcher& patcher, std::vector const& args): - Object(model, patcher), - m_name(), - m_tasks() - { - m_name = !args.empty() ? args[0].getString() : ""; - - if(!m_name.empty()) - { - tool::Beacon& beacon = getBeacon(m_name); - beacon.bind(*this); - } - } - - Receive::~Receive() - { - for (std::shared_ptr const& task : m_tasks) - { - getScheduler().unschedule(task); - } - - if(!m_name.empty()) - { - tool::Beacon& beacon = getBeacon(m_name); - beacon.unbind(*this); - } - } - - void Receive::receive(size_t, std::vector const& args) - { - - } - - void Receive::receive(std::vector const& args) - { - if (!args.empty()) - { - std::shared_ptr task(new Task(*this, args)); - - m_tasks.insert(task); - - getScheduler().defer(task); - } - } - } -} - diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Receive.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Receive.h deleted file mode 100644 index b990a504..00000000 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Receive.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#pragma once - -#include - -namespace kiwi -{ - namespace engine - { - // ================================================================================ // - // OBJECT RECEIVE // - // ================================================================================ // - - class Receive : public engine::Object, public tool::Beacon::Castaway - { - private: // classes - - class Task; - - public: // methods - - Receive(model::Object const& model, Patcher& patcher, std::vector const& args); - - ~Receive(); - - void receive(size_t, std::vector const& args) override; - - void receive(std::vector const& args) override; - - private: // members - - std::string m_name; - std::set> m_tasks; - }; - } -} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_MeterTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_MeterTilde.cpp similarity index 86% rename from Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_MeterTilde.cpp rename to Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_MeterTilde.cpp index 09066365..1b406db2 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_MeterTilde.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_MeterTilde.cpp @@ -19,11 +19,10 @@ ============================================================================== */ -#include +#include -#include - -#include +#include +#include namespace kiwi { namespace engine { @@ -31,7 +30,17 @@ namespace kiwi { namespace engine { // METER~ // // ================================================================================ // - MeterTilde::MeterTilde(model::Object const& model, Patcher& patcher, std::vector const& atom): + void MeterTilde::declare() + { + Factory::add("meter~", &MeterTilde::create); + } + + std::unique_ptr MeterTilde::create(model::Object const& model, Patcher & patcher) + { + return std::make_unique(model, patcher); + } + + MeterTilde::MeterTilde(model::Object const& model, Patcher& patcher): engine::AudioObject(model, patcher), tool::Scheduler<>::Timer(patcher.getScheduler()), m_interval(50), diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_MeterTilde.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_MeterTilde.h similarity index 79% rename from Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_MeterTilde.h rename to Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_MeterTilde.h index ee0b00c5..40b93550 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_MeterTilde.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_MeterTilde.h @@ -24,8 +24,7 @@ #include #include -#include -#include +#include #include @@ -43,24 +42,20 @@ namespace kiwi { namespace engine { public: // methods - //! @brief Constructor - MeterTilde(model::Object const& model, Patcher& patcher, std::vector const& atom); + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher & patcher); + + MeterTilde(model::Object const& model, Patcher& patcher); - //! @brief The engine's receive method. - //! @details Does nothing as no control inlets exists. void receive(size_t index, std::vector const& args) override final; - //! @brief The dsp perform method called. void perform(dsp::Buffer const& intput, dsp::Buffer& output); - //! @brief Called to prepare dsp processing. void prepare(dsp::Processor::PrepareInfo const& infos) override final; - //! @brief Stops the timer callback method. void release() override final; - //! @brief The timer callback method. - //! @details Sends last peak and trigger signal. void timerCallBack() override final; private: // members diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Metro.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Metro.cpp new file mode 100644 index 00000000..85c23a91 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Metro.cpp @@ -0,0 +1,98 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OBJECT METRO // + // ================================================================================ // + + void Metro::declare() + { + Factory::add("metro", &Metro::create); + } + + std::unique_ptr Metro::create(model::Object const& model, Patcher & patcher) + { + return std::make_unique(model, patcher); + } + + Metro::Metro(model::Object const& model, Patcher& patcher): + engine::Object(model, patcher), + m_period(std::chrono::milliseconds(1000)), + m_task(new tool::Scheduler<>::CallBack(std::bind(&Metro::timerCallBack, this))) + { + std::vector const& args = model.getArguments(); + + if(!args.empty()) + { + m_period = std::chrono::milliseconds(args[0].getInt()); + } + } + + Metro::~Metro() + { + getScheduler().unschedule(m_task); + } + + void Metro::receive(size_t index, std::vector const& args) + { + if (!args.empty()) + { + if (index == 0) + { + if (args[0].isNumber()) + { + if (static_cast(args[0].getFloat())) + { + getScheduler().unschedule(m_task); + timerCallBack(); + getScheduler().schedule(m_task, m_period); + } + else + { + getScheduler().unschedule(m_task); + } + } + } + else if(index == 1) + { + if (args[0].isNumber()) + { + m_period = std::chrono::milliseconds(args[0].getInt()); + } + else + { + warning("metro inlet 2 doesn't understand [" + args[0].getString() + "]"); + } + } + } + } + + void Metro::timerCallBack() + { + send(0, {"bang"}); + getScheduler().schedule(m_task, m_period); + } +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Metro.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Metro.h new file mode 100644 index 00000000..9a928145 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Metro.h @@ -0,0 +1,54 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OBJECT METRO // + // ================================================================================ // + + class Metro final : public engine::Object + { + public: // methods + + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher & patcher); + + Metro(model::Object const& model, Patcher& patcher); + + ~Metro(); + + void receive(size_t index, std::vector const& args) override; + + void timerCallBack(); + + private: // members + + tool::Scheduler<>::duration_t m_period; + std::shared_ptr::CallBack> m_task; + }; + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_NewBox.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_NewBox.cpp new file mode 100644 index 00000000..5af551c7 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_NewBox.cpp @@ -0,0 +1,52 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // NEWBOX // + // ================================================================================ // + + void NewBox::declare() + { + Factory::add("newbox", &NewBox::create); + } + + std::unique_ptr NewBox::create(model::Object const& model, Patcher& patcher) + { + return std::make_unique(model, patcher); + } + + NewBox::NewBox(model::Object const& model, Patcher& patcher) + : Object(model, patcher) + { + ; + } + + void NewBox::receive(size_t index, std::vector const& args) + { + ; + } +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Basic/KiwiEngine_NewBox.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_NewBox.h similarity index 57% rename from Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Basic/KiwiEngine_NewBox.h rename to Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_NewBox.h index 349f7710..3837fbb2 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Basic/KiwiEngine_NewBox.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_NewBox.h @@ -23,20 +23,23 @@ #include -namespace kiwi -{ - namespace engine +namespace kiwi { namespace engine { + + // ================================================================================ // + // NEWBOX // + // ================================================================================ // + + class NewBox : public engine::Object { - // ================================================================================ // - // NEWBOX // - // ================================================================================ // + public: // methods - class NewBox : public engine::Object - { - public: - NewBox(model::Object const& model, Patcher& patcher, std::vector const& args); - - void receive(size_t index, std::vector const& args) override; - }; - } -} + NewBox(model::Object const& model, Patcher& patcher); + + void receive(size_t index, std::vector const& args) override; + + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher& patcher); + }; + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h index 754cf17f..1d3ec068 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h @@ -21,53 +21,24 @@ #pragma once -// ================================================================================ // -// BASIC OBJECTS // -// ================================================================================ // - -#include -#include - -// ================================================================================ // -// DSP OBJECTS // -// ================================================================================ // - -#include -#include -#include -#include -#include -#include -#include -#include - -// ================================================================================ // -// MATH OBJECTS // -// ================================================================================ // - -#include -#include - -// ================================================================================ // -// MESSAGE OBJECTS // -// ================================================================================ // - -#include -#include -#include - -// ================================================================================ // -// TIME OBJECTS // -// ================================================================================ // - -#include -#include -#include - -// ================================================================================ // -// CONTROLLER OBJECTS // -// ================================================================================ // - -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Operator.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Operator.cpp new file mode 100644 index 00000000..084a78ca --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Operator.cpp @@ -0,0 +1,74 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OBJECT OPERATOR // + // ================================================================================ // + + Operator::Operator(model::Object const& model, Patcher& patcher): + Object(model, patcher), + m_lhs(), + m_rhs() + { + + std::vector const& args = model.getArguments(); + + m_lhs = 0.; + + if(!args.empty() && args[0].isNumber()) + { + m_rhs = args[0].getFloat(); + } + } + + void Operator::receive(size_t index, std::vector const& args) + { + if(!args.empty()) + { + if(args[0].isNumber()) + { + if(index == 0) + { + m_lhs = args[0].getFloat(); + bang(); + } + else if(index == 1) + { + m_rhs = args[0].getFloat(); + } + } + else if(index == 0 && args[0].getString() == "bang") + { + bang(); + } + } + } + + void Operator::bang() + { + send(0, {compute(m_lhs, m_rhs)}); + } + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Math/KiwiEngine_Times.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Operator.h similarity index 77% rename from Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Math/KiwiEngine_Times.h rename to Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Operator.h index 07057731..90a1067b 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Math/KiwiEngine_Times.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Operator.h @@ -23,28 +23,28 @@ #include -namespace kiwi -{ - namespace engine - { +namespace kiwi { namespace engine { + // ================================================================================ // - // OBJECT TIMES // + // OBJECT OPERATOR // // ================================================================================ // - class Times : public engine::Object + class Operator : public engine::Object { public: - Times(model::Object const& model, Patcher& patcher, std::vector const& args); + Operator(model::Object const& model, Patcher& patcher); - void receive(size_t index, std::vector const& args) override; + void receive(size_t index, std::vector const& args) override final; void bang(); + virtual double compute(double lhs, double rhs) const = 0; + private: - double m_lhs = 0.0; - double m_rhs = 0.0; + double m_lhs; + double m_rhs; }; - } -} + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_OperatorTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_OperatorTilde.cpp new file mode 100644 index 00000000..a93abd2c --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_OperatorTilde.cpp @@ -0,0 +1,117 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OPERATOR TILDE // + // ================================================================================ // + + OperatorTilde::OperatorTilde(model::Object const& model, Patcher& patcher): + AudioObject(model, patcher), + m_rhs() + { + std::vector const& args = model.getArguments(); + + if (!args.empty() && args[0].isNumber()) + { + m_rhs = args[0].getFloat(); + } + } + + void OperatorTilde::receive(size_t index, std::vector const& args) + { + if(!args.empty()) + { + if(args[0].isNumber() && index == 1) + { + m_rhs = args[0].getFloat(); + } + } + } + + void OperatorTilde::performVec(dsp::Buffer const& input, dsp::Buffer& output) noexcept + { + dsp::Signal const& in = input[0]; + const size_t size = in.size(); + dsp::sample_t const* in1 = in.data(); + dsp::sample_t const* in2 = input[1].data(); + dsp::sample_t* out = output[0].data(); + + for(size_t i = size>>3; i; --i, in1 += 8, in2 += 8, out += 8) + { + compute(out[0], in1[0], in2[0]); + compute(out[1], in1[1], in2[1]); + compute(out[2], in1[2], in2[2]); + compute(out[3], in1[3], in2[3]); + compute(out[4], in1[4], in2[4]); + compute(out[5], in1[5], in2[5]); + compute(out[6], in1[6], in2[6]); + compute(out[7], in1[7], in2[7]); + } + for(size_t i = size&7; i; --i, in1++, in2++, out++) + { + compute(out[0], in1[0], in2[0]); + } + } + + void OperatorTilde::performValue(dsp::Buffer const& input, dsp::Buffer& output) noexcept + { + dsp::Signal const& in = input[0]; + const size_t size = in.size(); + dsp::sample_t const* in1 = in.data(); + dsp::sample_t* out = output[0].data(); + + dsp::sample_t const value = m_rhs; + + for(size_t i = size>>3; i; --i, in1 += 8, out += 8) + { + compute(out[0], in1[0], value); + compute(out[1], in1[1], value); + compute(out[2], in1[2], value); + compute(out[3], in1[3], value); + compute(out[4], in1[4], value); + compute(out[5], in1[5], value); + compute(out[6], in1[6], value); + compute(out[7], in1[7], value); + } + + for(size_t i = size&7; i; --i, in1++, out++) + { + compute(out[0], in1[0], value); + } + } + + void OperatorTilde::prepare(dsp::Processor::PrepareInfo const& infos) + { + if (infos.inputs.size() > 1 && infos.inputs[1]) + { + setPerformCallBack(this, &OperatorTilde::performVec); + } + else + { + setPerformCallBack(this, &OperatorTilde::performValue); + } + } + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_OperatorTilde.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_OperatorTilde.h new file mode 100644 index 00000000..4eace68e --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_OperatorTilde.h @@ -0,0 +1,53 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OPERATOR TILDE // + // ================================================================================ // + + class OperatorTilde : public engine::AudioObject + { + public: + + OperatorTilde(model::Object const& model, Patcher& patcher); + + void prepare(dsp::Processor::PrepareInfo const& infos) override final; + + void receive(size_t index, std::vector const& args) override final; + + void performValue(dsp::Buffer const& input, dsp::Buffer& output) noexcept; + + void performVec(dsp::Buffer const& input, dsp::Buffer& output) noexcept; + + virtual void compute(dsp::sample_t & result, dsp::sample_t const& lhs, dsp::sample_t const& rhs) = 0; + + private: + + std::atomic m_rhs{0.f}; + }; + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_OscTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_OscTilde.cpp new file mode 100644 index 00000000..fea4a563 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_OscTilde.cpp @@ -0,0 +1,179 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OSC~ // + // ================================================================================ // + + void OscTilde::declare() + { + Factory::add("osc~", &OscTilde::create); + } + + std::unique_ptr OscTilde::create(model::Object const& model, Patcher & patcher) + { + return std::make_unique(model, patcher); + } + + OscTilde::OscTilde(model::Object const& model, Patcher& patcher): + AudioObject(model, patcher) + { + std::vector const& args = model.getArguments(); + + if (!args.empty() && args[0].isNumber()) + { + setFrequency(args[0].getFloat()); + } + } + + void OscTilde::setFrequency(dsp::sample_t const& freq) noexcept + { + m_freq = freq; + } + + void OscTilde::setSampleRate(dsp::sample_t const& sample_rate) + { + m_sr = sample_rate; + } + + void OscTilde::setOffset(dsp::sample_t const& offset) noexcept + { + m_offset = fmodf(offset, 1.f); + } + + void OscTilde::receive(size_t index, std::vector const& args) + { + if (index == 0) + { + if (args[0].isNumber()) + { + setFrequency(args[0].getFloat()); + } + else + { + warning("osc~ inlet 1 doesn't understanc [" + args[0].getString() + "]"); + } + } + else if(index == 1 && args[0].isNumber()) + { + if (args[0].isNumber()) + { + setOffset(args[0].getFloat()); + } + else + { + warning("osc~ inlet 2 doesn't understand [" + args[0].getString() + "]"); + } + } + } + + void OscTilde::prepare(PrepareInfo const& infos) + { + setSampleRate(static_cast(infos.sample_rate)); + + if (infos.inputs[0] && infos.inputs[1]) + { + setPerformCallBack(this, &OscTilde::performPhaseAndFreq); + } + else if(infos.inputs[0]) + { + setPerformCallBack(this, &OscTilde::performFreq); + } + else if(infos.inputs[1]) + { + setPerformCallBack(this, &OscTilde::performPhase); + } + else + { + setPerformCallBack(this, &OscTilde::performValue); + } + } + + void OscTilde::performValue(dsp::Buffer const& input, dsp::Buffer& output) noexcept + { + dsp::sample_t *sig_data = output[0ul].data(); + size_t sample_index = output[0ul].size(); + dsp::sample_t const time_inc = m_freq/m_sr; + dsp::sample_t const offset = m_offset; + + while(sample_index--) + { + *sig_data++ = std::cos(2.f * dsp::pi * (m_time + offset)); + m_time += time_inc; + } + + m_time = fmodf(m_time, 1.f); + } + + void OscTilde::performFreq(dsp::Buffer const& input, dsp::Buffer& output) noexcept + { + size_t sample_index = output[0ul].size(); + dsp::sample_t* output_sig = output[0ul].data(); + dsp::sample_t const* freq = input[0ul].data(); + dsp::sample_t const offset = m_offset; + + while(sample_index--) + { + *output_sig++ = std::cos(2.f *dsp::pi * (m_time + offset)); + m_time += (*freq++ / m_sr); + } + + m_time = fmodf(m_time, 1.f); + } + + void OscTilde::performPhase(dsp::Buffer const& input, dsp::Buffer& output) noexcept + { + dsp::sample_t* output_sig = output[0ul].data(); + size_t sample_index = output[0ul].size(); + dsp::sample_t const* phase = input[1ul].data(); + dsp::sample_t const time_inc = m_freq/m_sr; + + while(sample_index--) + { + *output_sig++ = std::cos(2.f * dsp::pi * (m_time + fmodf(*phase++, 1.f))); + m_time += time_inc; + } + + m_time = fmodf(m_time, 1.f); + } + + void OscTilde::performPhaseAndFreq(dsp::Buffer const& input, dsp::Buffer& output) noexcept + { + size_t sample_index = output[0].size(); + dsp::sample_t* output_sig = output[0].data(); + dsp::sample_t const* freq = input[0].data(); + dsp::sample_t const* phase = input[1].data(); + + while(sample_index--) + { + *output_sig++ = std::cos(2.f * dsp::pi * (m_time + fmodf(*phase++, 1.f))); + m_time += (*freq++ / m_sr); + } + + m_time = fmodf(m_time, 1.f); + } + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_OscTilde.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_OscTilde.h new file mode 100644 index 00000000..12718f64 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_OscTilde.h @@ -0,0 +1,70 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OSC~ // + // ================================================================================ // + + class OscTilde : public AudioObject + { + public: // methods + + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher & patcher); + + OscTilde(model::Object const& model, Patcher& patcher); + + void receive(size_t index, std::vector const& args) override; + + void performValue(dsp::Buffer const& input, dsp::Buffer& output) noexcept; + + void performFreq(dsp::Buffer const& input, dsp::Buffer& output) noexcept; + + void performPhase(dsp::Buffer const& input, dsp::Buffer& output) noexcept; + + void performPhaseAndFreq(dsp::Buffer const& input, dsp::Buffer& output) noexcept; + + void prepare(dsp::Processor::PrepareInfo const& infos) override final; + + private: // methods + + void setFrequency(dsp::sample_t const& freq) noexcept; + + void setOffset(dsp::sample_t const& offset) noexcept; + + void setSampleRate(dsp::sample_t const& sample_rate); + + private: // members + + dsp::sample_t m_sr = 0.f; + dsp::sample_t m_time = 0.f; + std::atomic m_freq{0.f}; + std::atomic m_offset{0.f}; + }; + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Pipe.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Pipe.cpp new file mode 100644 index 00000000..1abfef75 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Pipe.cpp @@ -0,0 +1,80 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OBJECT PIPE // + // ================================================================================ // + + void Pipe::declare() + { + Factory::add("pipe", &Pipe::create); + } + + std::unique_ptr Pipe::create(model::Object const& model, Patcher & patcher) + { + return std::make_unique(model, patcher); + } + + Pipe::Pipe(model::Object const& model, Patcher& patcher): + Object(model, patcher), + m_delay(std::chrono::milliseconds(0)) + { + std::vector const& args = model.getArguments(); + + if (!args.empty()) + { + m_delay = std::chrono::milliseconds(args[0].getInt()); + } + } + + Pipe::~Pipe() + { + } + + void Pipe::receive(size_t index, std::vector const& args) + { + if (!args.empty()) + { + if (index == 0) + { + schedule([this, args](){send(0, args);}, m_delay); + } + else if(index == 1 && args[0].isNumber()) + { + if (args[0].isNumber()) + { + m_delay = std::chrono::milliseconds(args[0].getInt()); + } + else + { + warning("pipe inlet 2 doesn't understand [" + args[0].getString() + "]"); + } + } + } + } + +}} + diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Pipe.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Pipe.h new file mode 100644 index 00000000..0a421523 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Pipe.h @@ -0,0 +1,51 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OBJECT PIPE // + // ================================================================================ // + + class Pipe final : public engine::Object + { + public: // methods + + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher & patcher); + + Pipe(model::Object const& model, Patcher& patcher); + + ~Pipe(); + + void receive(size_t index, std::vector const& args) override; + + private: // members + + tool::Scheduler<>::clock_t::duration m_delay; + }; + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Plus.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Plus.cpp new file mode 100644 index 00000000..a65ec7af --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Plus.cpp @@ -0,0 +1,52 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OBJECT PLUS // + // ================================================================================ // + + void Plus::declare() + { + Factory::add("plus", &Plus::create); + } + + std::unique_ptr Plus::create(model::Object const& model, Patcher & patcher) + { + return std::make_unique(model, patcher); + } + + Plus::Plus(model::Object const& model, Patcher& patcher): + Operator(model, patcher) + { + } + + double Plus::compute(double lhs, double rhs) const + { + return lhs + rhs; + } + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Basic/KiwiEngine_ErrorBox.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Plus.h similarity index 56% rename from Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Basic/KiwiEngine_ErrorBox.h rename to Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Plus.h index b90a9218..5e76a318 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Basic/KiwiEngine_ErrorBox.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Plus.h @@ -21,25 +21,25 @@ #pragma once +#include #include -namespace kiwi -{ - namespace engine +namespace kiwi { namespace engine { + + // ================================================================================ // + // OBJECT PLUS // + // ================================================================================ // + + class Plus : public Operator { - // ================================================================================ // - // ERRORBOX // - // ================================================================================ // + public: - class ErrorBox : public AudioObject - { - public: - ErrorBox(model::Object const& model, Patcher& patcher, std::vector const& args); - - void receive(size_t index, std::vector const& args) override; - - void prepare(dsp::Processor::PrepareInfo const& infos) override final; - }; + static void declare(); - } -} + static std::unique_ptr create(model::Object const& model, Patcher& patcher); + + Plus(model::Object const& model, Patcher& patcher); + + double compute(double lhs, double rhs) const override final; + }; +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_PlusTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_PlusTilde.cpp new file mode 100644 index 00000000..2c9f2f64 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_PlusTilde.cpp @@ -0,0 +1,51 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // PLUS~ // + // ================================================================================ // + + void PlusTilde::declare() + { + Factory::add("plus~", &PlusTilde::create); + } + + std::unique_ptr PlusTilde::create(model::Object const& model, Patcher & patcher) + { + return std::make_unique(model, patcher); + } + + PlusTilde::PlusTilde(model::Object const& model, Patcher& patcher): + OperatorTilde(model, patcher) + { + } + + void PlusTilde::compute(dsp::sample_t & result, dsp::sample_t const& lhs, dsp::sample_t const& rhs) + { + result = lhs + rhs; + } + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_PlusTilde.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_PlusTilde.h new file mode 100644 index 00000000..39c09940 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_PlusTilde.h @@ -0,0 +1,45 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // PLUS~ // + // ================================================================================ // + + class PlusTilde : public OperatorTilde + { + public: // methods + + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher & patcher); + + PlusTilde(model::Object const& model, Patcher& patcher); + + void compute(dsp::sample_t & result, dsp::sample_t const& lhs, dsp::sample_t const& rhs); + }; + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Print.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Print.cpp new file mode 100644 index 00000000..7aa0cb97 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Print.cpp @@ -0,0 +1,61 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include + +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OBJECT PRINT // + // ================================================================================ // + + void Print::declare() + { + Factory::add("print", &Print::create); + } + + std::unique_ptr Print::create(model::Object const& model, Patcher& patcher) + { + return std::make_unique(model, patcher); + } + + Print::Print(model::Object const& model, Patcher& patcher) + : Object(model, patcher) + { + std::vector const& args = model.getArguments(); + + m_name = !args.empty() ? args[0].getString() : "print"; + } + + void Print::receive(size_t, std::vector const& args) + { + if(!args.empty()) + { + post(m_name + " \xe2\x80\xa2 " + tool::AtomHelper::toString(args)); + } + } + +}} + diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Print.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Print.h new file mode 100644 index 00000000..5eaef3ce --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Print.h @@ -0,0 +1,48 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OBJECT PRINT // + // ================================================================================ // + + class Print : public engine::Object + { + public: + + Print(model::Object const& model, Patcher& patcher); + + void receive(size_t, std::vector const& args) override; + + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher& patcher); + + private: + + std::string m_name; + }; +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Receive.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Receive.cpp new file mode 100644 index 00000000..c0851532 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Receive.cpp @@ -0,0 +1,82 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include + +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OBJECT RECEIVE // + // ================================================================================ // + + void Receive::declare() + { + Factory::add("receive", &Receive::create); + } + + std::unique_ptr Receive::create(model::Object const& model, Patcher& patcher) + { + return std::make_unique(model, patcher); + } + + Receive::Receive(model::Object const& model, Patcher& patcher): + Object(model, patcher), + m_name() + { + std::vector const& args = model.getArguments(); + + m_name = !args.empty() ? args[0].getString() : ""; + + if(!m_name.empty()) + { + tool::Beacon& beacon = getBeacon(m_name); + beacon.bind(*this); + } + } + + Receive::~Receive() + { + if(!m_name.empty()) + { + tool::Beacon& beacon = getBeacon(m_name); + beacon.unbind(*this); + } + } + + void Receive::receive(size_t, std::vector const& args) + { + + } + + void Receive::receive(std::vector const& args) + { + defer([this, args]() + { + send(0, args); + }); + } + +}} + diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Receive.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Receive.h new file mode 100644 index 00000000..a2322ea3 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Receive.h @@ -0,0 +1,57 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OBJECT RECEIVE // + // ================================================================================ // + + class Receive : public engine::Object, public tool::Beacon::Castaway + { + public: // methods + + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher& patcher); + + Receive(model::Object const& model, Patcher& patcher); + + ~Receive(); + + //! @brief inlets receive. + void receive(size_t, std::vector const& args) override; + + //! @brief beacon receive. + void receive(std::vector const& args) override; + + private: // members + + std::string m_name; + }; + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_SigTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_SigTilde.cpp new file mode 100644 index 00000000..8702e267 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_SigTilde.cpp @@ -0,0 +1,77 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // SIG~ // + // ================================================================================ // + + void SigTilde::declare() + { + Factory::add("sig~", &SigTilde::create); + } + + std::unique_ptr SigTilde::create(model::Object const& model, Patcher & patcher) + { + return std::make_unique(model, patcher); + } + + SigTilde::SigTilde(model::Object const& model, Patcher& patcher): + AudioObject(model, patcher) + { + std::vector const& args = model.getArguments(); + + if (!args.empty() && args[0].isNumber()) + { + m_value = args[0].getFloat(); + } + } + + void SigTilde::receive(size_t index, std::vector const& args) + { + if (index == 0 && args[0].isNumber()) + { + m_value = args[0].getFloat(); + } + } + + void SigTilde::perform(dsp::Buffer const& input, dsp::Buffer& output) noexcept + { + size_t sample_index = output[0].size(); + dsp::sample_t* output_sig = output[0].data(); + dsp::sample_t const value = m_value; + + while(sample_index--) + { + *output_sig++ = value; + } + } + + void SigTilde::prepare(dsp::Processor::PrepareInfo const& infos) + { + setPerformCallBack(this, &SigTilde::perform); + } + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_SigTilde.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_SigTilde.h new file mode 100644 index 00000000..7835e369 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_SigTilde.h @@ -0,0 +1,53 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // SIG~ // + // ================================================================================ // + + class SigTilde : public AudioObject + { + public: // methods + + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher & patcher); + + SigTilde(model::Object const& model, Patcher& patcher); + + void receive(size_t index, std::vector const& args) override final; + + void perform(dsp::Buffer const& input, dsp::Buffer& output) noexcept; + + void prepare(dsp::Processor::PrepareInfo const& infos) override final; + + private: // members + + std::atomic m_value{0.f}; + }; + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Slider.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Slider.cpp similarity index 55% rename from Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Slider.cpp rename to Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Slider.cpp index 6feee12b..516b7236 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Slider.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Slider.cpp @@ -22,68 +22,43 @@ #include #include -#include - -#include -#include +#include +#include namespace kiwi { namespace engine { - class Slider::Task final : public tool::Scheduler<>::Task - { - public: // methods - - Task(double output_value, Slider & slider): - m_output_value(output_value), - m_slider(slider) - { - } - - ~Task() - { - } - - void execute() - { - m_slider.m_value = m_output_value; - m_slider.send(0, {m_slider.m_value}); - } - - private: // members - - double m_output_value; - Slider & m_slider; - }; - // ================================================================================ // // OBJECT SLIDER // // ================================================================================ // - Slider::Slider(model::Object const& object_model, Patcher& patcher, std::vector const& args): + void Slider::declare() + { + Factory::add("slider", &Slider::create); + } + + std::unique_ptr Slider::create(model::Object const& model, Patcher& patcher) + { + return std::make_unique(model, patcher); + } + + Slider::Slider(model::Object const& object_model, Patcher& patcher): Object(object_model, patcher), - m_signal(object_model.getSignal(model::Slider::Signal::ValueChanged)), - m_connection(m_signal.connect(std::bind(&Slider::valueChanged, this, std::placeholders::_1))), - m_tasks(100), - m_value(0) + m_value(object_model.getParameter("value")[0].getFloat()) { } Slider::~Slider() { - while(m_tasks.load_size() > 0) - { - std::shared_ptr task; - m_tasks.pop(task); - getScheduler().unschedule(task); - } } - void Slider::valueChanged(double new_value) + void Slider::parameterChanged(std::string const& name, tool::Parameter const& parameter) { - std::shared_ptr task(new Task(new_value, *this)); - m_tasks.push(task); - getScheduler().schedule(task); + if (name == "value") + { + m_value = parameter[0].getFloat(); + send(0, {m_value}); + } } void Slider::receive(size_t index, std::vector const& args) @@ -92,12 +67,16 @@ namespace kiwi { namespace engine { { if (args[0].isNumber()) { - m_signal(std::max(0., std::min(args[0].getFloat(), 1.))); + setParameter("value", tool::Parameter(tool::Parameter::Type::Float, {args[0].getFloat()})); } else if (args[0].isString() && args[0].getString() == "bang") { send(0, {m_value}); } + else + { + warning("slider inlet 1 doesn't understand [" + args[0].getString() + "]"); + } } } diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Slider.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Slider.h similarity index 73% rename from Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Slider.h rename to Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Slider.h index f5a2dce8..2fa88050 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Controller/KiwiEngine_Slider.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Slider.h @@ -24,9 +24,9 @@ #include #include -#include - #include +#include + #include #include @@ -34,31 +34,28 @@ namespace kiwi { namespace engine { // ================================================================================ // - // OBJECT BANG // + // OBJECT SLIDER // // ================================================================================ // class Slider : public engine::Object { - private: // classes - - class Task; - public: // methods - Slider(model::Object const& model, Patcher& patcher, std::vector const& args); + Slider(model::Object const& model, Patcher& patcher); ~Slider(); - void valueChanged(double new_value); + void parameterChanged(std::string const& name, tool::Parameter const& param) override final; void receive(size_t index, std::vector const& args) override final; - private: // members + static void declare(); - flip::Signal & m_signal; - flip::SignalConnection m_connection; - tool::ConcurrentQueue> m_tasks; - double m_value; + static std::unique_ptr create(model::Object const& model, Patcher& patcher); + + private: // members + + double m_value; }; }} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Delay.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Delay.h deleted file mode 100644 index 9fad2de9..00000000 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Delay.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#pragma once - -#include - -namespace kiwi -{ - namespace engine - { - // ================================================================================ // - // OBJECT DELAY // - // ================================================================================ // - - class Delay final : public engine::Object - { - public: // methods - - Delay(model::Object const& model, Patcher& patcher, std::vector const& args); - - ~Delay(); - - void receive(size_t index, std::vector const& args) override; - - private: // members - - struct Task final : public tool::Scheduler<>::Task - { - Task(Delay & object); - ~Task() = default; - void execute() override; - - private: - Delay& m_object; - }; - - std::shared_ptr m_task; - tool::Scheduler<>::clock_t::duration m_delay; - }; - } -} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Metro.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Metro.cpp deleted file mode 100644 index 4d395c2c..00000000 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Metro.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#include - -namespace kiwi -{ - namespace engine - { - // ================================================================================ // - // OBJECT METRO // - // ================================================================================ // - - Metro::Metro(model::Object const& model, Patcher& patcher, std::vector const& args): - engine::Object(model, patcher), - tool::Scheduler<>::Timer(patcher.getScheduler()), - m_period(std::chrono::milliseconds(0)) - { - if(!args.empty()) - { - m_period = std::chrono::milliseconds(args[0].getInt()); - } - } - - Metro::~Metro() - { - } - - void Metro::receive(size_t index, std::vector const& args) - { - if (!args.empty()) - { - if (index == 0) - { - if((args[0].isString() && args[0].getString() == "start") - || (args[0].isNumber() && static_cast(args[0].getInt()))) - { - timerCallBack(); - startTimer(m_period); - } - else if((args[0].isString() && args[0].getString() == "stop") - || (args[0].isNumber() && !static_cast(args[0].getInt()))) - { - stopTimer(); - } - } - else if(index == 1) - { - if (args[0].isNumber()) - { - m_period = std::chrono::milliseconds(args[0].getInt()); - } - } - } - } - - void Metro::timerCallBack() - { - send(0, {"bang"}); - } - - } -} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Metro.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Metro.h deleted file mode 100644 index 07441d3c..00000000 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Metro.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#pragma once - -#include - -namespace kiwi -{ - namespace engine - { - // ================================================================================ // - // OBJECT METRO // - // ================================================================================ // - - class Metro final : public engine::Object, tool::Scheduler<>::Timer - { - public: // methods - - Metro(model::Object const& model, Patcher& patcher, std::vector const& args); - - ~Metro(); - - void receive(size_t index, std::vector const& args) override; - - void timerCallBack() override; - - private: // members - - tool::Scheduler<>::duration_t m_period; - }; - } -} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Pipe.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Pipe.cpp deleted file mode 100644 index 8dbeff95..00000000 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Pipe.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#include - -namespace kiwi -{ - namespace engine - { - // ================================================================================ // - // OBJECT PIPE // - // ================================================================================ // - - class Pipe::Task final : public tool::Scheduler<>::Task - { - public: // methods - - Task(Pipe & object, std::vector const& atoms): - tool::Scheduler<>::Task(), - m_object(object), - m_atoms(atoms) - { - } - - ~Task() - { - } - - void execute() - { - m_object.send(0, m_atoms); - - m_object.m_tasks.erase(std::find_if(m_object.m_tasks.begin(), - m_object.m_tasks.end(), - [this](std::shared_ptr const& task) - { - return task.get() == this; - })); - } - - private: // members - - Pipe& m_object; - std::vector m_atoms; - }; - - Pipe::Pipe(model::Object const& model, Patcher& patcher, std::vector const& args): - Object(model, patcher), - m_tasks(), - m_delay(std::chrono::milliseconds(0)) - { - if (!args.empty()) - { - m_delay = std::chrono::milliseconds(args[0].getInt()); - } - } - - Pipe::~Pipe() - { - for (std::shared_ptr const& task : m_tasks) - { - getScheduler().unschedule(task); - } - } - - void Pipe::receive(size_t index, std::vector const& args) - { - if (!args.empty()) - { - if (index == 0) - { - std::shared_ptr task(new Task(*this, args)); - getScheduler().schedule(task, m_delay); - m_tasks.insert(std::move(task)); - } - else if(index == 1 && args[0].isNumber()) - { - m_delay = std::chrono::milliseconds(args[0].getInt()); - } - } - } - } -} - diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Pipe.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Pipe.h deleted file mode 100644 index a0c2e53c..00000000 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Time/KiwiEngine_Pipe.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#pragma once - -#include - -namespace kiwi -{ - namespace engine - { - // ================================================================================ // - // OBJECT PIPE // - // ================================================================================ // - - class Pipe final : public engine::Object - { - public: // classes - - class Task; - - public: // methods - - Pipe(model::Object const& model, Patcher& patcher, std::vector const& args); - - ~Pipe(); - - void receive(size_t index, std::vector const& args) override; - - private: // members - - std::set> m_tasks; - tool::Scheduler<>::clock_t::duration m_delay; - }; - } -} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Times.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Times.cpp new file mode 100644 index 00000000..3ea172a0 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Times.cpp @@ -0,0 +1,51 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace engine{ + + // ================================================================================ // + // OBJECT TIMES // + // ================================================================================ // + + void Times::declare() + { + Factory::add("times", &Times::create); + } + + std::unique_ptr Times::create(model::Object const& model, Patcher & patcher) + { + return std::make_unique(model, patcher); + } + + Times::Times(model::Object const& model, Patcher& patcher): + Operator(model, patcher) + { + } + + double Times::compute(double lhs, double rhs) const + { + return lhs * rhs; + } + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Print.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Times.h similarity index 56% rename from Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Print.h rename to Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Times.h index 7864f923..4ab4cdcf 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message/KiwiEngine_Print.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Times.h @@ -21,26 +21,26 @@ #pragma once +#include #include -namespace kiwi -{ - namespace engine +namespace kiwi { namespace engine { + + // ================================================================================ // + // OBJECT TIMES // + // ================================================================================ // + + class Times : public Operator { - // ================================================================================ // - // OBJECT PRINT // - // ================================================================================ // + public: - class Print : public engine::Object - { - public: - - Print(model::Object const& model, Patcher& patcher, std::vector const& args); - - void receive(size_t, std::vector const& args) override; - - private: - std::string m_name; - }; - } -} + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher& patcher); + + Times(model::Object const& model, Patcher& patcher); + + double compute(double lhs, double rhs) const override final; + }; + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_TimesTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_TimesTilde.cpp new file mode 100644 index 00000000..808db852 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_TimesTilde.cpp @@ -0,0 +1,51 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // TIMES~ // + // ================================================================================ // + + void TimesTilde::declare() + { + Factory::add("times~", &TimesTilde::create); + } + + std::unique_ptr TimesTilde::create(model::Object const& model, Patcher & patcher) + { + return std::make_unique(model, patcher); + } + + TimesTilde::TimesTilde(model::Object const& model, Patcher& patcher): + OperatorTilde(model, patcher) + { + } + + void TimesTilde::compute(dsp::sample_t & result, dsp::sample_t const& lhs, dsp::sample_t const& rhs) + { + result = lhs * rhs; + } + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_TimesTilde.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_TimesTilde.h new file mode 100644 index 00000000..cf49563b --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_TimesTilde.h @@ -0,0 +1,45 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // TIMES~ // + // ================================================================================ // + + class TimesTilde : public OperatorTilde + { + public: // methods + + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher & patcher); + + TimesTilde(model::Object const& model, Patcher& patcher); + + void compute(dsp::sample_t & result, dsp::sample_t const& lhs, dsp::sample_t const& rhs) override final; + }; + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Toggle.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Toggle.cpp new file mode 100644 index 00000000..1087ce96 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Toggle.cpp @@ -0,0 +1,125 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OBJECT TOGGLE // + // ================================================================================ // + + void Toggle::declare() + { + Factory::add("toggle", &Toggle::create); + } + + std::unique_ptr Toggle::create(model::Object const& model, Patcher & patcher) + { + return std::make_unique(model, patcher); + } + + Toggle::Toggle(model::Object const& model, Patcher& patcher): + Object(model, patcher), + m_connection(model.getSignal<>(model::Toggle::Signal::OutputValue) + .connect(std::bind(&Toggle::outputValue, this))), + m_is_on(false) + { + } + + Toggle::~Toggle() + { + } + + void Toggle::parameterChanged(std::string const& name, tool::Parameter const& param) + { + if (name == "value") + { + m_is_on = static_cast(param[0].getInt()); + } + } + + void Toggle::outputValue() + { + defer([this]() + { + send(0, {m_is_on}); + }); + } + + void Toggle::receive(size_t index, std::vector const& args) + { + if (!args.empty()) + { + if (index == 0) + { + if(args[0].isString()) + { + if (args[0].getString() == "bang") + { + send(0, {!m_is_on}); + setParameter("value", tool::Parameter(tool::Parameter::Type::Int, {!m_is_on})); + } + else if(args.size() == 2 && args[0].getString() == "set") + { + if (args[1].isNumber()) + { + if (args[1].getFloat() != 0) + { + setParameter("value", tool::Parameter(tool::Parameter::Type::Int, {1})); + } + else + { + setParameter("value", tool::Parameter(tool::Parameter::Type::Int, {0})); + } + } + else + { + warning("toggle set requires number value"); + } + } + else + { + warning("toggle doesn't understand message [" + args[0].getString() + "]"); + } + } + else if(args[0].isNumber()) + { + if (args[0].getFloat() != 0) + { + send(0, {true}); + setParameter("value", tool::Parameter(tool::Parameter::Type::Int, {1})); + } + else + { + send(0, {false}); + setParameter("value", tool::Parameter(tool::Parameter::Type::Int, {0})); + } + } + } + } + } + +}} + diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Toggle.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Toggle.h new file mode 100644 index 00000000..23a315cf --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Toggle.h @@ -0,0 +1,61 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OBJECT TOGGLE // + // ================================================================================ // + + class Toggle : public engine::Object + { + private: // classes + + class Task; + + public: // methods + + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher & patcher); + + Toggle(model::Object const& model, Patcher& patcher); + + ~Toggle(); + + void parameterChanged(std::string const& name, tool::Parameter const& param) override final; + + void receive(size_t index, std::vector const& args) override final; + + private: // methods + + void outputValue(); + + private: // members + + flip::SignalConnection m_connection; + bool m_is_on; + }; +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Utils/KiwiEngine_AudioInterface.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Utils/KiwiEngine_AudioInterface.cpp deleted file mode 100644 index bb3dee25..00000000 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Utils/KiwiEngine_AudioInterface.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#include - -namespace kiwi -{ - namespace engine - { - // ================================================================================ // - // AUDIOINTERFACE // - // ================================================================================ // - - AudioInterfaceObject::AudioInterfaceObject(model::Object const& model, - Patcher& patcher, - std::vector const& args): - AudioObject(model, patcher), - m_router(), - m_audio_controler(patcher.getAudioControler()) - { - } - - std::vector AudioInterfaceObject::parseArgs(std::vector const& args) const - { - std::vector routes; - - for(tool::Atom const& arg : args) - { - if (arg.isNumber()) - { - routes.push_back(arg.getInt() - 1); - } - else if(arg.isString()) - { - std::string inputs(arg.getString()); - - int left_input = std::stoi(inputs.substr(0, inputs.find(":"))) - 1; - int right_input = std::stoi(inputs.substr(inputs.find(":") + 1)) - 1; - - bool rev = left_input > right_input; - - for (int channel = left_input; rev ? channel >= right_input : channel <= right_input; rev ? --channel : ++channel) - { - routes.push_back(channel); - } - } - } - - if (routes.empty()) - { - routes = {0, 1}; - } - - return routes; - } - - void AudioInterfaceObject::receive(size_t index, std::vector const & args) - { - if(!args.empty()) - { - if(args[0].isString()) - { - const std::string sym = args[0].getString(); - - if(sym == "start") - { - m_audio_controler.startAudio(); - } - else if(sym == "stop") - { - m_audio_controler.stopAudio(); - } - } - } - } - } -} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Utils/KiwiEngine_AudioInterface.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Utils/KiwiEngine_AudioInterface.h deleted file mode 100644 index 939662b3..00000000 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Utils/KiwiEngine_AudioInterface.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#pragma once - -#include -#include - -#include - -namespace kiwi -{ - namespace engine - { - // ================================================================================ // - // AUDIO_INTERFACE // - // ================================================================================ // - - class AudioInterfaceObject : public AudioObject - { - public: // methods - - AudioInterfaceObject(model::Object const& model, Patcher& patcher, std::vector const& args); - - void receive(size_t index, std::vector const & args) override final; - - std::vector parseArgs(std::vector const& args) const; - - virtual ~AudioInterfaceObject() = default; - - protected: // members - - Router m_router; - engine::AudioControler& m_audio_controler; - }; - } -} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Utils/KiwiEngine_Router.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Utils/KiwiEngine_Router.cpp deleted file mode 100644 index 4d545dc4..00000000 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Utils/KiwiEngine_Router.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#include - -namespace kiwi -{ - namespace engine - { - // ================================================================================ // - // ROUTER // - // ================================================================================ // - - Router::Cnx::Cnx(size_t input, size_t output): - m_input(input), - m_output(output) - { - } - - bool Router::Cnx::operator<(Cnx const& other) const - { - return m_input < other.m_input - || (m_input == other.m_input && m_output < other.m_output); - } - - void Router::connect(size_t input_index, size_t output_index) - { - m_cnx.insert(Cnx(input_index, output_index)); - } - - void Router::disconnect(size_t input_index, size_t ouptut_index) - { - m_cnx.erase(Cnx(input_index, ouptut_index)); - } - - size_t Router::getNumberOfConnections() const - { - return m_cnx.size(); - } - - std::set const& Router::getConnections() const - { - return m_cnx; - } - } -} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Utils/KiwiEngine_Router.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Utils/KiwiEngine_Router.h deleted file mode 100644 index 773d6e7e..00000000 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Utils/KiwiEngine_Router.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#pragma once - -#include -#include - -namespace kiwi -{ - namespace engine - { - // ================================================================================ // - // ROUTER // - // ================================================================================ // - - class Router - { - public: // classes - - struct Cnx - { - Cnx(size_t input, size_t output); - - bool operator<(Cnx const& other) const; - - size_t m_input = 0; - size_t m_output = 0; - }; - - public: // method - - Router() = default; - - void connect(size_t input_index, size_t output_index); - - void disconnect(size_t intput_index, size_t output_index); - - size_t getNumberOfConnections() const; - - std::set const& getConnections() const; - - ~Router() = default; - - private: // memebers - - std::set m_cnx; - }; - } -} diff --git a/Modules/KiwiEngine/KiwiEngine_Patcher.cpp b/Modules/KiwiEngine/KiwiEngine_Patcher.cpp index d1a6f161..f3a6282e 100644 --- a/Modules/KiwiEngine/KiwiEngine_Patcher.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Patcher.cpp @@ -36,12 +36,12 @@ namespace kiwi // PATCHER // // ================================================================================ // - Patcher::Patcher(Instance& instance) noexcept : + Patcher::Patcher(Instance& instance, model::Patcher & patcher_model) noexcept : m_instance(instance), m_objects(), - m_mutex(), m_so_links(1), - m_chain() + m_chain(), + m_patcher_model(patcher_model) { m_instance.getAudioControler().add(m_chain); } @@ -51,6 +51,11 @@ namespace kiwi m_instance.getAudioControler().remove(m_chain); } + model::Patcher & Patcher::getPatcherModel() + { + return m_patcher_model; + } + void Patcher::addObject(uint64_t object_id, std::shared_ptr object) { m_objects[object_id] = object; @@ -196,6 +201,11 @@ namespace kiwi return m_instance.getScheduler(); } + tool::Scheduler<> & Patcher::getMainScheduler() const + { + return m_instance.getMainScheduler(); + } + // ================================================================================ // // BEACON // // ================================================================================ // @@ -213,48 +223,94 @@ namespace kiwi { if(model.changed()) { - const bool link_changed = model.linksChanged(); + updateGraph(model); + + updateAttributes(model); - // check links before objects - if(link_changed) + updateChain(); + } + } + + void Patcher::updateGraph(model::Patcher const& patcher_model) + { + std::set added_links; + std::set removed_links; + std::set added_objects; + std::set removed_objects; + + if (patcher_model.linksChanged()) + { + for (auto const& link : patcher_model.getLinks()) { - for(auto const& link : model.getLinks()) + if (link.added()) { - if(link.removed()) - { - linkRemoved(link); - } + added_links.insert(&link); + } + if (link.removed()) + { + removed_links.insert(&link); } } - - if(model.objectsChanged()) + } + + if (patcher_model.objectsChanged()) + { + for(auto const & object : patcher_model.getObjects()) { - for(auto& object : model.getObjects()) + if(object.added()) { - if(object.added()) - { - objectAdded(object); - } - else if(object.removed()) - { - objectRemoved(object); - } + added_objects.insert(&object); + } + else if(object.removed()) + { + removed_objects.insert(&object); } } + } + + if (!added_links.empty() || !removed_links.empty() || !added_objects.empty() || !removed_objects.empty()) + { + std::unique_lock lock(getScheduler().lock()); + + for (auto link : removed_links) + { + linkRemoved(*link); + } + + for (auto object : added_objects) + { + objectAdded(*object); + } - // check links before objects - if(link_changed) + for (auto object : removed_objects) { - for(auto& link : model.getLinks()) + objectRemoved(*object); + } + + for (auto link : added_links) + { + linkAdded(*link); + } + } + } + + void Patcher::updateAttributes(model::Patcher const& patcher_model) + { + if (patcher_model.objectsChanged()) + { + for(auto const & object : patcher_model.getObjects()) + { + if (!object.removed() && !object.added()) { - if(link.added()) + std::set changed_params = object.getChangedAttributes(); + + for (std::string const& param_name : changed_params) { - linkAdded(link); + m_objects.at(object.ref().obj())->modelAttributeChanged(param_name, + object.getAttribute(param_name)); } } } - - updateChain(); } } diff --git a/Modules/KiwiEngine/KiwiEngine_Patcher.h b/Modules/KiwiEngine/KiwiEngine_Patcher.h index 73d9d078..e485e8fb 100644 --- a/Modules/KiwiEngine/KiwiEngine_Patcher.h +++ b/Modules/KiwiEngine/KiwiEngine_Patcher.h @@ -31,6 +31,8 @@ #include +#include + namespace kiwi { namespace engine @@ -49,7 +51,7 @@ namespace kiwi public: // methods //! @brief Constructor. - Patcher(Instance& instance) noexcept; + Patcher(Instance& instance, model::Patcher & patcher_model) noexcept; //! @brief Destructor. ~Patcher(); @@ -92,6 +94,9 @@ namespace kiwi //! @internal Call the loadbang method of all objects. void sendLoadbang(); + //! @brief Returns the patcher's data model. + model::Patcher & getPatcherModel(); + // ================================================================================ // // CONSOLE // // ================================================================================ // @@ -115,6 +120,9 @@ namespace kiwi //! @brief Returns the engine's scheduler. tool::Scheduler<> & getScheduler() const; + //! @brief Returns the main scheduler + tool::Scheduler<> & getMainScheduler() const; + // ================================================================================ // // BEACON // // ================================================================================ // @@ -124,6 +132,12 @@ namespace kiwi private: // methods + //! @internal Update the patcher's graph according to datamodel. + void updateGraph(model::Patcher const& patcher_model); + + //! @internal Updates obects' parameters according to there data model. + void updateAttributes(model::Patcher const& patcher_model); + //! @internal Object model has just been added to the document. void objectAdded(model::Object const& object); @@ -148,9 +162,9 @@ namespace kiwi Instance& m_instance; std::map> m_objects; - mutable std::mutex m_mutex; std::vector m_so_links; dsp::Chain m_chain; + model::Patcher & m_patcher_model; private: // deleted methods diff --git a/Modules/KiwiModel/KiwiModel_DataModel.cpp b/Modules/KiwiModel/KiwiModel_DataModel.cpp index caaaa8b8..884d2c43 100644 --- a/Modules/KiwiModel/KiwiModel_DataModel.cpp +++ b/Modules/KiwiModel/KiwiModel_DataModel.cpp @@ -19,12 +19,11 @@ ============================================================================== */ -#include "flip/DataModel.h" +#include -#include "KiwiModel_Def.h" -#include "KiwiModel_DataModel.h" -#include "KiwiModel_PatcherUser.h" -#include +#include +#include +#include namespace kiwi { @@ -32,11 +31,36 @@ namespace kiwi { bool DataModel::initialised = false; - void DataModel::init() + void DataModel::declareObjects() + { + model::NewBox::declare(); + model::ErrorBox::declare(); + model::Slider::declare(); + model::Print::declare(); + model::Receive::declare(); + model::Plus::declare(); + model::Times::declare(); + model::Delay::declare(); + model::Metro::declare(); + model::Pipe::declare(); + model::Bang::declare(); + model::Toggle::declare(); + model::AdcTilde::declare(); + model::DacTilde::declare(); + model::OscTilde::declare(); + model::Loadmess::declare(); + model::PlusTilde::declare(); + model::TimesTilde::declare(); + model::SigTilde::declare(); + model::MeterTilde::declare(); + model::DelaySimpleTilde::declare(); + } + + void DataModel::init(std::function declare_object) { assert(!initialised); if(initialised) return; // abort - + const std::string model_version = KIWI_MODEL_VERSION_STRING; #ifdef DEBUG @@ -48,7 +72,7 @@ namespace kiwi // patcher elements declaration : model::Object::declare(); - declareObjects(); + declare_object(); // Links Link::declare(); @@ -58,30 +82,5 @@ namespace kiwi initialised = true; } - - void DataModel::declareObjects() - { - NewBox::declare(); - ErrorBox::declare(); - Plus::declare(); - Times::declare(); - Print::declare(); - Receive::declare(); - Loadmess::declare(); - Delay::declare(); - Pipe::declare(); - Metro::declare(); - DacTilde::declare(); - AdcTilde::declare(); - OscTilde::declare(); - TimesTilde::declare(); - PlusTilde::declare(); - SigTilde::declare(); - DelaySimpleTilde::declare(); - Bang::declare(); - Toggle::declare(); - Slider::declare(); - MeterTilde::declare(); - } } } diff --git a/Modules/KiwiModel/KiwiModel_DataModel.h b/Modules/KiwiModel/KiwiModel_DataModel.h index b9dec28d..e0dbbbfe 100644 --- a/Modules/KiwiModel/KiwiModel_DataModel.h +++ b/Modules/KiwiModel/KiwiModel_DataModel.h @@ -21,7 +21,11 @@ #pragma once -#include "flip/DataModel.h" +#include + +#include + +#include namespace kiwi { @@ -32,15 +36,14 @@ namespace kiwi { public: // methods - //! @brief Initializes the model. - //! @details Declares all flip classes. - static void init(); - - private: // methods - - //! @brief Declare all kiwi objects. + //! @brief Declare objects. static void declareObjects(); + //! @brief Initializes the model. + //! @details By default will declare all objects. + //! Can be overriden to declare custom objects or only a few objects. + static void init(std::function declare_object = &DataModel::declareObjects); + public: // members static bool initialised; diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_AdcTilde.h b/Modules/KiwiModel/KiwiModel_Error.h similarity index 53% rename from Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_AdcTilde.h rename to Modules/KiwiModel/KiwiModel_Error.h index b8da5325..3fdcd760 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Dsp/KiwiEngine_AdcTilde.h +++ b/Modules/KiwiModel/KiwiModel_Error.h @@ -1,46 +1,47 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#pragma once - -#include - -namespace kiwi -{ - namespace engine - { - - // ================================================================================ // - // ADC~ // - // ================================================================================ // - - class AdcTilde : public AudioInterfaceObject - { - public: // methods - - AdcTilde(model::Object const& model, Patcher& patcher, std::vector const& args); - - void perform(dsp::Buffer const& input, dsp::Buffer& output) noexcept; - - void prepare(dsp::Processor::PrepareInfo const& infos) override final; - }; - } -} +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +namespace kiwi { namespace model { + + // ==================================================================================== // + // ERROR // + // ==================================================================================== // + + //! @brief A generic exception for engine failures. + class Error : public std::runtime_error + { + public: + + //! @brief The std::string constructor. + explicit Error(const std::string& message) : + std::runtime_error(std::string("kiwi::model ") + message) {} + + //! @brief The const char* constructor. + explicit Error(const char* message) : + std::runtime_error(std::string("kiwi::model ") + std::string(message)) {} + + //! @brief The destructor. + virtual inline ~Error() noexcept = default; + }; + +}} diff --git a/Modules/KiwiModel/KiwiModel_Factory.cpp b/Modules/KiwiModel/KiwiModel_Factory.cpp index 7abd7cd0..52669b0a 100644 --- a/Modules/KiwiModel/KiwiModel_Factory.cpp +++ b/Modules/KiwiModel/KiwiModel_Factory.cpp @@ -19,7 +19,7 @@ ============================================================================== */ -#include +#include #include "KiwiModel_Factory.h" @@ -31,6 +31,8 @@ namespace kiwi // FACTORY // // ================================================================================ // + std::vector> Factory::m_object_classes; + std::unique_ptr Factory::create(std::vector const& atoms) { std::unique_ptr object; @@ -51,7 +53,7 @@ namespace kiwi std::vector args(atoms.empty() ? atoms.begin() : atoms.begin() + 1, atoms.end()); object = object_class->create(args); } - catch(std::runtime_error & e) + catch(model::Object::Error & e) { object_class = getClassByName("errorbox"); @@ -60,7 +62,6 @@ namespace kiwi } } - object->m_name = object_class->getName(); object->m_text = tool::AtomHelper::toString(atoms); return object; @@ -69,6 +70,7 @@ namespace kiwi std::unique_ptr Factory::create(std::string const& name, flip::Mold const& mold) { auto const* class_ptr = getClassByName(name); + if(class_ptr != nullptr) { return class_ptr->moldCast(mold); @@ -95,8 +97,7 @@ namespace kiwi bool Factory::has(std::string const& name) { - const auto& object_classes = getClasses(); - for(const auto& object_class : object_classes) + for(const auto& object_class : m_object_classes) { if(object_class->getName() == name || object_class->hasAlias(name)) return true; @@ -105,11 +106,10 @@ namespace kiwi return false; } - Factory::ObjectClassBase* Factory::getClassByName(std::string const& name, - const bool ignore_aliases) + ObjectClass const* Factory::getClassByName(std::string const& name, + const bool ignore_aliases) { - const auto& object_classes = getClasses(); - for(const auto& object_class : object_classes) + for(const auto& object_class : m_object_classes) { if(object_class->getName() == name || (!ignore_aliases && object_class->hasAlias(name))) return object_class.get(); @@ -118,15 +118,26 @@ namespace kiwi return nullptr; } + ObjectClass const* Factory::getClassByTypeId(size_t type_id) + { + auto found_class = std::find_if(m_object_classes.begin(), + m_object_classes.end(), + [type_id](std::unique_ptr const& object_class) + { + return object_class->m_type_id == type_id; + }); + + return found_class != m_object_classes.end() ? found_class->get() : nullptr; + } + std::vector Factory::getNames(const bool ignore_aliases, const bool ignore_internals) { - auto const& object_classes = getClasses(); std::vector names; - names.reserve(object_classes.size()); + names.reserve(m_object_classes.size()); - for(const auto& object_class : object_classes) + for(const auto& object_class : m_object_classes) { - if(!object_class->isInternal() || !ignore_internals) + if(!object_class->hasFlag(ObjectClass::Flag::Internal) || !ignore_internals) { names.emplace_back(object_class->getName()); @@ -160,11 +171,5 @@ namespace kiwi return model_name; } - - auto Factory::getClasses() -> object_classes_t& - { - static object_classes_t static_object_classes; - return static_object_classes; - } } } diff --git a/Modules/KiwiModel/KiwiModel_Factory.h b/Modules/KiwiModel/KiwiModel_Factory.h index e1240879..f35acc6a 100644 --- a/Modules/KiwiModel/KiwiModel_Factory.h +++ b/Modules/KiwiModel/KiwiModel_Factory.h @@ -21,8 +21,14 @@ #pragma once -#include "KiwiModel_Object.h" -#include "KiwiModel_DataModel.h" +#include +#include +#include +#include + +#include +#include +#include namespace kiwi { @@ -35,11 +41,6 @@ namespace kiwi //! @brief The model Object's factory class Factory { - public: // classes - - class ObjectClassBase; - template class ObjectClass; - public: // methods //! @brief isValidObject type traits @@ -54,7 +55,6 @@ namespace kiwi { value = std::is_base_of::value && !std::is_abstract::value - && std::is_constructible>::value && std::is_constructible::value }; }; @@ -65,24 +65,58 @@ namespace kiwi //! thus if you pass a different name later, this will imply a breaking change in the DataModel. //! @param name The name of the object (must not be empty and not already used by another object or alias name in the Factory). template - static ObjectClass& add(std::string const& name) + static void add(std::unique_ptr object_class, + flip::Class & data_model) { static_assert(isValidObject::value, "Not a valid Object"); - assert((!name.empty() && !DataModel::has()) - && "Object name empty or object class already added"); + std::string object_name = object_class->getName(); + + assert(std::string(data_model.name()) == object_class->getModelName()); + assert(!object_name.empty() && "Registring object with invalid name"); + assert(DataModel::has() && "Registering object without declaring its data model"); // check if the name match the name of another object in the factory. - if(has(name)) + if(has(object_name)) { - throw std::runtime_error("The \"" + name + "\" object is already in the factory"); + throw std::runtime_error("The \"" + object_name + "\" object is already in the factory"); } - - auto& object_classes = getClasses(); - const auto it = object_classes.emplace(object_classes.end(), - std::make_unique>(name)); - return dynamic_cast&>(*(it->get())); + // check aliases duplicates + std::set const& aliases = object_class->getAliases(); + + auto duplicate_aliases = std::find_if(aliases.begin(), + aliases.end(), + [](std::string const& alias) + { + return Factory::has(alias); + }); + + if (duplicate_aliases != aliases.end()) + { + throw std::runtime_error(object_name + "Adding twice the same alias"); + } + + ObjectClass::mold_maker_t mold_maker = [](model::Object const& object, flip::Mold& mold) + { + mold.make(static_cast(object), false); + }; + + object_class->setMoldMaker(mold_maker); + + ObjectClass::mold_caster_t mold_caster = [](flip::Mold const& mold) + { + flip::Default d; + auto object_uptr = std::make_unique(d); + mold.cast(static_cast(*(object_uptr.get()))); + return object_uptr; + }; + + object_class->setMoldCaster(mold_caster); + + object_class->setTypeId(typeid(TModel).hash_code()); + + m_object_classes.emplace_back(std::move(object_class)); } //! @brief Creates a new Object with a name and arguments. @@ -112,8 +146,11 @@ namespace kiwi //! @param name The name or an alias name of the class. //! @param ignore_aliases Default to false, pass true to ignore aliases. //! @return A ptr to an ObjectClassBase. - static ObjectClassBase* getClassByName(std::string const& name, - const bool ignore_aliases = false); + static ObjectClass const* getClassByName(std::string const& name, + const bool ignore_aliases = false); + + //! @brief Returns the object's class filtering by type id's hash code. + static ObjectClass const* getClassByTypeId(size_t type_id); //! @brief Returns true if a given string match a registered object class name. //! @param name The name of the object class to find. @@ -127,178 +164,17 @@ namespace kiwi static std::vector getNames(const bool ignore_aliases = false, const bool ignore_internals = true); - private: // methods - - using object_classes_t = std::vector>; - - using ctor_fn_t = std::function(std::vector)>; - using mold_maker_fn_t = std::function; - using mold_caster_fn_t = std::function(flip::Mold const&)>; - - //! @internal Returns a constructor function. - template - static ctor_fn_t getCtor(std::string const& name) - { - return [name](std::vector const& args) - { - return std::make_unique(name, args); - }; - } - - //! @internal Returns a mold maker function. - template - static mold_maker_fn_t getMoldMaker() - { - return [](model::Object const& object, flip::Mold& mold) - { - // make a mold with container_flag active - mold.make(static_cast(object), false); - }; - } - - //! @internal Returns a mold caster function. - template - static mold_caster_fn_t getMoldCaster() - { - return [](flip::Mold const& mold) - { - flip::Default d; - auto object_uptr = std::make_unique(d); - mold.cast(static_cast(*(object_uptr.get()))); - return object_uptr; - }; - } - //! @internal Returns a sanitized version of the string. static std::string sanitizeName(std::string const& name); - //! @internal Returns the object classes. - static object_classes_t& getClasses(); + private: // members + + static std::vector> m_object_classes; private: // deleted methods Factory() = delete; ~Factory() = delete; }; - - // ================================================================================ // - // FACTORY OBJECT CLASS BASE // - // ================================================================================ // - - //! @brief ObjectClass base class - class Factory::ObjectClassBase - { - public: // methods - - //! @brief Constructor. - ObjectClassBase(std::string const& name, - std::string const& model_name, - const ctor_fn_t ctor, - const mold_maker_fn_t mold_maker, - const mold_caster_fn_t mold_caster) - : - m_name(name), - m_model_name(model_name), - m_ctor(ctor), - m_mold_maker(mold_maker), - m_mold_caster(mold_caster) {} - - //! @brief Destructor. - virtual ~ObjectClassBase() = default; - - //! @brief Returns the name of the object. - std::string const& getName() const { return m_name; } - - //! @brief Returns the name used into the data model of kiwi. - std::string const& getModelName() const { return m_model_name; } - - //! @brief Returns true if it's an internal object. - bool isInternal() const noexcept { return m_internal; } - - //! @brief Pass true if this is an internal object. - void setInternal(const bool is_internal) noexcept { m_internal = is_internal; } - - //! @brief Returns true if this object class has aliases. - bool hasAlias() const noexcept { return !m_aliases.empty(); } - - //! @brief Pass true if this is an internal object. - std::set const& getAliases() const noexcept { return m_aliases; } - - //! @brief Returns true if this class has this alias name. - bool hasAlias(std::string const& alias) const noexcept { return (m_aliases.count(alias) != 0); } - - //! @brief Adds a creator name alias to the class. - void addAlias(std::string alias) - { - if(!Factory::has(alias)) - { - m_aliases.emplace(std::move(alias)); - } - } - - //! @brief Creates and returns a new Object with a vector of Atom as parameter. - //! @param args A vector of Atom. - //! @return A new model::Object. - std::unique_ptr create(std::vector const& args) const - { return m_ctor(args); } - - //! @brief Copy the content an object instance into a flip::Mold. - //! @param object The object instance. - //! @param mold The The flip::Mold where to copy object instance data. - void moldMake(model::Object const& object, flip::Mold& mold) const - { m_mold_maker(object, mold); } - - //! @brief Creates and returns a new Object from a flip::Mold. - //! @param mold The The flip::Mold from which to retrieve object instance data. - //! @return A new model::Object. - std::unique_ptr moldCast(flip::Mold const& mold) const - { return m_mold_caster(mold); } - - private: // members - - const std::string m_name {}; - const std::string m_model_name {}; - std::set m_aliases {}; - const ctor_fn_t m_ctor {}; - const mold_maker_fn_t m_mold_maker {}; - const mold_caster_fn_t m_mold_caster {}; - bool m_internal = false; - }; - - // ================================================================================ // - // FACTORY OBJECT CLASS // - // ================================================================================ // - - //! @brief ObjectClass - template - class Factory::ObjectClass : public ObjectClassBase - { - public: // methods - - using class_t = TObjectClass; - - ObjectClass(std::string const& name) - : ObjectClassBase(name, - Factory::sanitizeName(name), - getCtor(name), - getMoldMaker(), - getMoldCaster()), - m_flip_class(DataModel::declare()) - { - m_flip_class.name(getModelName().c_str()) - .template inherit(); - } - - //! @brief Add a flip member to the ObjectClass. - template - void addMember(char const* name) - { - m_flip_class.template member(name); - } - - private: // members - - flip::Class& m_flip_class; - }; } } diff --git a/Modules/KiwiModel/KiwiModel_Object.cpp b/Modules/KiwiModel/KiwiModel_Object.cpp index 4329b615..4586b4a2 100755 --- a/Modules/KiwiModel/KiwiModel_Object.cpp +++ b/Modules/KiwiModel/KiwiModel_Object.cpp @@ -19,9 +19,11 @@ ============================================================================== */ -#include "KiwiModel_Object.h" +#include -#include "KiwiModel_DataModel.h" +#include + +#include namespace kiwi { @@ -125,46 +127,6 @@ namespace kiwi .member("type"); }; - // ================================================================================ // - // FLAG // - // ================================================================================ // - - Flag::Flag(Flag::IFlag flag): - flip::Object(), - m_flag(flag) - { - } - - Flag::Flag(flip::Default& d): - flip::Object() - { - } - - void Flag::declare() - { - if(DataModel::has()) return; - - DataModel::declare() - .name("cicm.kiwi.iflag") - .enumerator("DefinedSize") - .enumerator("ResizeWidth") - .enumerator("ResizeHeight"); - - DataModel::declare() - .name("cicm.kiwi.flag") - .member, &Flag::m_flag>("flag"); - } - - bool Flag::operator==(Flag const& other) const - { - return m_flag.value() == other.m_flag.value(); - } - - bool Flag::operator!=(Flag const& other) const - { - return !this->operator==(other); - } - // ================================================================================ // // OBJECT::declare // // ================================================================================ // @@ -175,15 +137,12 @@ namespace kiwi Outlet::declare(); Inlet::declare(); - Flag::declare(); DataModel::declare() .name("cicm.kiwi.Object") - .member("name") .member("text") .member, &Object::m_inlets>("inlets") .member, &Object::m_outlets>("outlets") - .member, &Object::m_flags>("flags") .member("pos_x") .member("pos_y") .member("width") @@ -199,28 +158,156 @@ namespace kiwi Object::Object(flip::Default&) { - ; } Object::Object() : - m_name("noobj"), + m_text(), m_inlets(), m_outlets(), - m_flags(), m_position_x(0.), m_position_y(0.), m_width(60.), m_height(20.), m_min_width(0.), m_min_height(0.), - m_ratio(0.) + m_ratio(0.), + m_attributes(), + m_parameters(), + m_args(nullptr), + m_signals(), + m_listeners(), + m_class(nullptr) + { + } + + void Object::writeAttribute(std::string const& name, tool::Parameter const& parameter) { - ; + } + + void Object::readAttribute(std::string const& name, tool::Parameter & parameter) const + { + } + + bool Object::attributeChanged(std::string const& name) const + { + return false; + } + + void Object::addListener(Listener& listener) const + { + m_listeners.add(listener); + } + + void Object::removeListener(Listener& listener) const + { + m_listeners.remove(listener); + } + + std::vector const& Object::getArguments() const + { + if (m_args == nullptr) + { + m_args.reset(new std::vector()); + + std::vector parsed_text = tool::AtomHelper::parse(getText()); + + if (parsed_text.size() > 1) + { + *m_args->insert(m_args->begin(), parsed_text.begin() + 1, parsed_text.end()); + } + } + + return *m_args; + } + + tool::Parameter const& Object::getAttribute(std::string const& name) const + { + assert(getClass().hasAttribute(name) && "Atribute not declared"); + + ParameterClass const& attribute_class = getClass().getAttribute(name); + + if (m_attributes.find(name) == m_attributes.end()) + { + m_attributes.insert( make_pair(name, tool::Parameter(attribute_class.getDataType()))); + readAttribute(name, m_attributes.at(name)); + } + else if(attributeChanged(name)) + { + readAttribute(name, m_attributes.at(name)); + } + + return m_attributes.at(name); + } + + void Object::setAttribute(std::string const& name, tool::Parameter const& param) + { + assert(getClass().hasAttribute(name) && "Attribute not declare"); + + ParameterClass const& attribute_class = getClass().getAttribute(name); + + assert(attribute_class.getDataType() == param.getType()); + + writeAttribute(name, param); + } + + std::set Object::getChangedAttributes() const + { + std::set changed_parameters; + + for (auto & param_class : getClass().getParameters()) + { + if (param_class.second->getType() == ParameterClass::Type::Attribute + && attributeChanged(param_class.first)) + { + changed_parameters.insert(param_class.first); + } + } + + return changed_parameters; + } + + tool::Parameter const& Object::getParameter(std::string const& name) const + { + assert(getClass().hasParameter(name) && "Parameter not declare"); + + ParameterClass const& param_class = getClass().getParameter(name); + + if (m_parameters.find(name) == m_parameters.end()) + { + m_parameters.insert(make_pair(name, tool::Parameter(param_class.getDataType()))); + } + + return m_parameters.at(name); + } + + void Object::setParameter(std::string const& name, tool::Parameter const& param) + { + assert(getClass().hasParameter(name) && "Parameter not declare"); + + ParameterClass const& param_class = getClass().getParameter(name); + + assert(param_class.getDataType() == param.getType()); + + if (m_parameters.find(name) == m_parameters.end()) + { + m_parameters.insert(make_pair(name, param)); + } + else + { + m_parameters.at(name) = param; + } + + m_listeners.call(&Listener::modelParameterChanged, name, m_parameters.at(name)); } std::string Object::getName() const { - return m_name; + return getClass().getName(); + } + + ObjectClass const& Object::getClass() const + { + return *Factory::getClassByTypeId(typeid(*this).hash_code()); } std::string Object::getText() const @@ -241,7 +328,7 @@ namespace kiwi } size_t Object::getNumberOfInlets() const - { + { return m_inlets.count_if([](Inlet const&){return true;}); } @@ -413,17 +500,9 @@ namespace kiwi return (is_inlet ? "inlet " : "outlet ") + std::to_string(index); } - bool Object::hasFlag(Flag flag) const - { - return m_flags.count_if([&flag](Flag const& internal_flag) { return internal_flag == flag;}) != 0; - } - - void Object::setFlag(Flag flag) + bool Object::hasFlag(ObjectClass::Flag flag) const { - if (!hasFlag(flag)) - { - m_flags.insert(flag); - } + return getClass().hasFlag(flag); } } } diff --git a/Modules/KiwiModel/KiwiModel_Object.h b/Modules/KiwiModel/KiwiModel_Object.h index 453fa2c0..9efed14a 100755 --- a/Modules/KiwiModel/KiwiModel_Object.h +++ b/Modules/KiwiModel/KiwiModel_Object.h @@ -36,11 +36,17 @@ #include "flip/Signal.h" #include +#include +#include + +#include +#include #include #include #include #include +#include namespace kiwi { @@ -144,42 +150,6 @@ namespace kiwi PinType m_type; }; - //! @brief Class that represents an object's property. - //! @details Adding, removing new flags is a data model change and needs migration. - class Flag : public flip::Object - { - public: // classes - - //! @brief The internal enum representation of the flag. - enum class IFlag - { - DefinedSize = 0, // Initial object's Size defined by the model. - ResizeWidth, // Object is resizable horizontally. - ResizeHeight // Object is resizable vertically. - }; - - public: // methods - - //! @brief Flag constructor. - Flag(Flag::IFlag flag); - - //! @brief Flip default constructor. - Flag(flip::Default& d); - - //! @brief Checks if flags are equals. - bool operator==(Flag const& other) const; - - //! @brief Checks if flags are differents. - bool operator!=(Flag const& other) const; - - //! @internal Flip declarator. - static void declare(); - - private: // members - - flip::Enum m_flag; - }; - // ================================================================================ // // OBJECT // @@ -193,6 +163,33 @@ namespace kiwi using SignalKey = uint32_t; + class Listener + { + public: + + // @brief Destructor + virtual ~Listener() = default; + + //! @brief Called when a parameter has changed; + virtual void modelParameterChanged(std::string const& name, tool::Parameter const& param) = 0; + + //! @brief Called when an attribute has changed. + virtual void modelAttributeChanged(std::string const& name, tool::Parameter const& param) = 0; + }; + + //! @brief an error that object can throw to notify a problem. + //! @todo Check if object's id shall be added to error. + class Error : public model::Error + { + public: // methods + + //! @brief Constructor. + Error(std::string const& message):model::Error(message) {} + + //! @brief Destructor. + ~Error() = default; + }; + public: // methods //! @brief Constructor. @@ -201,9 +198,51 @@ namespace kiwi //! @brief Destructor. virtual ~Object() = default; + //! @brief Returns the arguments of the object. + std::vector const& getArguments() const; + + //! @brief Returns a list of changed attributes. + //! @details Use this function in the observation to check which values shall + //! be updated. + std::set getChangedAttributes() const; + + //! @brief Retrieve one of the object's attributes. + tool::Parameter const& getAttribute(std::string const& name) const; + + //! @brief Sets one of the object's attribute. + void setAttribute(std::string const& name, tool::Parameter const& param); + + //! @brief Returns one of the object's parameters. + tool::Parameter const& getParameter(std::string const& name) const; + + //! @brief Sets one of the object's parameter. + void setParameter(std::string const& name, tool::Parameter const& param); + + //! @brief Writes the parameter into data model. + //! @details If the parameter is saved this function will be called at every attempt to + //! modify the parameter. Never called for non saved parameters. + virtual void writeAttribute(std::string const& name, tool::Parameter const& paramter); + + //! @brief Reads the model to initialize a parameter. + //! @details Saved parameters may infos from the data model. + virtual void readAttribute(std::string const& name, tool::Parameter & parameter) const; + + //! @brief Checks the data model to see if a parameter has changed. + //! @details Only called for saved parameters. Default returns false. + virtual bool attributeChanged(std::string const& name) const; + + //! @brief Adds a listener of object's parameters. + void addListener(Listener& listener) const; + + //! @brief Removes listenere from list. + void removeListener(Listener& listener) const; + //! @brief Returns the name of the Object. std::string getName() const; + //! @brief Returns the object's static definition. + ObjectClass const& getClass() const; + //! @brief Returns the text of the Object. std::string getText() const; @@ -277,6 +316,9 @@ namespace kiwi //! @brief Returns inlet or outlet description. virtual std::string getIODescription(bool is_inlet, size_t index) const; + //! @brief Checks if the object has this flag set. + bool hasFlag(ObjectClass::Flag flag) const; + //! @brief Returns the object's signal referenced by this key. //! @details Throws an exception if no signal is referenced for key. template @@ -286,9 +328,6 @@ namespace kiwi return dynamic_cast&>(signal_base); } - //! @brief Checks if the object has this flag set. - bool hasFlag(Flag flag) const; - protected: //! @brief Adds a signal having singal key. @@ -298,10 +337,6 @@ namespace kiwi m_signals.emplace(key, std::make_unique>(key, object)); } - //! @brief Sets one of the flag for the object. - //! @details It is a modification of the model and requires commit. - void setFlag(Flag flag); - //! @brief Clear and replace all the object's inlets. void setInlets(flip::Array const& inlets); @@ -336,22 +371,22 @@ namespace kiwi private: // members - std::map> m_signals; - - flip::String m_name; - flip::String m_text; - flip::Array m_inlets; - flip::Array m_outlets; - flip::Collection m_flags; - - flip::Float m_position_x; - flip::Float m_position_y; - flip::Float m_width; - flip::Float m_height; - flip::Float m_min_width; - flip::Float m_min_height; - flip::Float m_ratio; - + flip::String m_text; + flip::Array m_inlets; + flip::Array m_outlets; + flip::Float m_position_x; + flip::Float m_position_y; + flip::Float m_width; + flip::Float m_height; + flip::Float m_min_width; + flip::Float m_min_height; + flip::Float m_ratio; + mutable std::map m_attributes; + mutable std::map m_parameters; + mutable std::unique_ptr> m_args; + std::map> m_signals; + mutable tool::Listeners m_listeners; + ObjectClass * m_class; friend class Factory; diff --git a/Modules/KiwiModel/KiwiModel_ObjectClass.cpp b/Modules/KiwiModel/KiwiModel_ObjectClass.cpp new file mode 100755 index 00000000..7b3d5d72 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_ObjectClass.cpp @@ -0,0 +1,197 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // PARAMETER CLASS // + // ================================================================================ // + + ParameterClass::ParameterClass(tool::Parameter::Type type): + m_type(), + m_data_type(type) + { + } + + ParameterClass::~ParameterClass() + { + } + + tool::Parameter::Type ParameterClass::getDataType() const + { + return m_data_type; + } + + void ParameterClass::setType(Type param_type) + { + m_type = param_type; + } + + ParameterClass::Type ParameterClass::getType() const + { + return m_type; + } + + + // ================================================================================ // + // OBJECT CLASS // + // ================================================================================ // + + ObjectClass::ObjectClass(std::string const& name, ctor_t ctor): + m_name(name), + m_model_name(Factory::sanitizeName(name)), + m_aliases(), + m_params(), + m_ctor(ctor), + m_flags(), + m_mold_maker(), + m_mold_caster(), + m_type_id() + { + } + + ObjectClass::~ObjectClass() + { + } + + bool ObjectClass::hasAlias() const noexcept + { + return !m_aliases.empty(); + } + + std::string const& ObjectClass::getName() const + { + return m_name; + } + + std::string const& ObjectClass::getModelName() const + { + return m_model_name; + } + + std::set const& ObjectClass::getAliases() const noexcept + { + return m_aliases; + } + + bool ObjectClass::hasAlias(std::string const& alias) const noexcept + { + return (m_aliases.count(alias) != 0); + } + + void ObjectClass::addAlias(std::string const& alias) + { + m_aliases.insert(alias); + } + + void ObjectClass::addAttribute(std::string const& name, std::unique_ptr param_class) + { + assert(param_class != nullptr); + + param_class->setType(ParameterClass::Type::Attribute); + + m_params[name] = std::move(param_class); + } + + bool ObjectClass::hasAttribute(std::string const& name) const + { + auto found_param = m_params.find(name); + + return found_param != m_params.end() + && found_param->second->getType() == ParameterClass::Type::Attribute; + } + + ParameterClass const& ObjectClass::getAttribute(std::string const& name) const + { + return *m_params.at(name); + } + + void ObjectClass::addParameter(std::string name, std::unique_ptr param_class) + { + assert(param_class != nullptr); + + param_class->setType(ParameterClass::Type::Parameter); + + m_params[name] = std::move(param_class); + } + + bool ObjectClass::hasParameter(std::string const& name) const + { + auto found_param = m_params.find(name); + + return found_param != m_params.end() + && found_param->second->getType() == ParameterClass::Type::Parameter; + } + + ParameterClass const& ObjectClass::getParameter(std::string const& name) const + { + return *m_params.at(name); + } + + std::map> const& ObjectClass::getParameters() const + { + return m_params; + } + + void ObjectClass::setFlag(Flag const& flag) + { + m_flags.insert(flag); + } + + bool ObjectClass::hasFlag(Flag const& flag) const + { + return m_flags.find(flag) != m_flags.end(); + } + + void ObjectClass::setMoldMaker(mold_maker_t maker) + { + m_mold_maker = maker; + } + + void ObjectClass::setMoldCaster(mold_caster_t caster) + { + m_mold_caster = caster; + } + + void ObjectClass::setTypeId(size_t type_id) + { + m_type_id = type_id; + } + + std::unique_ptr ObjectClass::create(std::vector const& args) const + { + return m_ctor(args); + } + + void ObjectClass::moldMake(model::Object const& object, flip::Mold& mold) const + { + m_mold_maker(object, mold); + } + std::unique_ptr ObjectClass::moldCast(flip::Mold const& mold) const + { + return m_mold_caster(mold); + } + +}} diff --git a/Modules/KiwiModel/KiwiModel_ObjectClass.h b/Modules/KiwiModel/KiwiModel_ObjectClass.h new file mode 100755 index 00000000..35dffebc --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_ObjectClass.h @@ -0,0 +1,225 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include +#include +#include + +#include +#include + +#include +#include + +namespace kiwi { namespace model { + + class Object; + + class Factory; + + // ================================================================================ // + // PARAMETER CLASS // + // ================================================================================ // + + //! @brief This is a parameter static informations. + //! @details Attributes and Parameters share the same static representation. + class ParameterClass + { + public: // classes + + enum class Type + { + Attribute, // Attributes are saved/collaborative but are not invariant. + Parameter // Parameters are not collaborative. + }; + + public: // methods + + //! @brief Constructor. + ParameterClass(tool::Parameter::Type type); + + //! @brief Destructor. + ~ParameterClass(); + + //! @brief Sets the attributes type. Only used by factory. + ParameterClass::Type getType() const; + + //! @brief Returns the parameter's data type. + tool::Parameter::Type getDataType() const; + + private: // methods + + //! @brief Sets the attributes type. Only used by factory. + void setType(Type param_type); + + private: // members + + Type m_type; + tool::Parameter::Type m_data_type; + + friend class ObjectClass; + + private: // deleted methods + + ParameterClass() = delete; + ParameterClass(ParameterClass const& other) = delete; + ParameterClass(ParameterClass && other) = delete; + ParameterClass& operator=(ParameterClass const& other) = delete; + ParameterClass& operator=(ParameterClass && other) = delete; + }; + + // ================================================================================ // + // OBJECTC LASS // + // ================================================================================ // + + //! @brief The static representation of an object. + class ObjectClass + { + public: // classes. + + //! @brief The construction method. + using ctor_t = std::function(std::vector const&)>; + + //! @brief A list of flags that defines the object's behavior. + enum class Flag + { + Internal, //! Internal objects are hidden from objects's dionnary. + ResizeWidth, //! Set this flag to resize object horizontally. + ResizeHeight, //! Set this flag to resize object vertically. + DefinedSize //! If the object has a predefined size. + }; + + private: // classes + + //! @brief The object's copy prototype. + using mold_maker_t = std::function; + + //! @brief The object paste prototype. + using mold_caster_t = std::function(flip::Mold const&)>; + + public:// methods + + //! @brief The ObjectClass constructor. + //! @details Used in the object declaration. + ObjectClass(std::string const& name, ctor_t ctor); + + //! @brief Destructor. + ~ObjectClass(); + + //! @brief Retrieves the object's class name. + std::string const& getName() const; + + //! @brief Retrieves object's data model name. + std::string const& getModelName() const; + + //! @brief Returns true if this object class has aliases. + bool hasAlias() const noexcept; + + //! @brief Returns a set of aliases for this object. + std::set const& getAliases() const noexcept; + + //! @brief Returns true if this class has this alias name. + bool hasAlias(std::string const& alias) const noexcept; + + //! @brief Adds a creator name alias to the class. + void addAlias(std::string const& alias); + + //! @brief Adds an attribute to the class definition. + void addAttribute(std::string const& name, std::unique_ptr param_class); + + //! @brief Returns true if attributes exists. + bool hasAttribute(std::string const& name) const; + + //! @brief Returns an attributes static definition. + //! @details Throws if no attributes refered by name. + ParameterClass const& getAttribute(std::string const& name) const; + + //! @brief Adds a parameter to the class definition. + void addParameter(std::string name, std::unique_ptr param_class); + + //! @brief Returns true if parameter exists. + bool hasParameter(std::string const& name) const; + + //! @brief Returns a parameter's static definition. + //! @details Throws if no parameter refered by name. + ParameterClass const& getParameter(std::string const& name) const; + + //! @brief Gets the list of parameters static definition. + std::map> const& getParameters() const; + + //! @brief Adds the flag to object static definition. + void setFlag(Flag const& flag); + + //! @brief Checks if the flag is set. + bool hasFlag(Flag const& flag) const; + + private: // methods + + //! @brief Sets the mold maker function. + void setMoldMaker(mold_maker_t maker); + + // @brief Sets the mold caster function. + void setMoldCaster(mold_caster_t caster); + + //! @brief Sets the type_id's hash code of the class. Used by factory. + void setTypeId(size_t); + + //! @brief Creates and returns a new Object with a vector of Atom as parameter. + //! @param args A vector of Atom. + //! @return A new model::Object. + std::unique_ptr create(std::vector const& args) const; + + //! @brief Copy the content an object instance into a flip::Mold. + //! @param object The object instance. + //! @param mold The The flip::Mold where to copy object instance data. + void moldMake(model::Object const& object, flip::Mold& mold) const; + + //! @brief Creates and returns a new Object from a flip::Mold. + //! @param mold The The flip::Mold from which to retrieve object instance data. + //! @return A new model::Object. + std::unique_ptr moldCast(flip::Mold const& mold) const; + + private: // members + + std::string m_name; + std::string m_model_name; + std::set m_aliases; + std::map> m_params; + ctor_t m_ctor; + std::set m_flags; + mold_maker_t m_mold_maker; + mold_caster_t m_mold_caster; + size_t m_type_id; + + friend class Factory; + + private: // deleted methods. + + ObjectClass() = delete; + ObjectClass(ObjectClass const& other) = delete; + ObjectClass(ObjectClass && other) = delete; + ObjectClass& operator=(ObjectClass const& other) = delete; + ObjectClass& operator=(ObjectClass && other) = delete; + }; + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_AdcTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_AdcTilde.cpp new file mode 100755 index 00000000..a1ee545e --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_AdcTilde.cpp @@ -0,0 +1,134 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT ADC~ // + // ================================================================================ // + + void AdcTilde::declare() + { + std::unique_ptr adctilde_class(new ObjectClass("adc~", &AdcTilde::create)); + + flip::Class & adctilde_model = DataModel::declare() + .name(adctilde_class->getModelName().c_str()) + .inherit(); + + Factory::add(std::move(adctilde_class), adctilde_model); + } + + std::unique_ptr AdcTilde::create(std::vector const& args) + { + return std::make_unique(args); + } + + AdcTilde::AdcTilde(std::vector const& args) + { + size_t channels = parseArgsAsChannelRoutes(args).size(); + + pushInlet({PinType::IType::Control}); + + for (int i = 0; i < channels; ++i) + { + pushOutlet({PinType::IType::Signal}); + } + } + + std::vector AdcTilde::parseArgsAsChannelRoutes(std::vector const& args) const + { + std::vector routes; + + for(tool::Atom const& arg : args) + { + if (arg.isNumber()) + { + if (arg.getInt() <= 0) + { + throw Error("audio interface null or negative channel"); + } + + routes.push_back(arg.getInt() - 1); + } + else if(arg.isString()) + { + std::string inputs(arg.getString()); + + size_t sep_pos = inputs.find(":"); + + if (sep_pos == std::string::npos) + { + throw Error("audio interface wrong arguments"); + } + + int left_input = std::stoi(inputs.substr(0, sep_pos)) - 1; + int right_input = std::stoi(inputs.substr(inputs.find(":") + 1)) - 1; + + if (left_input < 0 || right_input < 0) + { + throw Error("audio interface null or negative channel"); + } + + const bool rev = left_input > right_input; + + for (int channel = left_input; + rev ? channel >= right_input : channel <= right_input; + rev ? --channel : ++channel) + { + routes.push_back(channel); + } + } + } + + if (routes.empty()) + { + routes = {0, 1}; + } + + return routes; + } + + std::string AdcTilde::getIODescription(bool is_inlet, size_t index) const + { + if(is_inlet) + { + return "Start/Stop dsp"; + } + else + { + if(index < getNumberOfOutlets()) + { + auto text_atoms = tool::AtomHelper::parse(getText()); + text_atoms.erase(text_atoms.cbegin()); + const auto routes = parseArgsAsChannelRoutes(text_atoms); + + return "(signal) Audio In Channel " + std::to_string(routes[index] + 1); + } + } + + return {}; + } + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_NewBox.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_AdcTilde.h similarity index 51% rename from Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_NewBox.cpp rename to Modules/KiwiModel/KiwiModel_Objects/KiwiModel_AdcTilde.h index 909c36ac..0822eb27 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_NewBox.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_AdcTilde.h @@ -1,53 +1,50 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#include - -#include - -namespace kiwi -{ - namespace model - { - // ================================================================================ // - // NEWBOX // - // ================================================================================ // - - void NewBox::declare() - { - Factory::add("newbox").setInternal(true); - - } - - NewBox::NewBox(std::string const& name, std::vector const& args) - { - setFlag(Flag::IFlag::DefinedSize); - setWidth(80); - setHeight(20); - pushInlet({PinType::IType::Control}); - } - - std::string NewBox::getIODescription(bool is_inlet, size_t index) const - { - return "(nothing here)"; - } - } -} +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT ADC~ // + // ================================================================================ // + + //! @todo Check better way to get routes. + class AdcTilde : public model::Object + { + public: + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + + AdcTilde(flip::Default& d): model::Object(d){} + + AdcTilde(std::vector const& args); + + std::vector parseArgsAsChannelRoutes(std::vector const& args) const; + + std::string getIODescription(bool is_inlet, size_t index) const override; + }; + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Bang.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Bang.cpp new file mode 100755 index 00000000..b618178c --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Bang.cpp @@ -0,0 +1,88 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT BANG // + // ================================================================================ // + + void Bang::declare() + { + std::unique_ptr bang_class(new ObjectClass("bang", &Bang::create)); + + bang_class->setFlag(ObjectClass::Flag::DefinedSize); + bang_class->setFlag(ObjectClass::Flag::ResizeWidth); + bang_class->setFlag(ObjectClass::Flag::ResizeHeight); + + flip::Class & bang_model = DataModel::declare().name(bang_class->getModelName().c_str()).inherit(); + + Factory::add(std::move(bang_class), bang_model); + } + + std::unique_ptr Bang::create(std::vector const& args) + { + return std::make_unique(args); + } + + Bang::Bang(std::vector const& args): + Object() + { + if (!args.empty()) + { + throw Error("bang too many arguments"); + } + + addSignal<>(Signal::TriggerBang, *this); + setRatio(1.); + setMinWidth(20.); + setWidth(20); + pushInlet({PinType::IType::Control}); + pushOutlet(PinType::IType::Control); + } + + Bang::Bang(flip::Default& d): + Object(d) + { + addSignal<>(Signal::TriggerBang, *this); + } + + std::string Bang::getIODescription(bool is_inlet, size_t index) const + { + if (is_inlet && index == 0) + { + return "Makes the object flash and sends bang through first outlet"; + } + else if(!is_inlet && index == 0) + { + return "Sends bang"; + } + else + { + return ""; + } + } + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_OscTilde.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Bang.h similarity index 53% rename from Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_OscTilde.h rename to Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Bang.h index 45371202..0673c878 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_OscTilde.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Bang.h @@ -23,27 +23,32 @@ #include -namespace kiwi -{ - namespace model +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT BANG // + // ================================================================================ // + + class Bang : public model::Object { - // ================================================================================ // - // OBJECT OSC~ // - // ================================================================================ // + public: // enum - class OscTilde : public model::Object + enum Signal : SignalKey { - public: - //! @brief flip Default Constructor - OscTilde(flip::Default& d): model::Object(d){}; - - //! @brief Constructor - OscTilde(std::string const& name, std::vector const& args); - - std::string getIODescription(bool is_inlet, size_t index) const override; - - //! @internal flip static declare method - static void declare(); + TriggerBang }; - } -} + + public: // methods + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + + Bang(flip::Default& d); + + Bang(std::vector const& args); + + std::string getIODescription(bool is_inlet, size_t index) const override; + }; + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_ErrorBox.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_ErrorBox.cpp deleted file mode 100755 index a4f7cfed..00000000 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_ErrorBox.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#include - -#include - -namespace kiwi -{ - namespace model - { - // ================================================================================ // - // ERRORBOX // - // ================================================================================ // - - void ErrorBox::declare() - { - Factory::add("errorbox").setInternal(true); - } - - ErrorBox::ErrorBox(std::string const& name, std::vector const& args) - { - } - - void ErrorBox::setInlets(flip::Array const& inlets) - { - model::Object::setInlets(inlets); - } - - void ErrorBox::setOutlets(flip::Array const& outlets) - { - model::Object::setOutlets(outlets); - } - - std::string ErrorBox::getIODescription(bool is_inlet, size_t index) const - { - return "(nothing here)"; - } - - void ErrorBox::setError(std::string const& error_message) - { - m_error = error_message; - } - - std::string ErrorBox::getError() const - { - return m_error; - } - } -} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_ErrorBox.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_ErrorBox.h deleted file mode 100755 index 7f47f06c..00000000 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_ErrorBox.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#pragma once - -#include - -namespace kiwi -{ - namespace model - { - // ================================================================================ // - // ERRORBOX // - // ================================================================================ // - - class ErrorBox : public model::Object - { - public: - - //! @brief flip Default Constructor - ErrorBox(flip::Default& d) : model::Object(d) {} - - //! @brief Constructor - ErrorBox(std::string const& name, std::vector const& args); - - //! @brief Set the number of inlets. - //! @param inlets The number of inlets. - void setInlets(flip::Array const& inlets); - - //! @brief Set the number of inlets. - //! @param inlets The number of inlets. - void setOutlets(flip::Array const& outlets); - - //! @brief Sets the message error that caused the errorbox construction. - void setError(std::string const& error); - - //! @brief Returns the error that caused the errorbox construction. - std::string getError() const; - - std::string getIODescription(bool is_inlet, size_t index) const override; - - //! @internal flip static declare method - static void declare(); - - private: // members - - std::string m_error; - }; - } -} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_NewBox.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_NewBox.h deleted file mode 100755 index 06c3d288..00000000 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Basic/KiwiModel_NewBox.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#pragma once - -#include - -namespace kiwi -{ - namespace model - { - // ================================================================================ // - // NEWBOX // - // ================================================================================ // - - class NewBox : public model::Object - { - public: - - //! @brief flip Default Constructor - NewBox(flip::Default& d) : model::Object(d) {} - - //! @brief Constructor - NewBox(std::string const& name, std::vector const& args); - - std::string getIODescription(bool is_inlet, size_t index) const override; - - //! @internal flip static declare method - static void declare(); - }; - } -} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Bang.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Bang.cpp deleted file mode 100755 index d29b73c0..00000000 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Bang.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#include - -#include - -namespace kiwi -{ - namespace model - { - // ================================================================================ // - // OBJECT BANG // - // ================================================================================ // - - Bang::Bang(std::string const& name, std::vector const& args): - Object() - { - if (!args.empty()) - { - throw std::runtime_error("wrong arguments for object bang"); - } - - setFlag(Flag::IFlag::DefinedSize); - setFlag(Flag::IFlag::ResizeWidth); - setFlag(Flag::IFlag::ResizeHeight); - addSignal<>(Signal::TriggerBang, *this); - setRatio(1.); - setMinWidth(20.); - setWidth(20); - pushInlet({PinType::IType::Control}); - pushOutlet(PinType::IType::Control); - } - - Bang::Bang(flip::Default& d): - Object(d) - { - addSignal<>(Signal::TriggerBang, *this); - } - - void Bang::declare() - { - Factory::add("bang"); - } - - std::string Bang::getIODescription(bool is_inlet, size_t index) const - { - if (is_inlet && index == 0) - { - return "Makes the object flash and sends bang through first outlet"; - } - else if(!is_inlet && index == 0) - { - return "Sends bang"; - } - else - { - return ""; - } - } - } -} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Toggle.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Toggle.cpp deleted file mode 100755 index 4f6d5527..00000000 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Toggle.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#include - -#include - -namespace kiwi -{ - namespace model - { - // ================================================================================ // - // OBJECT TOGGLE // - // ================================================================================ // - - Toggle::Toggle(std::string const& name, std::vector const& args): - Object() - { - if (!args.empty()) - { - throw std::runtime_error("wrong arguments for object bang"); - } - - setFlag(Flag::IFlag::DefinedSize); - setFlag(Flag::IFlag::ResizeWidth); - setFlag(Flag::IFlag::ResizeHeight); - addSignal(Signal::Switch, *this); - setRatio(1.); - setMinWidth(20.); - setWidth(20); - pushInlet({PinType::IType::Control}); - pushOutlet(PinType::IType::Control); - } - - Toggle::Toggle(flip::Default& d): - Object(d) - { - addSignal(Signal::Switch, *this); - } - - void Toggle::declare() - { - Factory::add("toggle"); - } - - std::string Toggle::getIODescription(bool is_inlet, size_t index) const - { - if (is_inlet && index == 0) - { - return "Switches the toggle on or of"; - } - else if(!is_inlet && index == 0) - { - return "Sends 0 or 1 when toggle is switched on or off"; - } - else - { - return ""; - } - } - } -} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Toggle.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Toggle.h deleted file mode 100755 index ea431f6b..00000000 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Toggle.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#pragma once - -#include - -namespace kiwi -{ - namespace model - { - // ================================================================================ // - // OBJECT TOGGLE // - // ================================================================================ // - - - class Toggle : public model::Object - { - public: // enum - - enum Signal : SignalKey - { - Switch - }; - - enum class Request - { - Switch, // Switch state. - SwitchOn, // Explicitly switch on. - SwitchOff // Explicitly switch off. - }; - - public: // methods - - Toggle(flip::Default& d); - - Toggle(std::string const& name, std::vector const& args); - - std::string getIODescription(bool is_inlet, size_t index) const override; - - static void declare(); - }; - } -} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_DacTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_DacTilde.cpp similarity index 83% rename from Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_DacTilde.cpp rename to Modules/KiwiModel/KiwiModel_Objects/KiwiModel_DacTilde.cpp index 3ac749c1..b9b9b579 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_DacTilde.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_DacTilde.cpp @@ -19,19 +19,33 @@ ============================================================================== */ -#include - +#include +#include #include -namespace kiwi -{ - namespace model - { +namespace kiwi { namespace model { + // ================================================================================ // // OBJECT DAC~ // // ================================================================================ // - DacTilde::DacTilde(std::string const& name, std::vector const& args) + void DacTilde::declare() + { + std::unique_ptr dactilde_class(new ObjectClass("dac~", &DacTilde::create)); + + flip::Class & dactilde_model = DataModel::declare() + .name(dactilde_class->getModelName().c_str()) + .inherit(); + + Factory::add(std::move(dactilde_class), dactilde_model); + } + + std::unique_ptr DacTilde::create(std::vector const& args) + { + return std::make_unique(args); + } + + DacTilde::DacTilde(std::vector const& args) { size_t channels = parseArgsAsChannelRoutes(args).size(); @@ -96,11 +110,6 @@ namespace kiwi return routes; } - void DacTilde::declare() - { - Factory::add("dac~"); - } - std::string DacTilde::getIODescription(bool is_inlet, size_t index) const { if(is_inlet) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Bang.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_DacTilde.h similarity index 50% rename from Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Bang.h rename to Modules/KiwiModel/KiwiModel_Objects/KiwiModel_DacTilde.h index ef61b69c..9fcd704b 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Bang.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_DacTilde.h @@ -21,37 +21,30 @@ #pragma once -#include - #include -namespace kiwi -{ - namespace model +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT DAC~ // + // ================================================================================ // + + //! @todo Check better way to get routes. + class DacTilde : public model::Object { - // ================================================================================ // - // OBJECT BANG // - // ================================================================================ // + public: + static void declare(); - class Bang : public model::Object - { - public: // enum - - enum Signal : SignalKey - { - TriggerBang - }; - - public: // methods - - Bang(flip::Default& d); - - Bang(std::string const& name, std::vector const& args); - - std::string getIODescription(bool is_inlet, size_t index) const override; - - static void declare(); - }; - } -} + static std::unique_ptr create(std::vector const& arsg); + + DacTilde(std::vector const& args); + + DacTilde(flip::Default& d): model::Object(d){} + + std::vector parseArgsAsChannelRoutes(std::vector const& args) const; + + std::string getIODescription(bool is_inlet, size_t index) const override; + }; + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Delay.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Delay.cpp similarity index 68% rename from Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Delay.cpp rename to Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Delay.cpp index 9dc2d3ca..6d76c1fc 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Delay.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Delay.cpp @@ -19,10 +19,11 @@ ============================================================================== */ -#include - +#include #include +#include + namespace kiwi { namespace model @@ -31,12 +32,30 @@ namespace kiwi // OBJECT DELAY // // ================================================================================ // - Delay::Delay(std::string const& name, std::vector const& args) + void Delay::declare() { - if (args.size() > 1 || (args.size() == 1 && !args[0].isNumber())) - { - throw std::runtime_error("wrong argument for object Delay"); - } + std::unique_ptr delay_class(new ObjectClass("delay", + &Delay::create)); + + flip::Class & delay_model = DataModel::declare() + .name(delay_class->getModelName().c_str()) + .inherit(); + + Factory::add(std::move(delay_class), delay_model); + } + + std::unique_ptr Delay::create(std::vector const& args) + { + return std::make_unique(args); + } + + Delay::Delay(std::vector const& args) + { + if (args.size() > 1) + throw Error("delay too many arguments"); + + if(args.size() == 1 && !args[0].isNumber()) + throw Error("delay argument must be a number"); pushInlet({PinType::IType::Control}); @@ -48,11 +67,6 @@ namespace kiwi pushOutlet(PinType::IType::Control); } - void Delay::declare() - { - Factory::add("delay"); - } - std::string Delay::getIODescription(bool is_inlet, size_t index) const { if(is_inlet) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Delay.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Delay.h new file mode 100755 index 00000000..fbc2fa13 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Delay.h @@ -0,0 +1,47 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT DELAY // + // ================================================================================ // + + class Delay : public model::Object + { + public: // methods + + Delay(flip::Default& d) : model::Object(d) {}; + + Delay(std::vector const& args); + + std::string getIODescription(bool is_inlet, size_t index) const override; + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + }; + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_DelaySimpleTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_DelaySimpleTilde.cpp new file mode 100755 index 00000000..b0654e33 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_DelaySimpleTilde.cpp @@ -0,0 +1,98 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT DELAYSIMPLE~ // + // ================================================================================ // + + void DelaySimpleTilde::declare() + { + std::unique_ptr delaytilde_class(new ObjectClass("delaysimple~", + &DelaySimpleTilde::create)); + + flip::Class & delaytilde_model = DataModel::declare() + .name(delaytilde_class->getModelName().c_str()) + .inherit(); + + Factory::add(std::move(delaytilde_class), delaytilde_model); + } + + std::unique_ptr DelaySimpleTilde::create(std::vector const& args) + { + return std::make_unique(args); + } + + DelaySimpleTilde::DelaySimpleTilde(std::vector const& args) + { + if (args.size() > 2) + { + throw Error("delaysimple~ too many arguments"); + } + + if (args.size() > 0 && !args[0].isNumber()) + { + throw Error("delaysimple~ delay argument is not a number"); + } + + if (args.size() > 1 && !args[1].isNumber()) + { + throw Error("delaysimple~ feedback argument is not a number "); + } + + pushInlet({PinType::IType::Control, PinType::IType::Signal}); + pushInlet({PinType::IType::Control, PinType::IType::Signal}); + pushInlet({PinType::IType::Control}); + + pushOutlet(PinType::IType::Signal); + } + + std::string DelaySimpleTilde::getIODescription(bool is_inlet, size_t index) const + { + if(is_inlet) + { + if(index == 0) + { + return "(signal) Input to be delayed"; + } + else if(index == 1) + { + return "(signal/float) Delay time (ms)"; + } + else if(index == 2) + { + return "(float) Feedback (0-1)"; + } + } + else + { + return "(signal) Delayed output signal"; + } + + return {}; + } + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_DelaySimpleTilde.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_DelaySimpleTilde.h similarity index 82% rename from Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_DelaySimpleTilde.h rename to Modules/KiwiModel/KiwiModel_Objects/KiwiModel_DelaySimpleTilde.h index 98517c85..708578db 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_DelaySimpleTilde.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_DelaySimpleTilde.h @@ -23,10 +23,8 @@ #include -namespace kiwi -{ - namespace model - { +namespace kiwi { namespace model { + // ================================================================================ // // OBJECT DELAYSIMPLETILDE~ // // ================================================================================ // @@ -35,16 +33,15 @@ namespace kiwi { public: - //! @brief flip Default Constructor + static void declare(); + + static std::unique_ptr create(std::vector const& args); + DelaySimpleTilde(flip::Default& d): model::Object(d){}; - //! @brief Constructor - DelaySimpleTilde(std::string const& name, std::vector const& args); + DelaySimpleTilde(std::vector const& args); std::string getIODescription(bool is_inlet, size_t index) const override; - - //! @internal flip static declare method - static void declare(); }; - } -} + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_AdcTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_AdcTilde.cpp deleted file mode 100755 index e098ec02..00000000 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_AdcTilde.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#include - -#include - -namespace kiwi -{ - namespace model - { - // ================================================================================ // - // OBJECT ADC~ // - // ================================================================================ // - - AdcTilde::AdcTilde(std::string const& name, std::vector const& args) - { - size_t channels = parseArgsAsChannelRoutes(args).size(); - - pushInlet({PinType::IType::Control}); - - for (int i = 0; i < channels; ++i) - { - pushOutlet({PinType::IType::Signal}); - } - } - - std::vector AdcTilde::parseArgsAsChannelRoutes(std::vector const& args) const - { - std::vector routes; - - for(tool::Atom const& arg : args) - { - if (arg.isNumber()) - { - if (arg.getInt() <= 0) - { - throw std::runtime_error("null or negative channel"); - } - - routes.push_back(arg.getInt() - 1); - } - else if(arg.isString()) - { - std::string inputs(arg.getString()); - - size_t sep_pos = inputs.find(":"); - - if (sep_pos == std::string::npos) - { - throw std::runtime_error("wrong symbol syntax"); - } - - int left_input = std::stoi(inputs.substr(0, sep_pos)) - 1; - int right_input = std::stoi(inputs.substr(inputs.find(":") + 1)) - 1; - - if (left_input < 0 || right_input < 0) - { - throw std::runtime_error("null or negative channel"); - } - - const bool rev = left_input > right_input; - - for (int channel = left_input; - rev ? channel >= right_input : channel <= right_input; - rev ? --channel : ++channel) - { - routes.push_back(channel); - } - } - } - - if (routes.empty()) - { - routes = {0, 1}; - } - - return routes; - } - - void AdcTilde::declare() - { - Factory::add("adc~"); - } - - std::string AdcTilde::getIODescription(bool is_inlet, size_t index) const - { - if(is_inlet) - { - return "Start/Stop dsp"; - } - else - { - if(index < getNumberOfOutlets()) - { - auto text_atoms = tool::AtomHelper::parse(getText()); - text_atoms.erase(text_atoms.cbegin()); - const auto routes = parseArgsAsChannelRoutes(text_atoms); - - return "(signal) Audio In Channel " + std::to_string(routes[index] + 1); - } - } - - return {}; - } - } -} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_AdcTilde.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_AdcTilde.h deleted file mode 100755 index 9b41a66d..00000000 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_AdcTilde.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#pragma once - -#include - -namespace kiwi -{ - namespace model - { - // ================================================================================ // - // OBJECT ADC~ // - // ================================================================================ // - - class AdcTilde : public model::Object - { - public: - - //! @brief flip Default Constructor - AdcTilde(flip::Default& d): model::Object(d){} - - //! @brief Parses args to construct routes - //! @todo Mutualize with adc tilde object. - std::vector parseArgsAsChannelRoutes(std::vector const& args) const; - - //! @brief Constructor - AdcTilde(std::string const& name, std::vector const& args); - - std::string getIODescription(bool is_inlet, size_t index) const override; - - //! @internal flip static declare method - static void declare(); - }; - } -} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_DacTilde.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_DacTilde.h deleted file mode 100755 index d4cf4df3..00000000 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_DacTilde.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#pragma once - -#include - -namespace kiwi -{ - namespace model - { - // ================================================================================ // - // OBJECT DAC~ // - // ================================================================================ // - - class DacTilde : public model::Object - { - public: - - //! @brief flip Default Constructor - DacTilde(flip::Default& d): model::Object(d){} - - //! @brief Parses args to construct routes - std::vector parseArgsAsChannelRoutes(std::vector const& args) const; - - //! @brief Constructor - DacTilde(std::string const& name, std::vector const& args); - - std::string getIODescription(bool is_inlet, size_t index) const override; - - //! @internal flip static declare method - static void declare(); - }; - } -} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_DelaySimpleTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_DelaySimpleTilde.cpp deleted file mode 100755 index 6aaa273a..00000000 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_DelaySimpleTilde.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#include - -#include - -namespace kiwi -{ - namespace model - { - // ================================================================================ // - // OBJECT DELAYSIMPLE~ // - // ================================================================================ // - - DelaySimpleTilde::DelaySimpleTilde(std::string const& name, std::vector const& args) - { - if (args.size() > 0) - { - throw std::runtime_error("wrong argument for object delay~"); - } - - pushInlet({PinType::IType::Control, PinType::IType::Signal}); - pushInlet({PinType::IType::Control, PinType::IType::Signal}); - pushInlet({PinType::IType::Control}); - - pushOutlet(PinType::IType::Signal); - } - - void DelaySimpleTilde::declare() - { - Factory::add("delaysimple~"); - } - - std::string DelaySimpleTilde::getIODescription(bool is_inlet, size_t index) const - { - if(is_inlet) - { - if(index == 0) - { - return "(signal) Input to be delayed"; - } - else if(index == 1) - { - return "(signal/float) Delay time (ms)"; - } - else if(index == 2) - { - return "(float) Feedback (0-1)"; - } - } - else - { - return "(signal) Delayed output signal"; - } - - return {}; - } - } -} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_OscTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_OscTilde.cpp deleted file mode 100755 index 70e15974..00000000 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_OscTilde.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#include - -#include - -namespace kiwi -{ - namespace model - { - // ================================================================================ // - // OBJECT OSC~ // - // ================================================================================ // - - OscTilde::OscTilde(std::string const& name, std::vector const& args) - { - pushInlet({PinType::IType::Control, PinType::IType::Signal}); - pushInlet({PinType::IType::Control, PinType::IType::Signal}); - - pushOutlet(PinType::IType::Signal); - } - - void OscTilde::declare() - { - Factory::add("osc~"); - } - - std::string OscTilde::getIODescription(bool is_inlet, size_t index) const - { - if(is_inlet) - { - if(index == 0) - { - return "(signal/float) Set frequency"; - } - else if(index == 1) - { - return "(signal/float) Set phase (0-1)"; - } - } - else - { - return "(signal) Output"; - } - - return {}; - } - } -} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_PlusTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_PlusTilde.cpp deleted file mode 100755 index fedeb623..00000000 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_PlusTilde.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#include - -#include - -namespace kiwi -{ - namespace model - { - // ================================================================================ // - // OBJECT PLUS~ // - // ================================================================================ // - - PlusTilde::PlusTilde(std::string const& name, std::vector const& args) - { - pushInlet({PinType::IType::Signal}); - - if (args.empty() || !args[0].isNumber()) - { - pushInlet({PinType::IType::Signal, PinType::IType::Control}); - } - - pushOutlet(PinType::IType::Signal); - } - - void PlusTilde::declare() - { - Factory::add("plus~").addAlias("+~"); - } - - std::string PlusTilde::getIODescription(bool is_inlet, size_t index) const - { - return is_inlet ? (index == 0) ? "(signal) Left operand" : "(signal) Right operand" : "(signal) Output"; - } - } -} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_PlusTilde.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_PlusTilde.h deleted file mode 100755 index d16aa0c0..00000000 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_PlusTilde.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#pragma once - -#include - -namespace kiwi -{ - namespace model - { - // ================================================================================ // - // OBJECT PLUS~ // - // ================================================================================ // - - class PlusTilde : public model::Object - { - public: - - //! @brief flip Default Constructor - PlusTilde(flip::Default& d): model::Object(d){}; - - //! @brief Constructor - PlusTilde(std::string const& name, std::vector const& args); - - std::string getIODescription(bool is_inlet, size_t index) const override; - - //! @internal flip static declare method - static void declare(); - }; - } -} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_SigTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_SigTilde.cpp deleted file mode 100755 index 4fe9e3fa..00000000 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_SigTilde.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#include - -#include - -namespace kiwi -{ - namespace model - { - // ================================================================================ // - // OBJECT SIG~ // - // ================================================================================ // - - SigTilde::SigTilde(std::string const& name, std::vector const& args) - { - if (args.empty() || !args[0].isNumber()) - { - pushInlet({PinType::IType::Control}); - } - - pushOutlet(PinType::IType::Signal); - } - - void SigTilde::declare() - { - Factory::add("sig~"); - } - - std::string SigTilde::getIODescription(bool is_inlet, size_t index) const - { - return is_inlet ? "(float/int) Set signal value" : "(signal) Output value"; - } - } -} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_TimesTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_TimesTilde.cpp deleted file mode 100755 index b0598808..00000000 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_TimesTilde.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#include - -#include - -namespace kiwi -{ - namespace model - { - // ================================================================================ // - // OBJECT TIMES~ // - // ================================================================================ // - - TimesTilde::TimesTilde(std::string const& name, std::vector const& args) - { - pushInlet({PinType::IType::Signal}); - - if (args.empty() || !args[0].isNumber()) - { - pushInlet({PinType::IType::Signal, PinType::IType::Control}); - } - - pushOutlet(PinType::IType::Signal); - } - - void TimesTilde::declare() - { - Factory::add("times~").addAlias("*~"); - } - - std::string TimesTilde::getIODescription(bool is_inlet, size_t index) const - { - return is_inlet ? (index == 0) ? "(signal) Left operand" : "(signal) Right operand" : "(signal) Output"; - } - } -} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_TimesTilde.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_TimesTilde.h deleted file mode 100755 index 0a73d071..00000000 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_TimesTilde.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#pragma once - -#include - -namespace kiwi -{ - namespace model - { - // ================================================================================ // - // OBJECT *~ // - // ================================================================================ // - - class TimesTilde : public model::Object - { - public: - - //! @brief flip Default Constructor - TimesTilde(flip::Default& d): model::Object(d){}; - - //! @brief Constructor - TimesTilde(std::string const& name, std::vector const& args); - - std::string getIODescription(bool is_inlet, size_t index) const override; - - //! @internal flip static declare method - static void declare(); - }; - } -} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_ErrorBox.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_ErrorBox.cpp new file mode 100755 index 00000000..5c142ae7 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_ErrorBox.cpp @@ -0,0 +1,84 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include + +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // ERRORBOX // + // ================================================================================ // + + void ErrorBox::declare() + { + std::unique_ptr object_class(new ObjectClass("errorbox", + &ErrorBox::create)); + + object_class->setFlag(ObjectClass::Flag::Internal); + + flip::Class & data_model = DataModel::declare() + .name(object_class->getModelName().c_str()) + .inherit(); + + Factory::add(std::move(object_class), data_model); + } + + std::unique_ptr ErrorBox::create(std::vector const& atoms) + { + return std::make_unique(); + } + + ErrorBox::ErrorBox(): + m_error() + { + } + + void ErrorBox::setInlets(flip::Array const& inlets) + { + model::Object::setInlets(inlets); + } + + void ErrorBox::setOutlets(flip::Array const& outlets) + { + model::Object::setOutlets(outlets); + } + + std::string ErrorBox::getIODescription(bool is_inlet, size_t index) const + { + return "(nothing here)"; + } + + void ErrorBox::setError(std::string const& error_message) + { + m_error = error_message; + } + + std::string ErrorBox::getError() const + { + return m_error; + } + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_ErrorBox.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_ErrorBox.h new file mode 100755 index 00000000..1e0e6c06 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_ErrorBox.h @@ -0,0 +1,69 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // ERRORBOX // + // ================================================================================ // + + class ErrorBox : public model::Object + { + public: + + //! @brief flip Default Constructor + ErrorBox(flip::Default& d) : model::Object(d) {} + + //! @brief Constructor + ErrorBox(); + + //! @brief Set the number of inlets. + //! @param inlets The number of inlets. + void setInlets(flip::Array const& inlets); + + //! @brief Set the number of inlets. + //! @param inlets The number of inlets. + void setOutlets(flip::Array const& outlets); + + //! @brief Sets the message error that caused the errorbox construction. + void setError(std::string const& error); + + //! @brief Returns the error that caused the errorbox construction. + std::string getError() const; + + std::string getIODescription(bool is_inlet, size_t index) const override; + + //! @internal flip static declare method + static void declare(); + + //! @brief The error box construction method. + static std::unique_ptr create(std::vector const& args); + + private: // members + + std::string m_error; + }; + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Loadmess.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Loadmess.cpp new file mode 100755 index 00000000..e14c94e2 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Loadmess.cpp @@ -0,0 +1,71 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT LOADMESS // + // ================================================================================ // + + void Loadmess::declare() + { + std::unique_ptr loadmess_class(new ObjectClass("loadmess", &Loadmess::create)); + + flip::Class & loadmess_model = DataModel::declare() + .name(loadmess_class->getModelName().c_str()) + .inherit(); + + Factory::add(std::move(loadmess_class), loadmess_model); + } + + std::unique_ptr Loadmess::create(std::vector const& args) + { + return std::make_unique(args); + } + + Loadmess::Loadmess(std::vector const& args) + { + if (args.empty()) + throw Error("loadmess argument is required"); + + pushInlet({PinType::IType::Control}); + pushOutlet(PinType::IType::Control); + } + + std::string Loadmess::getIODescription(bool is_inlet, size_t index) const + { + if(!is_inlet && index == 0) + { + return "Sends message when patch is loaded"; + } + else if(is_inlet && index == 0) + { + return "Bang to retrigger message"; + } + + return {}; + } + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Basic/KiwiEngine_ErrorBox.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Loadmess.h old mode 100644 new mode 100755 similarity index 52% rename from Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Basic/KiwiEngine_ErrorBox.cpp rename to Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Loadmess.h index ef5a0755..093c15a0 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Basic/KiwiEngine_ErrorBox.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Loadmess.h @@ -1,48 +1,47 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#include - -namespace kiwi -{ - namespace engine - { - // ================================================================================ // - // ERRORBOX // - // ================================================================================ // - - ErrorBox::ErrorBox(model::Object const& model, Patcher& patcher, std::vector const& args) - : AudioObject(model, patcher) - { - ; - } - - void ErrorBox::receive(size_t index, std::vector const& args) - { - ; - } - - void ErrorBox::prepare(dsp::Processor::PrepareInfo const& infos) - { - ; - } - } -} +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT LOADMESS // + // ================================================================================ // + + class Loadmess : public model::Object + { + public: + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + + Loadmess(flip::Default& d) : model::Object(d) {} + + Loadmess(std::vector const& args); + + std::string getIODescription(bool is_inlet, size_t index) const override; + }; + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Math/KiwiModel_Plus.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Math/KiwiModel_Plus.cpp deleted file mode 100755 index bf7a6169..00000000 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Math/KiwiModel_Plus.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#include - -#include - -namespace kiwi -{ - namespace model - { - // ================================================================================ // - // OBJECT PLUS // - // ================================================================================ // - - void Plus::declare() - { - Factory::add("plus").addAlias("+"); - } - - Plus::Plus(std::string const& name, std::vector const& args) - { - pushInlet({PinType::IType::Control}); - - if (args.empty() || !args[0].isNumber()) - { - pushInlet({PinType::IType::Control}); - } - - pushOutlet(PinType::IType::Control); - } - - std::string Plus::getIODescription(bool is_inlet, size_t index) const - { - return is_inlet ? (index == 0) ? "Left operand" : "Right operand" : "Result"; - } - } -} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Math/KiwiModel_Plus.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Math/KiwiModel_Plus.h deleted file mode 100755 index f9047096..00000000 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Math/KiwiModel_Plus.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#pragma once - -#include - -namespace kiwi -{ - namespace model - { - // ================================================================================ // - // OBJECT PLUS // - // ================================================================================ // - - class Plus : public model::Object - { - public: - - //! @brief flip Default Constructor - Plus(flip::Default& d) : model::Object(d) {} - - //! @brief Constructor - Plus(std::string const& name, std::vector const& args); - - std::string getIODescription(bool is_inlet, size_t index) const override; - - //! @internal flip static declare method - static void declare(); - }; - } -} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Math/KiwiModel_Times.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Math/KiwiModel_Times.cpp deleted file mode 100755 index 06e513f5..00000000 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Math/KiwiModel_Times.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#include - -#include - -namespace kiwi -{ - namespace model - { - // ================================================================================ // - // OBJECT TIMES // - // ================================================================================ // - - void Times::declare() - { - Factory::add("times").addAlias("*"); - } - - Times::Times(std::string const& name, std::vector const& args) - { - pushInlet({PinType::IType::Control}); - - if (args.empty() || !args[0].isNumber()) - { - pushInlet({PinType::IType::Control}); - } - - pushOutlet(PinType::IType::Control); - } - - std::string Times::getIODescription(bool is_inlet, size_t index) const - { - return is_inlet ? (index == 0) ? "Left operand" : "Right operand" : "Result"; - } - } -} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Math/KiwiModel_Times.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Math/KiwiModel_Times.h deleted file mode 100755 index c5aaf1d1..00000000 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Math/KiwiModel_Times.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#pragma once - -#include - -namespace kiwi -{ - namespace model - { - // ================================================================================ // - // OBJECT TIMES // - // ================================================================================ // - - class Times : public model::Object - { - public: - - //! @brief flip Default Constructor - Times(flip::Default& d) : model::Object(d) {} - - //! @brief Constructor - Times(std::string const& name, std::vector const& args); - - std::string getIODescription(bool is_inlet, size_t index) const override; - - //! @internal flip static declare method - static void declare(); - }; - } -} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Loadmess.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Loadmess.cpp deleted file mode 100755 index c8c9adb9..00000000 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Loadmess.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#include - -#include - -namespace kiwi -{ - namespace model - { - // ================================================================================ // - // OBJECT LOADMESS // - // ================================================================================ // - - Loadmess::Loadmess(std::string const& name, std::vector const& args) - { - pushOutlet(PinType::IType::Control); - } - - void Loadmess::declare() - { - Factory::add("loadmess"); - } - - std::string Loadmess::getIODescription(bool is_inlet, size_t index) const - { - if(is_inlet) - { - return "Receive messages when the patch is loaded"; - } - - return {}; - } - } -} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Print.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Print.h deleted file mode 100755 index adcb7a55..00000000 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Print.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#pragma once - -#include - -namespace kiwi -{ - namespace model - { - // ================================================================================ // - // OBJECT PRINT // - // ================================================================================ // - - class Print : public model::Object - { - public: - - //! @brief flip Default Constructor - Print(flip::Default& d) : model::Object(d) {} - - //! @brief Constructor - Print(std::string const& name, std::vector const& args); - - std::string getIODescription(bool is_inlet, size_t index) const override; - - //! @internal flip static declare method - static void declare(); - }; - } -} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Receive.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Receive.cpp deleted file mode 100755 index fd9a1af5..00000000 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Receive.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#include - -#include - -namespace kiwi -{ - namespace model - { - // ================================================================================ // - // OBJECT RECEIVE // - // ================================================================================ // - - Receive::Receive(std::string const& name, std::vector const& args) - { - pushOutlet(PinType::IType::Control); - } - - void Receive::declare() - { - Factory::add("receive").addAlias("r"); - } - - std::string Receive::getIODescription(bool is_inlet, size_t index) const - { - if(!is_inlet) - { - return "Receive messages"; - } - - return {}; - } - } -} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Receive.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Receive.h deleted file mode 100755 index d97620f9..00000000 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Receive.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#pragma once - -#include - -namespace kiwi -{ - namespace model - { - // ================================================================================ // - // OBJECT RECEIVE // - // ================================================================================ // - - class Receive : public model::Object - { - public: - - //! @brief flip Default Constructor - Receive(flip::Default& d) : model::Object(d) {} - - //! @brief Constructor - Receive(std::string const& name, std::vector const& args); - - std::string getIODescription(bool is_inlet, size_t index) const override; - - //! @internal flip static declare method - static void declare(); - }; - } -} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_MeterTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_MeterTilde.cpp similarity index 67% rename from Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_MeterTilde.cpp rename to Modules/KiwiModel/KiwiModel_Objects/KiwiModel_MeterTilde.cpp index 7cffd6b5..30ff1dde 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_MeterTilde.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_MeterTilde.cpp @@ -19,33 +19,50 @@ ============================================================================== */ +#include +#include #include -#include - namespace kiwi { namespace model { // ================================================================================ // // OBJECT METER~ // // ================================================================================ // + void MeterTilde::declare() + { + std::unique_ptr metertilde_class(new ObjectClass("meter~", &MeterTilde::create)); + + metertilde_class->setFlag(ObjectClass::Flag::DefinedSize); + metertilde_class->setFlag(ObjectClass::Flag::ResizeWidth); + metertilde_class->setFlag(ObjectClass::Flag::ResizeHeight); + + flip::Class & metertilde_model = DataModel::declare() + .name(metertilde_class->getModelName().c_str()) + .inherit(); + + Factory::add(std::move(metertilde_class), metertilde_model); + } + + std::unique_ptr MeterTilde::create(std::vector const& args) + { + return std::make_unique(args); + } + MeterTilde::MeterTilde(flip::Default& d): model::Object(d) { addSignal(Signal::PeakChanged, *this); } - MeterTilde::MeterTilde(std::string const& name, std::vector const& args): + MeterTilde::MeterTilde(std::vector const& args): model::Object() { if (!args.empty()) { - throw std::runtime_error("wrong arguments for object meter"); + throw Error("meter~ too many arguments"); } - setFlag(Flag::IFlag::DefinedSize); - setFlag(Flag::IFlag::ResizeWidth); - setFlag(Flag::IFlag::ResizeHeight); setMinWidth(20); setMinHeight(20); setWidth(100); @@ -70,10 +87,5 @@ namespace kiwi { namespace model { return description; } - - void MeterTilde::declare() - { - Factory::add("meter~"); - } } } diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_MeterTilde.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_MeterTilde.h similarity index 84% rename from Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_MeterTilde.h rename to Modules/KiwiModel/KiwiModel_Objects/KiwiModel_MeterTilde.h index 9bb220d8..6459d85d 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_MeterTilde.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_MeterTilde.h @@ -38,19 +38,17 @@ namespace kiwi { namespace model { PeakChanged }; - //! @brief flip Default Constructor - MeterTilde(flip::Default& d); + public: // methods - //! @brief Constructor - MeterTilde(std::string const& name, std::vector const& args); + static void declare(); - //! @brief Returns the descriptions of an inlet/outlet. - std::string getIODescription(bool is_inlet, size_t index) const override final; + static std::unique_ptr create(std::vector const& args); - //! @internal flip static declare method. - static void declare(); + MeterTilde(flip::Default& d); + + MeterTilde(std::vector const& args); - private: // members + std::string getIODescription(bool is_inlet, size_t index) const override final; }; } diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Metro.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Metro.cpp new file mode 100755 index 00000000..049521f7 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Metro.cpp @@ -0,0 +1,87 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT METRO // + // ================================================================================ // + + void Metro::declare() + { + std::unique_ptr metro_class(new ObjectClass("metro", &Metro::create)); + + flip::Class & metro_model = DataModel::declare() + .name(metro_class->getModelName().c_str()) + .inherit(); + + Factory::add(std::move(metro_class), metro_model); + } + + std::unique_ptr Metro::create(std::vector const& args) + { + return std::make_unique(args); + } + + Metro::Metro(std::vector const& args) + { + if (args.size() > 1) + throw Error("metro too many arguments"); + + if (args.size() == 1 && !args[0].isNumber()) + throw Error("metro wrong argument [" + args[0].getString() + "]"); + + pushInlet({PinType::IType::Control}); + + if (args.empty()) + { + pushInlet({PinType::IType::Control}); + } + + pushOutlet(PinType::IType::Control); + } + + std::string Metro::getIODescription(bool is_inlet, size_t index) const + { + if(is_inlet) + { + if(index == 0) + { + return "Start/Stop metronome"; + } + else if(index == 1) + { + return "Set time interval"; + } + } + else + { + return "Outputs metronome ticks as bang"; + } + + return {}; + } + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Metro.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Metro.h new file mode 100755 index 00000000..18881dc9 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Metro.h @@ -0,0 +1,47 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT METRO // + // ================================================================================ // + + class Metro : public model::Object + { + public: // methods + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + + Metro(flip::Default& d) : model::Object(d) {}; + + Metro(std::vector const& args); + + std::string getIODescription(bool is_inlet, size_t index) const override; + }; + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_NewBox.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_NewBox.cpp new file mode 100755 index 00000000..2d1ce709 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_NewBox.cpp @@ -0,0 +1,65 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // NEWBOX // + // ================================================================================ // + + void NewBox::declare() + { + std::unique_ptr object_class(new ObjectClass("newbox", + &NewBox::create)); + + object_class->setFlag(ObjectClass::Flag::DefinedSize); + object_class->setFlag(ObjectClass::Flag::Internal); + + flip::Class & data_model = DataModel::declare() + .name(object_class->getModelName().c_str()) + .inherit(); + + Factory::add(std::move(object_class), data_model); + } + + std::unique_ptr NewBox::create(std::vector const& args) + { + return std::make_unique(); + } + + NewBox::NewBox() + { + setWidth(80); + setHeight(20); + pushInlet({PinType::IType::Control}); + } + + std::string NewBox::getIODescription(bool is_inlet, size_t index) const + { + return "(nothing here)"; + } + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Loadmess.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_NewBox.h similarity index 51% rename from Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Loadmess.h rename to Modules/KiwiModel/KiwiModel_Objects/KiwiModel_NewBox.h index 9405393c..a66e924d 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Loadmess.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_NewBox.h @@ -23,28 +23,29 @@ #include -namespace kiwi -{ - namespace model +namespace kiwi { namespace model { + + // ================================================================================ // + // NEWBOX // + // ================================================================================ // + + class NewBox : public model::Object { - // ================================================================================ // - // OBJECT LOADMESS // - // ================================================================================ // + public: - class Loadmess : public model::Object - { - public: - - //! @brief flip Default Constructor - Loadmess(flip::Default& d) : model::Object(d) {} - - //! @brief Constructor - Loadmess(std::string const& name, std::vector const& args); - - std::string getIODescription(bool is_inlet, size_t index) const override; - - //! @internal flip static declare method - static void declare(); - }; - } -} + //! @brief flip Default Constructor. + NewBox(flip::Default& d) : model::Object(d) {} + + //! @brief Constructor. + NewBox(); + + std::string getIODescription(bool is_inlet, size_t index) const override; + + //! @brief Declaration method. + static void declare(); + + //! @brief The object's creation method. + static std::unique_ptr create(std::vector const& args); + }; + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h index 83a6e2ba..198c809d 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h @@ -21,54 +21,24 @@ #pragma once -// ================================================================================ // -// BASIC OBJECTS // -// ================================================================================ // - -#include -#include - -// ================================================================================ // -// DSP OBJECTS // -// ================================================================================ // - -#include -#include -#include -#include -#include -#include -#include -#include - -// ================================================================================ // -// MATH OBJECTS // -// ================================================================================ // - -#include -#include - -// ================================================================================ // -// MESSAGE OBJECTS // -// ================================================================================ // - -#include -#include -#include - -// ================================================================================ // -// TIME OBJECTS // -// ================================================================================ // - -#include -#include -#include - -// ================================================================================ // -// CONTROLLER OBJECTS // -// ================================================================================ // - -#include -#include -#include - +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Operator.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Operator.cpp new file mode 100755 index 00000000..d3e4f5f1 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Operator.cpp @@ -0,0 +1,56 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OPERATOR // + // ================================================================================ // + + void Operator::declare() + { + DataModel::declare() + .name("cicm.kiwi.object.operator") + .inherit(); + } + + Operator::Operator(std::vector const& args): + Object() + { + pushInlet({PinType::IType::Control}); + + if (args.empty() || !args[0].isNumber()) + { + pushInlet({PinType::IType::Control}); + } + + pushOutlet(PinType::IType::Control); + } + + std::string Operator::getIODescription(bool is_inlet, size_t index) const + { + return is_inlet ? (index == 0) ? "Left operand" : "Right operand" : "Result"; + } +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Operator.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Operator.h new file mode 100755 index 00000000..9f04fe4e --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Operator.h @@ -0,0 +1,45 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OPERATOR // + // ================================================================================ // + + class Operator : public model::Object + { + public: // methods + + Operator(flip::Default& d) : model::Object(d) {} + + Operator(std::vector const& args); + + std::string getIODescription(bool is_inlet, size_t index) const override; + + static void declare(); + }; + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_OperatorTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_OperatorTilde.cpp new file mode 100755 index 00000000..776d411e --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_OperatorTilde.cpp @@ -0,0 +1,56 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OPERATOR TILDE // + // ================================================================================ // + + void OperatorTilde::declare() + { + DataModel::declare() + .name("cicm.kiwi.object.operatortilde") + .inherit(); + } + + OperatorTilde::OperatorTilde(std::vector const& args): + Object() + { + pushInlet({PinType::IType::Signal}); + + if (args.empty() || !args[0].isNumber()) + { + pushInlet({PinType::IType::Signal, PinType::IType::Control}); + } + + pushOutlet(PinType::IType::Signal); + } + + std::string OperatorTilde::getIODescription(bool is_inlet, size_t index) const + { + return is_inlet ? (index == 0) ? "Left operand" : "Right operand" : "Result"; + } +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_OperatorTilde.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_OperatorTilde.h new file mode 100755 index 00000000..dc0b3628 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_OperatorTilde.h @@ -0,0 +1,45 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OPERATOR TILDE // + // ================================================================================ // + + class OperatorTilde : public model::Object + { + public: // methods + + OperatorTilde(flip::Default& d) : model::Object(d) {} + + OperatorTilde(std::vector const& args); + + std::string getIODescription(bool is_inlet, size_t index) const override; + + static void declare(); + }; + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_OscTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_OscTilde.cpp new file mode 100755 index 00000000..14d27f64 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_OscTilde.cpp @@ -0,0 +1,84 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT OSC~ // + // ================================================================================ // + + void OscTilde::declare() + { + std::unique_ptr osctilde_class(new ObjectClass("osc~", &OscTilde::create)); + + flip::Class & osctilde_model = DataModel::declare() + .name(osctilde_class->getModelName().c_str()) + .inherit(); + + Factory::add(std::move(osctilde_class), osctilde_model); + } + + std::unique_ptr OscTilde::create(std::vector const& args) + { + return std::make_unique(args); + } + + OscTilde::OscTilde(std::vector const& args): + model::Object() + { + if (args.size() > 1) + throw Error("osc~ too many arguments"); + + if (args.size() == 1 && !args[0].isNumber()) + throw Error("osc~ wrong arguments [" + args[0].getString() + "]"); + + pushInlet({PinType::IType::Control, PinType::IType::Signal}); + pushInlet({PinType::IType::Control, PinType::IType::Signal}); + + pushOutlet(PinType::IType::Signal); + } + + std::string OscTilde::getIODescription(bool is_inlet, size_t index) const + { + if(is_inlet) + { + if(index == 0) + { + return "(signal/float) Set frequency"; + } + else if(index == 1) + { + return "(signal/float) Set phase (0-1)"; + } + } + else + { + return "(signal) Output"; + } + + return {}; + } + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_OscTilde.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_OscTilde.h new file mode 100755 index 00000000..37c3d00b --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_OscTilde.h @@ -0,0 +1,47 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT OSC~ // + // ================================================================================ // + + class OscTilde : public model::Object + { + public: + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + + OscTilde(flip::Default& d): model::Object(d){}; + + OscTilde(std::vector const& args); + + std::string getIODescription(bool is_inlet, size_t index) const override; + }; + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Pipe.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Pipe.cpp new file mode 100755 index 00000000..3a8bbd6e --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Pipe.cpp @@ -0,0 +1,87 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT PIPE // + // ================================================================================ // + + void Pipe::declare() + { + std::unique_ptr pipe_class(new ObjectClass("pipe", &Pipe::create)); + + flip::Class & pipe_model = DataModel::declare() + .name(pipe_class->getModelName().c_str()) + .inherit(); + + Factory::add(std::move(pipe_class), pipe_model); + } + + std::unique_ptr Pipe::create(std::vector const& args) + { + return std::make_unique(args); + } + + Pipe::Pipe(std::vector const& args) + { + if (args.size() > 1) + throw Error("pipe too many arguments"); + + if(args.size() == 1 && !args[0].isNumber()) + throw Error("pipe argument must be a number"); + + pushInlet({PinType::IType::Control}); + + if (args.empty()) + { + pushInlet({PinType::IType::Control}); + } + + pushOutlet(PinType::IType::Control); + } + + std::string Pipe::getIODescription(bool is_inlet, size_t index) const + { + if(is_inlet) + { + if(index == 0) + { + return "Anything to be delayed"; + } + else if(index == 1) + { + return "Set delay time"; + } + } + else + { + return "Delayed messages"; + } + + return {}; + } + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Pipe.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Pipe.h new file mode 100755 index 00000000..121b198a --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Pipe.h @@ -0,0 +1,47 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT PIPE // + // ================================================================================ // + + class Pipe : public model::Object + { + public: // methods + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + + Pipe(flip::Default& d) : model::Object(d) {}; + + Pipe(std::vector const& args); + + std::string getIODescription(bool is_inlet, size_t index) const override; + }; + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Plus.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Plus.cpp new file mode 100755 index 00000000..14d7f0f7 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Plus.cpp @@ -0,0 +1,61 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT PLUS // + // ================================================================================ // + + void Plus::declare() + { + if (!DataModel::has()) + { + Operator::declare(); + } + + std::unique_ptr plus_class(new ObjectClass("plus", + &Plus::create)); + + plus_class->addAlias("+"); + + flip::Class & plus_model = DataModel::declare() + .name(plus_class->getModelName().c_str()) + .inherit(); + + Factory::add(std::move(plus_class), plus_model); + } + + std::unique_ptr Plus::create(std::vector const& args) + { + return std::make_unique(args); + } + + Plus::Plus(std::vector const& args): + Operator(args) + { + } + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Plus.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Plus.h new file mode 100755 index 00000000..d564b793 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Plus.h @@ -0,0 +1,46 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT PLUS // + // ================================================================================ // + + class Plus : public Operator + { + public: + + Plus(flip::Default& d) : Operator(d) {} + + Plus(std::vector const& args); + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + }; + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_PlusTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_PlusTilde.cpp new file mode 100755 index 00000000..f40b83f9 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_PlusTilde.cpp @@ -0,0 +1,60 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT PLUS~ // + // ================================================================================ // + + void PlusTilde::declare() + { + if (!DataModel::has()) + { + OperatorTilde::declare(); + } + + std::unique_ptr plustilde_class(new ObjectClass("plus~", &PlusTilde::create)); + + plustilde_class->addAlias("+~"); + + flip::Class & plustilde_model = DataModel::declare() + .name(plustilde_class->getModelName().c_str()) + .inherit(); + + Factory::add(std::move(plustilde_class), plustilde_model); + } + + std::unique_ptr PlusTilde::create(std::vector const& args) + { + return std::make_unique(args); + } + + PlusTilde::PlusTilde(std::vector const& args): + OperatorTilde(args) + { + } + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_PlusTilde.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_PlusTilde.h new file mode 100755 index 00000000..6bca7a34 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_PlusTilde.h @@ -0,0 +1,45 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT PLUS~ // + // ================================================================================ // + + class PlusTilde : public OperatorTilde + { + public: + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + + PlusTilde(flip::Default& d): model::OperatorTilde(d){}; + + PlusTilde(std::vector const& args); + }; + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Print.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Print.cpp similarity index 67% rename from Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Print.cpp rename to Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Print.cpp index 548b56a8..ebac4166 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message/KiwiModel_Print.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Print.cpp @@ -19,7 +19,7 @@ ============================================================================== */ -#include +#include #include @@ -31,14 +31,29 @@ namespace kiwi // OBJECT PRINT // // ================================================================================ // - Print::Print(std::string const& name, std::vector const& args) + void Print::declare() { - pushInlet({PinType::IType::Control}); + std::unique_ptr print_class(new ObjectClass("print", + &Print::create)); + + // data model + + flip::Class & print_model = DataModel::declare() + .name(print_class->getModelName().c_str()) + .inherit(); + + Factory::add(std::move(print_class), print_model); } - void Print::declare() + std::unique_ptr Print::create(std::vector const& args) { - Factory::add("print"); + return std::make_unique(); + } + + Print::Print(): + Object() + { + pushInlet({PinType::IType::Control}); } std::string Print::getIODescription(bool is_inlet, size_t index) const diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Print.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Print.h new file mode 100755 index 00000000..465b9f14 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Print.h @@ -0,0 +1,48 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT PRINT // + // ================================================================================ // + + class Print : public model::Object + { + public: // methods + + Print(flip::Default& d) : model::Object(d) {} + + Print(); + + std::string getIODescription(bool is_inlet, size_t index) const override; + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + + }; + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Receive.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Receive.cpp new file mode 100755 index 00000000..f05c4478 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Receive.cpp @@ -0,0 +1,70 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT RECEIVE // + // ================================================================================ // + + void Receive::declare() + { + // class + std::unique_ptr receive_class(new ObjectClass("receive", + &Receive::create)); + + receive_class->addAlias("r"); + + // data model + + flip::Class & receive_model = DataModel::declare() + .name(receive_class->getModelName().c_str()) + .inherit(); + + Factory::add(std::move(receive_class), receive_model); + } + + std::unique_ptr Receive::create(std::vector const& args) + { + return std::make_unique(); + } + + Receive::Receive(): + Object() + { + pushOutlet(PinType::IType::Control); + } + + std::string Receive::getIODescription(bool is_inlet, size_t index) const + { + if(!is_inlet) + { + return "Receive messages"; + } + + return {}; + } + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Receive.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Receive.h new file mode 100755 index 00000000..81ddee00 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Receive.h @@ -0,0 +1,47 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT RECEIVE // + // ================================================================================ // + + class Receive : public model::Object + { + public: // methods + + Receive(flip::Default& d) : model::Object(d) {} + + Receive(); + + std::string getIODescription(bool is_inlet, size_t index) const override; + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + + }; +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_SigTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_SigTilde.cpp new file mode 100755 index 00000000..3a5d4e53 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_SigTilde.cpp @@ -0,0 +1,64 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT SIG~ // + // ================================================================================ // + + void SigTilde::declare() + { + std::unique_ptr sigtilde_class(new ObjectClass("sig~", &SigTilde::create)); + + flip::Class & sigtilde_model = DataModel::declare() + .name(sigtilde_class->getModelName().c_str()) + .inherit(); + + Factory::add(std::move(sigtilde_class), sigtilde_model); + } + + std::unique_ptr SigTilde::create(std::vector const& args) + { + return std::make_unique(args); + } + + + SigTilde::SigTilde(std::vector const& args) + { + if (args.empty() || !args[0].isNumber()) + { + pushInlet({PinType::IType::Control}); + } + + pushOutlet(PinType::IType::Signal); + } + + std::string SigTilde::getIODescription(bool is_inlet, size_t index) const + { + return is_inlet ? "(float/int) Set signal value" : "(signal) Output value"; + } + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_SigTilde.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_SigTilde.h new file mode 100755 index 00000000..092dd139 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_SigTilde.h @@ -0,0 +1,47 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT SIG~ // + // ================================================================================ // + + class SigTilde : public model::Object + { + public: + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + + SigTilde(flip::Default& d): model::Object(d){}; + + SigTilde(std::vector const& args); + + std::string getIODescription(bool is_inlet, size_t index) const override; + }; + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Slider.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Slider.cpp similarity index 61% rename from Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Slider.cpp rename to Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Slider.cpp index dc2fc0f7..6180c81d 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Slider.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Slider.cpp @@ -20,7 +20,9 @@ */ #include -#include +#include + +#include namespace kiwi { namespace model { @@ -28,18 +30,45 @@ namespace kiwi { namespace model { // OBJECT SLIDER // // ================================================================================ // - Slider::Slider(std::string const& name, std::vector const& args): - Object() + void Slider::declare() + { + std::unique_ptr slider_class(new ObjectClass("slider", + &Slider::create)); + // parameters + + std::unique_ptr param_value(new ParameterClass(tool::Parameter::Type::Float)); + + slider_class->addParameter("value", std::move(param_value)); + + + // flags + + slider_class->setFlag(ObjectClass::Flag::ResizeWidth); + slider_class->setFlag(ObjectClass::Flag::ResizeHeight); + slider_class->setFlag(ObjectClass::Flag::DefinedSize); + + // data model + + flip::Class & slider_model = DataModel::declare() + .name(slider_class->getModelName().c_str()) + .inherit(); + + Factory::add(std::move(slider_class), slider_model); + } + + std::unique_ptr Slider::create(std::vector const& args) { if (!args.empty()) { - throw std::runtime_error("wrong arguments for object bang"); + throw Error("slider too many arguments"); } - setFlag(Flag::IFlag::DefinedSize); - setFlag(Flag::IFlag::ResizeWidth); - setFlag(Flag::IFlag::ResizeHeight); - addSignal(Signal::ValueChanged, *this); + return std::make_unique(); + } + + Slider::Slider(): + Object() + { setMinWidth(20.); setMinHeight(20.); setWidth(20); @@ -51,12 +80,6 @@ namespace kiwi { namespace model { Slider::Slider(flip::Default& d): Object(d) { - addSignal(Signal::ValueChanged, *this); - } - - void Slider::declare() - { - Factory::add("slider"); } std::string Slider::getIODescription(bool is_inlet, size_t index) const diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Slider.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Slider.h similarity index 86% rename from Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Slider.h rename to Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Slider.h index 7f222151..7ab40625 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Controller/KiwiModel_Slider.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Slider.h @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -37,21 +38,16 @@ namespace kiwi { namespace model { class Slider : public model::Object { - public: // enums - - enum Signal : SignalKey - { - ValueChanged - }; - public: // methods Slider(flip::Default& d); - Slider(std::string const& name, std::vector const& args); + Slider(); std::string getIODescription(bool is_inlet, size_t index) const override; static void declare(); + + static std::unique_ptr create(std::vector const& args); }; }} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Delay.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Delay.h deleted file mode 100755 index ad755b69..00000000 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Delay.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#pragma once - -#include - -namespace kiwi -{ - namespace model - { - // ================================================================================ // - // OBJECT DELAY // - // ================================================================================ // - - class Delay : public model::Object - { - public: // methods - - //! @brief flip Default Constructor - Delay(flip::Default& d) : model::Object(d) {}; - - //! @brief Constructor - Delay(std::string const& name, std::vector const& args); - - std::string getIODescription(bool is_inlet, size_t index) const override; - - //! @internal flip static declare method - static void declare(); - }; - } -} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Metro.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Metro.cpp deleted file mode 100755 index 6778096b..00000000 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Metro.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#include - -#include - -namespace kiwi -{ - namespace model - { - // ================================================================================ // - // OBJECT METRO // - // ================================================================================ // - - Metro::Metro(std::string const& name, std::vector const& args) - { - if (args.size() < 1 || (args.size() == 1 && !args[0].isNumber())) - { - throw std::runtime_error("wrong argument for object Metro"); - } - - pushInlet({PinType::IType::Control}); - - if (args.empty()) - { - pushInlet({PinType::IType::Control}); - } - - pushOutlet(PinType::IType::Control); - } - - void Metro::declare() - { - Factory::add("metro"); - } - - std::string Metro::getIODescription(bool is_inlet, size_t index) const - { - if(is_inlet) - { - if(index == 0) - { - return "Start/Stop metronome"; - } - else if(index == 1) - { - return "Set time interval"; - } - } - else - { - return "Outputs metronome ticks as bang"; - } - - return {}; - } } -} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Metro.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Metro.h deleted file mode 100755 index 3632eb6d..00000000 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Metro.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#pragma once - -#include - -namespace kiwi -{ - namespace model - { - // ================================================================================ // - // OBJECT METRO // - // ================================================================================ // - - class Metro : public model::Object - { - public: // methods - - //! @brief flip Default Constructor - Metro(flip::Default& d) : model::Object(d) {}; - - //! @brief Constructor - Metro(std::string const& name, std::vector const& args); - - std::string getIODescription(bool is_inlet, size_t index) const override; - - //! @internal flip static declare method - static void declare(); - }; - } -} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Pipe.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Pipe.cpp deleted file mode 100755 index 35e76979..00000000 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Pipe.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#include - -#include - -namespace kiwi -{ - namespace model - { - // ================================================================================ // - // OBJECT PIPE // - // ================================================================================ // - - Pipe::Pipe(std::string const& name, std::vector const& args) - { - if (args.size() > 1 || (args.size() == 1 && !args[0].isNumber())) - { - throw std::runtime_error("wrong argument for object Pipe"); - } - - pushInlet({PinType::IType::Control}); - - if (args.empty()) - { - pushInlet({PinType::IType::Control}); - } - - pushOutlet(PinType::IType::Control); - } - - void Pipe::declare() - { - Factory::add("pipe"); - } - - std::string Pipe::getIODescription(bool is_inlet, size_t index) const - { - if(is_inlet) - { - if(index == 0) - { - return "Anything to be delayed"; - } - else if(index == 1) - { - return "Set delay time"; - } - } - else - { - return "Delayed messages"; - } - - return {}; - } - } -} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Pipe.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Pipe.h deleted file mode 100755 index f1b14ce5..00000000 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Time/KiwiModel_Pipe.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#pragma once - -#include - -namespace kiwi -{ - namespace model - { - // ================================================================================ // - // OBJECT PIPE // - // ================================================================================ // - - class Pipe : public model::Object - { - public: // methods - - //! @brief flip Default Constructor - Pipe(flip::Default& d) : model::Object(d) {}; - - //! @brief Constructor - Pipe(std::string const& name, std::vector const& args); - - std::string getIODescription(bool is_inlet, size_t index) const override; - - //! @internal flip static declare method - static void declare(); - }; - } -} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Times.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Times.cpp new file mode 100755 index 00000000..3532fe0b --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Times.cpp @@ -0,0 +1,61 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT TIMES // + // ================================================================================ // + + void Times::declare() + { + if (!DataModel::has()) + { + Operator::declare(); + } + + std::unique_ptr time_class(new ObjectClass("times", + &Times::create)); + + time_class->addAlias("*"); + + flip::Class & time_model = DataModel::declare() + .name(time_class->getModelName().c_str()) + .inherit(); + + Factory::add(std::move(time_class), time_model); + } + + std::unique_ptr Times::create(std::vector const& args) + { + return std::make_unique(args); + } + + Times::Times(std::vector const& args): + Operator(args) + { + } + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Times.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Times.h new file mode 100755 index 00000000..2afd456e --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Times.h @@ -0,0 +1,46 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT TIMES // + // ================================================================================ // + + class Times : public Operator + { + public: + + Times(flip::Default& d) : Operator(d) {} + + Times(std::vector const& args); + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + }; + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_TimesTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_TimesTilde.cpp new file mode 100755 index 00000000..25fa4d92 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_TimesTilde.cpp @@ -0,0 +1,60 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT TIMES~ // + // ================================================================================ // + + void TimesTilde::declare() + { + if (!DataModel::has()) + { + OperatorTilde::declare(); + } + + std::unique_ptr timestilde_class(new ObjectClass("times~", &TimesTilde::create)); + + timestilde_class->addAlias("*~"); + + flip::Class & plustilde_model = DataModel::declare() + .name(timestilde_class->getModelName().c_str()) + .inherit(); + + Factory::add(std::move(timestilde_class), plustilde_model); + } + + std::unique_ptr TimesTilde::create(std::vector const& args) + { + return std::make_unique(args); + } + + TimesTilde::TimesTilde(std::vector const& args): + OperatorTilde(args) + { + } + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_TimesTilde.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_TimesTilde.h new file mode 100755 index 00000000..68e405d1 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_TimesTilde.h @@ -0,0 +1,45 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT *~ // + // ================================================================================ // + + class TimesTilde : public OperatorTilde + { + public: + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + + TimesTilde(flip::Default& d): OperatorTilde(d){}; + + TimesTilde(std::vector const& args); + }; + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Toggle.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Toggle.cpp new file mode 100755 index 00000000..cec2f17d --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Toggle.cpp @@ -0,0 +1,94 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT TOGGLE // + // ================================================================================ // + + void Toggle::declare() + { + std::unique_ptr toggle_class(new ObjectClass("toggle", &Toggle::create)); + + toggle_class->setFlag(ObjectClass::Flag::DefinedSize); + toggle_class->setFlag(ObjectClass::Flag::ResizeWidth); + toggle_class->setFlag(ObjectClass::Flag::ResizeHeight); + + std::unique_ptr param_value(new ParameterClass(tool::Parameter::Type::Int)); + + toggle_class->addParameter("value", std::move(param_value)); + + flip::Class & toggle_model = DataModel::declare() + .name(toggle_class->getModelName().c_str()) + .inherit(); + + Factory::add(std::move(toggle_class), toggle_model); + } + + std::unique_ptr Toggle::create(std::vector const& args) + { + return std::make_unique(args); + } + + Toggle::Toggle(std::vector const& args): + Object() + { + if (!args.empty()) + { + throw Error("toggle too many arguments"); + } + + addSignal<>(Signal::OutputValue, *this); + setRatio(1.); + setMinWidth(20.); + setWidth(20); + pushInlet({PinType::IType::Control}); + pushOutlet(PinType::IType::Control); + } + + Toggle::Toggle(flip::Default& d): + Object(d) + { + addSignal<>(Signal::OutputValue, *this); + } + + std::string Toggle::getIODescription(bool is_inlet, size_t index) const + { + if (is_inlet && index == 0) + { + return "Switches the toggle on or of"; + } + else if(!is_inlet && index == 0) + { + return "Sends 0 or 1 when toggle is switched on or off"; + } + else + { + return ""; + } + } + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_SigTilde.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Toggle.h similarity index 52% rename from Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_SigTilde.h rename to Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Toggle.h index 680911ea..20691936 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Dsp/KiwiModel_SigTilde.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Toggle.h @@ -23,28 +23,33 @@ #include -namespace kiwi -{ - namespace model +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT TOGGLE // + // ================================================================================ // + + + class Toggle : public model::Object { - // ================================================================================ // - // OBJECT SIG~ // - // ================================================================================ // + public: // enum - class SigTilde : public model::Object + enum Signal : SignalKey { - public: - - //! @brief flip Default Constructor - SigTilde(flip::Default& d): model::Object(d){}; - - //! @brief Constructor - SigTilde(std::string const& name, std::vector const& args); - - std::string getIODescription(bool is_inlet, size_t index) const override; - - //! @internal flip static declare method - static void declare(); + OutputValue }; - } -} + + public: // methods + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + + Toggle(flip::Default& d); + + Toggle(std::vector const& args); + + std::string getIODescription(bool is_inlet, size_t index) const override; + }; + +}} diff --git a/Modules/KiwiTool/KiwiTool_Parameter.cpp b/Modules/KiwiTool/KiwiTool_Parameter.cpp new file mode 100644 index 00000000..573a261a --- /dev/null +++ b/Modules/KiwiTool/KiwiTool_Parameter.cpp @@ -0,0 +1,110 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +namespace kiwi { namespace tool { + + Parameter::Parameter(Type type): + m_type(type), + m_atoms() + { + switch (m_type) + { + case Type::Float: + { + float value = 0; + m_atoms.push_back(value); + break; + } + case Type::Int: + { + int value = 0; + m_atoms.push_back(value); + break; + } + case Type::String: + { + std::string value = ""; + m_atoms.push_back(value); + } + } + } + + Parameter::Parameter(Type type, std::vector const atoms): + m_type(type), + m_atoms(atoms) + { + switch (m_type) + { + case Type::Float: + { + assert(m_atoms.size() == 1 && m_atoms[0].isFloat() && "Parameter float bad initialization"); + m_atoms = atoms; + break; + } + case Type::Int: + { + assert(m_atoms.size() == 1 && m_atoms[0].isInt() && "Parameter int bad initialization"); + break; + } + case Type::String: + { + assert(m_atoms.size() == 1 && m_atoms[0].isString() && "Parameter string bad initialization"); + break; + } + } + } + + Parameter::Parameter(Parameter const& other): + m_type(other.m_type), + m_atoms(other.m_atoms) + { + } + + Parameter::~Parameter() + { + } + + Parameter& Parameter::operator=(Parameter const& other) + { + assert(m_type == other.m_type && "Parameter assignment with different types"); + + if (&other != this) + { + m_atoms = other.m_atoms; + } + + return *this; + } + + Parameter::Type Parameter::getType() const + { + return m_type; + } + + Atom const& Parameter::operator[](size_t index) const + { + assert(m_atoms.size() > index); + return m_atoms[index]; + } + +}} diff --git a/Modules/KiwiTool/KiwiTool_Parameter.h b/Modules/KiwiTool/KiwiTool_Parameter.h new file mode 100644 index 00000000..0eb73e80 --- /dev/null +++ b/Modules/KiwiTool/KiwiTool_Parameter.h @@ -0,0 +1,79 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace tool { + + //! @brief Parameter is a class designed to represent any type of data. + //! @details It's implemented as a vector of Atom. + //! @todo Use virtual classes that implements check of atoms, copy and default initialization instead of using + //! switches. See in juce::variant. + class Parameter + { + public: // classes + + //! @brief The different types of data represented. + enum class Type + { + Int, + Float, + String + }; + + public: // methods + + //! @brief Default Constructor. + //! @details Initialises data according to type. + Parameter(Type type); + + //! @brief Constructor. + //! @details Atoms must be well formated for the construction to succeed. + Parameter(Type type, std::vector const atoms); + + //! @brief Copy constructor. + Parameter(Parameter const& other); + + //! @brief Assignment operator. + Parameter& operator=(Parameter const& other); + + //! @brief Desctructor. + ~Parameter(); + + //! @brief Returns the type of the parameter. + Type getType() const; + + //! @brief Returns the underlying data of the parameter. + Atom const& operator[](size_t index) const; + + private: // members + + Type m_type; + std::vector m_atoms; + + private: // deleted methods + + Parameter() = delete; + }; + +}} diff --git a/Test/Model/test_KiwiModel.cpp b/Test/Model/test_KiwiModel.cpp index dfd0b10d..1474ba3b 100755 --- a/Test/Model/test_KiwiModel.cpp +++ b/Test/Model/test_KiwiModel.cpp @@ -25,6 +25,8 @@ #include +#include + using namespace kiwi; int main( int argc, char* const argv[] ) From fed492456bb07a09b21398baf32fec7cfb30bd81 Mon Sep 17 00:00:00 2001 From: jmillot Date: Mon, 20 Nov 2017 22:37:36 +0100 Subject: [PATCH 066/148] Adding object message. --- Client/Source/KiwiApp.cpp | 2 + .../KiwiApp_Objects/KiwiApp_MessageView.cpp | 175 ++++++++++++++++++ .../KiwiApp_Objects/KiwiApp_MessageView.h | 96 ++++++++++ .../KiwiApp_Objects/KiwiApp_Objects.h | 1 + .../KiwiApp_Patcher/KiwiApp_PatcherView.cpp | 11 ++ .../KiwiEngine_Objects/KiwiEngine_Message.cpp | 81 ++++++++ .../KiwiEngine_Objects/KiwiEngine_Message.h | 57 ++++++ .../KiwiEngine_Objects/KiwiEngine_Objects.h | 1 + Modules/KiwiModel/KiwiModel_DataModel.cpp | 1 + .../KiwiModel_Objects/KiwiModel_Message.cpp | 125 +++++++++++++ .../KiwiModel_Objects/KiwiModel_Message.h | 66 +++++++ .../KiwiModel_Objects/KiwiModel_Objects.h | 1 + 12 files changed, 617 insertions(+) create mode 100644 Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_MessageView.cpp create mode 100644 Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_MessageView.h create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message.h diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index cbdf53aa..048d33e5 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -157,6 +157,7 @@ namespace kiwi engine::PlusTilde::declare(); engine::MeterTilde::declare(); engine::DelaySimpleTilde::declare(); + engine::Message::declare(); } void KiwiApp::declareObjectViews() @@ -165,6 +166,7 @@ namespace kiwi BangView::declare(); ToggleView::declare(); MeterTildeView::declare(); + MessageView::declare(); } void KiwiApp::shutdown() diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_MessageView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_MessageView.cpp new file mode 100644 index 00000000..156397d3 --- /dev/null +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_MessageView.cpp @@ -0,0 +1,175 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include +#include + +namespace kiwi { + + // ================================================================================ // + // MESSAGE VIEW // + // ================================================================================ // + + void MessageView::declare() + { + Factory::add("message", &MessageView::create); + } + + std::unique_ptr MessageView::create(model::Object & object_model) + { + return std::make_unique(object_model); + } + + MessageView::MessageView(model::Object & object_model) : + EditableObjectView(object_model), + m_output_message(object_model.getSignal<>(model::Message::Signal::outputMessage)), + m_active(false) + { + juce::Label & label = getLabel(); + + label.setText(object_model.getAttribute("text")[0].getString(), + juce::NotificationType::dontSendNotification); + + label.setColour(juce::Label::backgroundColourId, findColour(ObjectView::ColourIds::Background)); + label.setColour(juce::Label::backgroundWhenEditingColourId, + findColour(ObjectView::ColourIds::Background)); + label.setColour(juce::Label::textColourId, findColour(ObjectView::ColourIds::Text)); + label.setColour(juce::Label::textWhenEditingColourId, findColour(ObjectView::ColourIds::Text)); + + addAndMakeVisible(label); + } + + MessageView::~MessageView() + { + } + + void MessageView::mouseDown(juce::MouseEvent const& e) + { + m_active = true; + + repaint(); + + m_output_message(); + } + + void MessageView::mouseUp(juce::MouseEvent const& e) + { + m_active = false; + + repaint(); + } + + void MessageView::paintOverChildren (juce::Graphics& g) + { + g.setColour (findColour (ObjectView::ColourIds::Outline)); + + drawOutline(g); + + juce::Path corner; + + juce::Rectangle bounds = getLocalBounds(); + + if (m_active) + { + g.setColour(findColour(ObjectView::ColourIds::Active)); + } + + corner.addTriangle(bounds.getTopRight().toFloat() - juce::Point(10, 0), + bounds.getTopRight().toFloat(), + bounds.getTopRight().toFloat() + juce::Point(0, 10)); + + g.fillPath(corner); + } + + void MessageView::resized() + { + getLabel().setBounds(getLocalBounds()); + } + + void MessageView::textEditorTextChanged(juce::TextEditor& editor) + { + const int text_width = editor.getFont().getStringWidth(editor.getText()); + + if(editor.getWidth() < text_width + 16) + { + setSize(text_width + 16, getHeight()); + } + } + + void MessageView::attributeChanged(std::string const& name, tool::Parameter const& param) + { + if (name == "text") + { + getLabel().setText(param[0].getString(), juce::NotificationType::dontSendNotification); + } + } + + void MessageView::textChanged() + { + juce::Label & label = getLabel(); + + const int text_width = label.getFont().getStringWidth(label.getText()); + + model::Object & model = getModel(); + + model.setWidth(text_width + 16); + + setAttribute("text", tool::Parameter(tool::Parameter::Type::String, + {label.getText().toStdString()})); + } + + juce::TextEditor* MessageView::createdTextEditor() + { + juce::TextEditor * editor = new juce::TextEditor(); + + editor->setBounds(getLocalBounds()); + editor->setBorder(juce::BorderSize(0)); + + + editor->setColour(juce::TextEditor::ColourIds::textColourId, + getLabel().findColour(juce::Label::textWhenEditingColourId)); + + editor->setColour(juce::TextEditor::backgroundColourId, + getLabel().findColour(juce::Label::backgroundWhenEditingColourId)); + + editor->setColour(juce::TextEditor::highlightColourId, + findColour(ObjectView::ColourIds::Highlight, true).withAlpha(0.4f)); + + + editor->setColour(juce::TextEditor::outlineColourId, + juce::Colours::transparentWhite); + + editor->setColour(juce::TextEditor::focusedOutlineColourId, + juce::Colours::transparentWhite); + + editor->setScrollbarsShown(false); + editor->setScrollToShowCursor(true); + editor->setReturnKeyStartsNewLine(false); + editor->setMultiLine(true, false); + editor->setInterceptsMouseClicks(true, false); + + editor->addListener(this); + + return editor; + } +} diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_MessageView.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_MessageView.h new file mode 100644 index 00000000..8ed61de2 --- /dev/null +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_MessageView.h @@ -0,0 +1,96 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +#include + +#include + +namespace kiwi { + + // ================================================================================ // + // MESSAGE VIEW // + // ================================================================================ // + + //! @brief The view of any textual kiwi object. + class MessageView : public EditableObjectView, + public juce::TextEditor::Listener + { + public: // methods + + // @brief The declaration method. + static void declare(); + + //! @brief Creation method. + static std::unique_ptr create(model::Object & object_model); + + //! @brief Constructor. + MessageView(model::Object & object_model); + + //! @brief Destructor. + ~MessageView(); + + private: // methods + + //! @brief Called when the message is clicked. + void mouseDown(juce::MouseEvent const& e) override final; + + //! @brief Called when the bang is unclicked. + void mouseUp(juce::MouseEvent const& e) override final; + + //! @brief Called when the object is resized. + void resized() override final; + + //! @brief Called when the text is being typed. + //! @details Used to resize in order to keep text visible. + void textEditorTextChanged(juce::TextEditor& editor) override final; + + //! @brief Paints elements over the text editor. + void paintOverChildren (juce::Graphics& g) override final; + + //! @brief Called whenever one of the object's attribute has changed. + void attributeChanged(std::string const& name, tool::Parameter const& param) override final; + + //! @brief Called when the label text has changed. + //! @details Overrides EditableObjectView::textChanged. + void textChanged() override final; + + //! @brief Constructs the label's text editor. + //! @details Overrides EditableOjectView::createTextEditor. + juce::TextEditor* createdTextEditor() override final; + + private: // members + + flip::Signal<> & m_output_message; + bool m_active; + + private: // deleted methods + + MessageView() = delete; + MessageView(MessageView const& other) = delete; + MessageView(MessageView && other) = delete; + MessageView& operator=(MessageView const& other) = delete; + MessageView& operator=(MessageView && other) = delete; + }; +} diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Objects.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Objects.h index 17abea8c..abd82c2c 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Objects.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Objects.h @@ -26,3 +26,4 @@ #include #include #include +#include diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp index 8ccc4eb0..83712f01 100755 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp @@ -1870,6 +1870,7 @@ namespace kiwi commands.add(CommandIDs::newBang); commands.add(CommandIDs::newToggle); commands.add(CommandIDs::newSlider); + commands.add(CommandIDs::newMessage); commands.add(CommandIDs::zoomIn); commands.add(CommandIDs::zoomOut); @@ -2016,6 +2017,15 @@ namespace kiwi result.setActive(!isLocked()); break; } + case CommandIDs::newMessage: + { + result.setInfo(TRANS("New Message Box"), + TRANS("Add a new message box"), + CommandCategories::editing, 0); + result.addDefaultKeypress('m', juce::ModifierKeys::noModifiers); + result.setActive(!isLocked()); + break; + } case CommandIDs::zoomIn: { result.setInfo(TRANS("Zoom in"), TRANS("Zoom in"), CommandCategories::view, 0); @@ -2087,6 +2097,7 @@ namespace kiwi case CommandIDs::newBang: { createObjectModel("bang", true); break; } case CommandIDs::newToggle: { createObjectModel("toggle", true); break; } case CommandIDs::newSlider: { createObjectModel("slider", true); break; } + case CommandIDs::newMessage: { createObjectModel("message", true); break; } case CommandIDs::zoomIn: { zoomIn(); break; } case CommandIDs::zoomOut: { zoomOut(); break; } diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message.cpp new file mode 100644 index 00000000..5e1c9158 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message.cpp @@ -0,0 +1,81 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OBJECT MESSAGE // + // ================================================================================ // + + void Message::declare() + { + Factory::add("message", &Message::create); + } + + std::unique_ptr Message::create(model::Object const& model, Patcher& patcher) + { + return std::make_unique(model, patcher); + } + + Message::Message(model::Object const& object_model, Patcher& patcher): + Object(object_model, patcher), + m_text(object_model.getAttribute("text")[0].getString()), + m_connection(object_model.getSignal<>(model::Message::Signal::outputMessage) + .connect(std::bind(&Message::outputMessage, this))) + { + } + + + Message::~Message() + { + } + + void Message::outputMessage() + { + defer([this]() + { + send(0, tool::AtomHelper::parse(m_text)); + }); + } + + void Message::attributeChanged(std::string const& name, tool::Parameter const& parameter) + { + if (name == "text") + { + m_text = parameter[0].getString(); + } + } + + void Message::receive(size_t index, std::vector const& args) + { + if (index == 0 && !args.empty()) + { + send(0, tool::AtomHelper::parse(m_text));; + } + } + +}} + diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message.h new file mode 100644 index 00000000..41da4fdf --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message.h @@ -0,0 +1,57 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OBJECT MESSAGE // + // ================================================================================ // + + class Message : public engine::Object + { + public: // methods + + Message(model::Object const& model, Patcher& patcher); + + ~Message(); + + void attributeChanged(std::string const& name, tool::Parameter const& param) override final; + + void receive(size_t index, std::vector const& args) override final; + + void outputMessage(); + + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher& patcher); + + private: // members + + std::string m_text; + flip::SignalConnection m_connection; + + }; + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h index 1d3ec068..1770b625 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h @@ -42,3 +42,4 @@ #include #include #include +#include diff --git a/Modules/KiwiModel/KiwiModel_DataModel.cpp b/Modules/KiwiModel/KiwiModel_DataModel.cpp index 884d2c43..80df8d0a 100644 --- a/Modules/KiwiModel/KiwiModel_DataModel.cpp +++ b/Modules/KiwiModel/KiwiModel_DataModel.cpp @@ -54,6 +54,7 @@ namespace kiwi model::SigTilde::declare(); model::MeterTilde::declare(); model::DelaySimpleTilde::declare(); + model::Message::declare(); } void DataModel::init(std::function declare_object) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message.cpp new file mode 100755 index 00000000..2e83830f --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message.cpp @@ -0,0 +1,125 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT SLIDER // + // ================================================================================ // + + void Message::declare() + { + // Objectclass + std::unique_ptr mess_class(new ObjectClass("message", &Message::create)); + + // Parameters + std::unique_ptr param_text(new ParameterClass(tool::Parameter::Type::String)); + + mess_class->addAttribute("text", std::move(param_text)); + + // Flags + mess_class->setFlag(ObjectClass::Flag::DefinedSize); + + // DataModel + flip::Class & message_model = DataModel::declare() + .name(mess_class->getModelName().c_str()) + .inherit() + .member("message_text"); + + Factory::add(std::move(mess_class), message_model); + } + + std::unique_ptr Message::create(std::vector const& args) + { + if (args.size() > 0) + throw Error("message too many arguments"); + + return std::make_unique(); + } + + Message::Message(): + Object(), + m_message_text("") + { + setMinWidth(20.); + setMinHeight(20.); + setWidth(40); + setHeight(20.); + pushInlet({PinType::IType::Control}); + pushOutlet(PinType::IType::Control); + addSignal<>(Signal::outputMessage, *this); + } + + Message::Message(flip::Default& d): + Object(d), + m_message_text("") + { + addSignal<>(Signal::outputMessage, *this); + } + + void Message::writeAttribute(std::string const& name, tool::Parameter const& parameter) + { + if (name == "text") + { + m_message_text = parameter[0].getString(); + } + } + + void Message::readAttribute(std::string const& name, tool::Parameter & parameter) const + { + std::string const& message = m_message_text; + + parameter = tool::Parameter(tool::Parameter::Type::String, {message}); + } + + bool Message::attributeChanged(std::string const& name) const + { + bool changed = false; + + if (name == "text" && m_message_text.changed()) + { + changed = true; + } + + return changed; + } + + std::string Message::getIODescription(bool is_inlet, size_t index) const + { + if (is_inlet && index == 0) + { + return "Trigger the message"; + } + else if(!is_inlet && index == 0) + { + return "Message result"; + } + else + { + return ""; + } + } +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message.h new file mode 100755 index 00000000..7921f88a --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Message.h @@ -0,0 +1,66 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT SLIDER // + // ================================================================================ // + + class Message : public model::Object + { + public: // classes + + enum Signal : SignalKey + { + outputMessage + }; + + public: // methods + + Message(flip::Default& d); + + Message(); + + std::string getIODescription(bool is_inlet, size_t index) const override; + + void writeAttribute(std::string const& name, tool::Parameter const& parameter) override final; + + void readAttribute(std::string const& name, tool::Parameter & parameter) const override final; + + bool attributeChanged(std::string const& name) const override final; + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + + private: // members + + flip::String m_message_text; + + }; +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h index 198c809d..2cd666df 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h @@ -42,3 +42,4 @@ #include #include #include +#include From 23995ff8349331c1515c9cf062d92dee8eb7b558 Mon Sep 17 00:00:00 2001 From: eliott PARIS Date: Thu, 9 Nov 2017 01:05:11 +0100 Subject: [PATCH 067/148] Add [noise~] object --- Client/Source/KiwiApp.cpp | 1 + .../KiwiEngine_NoiseTilde.cpp | 74 +++++++++++++++++++ .../KiwiEngine_NoiseTilde.h | 57 ++++++++++++++ .../KiwiEngine_Objects/KiwiEngine_Objects.h | 1 + Modules/KiwiModel/KiwiModel_DataModel.cpp | 1 + .../KiwiModel_NoiseTilde.cpp | 61 +++++++++++++++ .../KiwiModel_Objects/KiwiModel_NoiseTilde.h | 47 ++++++++++++ .../KiwiModel_Objects/KiwiModel_Objects.h | 1 + 8 files changed, 243 insertions(+) create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_NoiseTilde.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_NoiseTilde.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_NoiseTilde.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_NoiseTilde.h diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index 048d33e5..0212ec42 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -158,6 +158,7 @@ namespace kiwi engine::MeterTilde::declare(); engine::DelaySimpleTilde::declare(); engine::Message::declare(); + engine::NoiseTilde::declare(); } void KiwiApp::declareObjectViews() diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_NoiseTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_NoiseTilde.cpp new file mode 100644 index 00000000..08c663b0 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_NoiseTilde.cpp @@ -0,0 +1,74 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // NOISE~ // + // ================================================================================ // + + void NoiseTilde::declare() + { + Factory::add("noise~", &NoiseTilde::create); + } + + std::unique_ptr NoiseTilde::create(model::Object const& model, Patcher & patcher) + { + return std::make_unique(model, patcher); + } + + NoiseTilde::NoiseTilde(model::Object const& model, + Patcher& patcher) + : AudioObject(model, patcher) + , m_random_devive() + , m_random_generator(m_random_devive()) + , m_random_distribution(-1., 1.) + { + ; + } + + void NoiseTilde::receive(size_t index, std::vector const& args) + { + ; + } + + void NoiseTilde::perform(dsp::Buffer const& input, dsp::Buffer& output) noexcept + { + size_t frames = output[0].size(); + dsp::sample_t* out = output[0].data(); + + while(frames--) + { + *out++ = m_random_distribution(m_random_generator); + } + } + + void NoiseTilde::prepare(dsp::Processor::PrepareInfo const& infos) + { + setPerformCallBack(this, &NoiseTilde::perform); + } + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_NoiseTilde.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_NoiseTilde.h new file mode 100644 index 00000000..ce62dbc0 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_NoiseTilde.h @@ -0,0 +1,57 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // NOISE~ // + // ================================================================================ // + + class NoiseTilde : public AudioObject + { + public: // methods + + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher & patcher); + + NoiseTilde(model::Object const& model, Patcher& patcher); + + void receive(size_t index, std::vector const& args) override final; + + void perform(dsp::Buffer const& input, dsp::Buffer& output) noexcept; + + void prepare(dsp::Processor::PrepareInfo const& infos) override final; + + private: // members + + std::random_device m_random_devive; + std::mt19937 m_random_generator; + std::uniform_real_distribution m_random_distribution; + }; + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h index 1770b625..86e45c8d 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h @@ -43,3 +43,4 @@ #include #include #include +#include diff --git a/Modules/KiwiModel/KiwiModel_DataModel.cpp b/Modules/KiwiModel/KiwiModel_DataModel.cpp index 80df8d0a..62ee9f6c 100644 --- a/Modules/KiwiModel/KiwiModel_DataModel.cpp +++ b/Modules/KiwiModel/KiwiModel_DataModel.cpp @@ -55,6 +55,7 @@ namespace kiwi model::MeterTilde::declare(); model::DelaySimpleTilde::declare(); model::Message::declare(); + model::NoiseTilde::declare(); } void DataModel::init(std::function declare_object) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_NoiseTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_NoiseTilde.cpp new file mode 100755 index 00000000..30078bc2 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_NoiseTilde.cpp @@ -0,0 +1,61 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // NOISE~ // + // ================================================================================ // + + void NoiseTilde::declare() + { + std::unique_ptr noisetilde_class(new ObjectClass("noise~", &NoiseTilde::create)); + + flip::Class & noisetilde_model = DataModel::declare().name(noisetilde_class->getModelName().c_str()).inherit(); + + Factory::add(std::move(noisetilde_class), noisetilde_model); + } + + std::unique_ptr NoiseTilde::create(std::vector const& args) + { + return std::make_unique(args); + } + + NoiseTilde::NoiseTilde(std::vector const& args) + { + if (args.size() > 0) + { + throw Error("noise~ too many arguments"); + } + + pushOutlet(PinType::IType::Signal); + } + + std::string NoiseTilde::getIODescription(bool is_inlet, size_t index) const + { + return "(signal) noise value"; + } + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_NoiseTilde.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_NoiseTilde.h new file mode 100755 index 00000000..4e988a4b --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_NoiseTilde.h @@ -0,0 +1,47 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // NOISE~ // + // ================================================================================ // + + class NoiseTilde : public model::Object + { + public: + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + + NoiseTilde(flip::Default& d): model::Object(d){}; + + NoiseTilde(std::vector const& args); + + std::string getIODescription(bool is_inlet, size_t index) const override; + }; + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h index 2cd666df..c53d898a 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h @@ -43,3 +43,4 @@ #include #include #include +#include From 0235a98ac9adb2d584eb7563d73bd483ed63944d Mon Sep 17 00:00:00 2001 From: eliott PARIS Date: Thu, 9 Nov 2017 03:39:07 +0100 Subject: [PATCH 068/148] Add [phasor~] object --- Client/Source/KiwiApp.cpp | 1 + .../KiwiEngine_Objects/KiwiEngine_Objects.h | 1 + .../KiwiEngine_PhasorTilde.cpp | 144 ++++++++++++++++++ .../KiwiEngine_PhasorTilde.h | 68 +++++++++ Modules/KiwiModel/KiwiModel_DataModel.cpp | 1 + .../KiwiModel_Objects/KiwiModel_Objects.h | 1 + .../KiwiModel_PhasorTilde.cpp | 87 +++++++++++ .../KiwiModel_Objects/KiwiModel_PhasorTilde.h | 47 ++++++ 8 files changed, 350 insertions(+) create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_PhasorTilde.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_PhasorTilde.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_PhasorTilde.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_PhasorTilde.h diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index 0212ec42..8fbb90ee 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -159,6 +159,7 @@ namespace kiwi engine::DelaySimpleTilde::declare(); engine::Message::declare(); engine::NoiseTilde::declare(); + engine::PhasorTilde::declare(); } void KiwiApp::declareObjectViews() diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h index 86e45c8d..abacd798 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h @@ -44,3 +44,4 @@ #include #include #include +#include diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_PhasorTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_PhasorTilde.cpp new file mode 100644 index 00000000..f5f9181f --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_PhasorTilde.cpp @@ -0,0 +1,144 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi{ namespace engine { + + // ================================================================================ // + // PHASOR~ // + // ================================================================================ // + + void PhasorTilde::declare() + { + Factory::add("phasor~", &PhasorTilde::create); + } + + std::unique_ptr PhasorTilde::create(model::Object const& model, Patcher & patcher) + { + return std::make_unique(model, patcher); + } + + PhasorTilde::PhasorTilde(model::Object const& model, Patcher& patcher): + AudioObject(model, patcher) + { + std::vector const& args = model.getArguments(); + + if (!args.empty() && args[0].isNumber()) + { + setFrequency(args[0].getFloat()); + } + } + + void PhasorTilde::setFrequency(dsp::sample_t const& freq) noexcept + { + m_freq = freq; + m_phase_inc.store(m_freq / m_sr); + } + + void PhasorTilde::setSampleRate(dsp::sample_t const& sample_rate) + { + m_sr = sample_rate; + m_phase_inc.store(m_freq / m_sr); + } + + void PhasorTilde::setPhase(dsp::sample_t const& phase) noexcept + { + auto new_phase = phase; + while(new_phase > 1.f) { new_phase -= 1.f; } + while(new_phase < 0.f) { new_phase += 1.f; } + m_phase.store(new_phase); + } + + void PhasorTilde::receive(size_t index, std::vector const& args) + { + if (index == 0) + { + if (args[0].isNumber()) + { + setFrequency(args[0].getFloat()); + } + else + { + warning("phasor~ inlet 1 only take numbers"); + } + } + else if(index == 1) + { + if (args[0].isNumber()) + { + setPhase(args[0].getFloat()); + } + else + { + warning("phasor~ inlet 2 only takes numbers"); + } + } + } + + void PhasorTilde::prepare(PrepareInfo const& infos) + { + setSampleRate(static_cast(infos.sample_rate)); + + setPerformCallBack(this, (infos.inputs[0] + ? &PhasorTilde::performSignal + : &PhasorTilde::performValue)); + } + + dsp::sample_t PhasorTilde::getAndIncrementPhase(const dsp::sample_t inc) + { + dsp::sample_t old_phase = m_phase.load(); + dsp::sample_t phase = old_phase; + + if(phase > 1.f) { phase -= 1.f; } + else if(phase < 0.f) { phase += 1.f; } + + m_phase.compare_exchange_strong(old_phase, phase += inc); + return phase; + } + + void PhasorTilde::performSignal(dsp::Buffer const& input, dsp::Buffer& output) noexcept + { + size_t sampleframes = output[0ul].size(); + dsp::sample_t const* in = input[0ul].data(); + dsp::sample_t* out = output[0ul].data(); + dsp::sample_t freq = 0.f; + + while(sampleframes--) + { + freq = *in++; + *out++ = getAndIncrementPhase(freq / m_sr); + } + } + + void PhasorTilde::performValue(dsp::Buffer const& input, dsp::Buffer& output) noexcept + { + size_t sampleframes = output[0ul].size(); + dsp::sample_t *out = output[0ul].data(); + + while(sampleframes--) + { + *out++ = getAndIncrementPhase(m_phase_inc.load()); + } + } + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_PhasorTilde.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_PhasorTilde.h new file mode 100644 index 00000000..60753208 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_PhasorTilde.h @@ -0,0 +1,68 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // PHASOR~ // + // ================================================================================ // + + class PhasorTilde : public AudioObject + { + public: // methods + + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher & patcher); + + PhasorTilde(model::Object const& model, Patcher& patcher); + + void receive(size_t index, std::vector const& args) override final; + + void prepare(dsp::Processor::PrepareInfo const& infos) override final; + + void performSignal(dsp::Buffer const& input, dsp::Buffer& output) noexcept; + + void performValue(dsp::Buffer const& input, dsp::Buffer& output) noexcept; + + private: // methods + + void setFrequency(dsp::sample_t const& freq) noexcept; + + void setPhase(dsp::sample_t const& phase) noexcept; + + void setSampleRate(dsp::sample_t const& sample_rate); + + dsp::sample_t getAndIncrementPhase(const dsp::sample_t inc); + + private: // members + + dsp::sample_t m_sr {0.f}; + dsp::sample_t m_freq {0.f}; + std::atomic m_phase {0.f}; + std::atomic m_phase_inc {0.f}; + }; + +}} diff --git a/Modules/KiwiModel/KiwiModel_DataModel.cpp b/Modules/KiwiModel/KiwiModel_DataModel.cpp index 62ee9f6c..5581d59b 100644 --- a/Modules/KiwiModel/KiwiModel_DataModel.cpp +++ b/Modules/KiwiModel/KiwiModel_DataModel.cpp @@ -56,6 +56,7 @@ namespace kiwi model::DelaySimpleTilde::declare(); model::Message::declare(); model::NoiseTilde::declare(); + model::PhasorTilde::declare(); } void DataModel::init(std::function declare_object) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h index c53d898a..95db7d4e 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h @@ -44,3 +44,4 @@ #include #include #include +#include diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_PhasorTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_PhasorTilde.cpp new file mode 100755 index 00000000..40b269ee --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_PhasorTilde.cpp @@ -0,0 +1,87 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // PHASOR~ // + // ================================================================================ // + + void PhasorTilde::declare() + { + std::unique_ptr phasortilde_class(new ObjectClass("phasor~", &PhasorTilde::create)); + + flip::Class & phasortilde_model = DataModel::declare() + .name(phasortilde_class->getModelName().c_str()) + .inherit(); + + Factory::add(std::move(phasortilde_class), phasortilde_model); + } + + std::unique_ptr PhasorTilde::create(std::vector const& args) + { + return std::make_unique(args); + } + + PhasorTilde::PhasorTilde(std::vector const& args) + { + if (args.size() > 1) + { + throw Error("phasor~ too many arguments"); + } + + if (args.size() == 1 && !args[0].isNumber()) + { + throw Error("phasor~ frequency must be a number"); + } + + pushInlet({PinType::IType::Control, PinType::IType::Signal}); + pushInlet({PinType::IType::Control}); + + pushOutlet(PinType::IType::Signal); + } + + std::string PhasorTilde::getIODescription(bool is_inlet, size_t index) const + { + if(is_inlet) + { + if(index == 0) + { + return "(signal/float) Set frequency"; + } + else if(index == 1) + { + return "(signal/float) Set phase (0-1)"; + } + } + else + { + return "(signal) Output"; + } + + return {}; + } + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_PhasorTilde.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_PhasorTilde.h new file mode 100755 index 00000000..2180bf61 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_PhasorTilde.h @@ -0,0 +1,47 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // PHASOR~ // + // ================================================================================ // + + class PhasorTilde : public model::Object + { + public: + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + + PhasorTilde(flip::Default& d): model::Object(d){}; + + PhasorTilde(std::vector const& args); + + std::string getIODescription(bool is_inlet, size_t index) const override; + }; +}} + From c59dcbc3545e4d70d8588a9fbf21e9443730b73a Mon Sep 17 00:00:00 2001 From: eliott PARIS Date: Thu, 9 Nov 2017 15:54:28 +0100 Subject: [PATCH 069/148] Add [sah~] object --- Client/Source/KiwiApp.cpp | 1 + .../KiwiEngine_Objects/KiwiEngine_Objects.h | 1 + .../KiwiEngine_SahTilde.cpp | 102 ++++++++++++++++++ .../KiwiEngine_Objects/KiwiEngine_SahTilde.h | 59 ++++++++++ Modules/KiwiModel/KiwiModel_DataModel.cpp | 1 + .../KiwiModel_Objects/KiwiModel_Objects.h | 1 + .../KiwiModel_Objects/KiwiModel_SahTilde.cpp | 85 +++++++++++++++ .../KiwiModel_Objects/KiwiModel_SahTilde.h | 47 ++++++++ 8 files changed, 297 insertions(+) create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_SahTilde.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_SahTilde.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_SahTilde.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_SahTilde.h diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index 8fbb90ee..e01e0efb 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -160,6 +160,7 @@ namespace kiwi engine::Message::declare(); engine::NoiseTilde::declare(); engine::PhasorTilde::declare(); + engine::SahTilde::declare(); } void KiwiApp::declareObjectViews() diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h index abacd798..e37590d1 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h @@ -45,3 +45,4 @@ #include #include #include +#include diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_SahTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_SahTilde.cpp new file mode 100644 index 00000000..e3ce9894 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_SahTilde.cpp @@ -0,0 +1,102 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi{ namespace engine { + + // ================================================================================ // + // SAH~ // + // ================================================================================ // + + void SahTilde::declare() + { + Factory::add("sah~", &SahTilde::create); + } + + std::unique_ptr SahTilde::create(model::Object const& model, Patcher & patcher) + { + return std::make_unique(model, patcher); + } + + SahTilde::SahTilde(model::Object const& model, Patcher& patcher) + : AudioObject(model, patcher) + { + std::vector const& args = model.getArguments(); + + if (!args.empty() && args[0].isNumber()) + { + setThreshold(args[0].getFloat()); + } + } + + void SahTilde::setThreshold(dsp::sample_t const& value) noexcept + { + m_threshold.store(value); + } + + void SahTilde::receive(size_t index, std::vector const& args) + { + if (index == 1 && !args.empty()) + { + if (args[0].isNumber()) + { + setThreshold(args[0].getFloat()); + } + else + { + warning("sah~ inlet 1 only takes numbers"); + } + } + } + + void SahTilde::prepare(PrepareInfo const& infos) + { + setPerformCallBack(this, &SahTilde::perform); + } + + void SahTilde::perform(dsp::Buffer const& input, dsp::Buffer& output) noexcept + { + size_t sampleframes = output[0ul].size(); + dsp::sample_t const* in1 = input[0ul].data(); + dsp::sample_t const* in2 = input[1ul].data(); + dsp::sample_t* out = output[0ul].data(); + + const dsp::sample_t threshold = m_threshold.load(); + + while(sampleframes--) + { + dsp::sample_t sample = *in1++; + dsp::sample_t ctrl_sample = *in2++; + + if(m_last_ctrl_sample <= threshold + && ctrl_sample > threshold) + { + m_hold_value = sample; + } + + *out++ = m_hold_value; + m_last_ctrl_sample = ctrl_sample; + } + } + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_SahTilde.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_SahTilde.h new file mode 100644 index 00000000..af318fa8 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_SahTilde.h @@ -0,0 +1,59 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // SAH~ // + // ================================================================================ // + + class SahTilde : public AudioObject + { + public: // methods + + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher & patcher); + + SahTilde(model::Object const& model, Patcher& patcher); + + void receive(size_t index, std::vector const& args) override; + + void prepare(dsp::Processor::PrepareInfo const& infos) override final; + + void perform(dsp::Buffer const& input, dsp::Buffer& output) noexcept; + + private: // methods + + void setThreshold(dsp::sample_t const& value) noexcept; + + private: // members + + std::atomic m_threshold {0.f}; + dsp::sample_t m_hold_value {0.f}; + dsp::sample_t m_last_ctrl_sample {0.f}; + }; + +}} diff --git a/Modules/KiwiModel/KiwiModel_DataModel.cpp b/Modules/KiwiModel/KiwiModel_DataModel.cpp index 5581d59b..6d9849eb 100644 --- a/Modules/KiwiModel/KiwiModel_DataModel.cpp +++ b/Modules/KiwiModel/KiwiModel_DataModel.cpp @@ -57,6 +57,7 @@ namespace kiwi model::Message::declare(); model::NoiseTilde::declare(); model::PhasorTilde::declare(); + model::SahTilde::declare(); } void DataModel::init(std::function declare_object) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h index 95db7d4e..91d33e0b 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h @@ -45,3 +45,4 @@ #include #include #include +#include diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_SahTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_SahTilde.cpp new file mode 100755 index 00000000..1a264950 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_SahTilde.cpp @@ -0,0 +1,85 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // SAH~ // + // ================================================================================ // + + void SahTilde::declare() + { + std::unique_ptr sahtilde_class(new ObjectClass("sah~", &SahTilde::create)); + + flip::Class & sahtilde_model = DataModel::declare().name(sahtilde_class->getModelName().c_str()).inherit(); + + Factory::add(std::move(sahtilde_class), sahtilde_model); + } + + + std::unique_ptr SahTilde::create(std::vector const& args) + { + return std::make_unique(args); + } + + SahTilde::SahTilde(std::vector const& args) + { + if (args.size() > 1) + { + throw Error("sah~ too many arguments"); + } + + if (args.size() == 1 && !args[0].isNumber()) + { + throw Error("sah~ threshold shall be a number"); + } + + pushInlet({PinType::IType::Signal}); + pushInlet({PinType::IType::Control, PinType::IType::Signal}); + + pushOutlet(PinType::IType::Signal); + } + + std::string SahTilde::getIODescription(bool is_inlet, size_t index) const + { + if(is_inlet) + { + if(index == 0) + { + return "(signal) Values to sample"; + } + else if(index == 1) + { + return "(signal/control) Trigger input"; + } + } + else + { + return "(signal) Output sampled value"; + } + + return {}; + } + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_SahTilde.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_SahTilde.h new file mode 100755 index 00000000..23ed89f4 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_SahTilde.h @@ -0,0 +1,47 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // SAH~ // + // ================================================================================ // + + class SahTilde : public model::Object + { + public: + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + + SahTilde(flip::Default& d): model::Object(d){}; + + SahTilde(std::vector const& args); + + std::string getIODescription(bool is_inlet, size_t index) const override; + }; +}} + From 851c463ffb0fd42137b8a210a350e33680a9be8a Mon Sep 17 00:00:00 2001 From: eliott PARIS Date: Thu, 9 Nov 2017 16:38:40 +0100 Subject: [PATCH 070/148] Add [snapshot~] object --- Client/Source/KiwiApp.cpp | 1 + .../KiwiEngine_Objects/KiwiEngine_Objects.h | 1 + .../KiwiEngine_SnapshotTilde.cpp | 81 +++++++++++++++++++ .../KiwiEngine_SnapshotTilde.h | 54 +++++++++++++ Modules/KiwiModel/KiwiModel_DataModel.cpp | 1 + .../KiwiModel_Objects/KiwiModel_Objects.h | 1 + .../KiwiModel_SnapshotTilde.cpp | 66 +++++++++++++++ .../KiwiModel_SnapshotTilde.h | 47 +++++++++++ 8 files changed, 252 insertions(+) create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_SnapshotTilde.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_SnapshotTilde.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_SnapshotTilde.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_SnapshotTilde.h diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index e01e0efb..39183db5 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -161,6 +161,7 @@ namespace kiwi engine::NoiseTilde::declare(); engine::PhasorTilde::declare(); engine::SahTilde::declare(); + engine::SnapshotTilde::declare(); } void KiwiApp::declareObjectViews() diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h index e37590d1..ecce1e05 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h @@ -46,3 +46,4 @@ #include #include #include +#include diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_SnapshotTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_SnapshotTilde.cpp new file mode 100644 index 00000000..43261899 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_SnapshotTilde.cpp @@ -0,0 +1,81 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // SNAPSHOT~ // + // ================================================================================ // + + void SnapshotTilde::declare() + { + Factory::add("snapshot~", &SnapshotTilde::create); + } + + std::unique_ptr SnapshotTilde::create(model::Object const& model, Patcher & patcher) + { + return std::make_unique(model, patcher); + } + + SnapshotTilde::SnapshotTilde(model::Object const& model, Patcher& patcher) + : AudioObject(model, patcher) + { + ; + } + + void SnapshotTilde::receive(size_t index, std::vector const& args) + { + if (index == 0 && !args.empty()) + { + if(args[0].getString() == "bang") + { + send(0, {m_value.load()}); + } + else + { + warning("snapshot~ inlet 1 doesn't understanc [" + args[0].getString() + "]"); + } + } + } + + void SnapshotTilde::perform(dsp::Buffer const& input, dsp::Buffer& output) noexcept + { + size_t sample_index = input[0].size(); + dsp::sample_t const* in = input[0].data(); + + while(sample_index--) + { + m_value.store(*in++); + } + } + + void SnapshotTilde::prepare(dsp::Processor::PrepareInfo const& infos) + { + if(infos.inputs[0]) + { + setPerformCallBack(this, &SnapshotTilde::perform); + } + } + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_SnapshotTilde.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_SnapshotTilde.h new file mode 100644 index 00000000..4e471f31 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_SnapshotTilde.h @@ -0,0 +1,54 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // SNAPSHOT~ // + // ================================================================================ // + + class SnapshotTilde : public AudioObject + { + public: // methods + + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher & patcher); + + SnapshotTilde(model::Object const& model, Patcher& patcher); + + void receive(size_t index, std::vector const& args) override final; + + void perform(dsp::Buffer const& input, dsp::Buffer& output) noexcept; + + void prepare(dsp::Processor::PrepareInfo const& infos) override final; + + private: // members + + std::atomic m_value {0.f}; + }; + +}} + diff --git a/Modules/KiwiModel/KiwiModel_DataModel.cpp b/Modules/KiwiModel/KiwiModel_DataModel.cpp index 6d9849eb..8efa6658 100644 --- a/Modules/KiwiModel/KiwiModel_DataModel.cpp +++ b/Modules/KiwiModel/KiwiModel_DataModel.cpp @@ -58,6 +58,7 @@ namespace kiwi model::NoiseTilde::declare(); model::PhasorTilde::declare(); model::SahTilde::declare(); + model::SnapshotTilde::declare(); } void DataModel::init(std::function declare_object) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h index 91d33e0b..47a54262 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h @@ -46,3 +46,4 @@ #include #include #include +#include diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_SnapshotTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_SnapshotTilde.cpp new file mode 100755 index 00000000..402ba36b --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_SnapshotTilde.cpp @@ -0,0 +1,66 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // SNAPSHOT~ // + // ================================================================================ // + + void SnapshotTilde::declare() + { + std::unique_ptr snapshottilde_class(new ObjectClass("snapshot~", &SnapshotTilde::create)); + + flip::Class & snapshottilde_model = DataModel::declare() + .name(snapshottilde_class->getModelName().c_str()) + .inherit(); + + Factory::add(std::move(snapshottilde_class), snapshottilde_model); + } + + std::unique_ptr SnapshotTilde::create(std::vector const& args) + { + return std::make_unique(args); + } + + SnapshotTilde::SnapshotTilde(std::vector const& args) + { + if (args.size() > 0) + { + throw Error("snapshot~ too many arguments"); + } + pushInlet({PinType::IType::Signal, PinType::IType::Control}); + pushOutlet(PinType::IType::Control); + } + + std::string SnapshotTilde::getIODescription(bool is_inlet, size_t index) const + { + return (is_inlet + ? "(signal) Input, (bang) Reports signal value" + : "(signal) Values"); + } + +}} + diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_SnapshotTilde.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_SnapshotTilde.h new file mode 100755 index 00000000..f3ddbf68 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_SnapshotTilde.h @@ -0,0 +1,47 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // SNAPSHOT~ // + // ================================================================================ // + + class SnapshotTilde : public model::Object + { + public: + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + + SnapshotTilde(flip::Default& d): model::Object(d){}; + + SnapshotTilde(std::vector const& args); + + std::string getIODescription(bool is_inlet, size_t index) const override; + }; +}} + From e81110e4ab0d5564a4cd286b5c63010b32798c79 Mon Sep 17 00:00:00 2001 From: jmillot Date: Tue, 21 Nov 2017 00:22:45 +0100 Subject: [PATCH 071/148] Add trigger object. --- Client/Source/KiwiApp.cpp | 1 + .../KiwiEngine_Objects/KiwiEngine_Objects.h | 1 + .../KiwiEngine_Objects/KiwiEngine_Trigger.cpp | 171 ++++++++++++++++++ .../KiwiEngine_Objects/KiwiEngine_Trigger.h | 53 ++++++ Modules/KiwiModel/KiwiModel_DataModel.cpp | 1 + .../KiwiModel_Objects/KiwiModel_Objects.h | 1 + .../KiwiModel_Objects/KiwiModel_Trigger.cpp | 103 +++++++++++ .../KiwiModel_Objects/KiwiModel_Trigger.h | 51 ++++++ 8 files changed, 382 insertions(+) create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Trigger.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Trigger.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Trigger.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Trigger.h diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index 39183db5..db152efc 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -162,6 +162,7 @@ namespace kiwi engine::PhasorTilde::declare(); engine::SahTilde::declare(); engine::SnapshotTilde::declare(); + engine::Trigger::declare(); } void KiwiApp::declareObjectViews() diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h index ecce1e05..355c4bb5 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h @@ -47,3 +47,4 @@ #include #include #include +#include diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Trigger.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Trigger.cpp new file mode 100644 index 00000000..89e37ca6 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Trigger.cpp @@ -0,0 +1,171 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // TRIGGER // + // ================================================================================ // + + void Trigger::declare() + { + Factory::add("trigger", &Trigger::create); + } + + std::unique_ptr Trigger::create(model::Object const& model, Patcher & patcher) + { + return std::make_unique(model, patcher); + } + + Trigger::Trigger(model::Object const& model, Patcher& patcher) + : Object(model, patcher) + , m_triggers(initializeTriggers(model.getArguments())) + { + ; + } + + auto Trigger::initializeTriggers(std::vector const& _args) -> std::vector + { + const auto trigger_fn_factory = [](tool::Atom const& atom) -> trigger_fn_t { + + if(atom.isNumber()) + { + const auto value = atom.isInt() ? atom.getInt() : atom.getFloat(); + + return [value](std::vector const&){ + return std::vector{{value}}; + }; + } + + const auto str = atom.getString(); + + if(str == "b") + { + return [](std::vector const&) { return std::vector{{"bang"}}; }; + } + + if(str == "i") + { + return [](std::vector const& args) { + return std::vector {{args[0].getInt()}}; + }; + } + + if(str == "f") + { + return [](std::vector const& args) { + return std::vector {{args[0].getFloat()}}; + }; + } + + if(str == "s") + { + return [](std::vector const& args) { + return std::vector {{args[0].getString()}}; + }; + } + + if(str == "l") + { + return [](std::vector const& args) { return args; }; + } + + return [str](std::vector const&) { return std::vector{{str}}; }; + }; + + std::vector triggers; + triggers.reserve(_args.size()); + + for(auto& atom : _args) + { + triggers.emplace_back(trigger_fn_factory(atom)); + } + + return triggers; + + /* + trigger_fn_t test = trigger_fn_factory(atom); + + triggers.emplace_back([atom](std::vector const& args) { + + if(atom.isNumber()) + { + const auto value = atom.isInt() ? atom.getInt() : atom.getFloat(); + return std::vector{{value}}; + } + + const auto str = atom.getString(); + + if(str.empty()) + { + return std::vector(); + } + + if(str == "b" || str == "bang") + { + return std::vector{{"bang"}}; + } + + if(str == "i" || str == "int") + { + return std::vector{{args[0].getInt()}}; + } + + if(str == "f" || str == "float") + { + return std::vector{{args[0].getFloat()}}; + } + + if(str == "s" || str == "symbol") + { + return args; + } + + if(str == "l" || str == "list") + { + return args; + } + + return std::vector{{str}}; + + }); + + } + */ + } + + void Trigger::receive(size_t, std::vector const& args) + { + if(m_triggers.empty()) + return; + + const auto size = m_triggers.size(); + size_t idx = size - 1; + for (auto rit = m_triggers.rbegin(); rit != m_triggers.rend(); ++rit) + { + send(idx--, (*rit)(args)); + } + } + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Trigger.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Trigger.h new file mode 100644 index 00000000..7e94ad6a --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Trigger.h @@ -0,0 +1,53 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // TRIGGER // + // ================================================================================ // + + class Trigger : public engine::Object + { + public: + + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher & patcher); + + Trigger(model::Object const& model, Patcher& patcher); + + ~Trigger() = default; + + void receive(size_t, std::vector const& args) override; + + private: + + using trigger_fn_t = std::function(std::vector const&)>; + static std::vector initializeTriggers(std::vector const&); + const std::vector m_triggers; + }; + +}} diff --git a/Modules/KiwiModel/KiwiModel_DataModel.cpp b/Modules/KiwiModel/KiwiModel_DataModel.cpp index 8efa6658..16a4c009 100644 --- a/Modules/KiwiModel/KiwiModel_DataModel.cpp +++ b/Modules/KiwiModel/KiwiModel_DataModel.cpp @@ -59,6 +59,7 @@ namespace kiwi model::PhasorTilde::declare(); model::SahTilde::declare(); model::SnapshotTilde::declare(); + model::Trigger::declare(); } void DataModel::init(std::function declare_object) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h index 47a54262..6ad5c416 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h @@ -47,3 +47,4 @@ #include #include #include +#include diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Trigger.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Trigger.cpp new file mode 100755 index 00000000..57717730 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Trigger.cpp @@ -0,0 +1,103 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // TRIGGER // + // ================================================================================ // + + void Trigger::declare() + { + std::unique_ptr trigger_class(new ObjectClass("trigger", &Trigger::create)); + + trigger_class->addAlias("t"); + + flip::Class & trigger_model = DataModel::declare() + .name(trigger_class->getModelName().c_str()) + .inherit(); + + Factory::add(std::move(trigger_class), trigger_model); + } + + std::unique_ptr Trigger::create(std::vector const& args) + { + return std::make_unique(args); + } + + Trigger::Trigger(std::vector const& args) + { + pushInlet({PinType::IType::Control}); + + for(size_t i = 0; i < args.size(); ++i) + { + pushOutlet(PinType::IType::Control); + } + } + + std::string Trigger::getTypeDescription(tool::Atom const& atom) + { + if(atom.isInt()) + return std::to_string(atom.getInt()); + + if(atom.isFloat()) + return std::to_string(atom.getFloat()); + + if(atom.isString()) + { + const std::string str = atom.getString(); + + if(str == "b") return "bang"; + if(str == "i") return "int"; + if(str == "f") return "float"; + if(str == "s") return "symbol"; + if(str == "l") return "list"; + + return str; + } + + return {"??"}; + } + + std::string Trigger::getIODescription(bool is_inlet, size_t index) const + { + if(is_inlet) + { + return "(anything) Message to be fanned to multiple outputs"; + } + + auto args = tool::AtomHelper::parse(getText()); + args.erase(args.cbegin()); + + const auto size = args.size(); + if(!args.empty() && index < size) + { + return ("Output order " + std::to_string(size - index) + + " (" + getTypeDescription(args[index]) + ")"); + } + + return {}; + } + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Trigger.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Trigger.h new file mode 100755 index 00000000..ad0f9f42 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Trigger.h @@ -0,0 +1,51 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // TRIGGER // + // ================================================================================ // + + class Trigger : public model::Object + { + public: + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + + Trigger(flip::Default& d) : model::Object(d) {} + + Trigger(std::vector const& args); + + std::string getIODescription(bool is_inlet, size_t index) const override; + + private: // methods + + static std::string getTypeDescription(tool::Atom const& atom); + }; + +}} From 6f2afcd73bf3c72fd3b8aec5101cbb1e501a6306 Mon Sep 17 00:00:00 2001 From: jmillot Date: Tue, 21 Nov 2017 00:46:23 +0100 Subject: [PATCH 072/148] Add line~ object. --- Client/Source/KiwiApp.cpp | 1 + .../KiwiEngine_LineTilde.cpp | 291 ++++++++++++++++++ .../KiwiEngine_Objects/KiwiEngine_LineTilde.h | 135 ++++++++ .../KiwiEngine_Objects/KiwiEngine_Objects.h | 1 + Modules/KiwiModel/KiwiModel_DataModel.cpp | 1 + .../KiwiModel_Objects/KiwiModel_LineTilde.cpp | 84 +++++ .../KiwiModel_Objects/KiwiModel_LineTilde.h | 47 +++ .../KiwiModel_Objects/KiwiModel_Objects.h | 1 + 8 files changed, 561 insertions(+) create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_LineTilde.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_LineTilde.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_LineTilde.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_LineTilde.h diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index db152efc..5190e4c1 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -163,6 +163,7 @@ namespace kiwi engine::SahTilde::declare(); engine::SnapshotTilde::declare(); engine::Trigger::declare(); + engine::LineTilde::declare(); } void KiwiApp::declareObjectViews() diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_LineTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_LineTilde.cpp new file mode 100644 index 00000000..278ea9da --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_LineTilde.cpp @@ -0,0 +1,291 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi{ namespace engine { + + // ================================================================================ // + // RAMP // + // ================================================================================ // + + Ramp::Ramp(dsp::sample_t start) noexcept + : m_current_value(start) + , m_destination_value(start) + { + } + + void Ramp::setSampleRate(double sample_rate) noexcept + { + //! Note: this will only affect next value-time pairs. + m_sr = sample_rate; + } + + void Ramp::setEndOfRampCallback(std::function callback) + { + m_ramp_ended_callback = callback; + } + + void Ramp::setValueDirect(dsp::sample_t new_value) noexcept + { + auto lock = std::unique_lock(m_lock); + reset(); + m_current_value = m_destination_value = new_value; + m_countdown = m_steps_to_destination = 0; + m_step = 0.; + } + + void Ramp::setValueTimePairs(std::vector value_time_pairs) + { + auto lock = std::unique_lock(m_lock); + reset(); + m_value_time_pairs.swap(value_time_pairs); + m_valuetime_pairs_countdown = m_value_time_pairs.size(); + } + + dsp::sample_t Ramp::getNextValue() noexcept + { + auto lock = std::unique_lock(m_lock); + + if (m_countdown <= 0) + { + const auto value = m_destination_value; + triggerNextRamp(); + return value; + } + + --m_countdown; + m_current_value += m_step; + return m_current_value; + } + + dsp::sample_t Ramp::getValue() noexcept + { + return m_current_value; + } + + void Ramp::triggerNextRamp() + { + if(m_valuetime_pairs_countdown > 0) + { + assert(m_valuetime_pairs_countdown <= m_value_time_pairs.size()); + + const size_t index = m_value_time_pairs.size() - m_valuetime_pairs_countdown; + setNextValueTime(m_value_time_pairs[index]); + --m_valuetime_pairs_countdown; + m_should_notify_end = (m_valuetime_pairs_countdown == 0); + } + else if(m_should_notify_end && m_ramp_ended_callback) + { + m_ramp_ended_callback(); + m_should_notify_end = false; + } + } + + void Ramp::setNextValueTime(ValueTimePair const& value_time) noexcept + { + m_countdown = m_steps_to_destination = std::floor(value_time.time_ms * 0.001 * m_sr); + m_destination_value = value_time.value; + + if (m_countdown <= 0) + { + m_current_value = m_destination_value; + m_step = 0.; + } + else + { + m_step = (m_destination_value - m_current_value) / (dsp::sample_t) m_countdown; + } + } + + void Ramp::reset() + { + m_value_time_pairs.clear(); + m_valuetime_pairs_countdown = 0; + m_destination_value = m_current_value; + m_countdown = 0; + m_should_notify_end = false; + } + + // ================================================================================ // + // LINE~ TASK // + // ================================================================================ // + + class LineTilde::BangTask : public tool::Scheduler<>::Task + { + public: // methods + + BangTask(LineTilde& owner) : m_owner(owner) {} + ~BangTask() = default; + void execute() override { m_owner.send(1ul, {"bang"}); } + + private: // members + LineTilde& m_owner; + }; + + // ================================================================================ // + // LINE~ // + // ================================================================================ // + + void LineTilde::declare() + { + Factory::add("line~", &LineTilde::create); + } + + std::unique_ptr LineTilde::create(model::Object const& model, Patcher & patcher) + { + return std::make_unique(model, patcher); + } + + LineTilde::LineTilde(model::Object const& model, Patcher& patcher) + : AudioObject(model, patcher) + , m_bang_task(std::make_shared(*this)) + , m_ramp(0.) + { + std::vector const& args = model.getArguments(); + + if (!args.empty() && args[0].isNumber()) + { + m_ramp.setValueDirect(args[0].getFloat()); + } + + m_ramp.setEndOfRampCallback([this]{ + getScheduler().defer(m_bang_task); + }); + } + + LineTilde::~LineTilde() + { + getScheduler().unschedule(m_bang_task); + } + + std::vector + LineTilde::parseAtomsAsValueTimePairs(std::vector const& atoms) const + { + std::vector value_time_pairs; + + for(size_t i = 0; i < atoms.size(); i += 2) + { + auto const& time_atom = atoms[i+1]; + if(!time_atom.isNumber() || !atoms[i].isNumber()) + { + error("line~ only accepts value-time numbers"); + return value_time_pairs; + } + + if(time_atom.getFloat() < 0.) + { + error("line~ do not accepts negative ramp time"); + return value_time_pairs; + } + + Ramp::ValueTimePair pair { + (dsp::sample_t) atoms[i].getFloat(), + (dsp::sample_t) time_atom.getFloat() + }; + + value_time_pairs.emplace_back(std::move(pair)); + } + + return value_time_pairs; + } + + void LineTilde::receive(size_t index, std::vector const& args) + { + if (!args.empty()) + { + if(args[0].isNumber()) + { + if(index == 0) + { + if(args.size() >= 2) + { + auto value_time_pairs = parseAtomsAsValueTimePairs(args); + + if(!value_time_pairs.empty()) + { + m_ramp.setValueTimePairs(value_time_pairs); + } + } + else + { + if(!m_next_ramp_time_consumed) + { + Ramp::ValueTimePair pair { + (dsp::sample_t) args[0].getFloat(), + (dsp::sample_t) m_next_ramp_time_ms + }; + + m_ramp.setValueTimePairs({std::move(pair)}); + m_next_ramp_time_consumed = true; + } + else + { + m_ramp.setValueDirect(args[0].getFloat()); + } + } + } + else if(index == 1) + { + m_next_ramp_time_ms = args[0].getFloat(); + m_next_ramp_time_consumed = false; + } + } + /* //! @todo + else if(args[0].isString()) + { + const auto str = args[0].getString(); + if(str == "stop") + { + ; + } + else if(str == "pause") + { + ; + } + else if(str == "resume") + { + ; + } + } + */ + } + } + + void LineTilde::prepare(PrepareInfo const& infos) + { + m_ramp.setSampleRate((double) infos.sample_rate); + setPerformCallBack(this, &LineTilde::perform); + } + + void LineTilde::perform(dsp::Buffer const&, dsp::Buffer& output) noexcept + { + size_t sampleframes = output[0ul].size(); + dsp::sample_t* out = output[0ul].data(); + + while(sampleframes--) + { + *out++ = m_ramp.getNextValue(); + } + } + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_LineTilde.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_LineTilde.h new file mode 100644 index 00000000..91c54cc2 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_LineTilde.h @@ -0,0 +1,135 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +#include + +namespace kiwi { namespace engine { + + class Ramp + { + public: // classes + + struct ValueTimePair + { + ValueTimePair(dsp::sample_t value_, + dsp::sample_t time_ms_) + : value(value_) + , time_ms(time_ms_) + { + assert(time_ms_ >= 0.); + } + + dsp::sample_t value; + dsp::sample_t time_ms; + }; + + public: // methods + + //! @brief Constructor + Ramp(dsp::sample_t start = 0) noexcept; + + //! @brief Set sample rate. + //! @details The sample rate is used to compute the step value of the ramp. + //! @param sample_rate The current sample rate. + void setSampleRate(double sample_rate) noexcept; + + //! @brief Set the function to call when the ramp reached its final destination. + //! @brief This callback function will be called by the getNextValue() method. + //! @param callback The callback function to be called. + void setEndOfRampCallback(std::function callback); + + //! @brief Set a new value directly. + //! @param new_value New value + void setValueDirect(dsp::sample_t new_value) noexcept; + + //! @brief Resets the value-time pairs of the ramp. + //! @param value_time_pairs A vector of ValueTimePair. + void setValueTimePairs(std::vector value_time_pairs); + + //! @brief Compute and returns the next value. + //! @details The sampling rate must be set before calling this method. + dsp::sample_t getNextValue() noexcept; + + //! @brief Returns the current value. + dsp::sample_t getValue() noexcept; + + private: // methods + + void reset(); + void setNextValueTime(ValueTimePair const& value_time_pair) noexcept; + void triggerNextRamp(); + + private: // variables + + std::mutex m_lock; + double m_sr = 0.; + dsp::sample_t m_current_value = 0, m_destination_value = 0, m_step = 0; + int m_countdown = 0, m_steps_to_destination = 0; + + std::vector m_value_time_pairs {}; + size_t m_valuetime_pairs_countdown = 0; + + std::function m_ramp_ended_callback = nullptr; + bool m_should_notify_end {false}; + }; + + // ================================================================================ // + // LINE~ // + // ================================================================================ // + + class LineTilde : public AudioObject + { + public: // methods + + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher & patcher); + + LineTilde(model::Object const& model, Patcher& patcher); + + ~LineTilde(); + + void receive(size_t index, std::vector const& args) override; + + void prepare(dsp::Processor::PrepareInfo const& infos) override; + + void perform(dsp::Buffer const& input, dsp::Buffer& output) noexcept; + + private: // methods + + std::vector parseAtomsAsValueTimePairs(std::vector const& atoms) const; + + private: // variables + + class BangTask; + std::shared_ptr m_bang_task; + + double m_next_ramp_time_ms; + bool m_next_ramp_time_consumed; + + Ramp m_ramp; + }; + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h index 355c4bb5..76ae89cd 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h @@ -48,3 +48,4 @@ #include #include #include +#include diff --git a/Modules/KiwiModel/KiwiModel_DataModel.cpp b/Modules/KiwiModel/KiwiModel_DataModel.cpp index 16a4c009..9e3740ed 100644 --- a/Modules/KiwiModel/KiwiModel_DataModel.cpp +++ b/Modules/KiwiModel/KiwiModel_DataModel.cpp @@ -60,6 +60,7 @@ namespace kiwi model::SahTilde::declare(); model::SnapshotTilde::declare(); model::Trigger::declare(); + model::LineTilde::declare(); } void DataModel::init(std::function declare_object) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_LineTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_LineTilde.cpp new file mode 100755 index 00000000..b79420b6 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_LineTilde.cpp @@ -0,0 +1,84 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // LINE~ // + // ================================================================================ // + + void LineTilde::declare() + { + std::unique_ptr linetilde_class(new ObjectClass("line~", &LineTilde::create)); + + flip::Class & linetilde_model = DataModel::declare() + .name(linetilde_class->getModelName().c_str()) + .inherit(); + + Factory::add(std::move(linetilde_class), linetilde_model); + } + + std::unique_ptr LineTilde::create(std::vector const& args) + { + return std::make_unique(args); + } + + LineTilde::LineTilde(std::vector const& args) + { + pushInlet({PinType::IType::Control}); + pushInlet({PinType::IType::Control}); + pushOutlet(PinType::IType::Signal); + pushOutlet(PinType::IType::Control); + } + + std::string LineTilde::getIODescription(bool is_inlet, size_t index) const + { + if(is_inlet) + { + if(index == 0) + { + return "(number/list) Destination value"; + } + else if(index == 1) + { + return "(float) Ramp time"; + } + } + else + { + if(index == 0) + { + return "(signal) Output ramp"; + } + else if(index == 1) + { + return "(bang) When the ramp reached its destination"; + } + } + + return {}; + } + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_LineTilde.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_LineTilde.h new file mode 100755 index 00000000..2217d662 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_LineTilde.h @@ -0,0 +1,47 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // LINE~ // + // ================================================================================ // + + class LineTilde : public model::Object + { + public: + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + + LineTilde(flip::Default& d): model::Object(d){}; + + LineTilde(std::vector const& args); + + std::string getIODescription(bool is_inlet, size_t index) const override; + }; +}} + diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h index 6ad5c416..d60a87ad 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h @@ -48,3 +48,4 @@ #include #include #include +#include From ed32e2dc5911db4f2d5b3a2dba0263bd9d8a6a0e Mon Sep 17 00:00:00 2001 From: jean-millot Date: Tue, 21 Nov 2017 18:04:45 +0100 Subject: [PATCH 073/148] [snaphshot~] Check args and messages. --- .../KiwiEngine/KiwiEngine_Objects/KiwiEngine_SnapshotTilde.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_SnapshotTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_SnapshotTilde.cpp index 43261899..774f4f9f 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_SnapshotTilde.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_SnapshotTilde.cpp @@ -54,7 +54,7 @@ namespace kiwi { namespace engine { } else { - warning("snapshot~ inlet 1 doesn't understanc [" + args[0].getString() + "]"); + warning("snapshot~ inlet 1 doesn't understand args"); } } } From b436a375f249188f986f0f91116310caace9b2e2 Mon Sep 17 00:00:00 2001 From: jean-millot Date: Tue, 21 Nov 2017 18:05:08 +0100 Subject: [PATCH 074/148] [line~] Check arguments. --- .../KiwiModel_Objects/KiwiModel_LineTilde.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_LineTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_LineTilde.cpp index b79420b6..260383c4 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_LineTilde.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_LineTilde.cpp @@ -47,6 +47,16 @@ namespace kiwi { namespace model { LineTilde::LineTilde(std::vector const& args) { + if (args.size() > 1) + { + throw Error("line~ too many arguments"); + } + + if (args.size() == 1 && !args[0].isNumber()) + { + throw Error("line~ initial value shall be a number"); + } + pushInlet({PinType::IType::Control}); pushInlet({PinType::IType::Control}); pushOutlet(PinType::IType::Signal); From c39094be15c3f4036bf91820f645faea8e499f65 Mon Sep 17 00:00:00 2001 From: jean-millot Date: Wed, 22 Nov 2017 12:45:03 +0100 Subject: [PATCH 075/148] Object minus. --- Client/Source/KiwiApp.cpp | 1 + .../KiwiEngine_Objects/KiwiEngine_Minus.cpp | 51 ++++++++++++++++ .../KiwiEngine_Objects/KiwiEngine_Minus.h | 45 ++++++++++++++ .../KiwiEngine_Objects/KiwiEngine_Objects.h | 1 + Modules/KiwiModel/KiwiModel_DataModel.cpp | 1 + .../KiwiModel_Objects/KiwiModel_Minus.cpp | 60 +++++++++++++++++++ .../KiwiModel_Objects/KiwiModel_Minus.h | 46 ++++++++++++++ .../KiwiModel_Objects/KiwiModel_Objects.h | 1 + 8 files changed, 206 insertions(+) create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Minus.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Minus.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Minus.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Minus.h diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index 5190e4c1..09a5eccd 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -164,6 +164,7 @@ namespace kiwi engine::SnapshotTilde::declare(); engine::Trigger::declare(); engine::LineTilde::declare(); + engine::Minus::declare(); } void KiwiApp::declareObjectViews() diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Minus.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Minus.cpp new file mode 100644 index 00000000..295c6acf --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Minus.cpp @@ -0,0 +1,51 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OBJECT MINUS // + // ================================================================================ // + + void Minus::declare() + { + Factory::add("minus", &Minus::create); + } + + std::unique_ptr Minus::create(model::Object const& model, Patcher & patcher) + { + return std::make_unique(model, patcher); + } + + Minus::Minus(model::Object const& model, Patcher& patcher): + Operator(model, patcher) + { + } + + double Minus::compute(double lhs, double rhs) const + { + return lhs - rhs; + } + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Minus.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Minus.h new file mode 100644 index 00000000..5783f77d --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Minus.h @@ -0,0 +1,45 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OBJECT MINUS // + // ================================================================================ // + + class Minus : public Operator + { + public: + + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher& patcher); + + Minus(model::Object const& model, Patcher& patcher); + + double compute(double lhs, double rhs) const override final; + }; +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h index 76ae89cd..7acba82d 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h @@ -49,3 +49,4 @@ #include #include #include +#include diff --git a/Modules/KiwiModel/KiwiModel_DataModel.cpp b/Modules/KiwiModel/KiwiModel_DataModel.cpp index 9e3740ed..d7b91d06 100644 --- a/Modules/KiwiModel/KiwiModel_DataModel.cpp +++ b/Modules/KiwiModel/KiwiModel_DataModel.cpp @@ -61,6 +61,7 @@ namespace kiwi model::SnapshotTilde::declare(); model::Trigger::declare(); model::LineTilde::declare(); + model::Minus::declare(); } void DataModel::init(std::function declare_object) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Minus.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Minus.cpp new file mode 100755 index 00000000..cc4b70f8 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Minus.cpp @@ -0,0 +1,60 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT MINUS // + // ================================================================================ // + + void Minus::declare() + { + if (!DataModel::has()) + { + Operator::declare(); + } + + std::unique_ptr minus_class(new ObjectClass("minus", + &Minus::create)); + + minus_class->addAlias("-"); + + flip::Class & minus_model = DataModel::declare() + .name(minus_class->getModelName().c_str()) + .inherit(); + + Factory::add(std::move(minus_class), minus_model); + } + + std::unique_ptr Minus::create(std::vector const& args) + { + return std::make_unique(args); + } + + Minus::Minus(std::vector const& args): + Operator(args) + { + } + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Minus.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Minus.h new file mode 100755 index 00000000..76ee282b --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Minus.h @@ -0,0 +1,46 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT MINUS // + // ================================================================================ // + + class Minus : public Operator + { + public: + + Minus(flip::Default& d) : Operator(d) {} + + Minus(std::vector const& args); + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + }; + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h index d60a87ad..fcde7c29 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h @@ -49,3 +49,4 @@ #include #include #include +#include From 61245e1fd71901e8d9969d8d538438eed1fc9de3 Mon Sep 17 00:00:00 2001 From: jean-millot Date: Wed, 22 Nov 2017 13:05:57 +0100 Subject: [PATCH 076/148] Object divide. --- Client/Source/KiwiApp.cpp | 1 + .../KiwiEngine_Objects/KiwiEngine_Divide.cpp | 57 ++++++++++++++++++ .../KiwiEngine_Objects/KiwiEngine_Divide.h | 45 ++++++++++++++ .../KiwiEngine_Objects/KiwiEngine_Objects.h | 1 + .../KiwiEngine_Objects/KiwiEngine_Operator.h | 2 +- Modules/KiwiModel/KiwiModel_DataModel.cpp | 1 + .../KiwiModel_Objects/KiwiModel_Divide.cpp | 60 +++++++++++++++++++ .../KiwiModel_Objects/KiwiModel_Divide.h | 46 ++++++++++++++ .../KiwiModel_Objects/KiwiModel_Objects.h | 1 + 9 files changed, 213 insertions(+), 1 deletion(-) create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Divide.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Divide.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Divide.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Divide.h diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index 09a5eccd..86b86d8e 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -165,6 +165,7 @@ namespace kiwi engine::Trigger::declare(); engine::LineTilde::declare(); engine::Minus::declare(); + engine::Divide::declare(); } void KiwiApp::declareObjectViews() diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Divide.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Divide.cpp new file mode 100644 index 00000000..3dfb6a2c --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Divide.cpp @@ -0,0 +1,57 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OBJECT DIVIDE // + // ================================================================================ // + + void Divide::declare() + { + Factory::add("divide", &Divide::create); + } + + std::unique_ptr Divide::create(model::Object const& model, Patcher & patcher) + { + return std::make_unique(model, patcher); + } + + Divide::Divide(model::Object const& model, Patcher& patcher): + Operator(model, patcher) + { + std::vector const& args = model.getArguments(); + + if (args.empty()) + { + m_rhs = 1; + } + } + + double Divide::compute(double lhs, double rhs) const + { + return lhs / rhs; + } + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Divide.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Divide.h new file mode 100644 index 00000000..3f0ba682 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Divide.h @@ -0,0 +1,45 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OBJECT DIVIDE // + // ================================================================================ // + + class Divide : public Operator + { + public: + + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher& patcher); + + Divide(model::Object const& model, Patcher& patcher); + + double compute(double lhs, double rhs) const override final; + }; +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h index 7acba82d..6b90daf1 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h @@ -50,3 +50,4 @@ #include #include #include +#include diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Operator.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Operator.h index 90a1067b..cb929e2c 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Operator.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Operator.h @@ -41,7 +41,7 @@ namespace kiwi { namespace engine { virtual double compute(double lhs, double rhs) const = 0; - private: + protected: double m_lhs; double m_rhs; diff --git a/Modules/KiwiModel/KiwiModel_DataModel.cpp b/Modules/KiwiModel/KiwiModel_DataModel.cpp index d7b91d06..d8ee804e 100644 --- a/Modules/KiwiModel/KiwiModel_DataModel.cpp +++ b/Modules/KiwiModel/KiwiModel_DataModel.cpp @@ -62,6 +62,7 @@ namespace kiwi model::Trigger::declare(); model::LineTilde::declare(); model::Minus::declare(); + model::Divide::declare(); } void DataModel::init(std::function declare_object) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Divide.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Divide.cpp new file mode 100755 index 00000000..2f54e8f6 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Divide.cpp @@ -0,0 +1,60 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT DIVIDE // + // ================================================================================ // + + void Divide::declare() + { + if (!DataModel::has()) + { + Operator::declare(); + } + + std::unique_ptr divide_class(new ObjectClass("divide", + &Divide::create)); + + divide_class->addAlias("/"); + + flip::Class & divide_model = DataModel::declare() + .name(divide_class->getModelName().c_str()) + .inherit(); + + Factory::add(std::move(divide_class), divide_model); + } + + std::unique_ptr Divide::create(std::vector const& args) + { + return std::make_unique(args); + } + + Divide::Divide(std::vector const& args): + Operator(args) + { + } + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Divide.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Divide.h new file mode 100755 index 00000000..2c71aff9 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Divide.h @@ -0,0 +1,46 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT DIVIDE // + // ================================================================================ // + + class Divide : public Operator + { + public: + + Divide(flip::Default& d) : Operator(d) {} + + Divide(std::vector const& args); + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + }; + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h index fcde7c29..1d214efb 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h @@ -50,3 +50,4 @@ #include #include #include +#include From 217d9f580c958debe74c145d0dbbd74dd95168c7 Mon Sep 17 00:00:00 2001 From: jean-millot Date: Wed, 22 Nov 2017 14:02:34 +0100 Subject: [PATCH 077/148] Object equal. --- Client/Source/KiwiApp.cpp | 1 + .../KiwiEngine_Objects/KiwiEngine_Equal.cpp | 51 ++++++++++++++++ .../KiwiEngine_Objects/KiwiEngine_Equal.h | 45 ++++++++++++++ .../KiwiEngine_Objects/KiwiEngine_Objects.h | 1 + Modules/KiwiModel/KiwiModel_DataModel.cpp | 1 + .../KiwiModel_Objects/KiwiModel_Equal.cpp | 60 +++++++++++++++++++ .../KiwiModel_Objects/KiwiModel_Equal.h | 46 ++++++++++++++ .../KiwiModel_Objects/KiwiModel_Objects.h | 1 + 8 files changed, 206 insertions(+) create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Equal.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Equal.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Equal.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Equal.h diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index 86b86d8e..9a339eae 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -166,6 +166,7 @@ namespace kiwi engine::LineTilde::declare(); engine::Minus::declare(); engine::Divide::declare(); + engine::Equal::declare(); } void KiwiApp::declareObjectViews() diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Equal.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Equal.cpp new file mode 100644 index 00000000..c491f7ee --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Equal.cpp @@ -0,0 +1,51 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OBJECT EQUAL // + // ================================================================================ // + + void Equal::declare() + { + Factory::add("equal", &Equal::create); + } + + std::unique_ptr Equal::create(model::Object const& model, Patcher & patcher) + { + return std::make_unique(model, patcher); + } + + Equal::Equal(model::Object const& model, Patcher& patcher): + Operator(model, patcher) + { + } + + double Equal::compute(double lhs, double rhs) const + { + return lhs == rhs ? 1 : 0; + } + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Equal.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Equal.h new file mode 100644 index 00000000..2f599004 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Equal.h @@ -0,0 +1,45 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OBJECT EQUAL // + // ================================================================================ // + + class Equal : public Operator + { + public: + + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher& patcher); + + Equal(model::Object const& model, Patcher& patcher); + + double compute(double lhs, double rhs) const override final; + }; +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h index 6b90daf1..e5ade7c8 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h @@ -51,3 +51,4 @@ #include #include #include +#include diff --git a/Modules/KiwiModel/KiwiModel_DataModel.cpp b/Modules/KiwiModel/KiwiModel_DataModel.cpp index d8ee804e..c9020c1d 100644 --- a/Modules/KiwiModel/KiwiModel_DataModel.cpp +++ b/Modules/KiwiModel/KiwiModel_DataModel.cpp @@ -63,6 +63,7 @@ namespace kiwi model::LineTilde::declare(); model::Minus::declare(); model::Divide::declare(); + model::Equal::declare(); } void DataModel::init(std::function declare_object) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Equal.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Equal.cpp new file mode 100755 index 00000000..3d820545 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Equal.cpp @@ -0,0 +1,60 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT EQUAL // + // ================================================================================ // + + void Equal::declare() + { + if (!DataModel::has()) + { + Operator::declare(); + } + + std::unique_ptr equal_class(new ObjectClass("equal", + &Equal::create)); + + equal_class->addAlias("=="); + + flip::Class & equal_model = DataModel::declare() + .name(equal_class->getModelName().c_str()) + .inherit(); + + Factory::add(std::move(equal_class), equal_model); + } + + std::unique_ptr Equal::create(std::vector const& args) + { + return std::make_unique(args); + } + + Equal::Equal(std::vector const& args): + Operator(args) + { + } + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Equal.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Equal.h new file mode 100755 index 00000000..08426a14 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Equal.h @@ -0,0 +1,46 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT EQUAL // + // ================================================================================ // + + class Equal : public Operator + { + public: + + Equal(flip::Default& d) : Operator(d) {} + + Equal(std::vector const& args); + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + }; + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h index 1d214efb..f15b654d 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h @@ -51,3 +51,4 @@ #include #include #include +#include From 3437790c14db09f18fbf1ea26da6fd29fdeed794 Mon Sep 17 00:00:00 2001 From: jean-millot Date: Wed, 22 Nov 2017 14:30:00 +0100 Subject: [PATCH 078/148] Object less. --- Client/Source/KiwiApp.cpp | 1 + .../KiwiEngine_Objects/KiwiEngine_Less.cpp | 51 ++++++++++++++++ .../KiwiEngine_Objects/KiwiEngine_Less.h | 45 ++++++++++++++ .../KiwiEngine_Objects/KiwiEngine_Objects.h | 1 + Modules/KiwiModel/KiwiModel_DataModel.cpp | 1 + .../KiwiModel_Objects/KiwiModel_Less.cpp | 60 +++++++++++++++++++ .../KiwiModel_Objects/KiwiModel_Less.h | 46 ++++++++++++++ .../KiwiModel_Objects/KiwiModel_Objects.h | 1 + 8 files changed, 206 insertions(+) create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Less.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Less.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Less.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Less.h diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index 9a339eae..b3534f6c 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -167,6 +167,7 @@ namespace kiwi engine::Minus::declare(); engine::Divide::declare(); engine::Equal::declare(); + engine::Less::declare(); } void KiwiApp::declareObjectViews() diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Less.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Less.cpp new file mode 100644 index 00000000..85b6f463 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Less.cpp @@ -0,0 +1,51 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OBJECT LESS // + // ================================================================================ // + + void Less::declare() + { + Factory::add("less", &Less::create); + } + + std::unique_ptr Less::create(model::Object const& model, Patcher & patcher) + { + return std::make_unique(model, patcher); + } + + Less::Less(model::Object const& model, Patcher& patcher): + Operator(model, patcher) + { + } + + double Less::compute(double lhs, double rhs) const + { + return lhs < rhs ? 1 : 0; + } + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Less.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Less.h new file mode 100644 index 00000000..fb437dc9 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Less.h @@ -0,0 +1,45 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OBJECT LESS // + // ================================================================================ // + + class Less : public Operator + { + public: + + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher& patcher); + + Less(model::Object const& model, Patcher& patcher); + + double compute(double lhs, double rhs) const override final; + }; +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h index e5ade7c8..3cfad6bd 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h @@ -52,3 +52,4 @@ #include #include #include +#include diff --git a/Modules/KiwiModel/KiwiModel_DataModel.cpp b/Modules/KiwiModel/KiwiModel_DataModel.cpp index c9020c1d..a5f44421 100644 --- a/Modules/KiwiModel/KiwiModel_DataModel.cpp +++ b/Modules/KiwiModel/KiwiModel_DataModel.cpp @@ -64,6 +64,7 @@ namespace kiwi model::Minus::declare(); model::Divide::declare(); model::Equal::declare(); + model::Less::declare(); } void DataModel::init(std::function declare_object) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Less.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Less.cpp new file mode 100755 index 00000000..dea48678 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Less.cpp @@ -0,0 +1,60 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT LESS // + // ================================================================================ // + + void Less::declare() + { + if (!DataModel::has()) + { + Operator::declare(); + } + + std::unique_ptr less_class(new ObjectClass("less", + &Less::create)); + + less_class->addAlias("<"); + + flip::Class & less_model = DataModel::declare() + .name(less_class->getModelName().c_str()) + .inherit(); + + Factory::add(std::move(less_class), less_model); + } + + std::unique_ptr Less::create(std::vector const& args) + { + return std::make_unique(args); + } + + Less::Less(std::vector const& args): + Operator(args) + { + } + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Less.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Less.h new file mode 100755 index 00000000..96f702f0 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Less.h @@ -0,0 +1,46 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT LESS // + // ================================================================================ // + + class Less : public Operator + { + public: + + Less(flip::Default& d) : Operator(d) {} + + Less(std::vector const& args); + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + }; + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h index f15b654d..366e6519 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h @@ -52,3 +52,4 @@ #include #include #include +#include From d4972a05e6526d46d6e14896eab7af782d6a6915 Mon Sep 17 00:00:00 2001 From: jean-millot Date: Wed, 22 Nov 2017 14:43:01 +0100 Subject: [PATCH 079/148] Object greater. --- Client/Source/KiwiApp.cpp | 1 + .../KiwiEngine_Objects/KiwiEngine_Greater.cpp | 51 ++++++++++++++++ .../KiwiEngine_Objects/KiwiEngine_Greater.h | 45 ++++++++++++++ .../KiwiEngine_Objects/KiwiEngine_Objects.h | 1 + Modules/KiwiModel/KiwiModel_DataModel.cpp | 1 + .../KiwiModel_Objects/KiwiModel_Greater.cpp | 60 +++++++++++++++++++ .../KiwiModel_Objects/KiwiModel_Greater.h | 46 ++++++++++++++ .../KiwiModel_Objects/KiwiModel_Objects.h | 1 + 8 files changed, 206 insertions(+) create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Greater.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Greater.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Greater.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Greater.h diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index b3534f6c..bda060fd 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -168,6 +168,7 @@ namespace kiwi engine::Divide::declare(); engine::Equal::declare(); engine::Less::declare(); + engine::Greater::declare(); } void KiwiApp::declareObjectViews() diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Greater.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Greater.cpp new file mode 100644 index 00000000..2f538cc6 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Greater.cpp @@ -0,0 +1,51 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OBJECT GREATER // + // ================================================================================ // + + void Greater::declare() + { + Factory::add("greater", &Greater::create); + } + + std::unique_ptr Greater::create(model::Object const& model, Patcher & patcher) + { + return std::make_unique(model, patcher); + } + + Greater::Greater(model::Object const& model, Patcher& patcher): + Operator(model, patcher) + { + } + + double Greater::compute(double lhs, double rhs) const + { + return lhs > rhs ? 1 : 0; + } + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Greater.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Greater.h new file mode 100644 index 00000000..3167aa04 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Greater.h @@ -0,0 +1,45 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OBJECT GREATER // + // ================================================================================ // + + class Greater : public Operator + { + public: + + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher& patcher); + + Greater(model::Object const& model, Patcher& patcher); + + double compute(double lhs, double rhs) const override final; + }; +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h index 3cfad6bd..7afe22f5 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h @@ -53,3 +53,4 @@ #include #include #include +#include diff --git a/Modules/KiwiModel/KiwiModel_DataModel.cpp b/Modules/KiwiModel/KiwiModel_DataModel.cpp index a5f44421..2269949c 100644 --- a/Modules/KiwiModel/KiwiModel_DataModel.cpp +++ b/Modules/KiwiModel/KiwiModel_DataModel.cpp @@ -65,6 +65,7 @@ namespace kiwi model::Divide::declare(); model::Equal::declare(); model::Less::declare(); + model::Greater::declare(); } void DataModel::init(std::function declare_object) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Greater.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Greater.cpp new file mode 100755 index 00000000..29548b2d --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Greater.cpp @@ -0,0 +1,60 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT GREATER // + // ================================================================================ // + + void Greater::declare() + { + if (!DataModel::has()) + { + Operator::declare(); + } + + std::unique_ptr greater_class(new ObjectClass("greater", + &Greater::create)); + + greater_class->addAlias(">"); + + flip::Class & greater_model = DataModel::declare() + .name(greater_class->getModelName().c_str()) + .inherit(); + + Factory::add(std::move(greater_class), greater_model); + } + + std::unique_ptr Greater::create(std::vector const& args) + { + return std::make_unique(args); + } + + Greater::Greater(std::vector const& args): + Operator(args) + { + } + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Greater.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Greater.h new file mode 100755 index 00000000..0417d44c --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Greater.h @@ -0,0 +1,46 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT GREATER // + // ================================================================================ // + + class Greater : public Operator + { + public: + + Greater(flip::Default& d) : Operator(d) {} + + Greater(std::vector const& args); + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + }; + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h index 366e6519..4adcca7a 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h @@ -53,3 +53,4 @@ #include #include #include +#include From 0cc7ee527feaa36784e244c98716f2d8435cdc76 Mon Sep 17 00:00:00 2001 From: jean-millot Date: Wed, 22 Nov 2017 14:55:52 +0100 Subject: [PATCH 080/148] Object different. --- Client/Source/KiwiApp.cpp | 1 + .../KiwiEngine_Different.cpp | 51 ++++++++++++++++ .../KiwiEngine_Objects/KiwiEngine_Different.h | 45 ++++++++++++++ .../KiwiEngine_Objects/KiwiEngine_Objects.h | 1 + Modules/KiwiModel/KiwiModel_DataModel.cpp | 1 + .../KiwiModel_Objects/KiwiModel_Different.cpp | 60 +++++++++++++++++++ .../KiwiModel_Objects/KiwiModel_Different.h | 46 ++++++++++++++ .../KiwiModel_Objects/KiwiModel_Objects.h | 1 + 8 files changed, 206 insertions(+) create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Different.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Different.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Different.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Different.h diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index bda060fd..47231762 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -169,6 +169,7 @@ namespace kiwi engine::Equal::declare(); engine::Less::declare(); engine::Greater::declare(); + engine::Different::declare(); } void KiwiApp::declareObjectViews() diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Different.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Different.cpp new file mode 100644 index 00000000..35a737ee --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Different.cpp @@ -0,0 +1,51 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OBJECT DIFFERENT // + // ================================================================================ // + + void Different::declare() + { + Factory::add("different", &Different::create); + } + + std::unique_ptr Different::create(model::Object const& model, Patcher & patcher) + { + return std::make_unique(model, patcher); + } + + Different::Different(model::Object const& model, Patcher& patcher): + Operator(model, patcher) + { + } + + double Different::compute(double lhs, double rhs) const + { + return lhs != rhs ? 1 : 0; + } + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Different.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Different.h new file mode 100644 index 00000000..cab54351 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Different.h @@ -0,0 +1,45 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OBJECT DIFERRENT // + // ================================================================================ // + + class Different : public Operator + { + public: + + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher& patcher); + + Different(model::Object const& model, Patcher& patcher); + + double compute(double lhs, double rhs) const override final; + }; +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h index 7afe22f5..d2bb5e59 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h @@ -54,3 +54,4 @@ #include #include #include +#include diff --git a/Modules/KiwiModel/KiwiModel_DataModel.cpp b/Modules/KiwiModel/KiwiModel_DataModel.cpp index 2269949c..ac0785a2 100644 --- a/Modules/KiwiModel/KiwiModel_DataModel.cpp +++ b/Modules/KiwiModel/KiwiModel_DataModel.cpp @@ -66,6 +66,7 @@ namespace kiwi model::Equal::declare(); model::Less::declare(); model::Greater::declare(); + model::Different::declare(); } void DataModel::init(std::function declare_object) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Different.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Different.cpp new file mode 100755 index 00000000..eadc0501 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Different.cpp @@ -0,0 +1,60 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT DIFFERENT // + // ================================================================================ // + + void Different::declare() + { + if (!DataModel::has()) + { + Operator::declare(); + } + + std::unique_ptr different_class(new ObjectClass("different", + &Different::create)); + + different_class->addAlias("!="); + + flip::Class & different_model = DataModel::declare() + .name(different_class->getModelName().c_str()) + .inherit(); + + Factory::add(std::move(different_class), different_model); + } + + std::unique_ptr Different::create(std::vector const& args) + { + return std::make_unique(args); + } + + Different::Different(std::vector const& args): + Operator(args) + { + } + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Different.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Different.h new file mode 100755 index 00000000..6f4e6444 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Different.h @@ -0,0 +1,46 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT DIFFERENT // + // ================================================================================ // + + class Different : public Operator + { + public: + + Different(flip::Default& d) : Operator(d) {} + + Different(std::vector const& args); + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + }; + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h index 4adcca7a..089a532b 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h @@ -54,3 +54,4 @@ #include #include #include +#include From 0cc79e945b0f1c683b8aeab977185ea6c91abdff Mon Sep 17 00:00:00 2001 From: jean-millot Date: Wed, 22 Nov 2017 15:23:16 +0100 Subject: [PATCH 081/148] Pow object. --- Client/Source/KiwiApp.cpp | 1 + .../KiwiEngine_Objects/KiwiEngine_Objects.h | 1 + .../KiwiEngine_Objects/KiwiEngine_Pow.cpp | 53 +++++++++++++++++ .../KiwiEngine_Objects/KiwiEngine_Pow.h | 45 ++++++++++++++ Modules/KiwiModel/KiwiModel_DataModel.cpp | 1 + .../KiwiModel_Objects/KiwiModel_Objects.h | 1 + .../KiwiModel_Objects/KiwiModel_Pow.cpp | 58 +++++++++++++++++++ .../KiwiModel_Objects/KiwiModel_Pow.h | 46 +++++++++++++++ 8 files changed, 206 insertions(+) create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Pow.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Pow.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Pow.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Pow.h diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index 47231762..5eb6af6e 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -170,6 +170,7 @@ namespace kiwi engine::Less::declare(); engine::Greater::declare(); engine::Different::declare(); + engine::Pow::declare(); } void KiwiApp::declareObjectViews() diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h index d2bb5e59..f5b931c9 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h @@ -55,3 +55,4 @@ #include #include #include +#include diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Pow.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Pow.cpp new file mode 100644 index 00000000..8f4b4613 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Pow.cpp @@ -0,0 +1,53 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OBJECT POW // + // ================================================================================ // + + void Pow::declare() + { + Factory::add("pow", &Pow::create); + } + + std::unique_ptr Pow::create(model::Object const& model, Patcher & patcher) + { + return std::make_unique(model, patcher); + } + + Pow::Pow(model::Object const& model, Patcher& patcher): + Operator(model, patcher) + { + } + + double Pow::compute(double lhs, double rhs) const + { + return std::pow(lhs, rhs); + } + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Pow.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Pow.h new file mode 100644 index 00000000..5c1711ed --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Pow.h @@ -0,0 +1,45 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OBJECT POW // + // ================================================================================ // + + class Pow : public Operator + { + public: + + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher& patcher); + + Pow(model::Object const& model, Patcher& patcher); + + double compute(double lhs, double rhs) const override final; + }; +}} diff --git a/Modules/KiwiModel/KiwiModel_DataModel.cpp b/Modules/KiwiModel/KiwiModel_DataModel.cpp index ac0785a2..fb5ad8dd 100644 --- a/Modules/KiwiModel/KiwiModel_DataModel.cpp +++ b/Modules/KiwiModel/KiwiModel_DataModel.cpp @@ -67,6 +67,7 @@ namespace kiwi model::Less::declare(); model::Greater::declare(); model::Different::declare(); + model::Pow::declare(); } void DataModel::init(std::function declare_object) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h index 089a532b..caa4c5c4 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h @@ -55,3 +55,4 @@ #include #include #include +#include diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Pow.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Pow.cpp new file mode 100755 index 00000000..1019dbaf --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Pow.cpp @@ -0,0 +1,58 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT POW // + // ================================================================================ // + + void Pow::declare() + { + if (!DataModel::has()) + { + Operator::declare(); + } + + std::unique_ptr pow_class(new ObjectClass("pow", + &Pow::create)); + + flip::Class & pow_model = DataModel::declare() + .name(pow_class->getModelName().c_str()) + .inherit(); + + Factory::add(std::move(pow_class), pow_model); + } + + std::unique_ptr Pow::create(std::vector const& args) + { + return std::make_unique(args); + } + + Pow::Pow(std::vector const& args): + Operator(args) + { + } + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Pow.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Pow.h new file mode 100755 index 00000000..85639e53 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Pow.h @@ -0,0 +1,46 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT POW // + // ================================================================================ // + + class Pow : public Operator + { + public: + + Pow(flip::Default& d) : Operator(d) {} + + Pow(std::vector const& args); + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + }; + +}} From 8c2360cd30f20808d4265d40ca016f099bb5bd61 Mon Sep 17 00:00:00 2001 From: jean-millot Date: Wed, 22 Nov 2017 15:40:28 +0100 Subject: [PATCH 082/148] Modulo object. --- Client/Source/KiwiApp.cpp | 1 + .../KiwiEngine_Objects/KiwiEngine_Modulo.cpp | 59 ++++++++++++++++++ .../KiwiEngine_Objects/KiwiEngine_Modulo.h | 45 ++++++++++++++ .../KiwiEngine_Objects/KiwiEngine_Objects.h | 1 + Modules/KiwiModel/KiwiModel_DataModel.cpp | 1 + .../KiwiModel_Objects/KiwiModel_Modulo.cpp | 60 +++++++++++++++++++ .../KiwiModel_Objects/KiwiModel_Modulo.h | 46 ++++++++++++++ .../KiwiModel_Objects/KiwiModel_Objects.h | 1 + 8 files changed, 214 insertions(+) create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Modulo.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Modulo.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Modulo.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Modulo.h diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index 5eb6af6e..8e3eb18d 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -171,6 +171,7 @@ namespace kiwi engine::Greater::declare(); engine::Different::declare(); engine::Pow::declare(); + engine::Modulo::declare(); } void KiwiApp::declareObjectViews() diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Modulo.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Modulo.cpp new file mode 100644 index 00000000..41ddc648 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Modulo.cpp @@ -0,0 +1,59 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OBJECT MODULO // + // ================================================================================ // + + void Modulo::declare() + { + Factory::add("modulo", &Modulo::create); + } + + std::unique_ptr Modulo::create(model::Object const& model, Patcher & patcher) + { + return std::make_unique(model, patcher); + } + + Modulo::Modulo(model::Object const& model, Patcher& patcher): + Operator(model, patcher) + { + std::vector const& args = model.getArguments(); + + if (args.empty()) + { + m_rhs = 1; + } + } + + double Modulo::compute(double lhs, double rhs) const + { + return fmodf(lhs, rhs); + } + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Modulo.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Modulo.h new file mode 100644 index 00000000..8431ff6e --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Modulo.h @@ -0,0 +1,45 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OBJECT MODULO // + // ================================================================================ // + + class Modulo : public Operator + { + public: + + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher& patcher); + + Modulo(model::Object const& model, Patcher& patcher); + + double compute(double lhs, double rhs) const override final; + }; +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h index f5b931c9..d640b905 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h @@ -56,3 +56,4 @@ #include #include #include +#include diff --git a/Modules/KiwiModel/KiwiModel_DataModel.cpp b/Modules/KiwiModel/KiwiModel_DataModel.cpp index fb5ad8dd..9efabad6 100644 --- a/Modules/KiwiModel/KiwiModel_DataModel.cpp +++ b/Modules/KiwiModel/KiwiModel_DataModel.cpp @@ -68,6 +68,7 @@ namespace kiwi model::Greater::declare(); model::Different::declare(); model::Pow::declare(); + model::Modulo::declare(); } void DataModel::init(std::function declare_object) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Modulo.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Modulo.cpp new file mode 100755 index 00000000..aec41130 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Modulo.cpp @@ -0,0 +1,60 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT MODULO // + // ================================================================================ // + + void Modulo::declare() + { + if (!DataModel::has()) + { + Operator::declare(); + } + + std::unique_ptr modulo_class(new ObjectClass("modulo", + &Modulo::create)); + + modulo_class->addAlias("%"); + + flip::Class & modulo_model = DataModel::declare() + .name(modulo_class->getModelName().c_str()) + .inherit(); + + Factory::add(std::move(modulo_class), modulo_model); + } + + std::unique_ptr Modulo::create(std::vector const& args) + { + return std::make_unique(args); + } + + Modulo::Modulo(std::vector const& args): + Operator(args) + { + } + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Modulo.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Modulo.h new file mode 100755 index 00000000..657c6f56 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Modulo.h @@ -0,0 +1,46 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT MODULO // + // ================================================================================ // + + class Modulo : public Operator + { + public: + + Modulo(flip::Default& d) : Operator(d) {} + + Modulo(std::vector const& args); + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + }; + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h index caa4c5c4..62ec071c 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h @@ -56,3 +56,4 @@ #include #include #include +#include From 39febad7e8d864687542f86e56edd180103b0cc5 Mon Sep 17 00:00:00 2001 From: jean-millot Date: Wed, 22 Nov 2017 16:16:42 +0100 Subject: [PATCH 083/148] Object minustilde. --- Client/Source/KiwiApp.cpp | 1 + .../KiwiEngine_MinusTilde.cpp | 51 ++++++++++++++++ .../KiwiEngine_MinusTilde.h | 45 ++++++++++++++ .../KiwiEngine_Objects/KiwiEngine_Objects.h | 1 + Modules/KiwiModel/KiwiModel_DataModel.cpp | 1 + .../KiwiModel_MinusTilde.cpp | 59 +++++++++++++++++++ .../KiwiModel_Objects/KiwiModel_MinusTilde.h | 45 ++++++++++++++ .../KiwiModel_Objects/KiwiModel_Objects.h | 1 + 8 files changed, 204 insertions(+) create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_MinusTilde.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_MinusTilde.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_MinusTilde.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_MinusTilde.h diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index 8e3eb18d..e845439d 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -172,6 +172,7 @@ namespace kiwi engine::Different::declare(); engine::Pow::declare(); engine::Modulo::declare(); + engine::MinusTilde::declare(); } void KiwiApp::declareObjectViews() diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_MinusTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_MinusTilde.cpp new file mode 100644 index 00000000..eb56e89e --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_MinusTilde.cpp @@ -0,0 +1,51 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // -~ // + // ================================================================================ // + + void MinusTilde::declare() + { + Factory::add("minus~", &MinusTilde::create); + } + + std::unique_ptr MinusTilde::create(model::Object const& model, Patcher & patcher) + { + return std::make_unique(model, patcher); + } + + MinusTilde::MinusTilde(model::Object const& model, Patcher& patcher): + OperatorTilde(model, patcher) + { + } + + void MinusTilde::compute(dsp::sample_t & result, dsp::sample_t const& lhs, dsp::sample_t const& rhs) + { + result = lhs - rhs; + } + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_MinusTilde.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_MinusTilde.h new file mode 100644 index 00000000..a9eef88e --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_MinusTilde.h @@ -0,0 +1,45 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // -~ // + // ================================================================================ // + + class MinusTilde : public OperatorTilde + { + public: // methods + + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher & patcher); + + MinusTilde(model::Object const& model, Patcher& patcher); + + void compute(dsp::sample_t & result, dsp::sample_t const& lhs, dsp::sample_t const& rhs); + }; + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h index d640b905..0bcf1493 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h @@ -57,3 +57,4 @@ #include #include #include +#include diff --git a/Modules/KiwiModel/KiwiModel_DataModel.cpp b/Modules/KiwiModel/KiwiModel_DataModel.cpp index 9efabad6..27a8cc39 100644 --- a/Modules/KiwiModel/KiwiModel_DataModel.cpp +++ b/Modules/KiwiModel/KiwiModel_DataModel.cpp @@ -69,6 +69,7 @@ namespace kiwi model::Different::declare(); model::Pow::declare(); model::Modulo::declare(); + model::MinusTilde::declare(); } void DataModel::init(std::function declare_object) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_MinusTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_MinusTilde.cpp new file mode 100755 index 00000000..c2994737 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_MinusTilde.cpp @@ -0,0 +1,59 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT -~ // + // ================================================================================ // + + void MinusTilde::declare() + { + if (!DataModel::has()) + { + OperatorTilde::declare(); + } + + std::unique_ptr minustilde_class(new ObjectClass("minus~", &MinusTilde::create)); + + minustilde_class->addAlias("-~"); + + flip::Class & plustilde_model = DataModel::declare() + .name(minustilde_class->getModelName().c_str()) + .inherit(); + + Factory::add(std::move(minustilde_class), plustilde_model); + } + + std::unique_ptr MinusTilde::create(std::vector const& args) + { + return std::make_unique(args); + } + + MinusTilde::MinusTilde(std::vector const& args): + OperatorTilde(args) + { + } + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_MinusTilde.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_MinusTilde.h new file mode 100755 index 00000000..0a77c5ad --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_MinusTilde.h @@ -0,0 +1,45 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT -~ // + // ================================================================================ // + + class MinusTilde : public OperatorTilde + { + public: + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + + MinusTilde(flip::Default& d): OperatorTilde(d){}; + + MinusTilde(std::vector const& args); + }; + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h index 62ec071c..a26599de 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h @@ -57,3 +57,4 @@ #include #include #include +#include From 0799361ca6332f51c25277963d6a8dfc415f68ce Mon Sep 17 00:00:00 2001 From: jean-millot Date: Wed, 22 Nov 2017 16:37:53 +0100 Subject: [PATCH 084/148] Object divide~. --- Client/Source/KiwiApp.cpp | 1 + .../KiwiEngine_DivideTilde.cpp | 55 +++++++++++++++++ .../KiwiEngine_DivideTilde.h | 45 ++++++++++++++ .../KiwiEngine_Objects/KiwiEngine_Objects.h | 1 + .../KiwiEngine_OperatorTilde.h | 2 +- Modules/KiwiModel/KiwiModel_DataModel.cpp | 1 + .../KiwiModel_DivideTilde.cpp | 59 +++++++++++++++++++ .../KiwiModel_Objects/KiwiModel_DivideTilde.h | 45 ++++++++++++++ .../KiwiModel_Objects/KiwiModel_Objects.h | 1 + 9 files changed, 209 insertions(+), 1 deletion(-) create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_DivideTilde.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_DivideTilde.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_DivideTilde.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_DivideTilde.h diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index e845439d..f1b24c76 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -173,6 +173,7 @@ namespace kiwi engine::Pow::declare(); engine::Modulo::declare(); engine::MinusTilde::declare(); + engine::DivideTilde::declare(); } void KiwiApp::declareObjectViews() diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_DivideTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_DivideTilde.cpp new file mode 100644 index 00000000..6a6c3be9 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_DivideTilde.cpp @@ -0,0 +1,55 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // /~ // + // ================================================================================ // + + void DivideTilde::declare() + { + Factory::add("divide~", &DivideTilde::create); + } + + std::unique_ptr DivideTilde::create(model::Object const& model, Patcher & patcher) + { + return std::make_unique(model, patcher); + } + + DivideTilde::DivideTilde(model::Object const& model, Patcher& patcher): + OperatorTilde(model, patcher) + { + if (model.getArguments().empty()) + { + m_rhs = 1; + } + } + + void DivideTilde::compute(dsp::sample_t & result, dsp::sample_t const& lhs, dsp::sample_t const& rhs) + { + result = rhs != 0 ? lhs / rhs : 0.; + } + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_DivideTilde.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_DivideTilde.h new file mode 100644 index 00000000..653ab472 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_DivideTilde.h @@ -0,0 +1,45 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // /~ // + // ================================================================================ // + + class DivideTilde : public OperatorTilde + { + public: // methods + + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher & patcher); + + DivideTilde(model::Object const& model, Patcher& patcher); + + void compute(dsp::sample_t & result, dsp::sample_t const& lhs, dsp::sample_t const& rhs); + }; + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h index 0bcf1493..209c02d1 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h @@ -58,3 +58,4 @@ #include #include #include +#include diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_OperatorTilde.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_OperatorTilde.h index 4eace68e..1ba10bc1 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_OperatorTilde.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_OperatorTilde.h @@ -45,7 +45,7 @@ namespace kiwi { namespace engine { virtual void compute(dsp::sample_t & result, dsp::sample_t const& lhs, dsp::sample_t const& rhs) = 0; - private: + protected: std::atomic m_rhs{0.f}; }; diff --git a/Modules/KiwiModel/KiwiModel_DataModel.cpp b/Modules/KiwiModel/KiwiModel_DataModel.cpp index 27a8cc39..c192d914 100644 --- a/Modules/KiwiModel/KiwiModel_DataModel.cpp +++ b/Modules/KiwiModel/KiwiModel_DataModel.cpp @@ -70,6 +70,7 @@ namespace kiwi model::Pow::declare(); model::Modulo::declare(); model::MinusTilde::declare(); + model::DivideTilde::declare(); } void DataModel::init(std::function declare_object) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_DivideTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_DivideTilde.cpp new file mode 100755 index 00000000..57ab9961 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_DivideTilde.cpp @@ -0,0 +1,59 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT /~ // + // ================================================================================ // + + void DivideTilde::declare() + { + if (!DataModel::has()) + { + OperatorTilde::declare(); + } + + std::unique_ptr dividetilde_class(new ObjectClass("divide~", &DivideTilde::create)); + + dividetilde_class->addAlias("/~"); + + flip::Class & dividetilde_model = DataModel::declare() + .name(dividetilde_class->getModelName().c_str()) + .inherit(); + + Factory::add(std::move(dividetilde_class), dividetilde_model); + } + + std::unique_ptr DivideTilde::create(std::vector const& args) + { + return std::make_unique(args); + } + + DivideTilde::DivideTilde(std::vector const& args): + OperatorTilde(args) + { + } + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_DivideTilde.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_DivideTilde.h new file mode 100755 index 00000000..54169a2d --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_DivideTilde.h @@ -0,0 +1,45 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT /~ // + // ================================================================================ // + + class DivideTilde : public OperatorTilde + { + public: + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + + DivideTilde(flip::Default& d): OperatorTilde(d){}; + + DivideTilde(std::vector const& args); + }; + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h index a26599de..a2f5e17e 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h @@ -58,3 +58,4 @@ #include #include #include +#include From 3d7d2ebf16668cc1c42b67b3d51f26c32ebd1004 Mon Sep 17 00:00:00 2001 From: jean-millot Date: Wed, 22 Nov 2017 16:53:58 +0100 Subject: [PATCH 085/148] Object <~ --- Client/Source/KiwiApp.cpp | 1 + .../KiwiEngine_LessTilde.cpp | 51 ++++++++++++++++ .../KiwiEngine_Objects/KiwiEngine_LessTilde.h | 45 ++++++++++++++ .../KiwiEngine_Objects/KiwiEngine_Objects.h | 1 + Modules/KiwiModel/KiwiModel_DataModel.cpp | 1 + .../KiwiModel_Objects/KiwiModel_LessTilde.cpp | 59 +++++++++++++++++++ .../KiwiModel_Objects/KiwiModel_LessTilde.h | 45 ++++++++++++++ .../KiwiModel_Objects/KiwiModel_Objects.h | 1 + 8 files changed, 204 insertions(+) create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_LessTilde.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_LessTilde.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_LessTilde.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_LessTilde.h diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index f1b24c76..a4306387 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -174,6 +174,7 @@ namespace kiwi engine::Modulo::declare(); engine::MinusTilde::declare(); engine::DivideTilde::declare(); + engine::LessTilde::declare(); } void KiwiApp::declareObjectViews() diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_LessTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_LessTilde.cpp new file mode 100644 index 00000000..06abdf22 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_LessTilde.cpp @@ -0,0 +1,51 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // <~ // + // ================================================================================ // + + void LessTilde::declare() + { + Factory::add("less~", &LessTilde::create); + } + + std::unique_ptr LessTilde::create(model::Object const& model, Patcher & patcher) + { + return std::make_unique(model, patcher); + } + + LessTilde::LessTilde(model::Object const& model, Patcher& patcher): + OperatorTilde(model, patcher) + { + } + + void LessTilde::compute(dsp::sample_t & result, dsp::sample_t const& lhs, dsp::sample_t const& rhs) + { + result = lhs < rhs ? 1 : 0; + } + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_LessTilde.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_LessTilde.h new file mode 100644 index 00000000..199f167f --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_LessTilde.h @@ -0,0 +1,45 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // <~ // + // ================================================================================ // + + class LessTilde : public OperatorTilde + { + public: // methods + + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher & patcher); + + LessTilde(model::Object const& model, Patcher& patcher); + + void compute(dsp::sample_t & result, dsp::sample_t const& lhs, dsp::sample_t const& rhs); + }; + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h index 209c02d1..cbf1da84 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h @@ -59,3 +59,4 @@ #include #include #include +#include diff --git a/Modules/KiwiModel/KiwiModel_DataModel.cpp b/Modules/KiwiModel/KiwiModel_DataModel.cpp index c192d914..94ff344c 100644 --- a/Modules/KiwiModel/KiwiModel_DataModel.cpp +++ b/Modules/KiwiModel/KiwiModel_DataModel.cpp @@ -71,6 +71,7 @@ namespace kiwi model::Modulo::declare(); model::MinusTilde::declare(); model::DivideTilde::declare(); + model::LessTilde::declare(); } void DataModel::init(std::function declare_object) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_LessTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_LessTilde.cpp new file mode 100755 index 00000000..87784431 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_LessTilde.cpp @@ -0,0 +1,59 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT <~ // + // ================================================================================ // + + void LessTilde::declare() + { + if (!DataModel::has()) + { + OperatorTilde::declare(); + } + + std::unique_ptr lesstilde_class(new ObjectClass("less~", &LessTilde::create)); + + lesstilde_class->addAlias("<~"); + + flip::Class & lesstilde_model = DataModel::declare() + .name(lesstilde_class->getModelName().c_str()) + .inherit(); + + Factory::add(std::move(lesstilde_class), lesstilde_model); + } + + std::unique_ptr LessTilde::create(std::vector const& args) + { + return std::make_unique(args); + } + + LessTilde::LessTilde(std::vector const& args): + OperatorTilde(args) + { + } + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_LessTilde.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_LessTilde.h new file mode 100755 index 00000000..959589ae --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_LessTilde.h @@ -0,0 +1,45 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT <~ // + // ================================================================================ // + + class LessTilde : public OperatorTilde + { + public: + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + + LessTilde(flip::Default& d): OperatorTilde(d){}; + + LessTilde(std::vector const& args); + }; + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h index a2f5e17e..70ec3689 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h @@ -59,3 +59,4 @@ #include #include #include +#include From 3a4b4d3142ef43143ade97f07248965a107b3a08 Mon Sep 17 00:00:00 2001 From: jean-millot Date: Wed, 22 Nov 2017 17:02:44 +0100 Subject: [PATCH 086/148] Object greater~. --- Client/Source/KiwiApp.cpp | 1 + .../KiwiEngine_GreaterTilde.cpp | 51 ++++++++++++++++ .../KiwiEngine_GreaterTilde.h | 45 ++++++++++++++ .../KiwiEngine_Objects/KiwiEngine_Objects.h | 1 + Modules/KiwiModel/KiwiModel_DataModel.cpp | 1 + .../KiwiModel_GreaterTilde.cpp | 59 +++++++++++++++++++ .../KiwiModel_GreaterTilde.h | 45 ++++++++++++++ .../KiwiModel_Objects/KiwiModel_Objects.h | 1 + 8 files changed, 204 insertions(+) create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_GreaterTilde.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_GreaterTilde.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_GreaterTilde.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_GreaterTilde.h diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index a4306387..e5edf54c 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -175,6 +175,7 @@ namespace kiwi engine::MinusTilde::declare(); engine::DivideTilde::declare(); engine::LessTilde::declare(); + engine::GreaterTilde::declare(); } void KiwiApp::declareObjectViews() diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_GreaterTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_GreaterTilde.cpp new file mode 100644 index 00000000..ee1e4db5 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_GreaterTilde.cpp @@ -0,0 +1,51 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // >~ // + // ================================================================================ // + + void GreaterTilde::declare() + { + Factory::add("greater~", &GreaterTilde::create); + } + + std::unique_ptr GreaterTilde::create(model::Object const& model, Patcher & patcher) + { + return std::make_unique(model, patcher); + } + + GreaterTilde::GreaterTilde(model::Object const& model, Patcher& patcher): + OperatorTilde(model, patcher) + { + } + + void GreaterTilde::compute(dsp::sample_t & result, dsp::sample_t const& lhs, dsp::sample_t const& rhs) + { + result = lhs > rhs ? 1 : 0; + } + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_GreaterTilde.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_GreaterTilde.h new file mode 100644 index 00000000..7e6fdb82 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_GreaterTilde.h @@ -0,0 +1,45 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // >~ // + // ================================================================================ // + + class GreaterTilde : public OperatorTilde + { + public: // methods + + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher & patcher); + + GreaterTilde(model::Object const& model, Patcher& patcher); + + void compute(dsp::sample_t & result, dsp::sample_t const& lhs, dsp::sample_t const& rhs); + }; + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h index cbf1da84..8b7b96a5 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h @@ -60,3 +60,4 @@ #include #include #include +#include diff --git a/Modules/KiwiModel/KiwiModel_DataModel.cpp b/Modules/KiwiModel/KiwiModel_DataModel.cpp index 94ff344c..51b52c7c 100644 --- a/Modules/KiwiModel/KiwiModel_DataModel.cpp +++ b/Modules/KiwiModel/KiwiModel_DataModel.cpp @@ -72,6 +72,7 @@ namespace kiwi model::MinusTilde::declare(); model::DivideTilde::declare(); model::LessTilde::declare(); + model::GreaterTilde::declare(); } void DataModel::init(std::function declare_object) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_GreaterTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_GreaterTilde.cpp new file mode 100755 index 00000000..3abeba1f --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_GreaterTilde.cpp @@ -0,0 +1,59 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT >~ // + // ================================================================================ // + + void GreaterTilde::declare() + { + if (!DataModel::has()) + { + OperatorTilde::declare(); + } + + std::unique_ptr greatertilde_class(new ObjectClass("greater~", &GreaterTilde::create)); + + greatertilde_class->addAlias(">~"); + + flip::Class & greatertilde_model = DataModel::declare() + .name(greatertilde_class->getModelName().c_str()) + .inherit(); + + Factory::add(std::move(greatertilde_class), greatertilde_model); + } + + std::unique_ptr GreaterTilde::create(std::vector const& args) + { + return std::make_unique(args); + } + + GreaterTilde::GreaterTilde(std::vector const& args): + OperatorTilde(args) + { + } + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_GreaterTilde.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_GreaterTilde.h new file mode 100755 index 00000000..b4811e84 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_GreaterTilde.h @@ -0,0 +1,45 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT >~ // + // ================================================================================ // + + class GreaterTilde : public OperatorTilde + { + public: + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + + GreaterTilde(flip::Default& d): OperatorTilde(d){}; + + GreaterTilde(std::vector const& args); + }; + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h index 70ec3689..3258968d 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h @@ -60,3 +60,4 @@ #include #include #include +#include From ec0e960d13756bc80750e0e696dae84560d3c6b4 Mon Sep 17 00:00:00 2001 From: jean-millot Date: Wed, 22 Nov 2017 17:13:49 +0100 Subject: [PATCH 087/148] Object ==~ --- Client/Source/KiwiApp.cpp | 1 + .../KiwiEngine_EqualTilde.cpp | 51 ++++++++++++++++ .../KiwiEngine_EqualTilde.h | 45 ++++++++++++++ .../KiwiEngine_Objects/KiwiEngine_Objects.h | 1 + Modules/KiwiModel/KiwiModel_DataModel.cpp | 1 + .../KiwiModel_EqualTilde.cpp | 59 +++++++++++++++++++ .../KiwiModel_Objects/KiwiModel_EqualTilde.h | 45 ++++++++++++++ .../KiwiModel_Objects/KiwiModel_Objects.h | 1 + 8 files changed, 204 insertions(+) create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_EqualTilde.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_EqualTilde.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_EqualTilde.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_EqualTilde.h diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index e5edf54c..30b523fe 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -176,6 +176,7 @@ namespace kiwi engine::DivideTilde::declare(); engine::LessTilde::declare(); engine::GreaterTilde::declare(); + engine::EqualTilde::declare(); } void KiwiApp::declareObjectViews() diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_EqualTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_EqualTilde.cpp new file mode 100644 index 00000000..3b3aecd4 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_EqualTilde.cpp @@ -0,0 +1,51 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // ==~ // + // ================================================================================ // + + void EqualTilde::declare() + { + Factory::add("equal~", &EqualTilde::create); + } + + std::unique_ptr EqualTilde::create(model::Object const& model, Patcher & patcher) + { + return std::make_unique(model, patcher); + } + + EqualTilde::EqualTilde(model::Object const& model, Patcher& patcher): + OperatorTilde(model, patcher) + { + } + + void EqualTilde::compute(dsp::sample_t & result, dsp::sample_t const& lhs, dsp::sample_t const& rhs) + { + result = lhs == rhs ? 1 : 0; + } + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_EqualTilde.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_EqualTilde.h new file mode 100644 index 00000000..f204e6a2 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_EqualTilde.h @@ -0,0 +1,45 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // ==~ // + // ================================================================================ // + + class EqualTilde : public OperatorTilde + { + public: // methods + + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher & patcher); + + EqualTilde(model::Object const& model, Patcher& patcher); + + void compute(dsp::sample_t & result, dsp::sample_t const& lhs, dsp::sample_t const& rhs); + }; + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h index 8b7b96a5..d51248f6 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h @@ -61,3 +61,4 @@ #include #include #include +#include diff --git a/Modules/KiwiModel/KiwiModel_DataModel.cpp b/Modules/KiwiModel/KiwiModel_DataModel.cpp index 51b52c7c..27a8a610 100644 --- a/Modules/KiwiModel/KiwiModel_DataModel.cpp +++ b/Modules/KiwiModel/KiwiModel_DataModel.cpp @@ -73,6 +73,7 @@ namespace kiwi model::DivideTilde::declare(); model::LessTilde::declare(); model::GreaterTilde::declare(); + model::EqualTilde::declare(); } void DataModel::init(std::function declare_object) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_EqualTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_EqualTilde.cpp new file mode 100755 index 00000000..905f26d7 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_EqualTilde.cpp @@ -0,0 +1,59 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT ==~ // + // ================================================================================ // + + void EqualTilde::declare() + { + if (!DataModel::has()) + { + OperatorTilde::declare(); + } + + std::unique_ptr equaltilde_class(new ObjectClass("equal~", &EqualTilde::create)); + + equaltilde_class->addAlias("==~"); + + flip::Class & equaltilde_model = DataModel::declare() + .name(equaltilde_class->getModelName().c_str()) + .inherit(); + + Factory::add(std::move(equaltilde_class), equaltilde_model); + } + + std::unique_ptr EqualTilde::create(std::vector const& args) + { + return std::make_unique(args); + } + + EqualTilde::EqualTilde(std::vector const& args): + OperatorTilde(args) + { + } + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_EqualTilde.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_EqualTilde.h new file mode 100755 index 00000000..eaaa7a9d --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_EqualTilde.h @@ -0,0 +1,45 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT ==~ // + // ================================================================================ // + + class EqualTilde : public OperatorTilde + { + public: + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + + EqualTilde(flip::Default& d): OperatorTilde(d){}; + + EqualTilde(std::vector const& args); + }; + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h index 3258968d..52da103d 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h @@ -61,3 +61,4 @@ #include #include #include +#include From b3edf07b4cff373e49dc1a50d937cd69cbfc368d Mon Sep 17 00:00:00 2001 From: jean-millot Date: Wed, 22 Nov 2017 17:24:11 +0100 Subject: [PATCH 088/148] Object !=~ --- Client/Source/KiwiApp.cpp | 1 + .../KiwiEngine_DifferentTilde.cpp | 51 ++++++++++++++++ .../KiwiEngine_DifferentTilde.h | 45 ++++++++++++++ .../KiwiEngine_Objects/KiwiEngine_Objects.h | 1 + Modules/KiwiModel/KiwiModel_DataModel.cpp | 1 + .../KiwiModel_DifferentTilde.cpp | 59 +++++++++++++++++++ .../KiwiModel_DifferentTilde.h | 45 ++++++++++++++ .../KiwiModel_Objects/KiwiModel_Objects.h | 1 + 8 files changed, 204 insertions(+) create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_DifferentTilde.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_DifferentTilde.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_DifferentTilde.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_DifferentTilde.h diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index 30b523fe..2ecc50b1 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -177,6 +177,7 @@ namespace kiwi engine::LessTilde::declare(); engine::GreaterTilde::declare(); engine::EqualTilde::declare(); + engine::DifferentTilde::declare(); } void KiwiApp::declareObjectViews() diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_DifferentTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_DifferentTilde.cpp new file mode 100644 index 00000000..5aee0fca --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_DifferentTilde.cpp @@ -0,0 +1,51 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // !=~ // + // ================================================================================ // + + void DifferentTilde::declare() + { + Factory::add("different~", &DifferentTilde::create); + } + + std::unique_ptr DifferentTilde::create(model::Object const& model, Patcher & patcher) + { + return std::make_unique(model, patcher); + } + + DifferentTilde::DifferentTilde(model::Object const& model, Patcher& patcher): + OperatorTilde(model, patcher) + { + } + + void DifferentTilde::compute(dsp::sample_t & result, dsp::sample_t const& lhs, dsp::sample_t const& rhs) + { + result = lhs != rhs ? 1. : 0.; + } + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_DifferentTilde.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_DifferentTilde.h new file mode 100644 index 00000000..dd61fde5 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_DifferentTilde.h @@ -0,0 +1,45 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // !=~ // + // ================================================================================ // + + class DifferentTilde : public OperatorTilde + { + public: // methods + + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher & patcher); + + DifferentTilde(model::Object const& model, Patcher& patcher); + + void compute(dsp::sample_t & result, dsp::sample_t const& lhs, dsp::sample_t const& rhs); + }; + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h index d51248f6..3f8e2ed0 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h @@ -62,3 +62,4 @@ #include #include #include +#include diff --git a/Modules/KiwiModel/KiwiModel_DataModel.cpp b/Modules/KiwiModel/KiwiModel_DataModel.cpp index 27a8a610..14811a40 100644 --- a/Modules/KiwiModel/KiwiModel_DataModel.cpp +++ b/Modules/KiwiModel/KiwiModel_DataModel.cpp @@ -74,6 +74,7 @@ namespace kiwi model::LessTilde::declare(); model::GreaterTilde::declare(); model::EqualTilde::declare(); + model::DifferentTilde::declare(); } void DataModel::init(std::function declare_object) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_DifferentTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_DifferentTilde.cpp new file mode 100755 index 00000000..447b061d --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_DifferentTilde.cpp @@ -0,0 +1,59 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT !=~ // + // ================================================================================ // + + void DifferentTilde::declare() + { + if (!DataModel::has()) + { + OperatorTilde::declare(); + } + + std::unique_ptr differenttilde_class(new ObjectClass("different~", &DifferentTilde::create)); + + differenttilde_class->addAlias("!=~"); + + flip::Class & differenttilde_model = DataModel::declare() + .name(differenttilde_class->getModelName().c_str()) + .inherit(); + + Factory::add(std::move(differenttilde_class), differenttilde_model); + } + + std::unique_ptr DifferentTilde::create(std::vector const& args) + { + return std::make_unique(args); + } + + DifferentTilde::DifferentTilde(std::vector const& args): + OperatorTilde(args) + { + } + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_DifferentTilde.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_DifferentTilde.h new file mode 100755 index 00000000..e71fec50 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_DifferentTilde.h @@ -0,0 +1,45 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT !=~ // + // ================================================================================ // + + class DifferentTilde : public OperatorTilde + { + public: + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + + DifferentTilde(flip::Default& d): OperatorTilde(d){}; + + DifferentTilde(std::vector const& args); + }; + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h index 52da103d..116594c6 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h @@ -62,3 +62,4 @@ #include #include #include +#include From 707f2279ac5e5283e2fc088ca831eec5430ae9e0 Mon Sep 17 00:00:00 2001 From: jmillot Date: Fri, 24 Nov 2017 15:53:23 +0100 Subject: [PATCH 089/148] Using operator real names instead of aliases. --- .../KiwiEngine_Different.cpp | 2 +- .../KiwiEngine_DifferentTilde.cpp | 2 +- .../KiwiEngine_Objects/KiwiEngine_Divide.cpp | 2 +- .../KiwiEngine_DivideTilde.cpp | 2 +- .../KiwiEngine_Objects/KiwiEngine_Equal.cpp | 2 +- .../KiwiEngine_EqualTilde.cpp | 2 +- .../KiwiEngine_Objects/KiwiEngine_Greater.cpp | 2 +- .../KiwiEngine_GreaterTilde.cpp | 2 +- .../KiwiEngine_Objects/KiwiEngine_Less.cpp | 2 +- .../KiwiEngine_LessTilde.cpp | 2 +- .../KiwiEngine_Objects/KiwiEngine_Minus.cpp | 2 +- .../KiwiEngine_MinusTilde.cpp | 2 +- .../KiwiEngine_Objects/KiwiEngine_Modulo.cpp | 2 +- .../KiwiEngine_Objects/KiwiEngine_Plus.cpp | 2 +- .../KiwiEngine_PlusTilde.cpp | 2 +- .../KiwiEngine_Objects/KiwiEngine_Times.cpp | 2 +- .../KiwiEngine_TimesTilde.cpp | 2 +- Modules/KiwiModel/KiwiModel_Factory.cpp | 56 ++++++++++++++++--- Modules/KiwiModel/KiwiModel_Factory.h | 9 ++- Modules/KiwiModel/KiwiModel_ObjectClass.cpp | 2 +- .../KiwiModel_Objects/KiwiModel_Different.cpp | 4 +- .../KiwiModel_DifferentTilde.cpp | 4 +- .../KiwiModel_Objects/KiwiModel_Divide.cpp | 4 +- .../KiwiModel_DivideTilde.cpp | 4 +- .../KiwiModel_Objects/KiwiModel_Equal.cpp | 4 +- .../KiwiModel_EqualTilde.cpp | 4 +- .../KiwiModel_Objects/KiwiModel_Greater.cpp | 4 +- .../KiwiModel_GreaterTilde.cpp | 4 +- .../KiwiModel_Objects/KiwiModel_Less.cpp | 4 +- .../KiwiModel_Objects/KiwiModel_LessTilde.cpp | 4 +- .../KiwiModel_Objects/KiwiModel_Minus.cpp | 4 +- .../KiwiModel_MinusTilde.cpp | 4 +- .../KiwiModel_Objects/KiwiModel_Modulo.cpp | 4 +- .../KiwiModel_Objects/KiwiModel_Plus.cpp | 4 +- .../KiwiModel_Objects/KiwiModel_PlusTilde.cpp | 4 +- .../KiwiModel_Objects/KiwiModel_Times.cpp | 4 +- .../KiwiModel_TimesTilde.cpp | 4 +- Test/Model/test_Factory.cpp | 53 ++++++++++++++++++ 38 files changed, 142 insertions(+), 80 deletions(-) create mode 100755 Test/Model/test_Factory.cpp diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Different.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Different.cpp index 35a737ee..b8531bcc 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Different.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Different.cpp @@ -30,7 +30,7 @@ namespace kiwi { namespace engine { void Different::declare() { - Factory::add("different", &Different::create); + Factory::add("!=", &Different::create); } std::unique_ptr Different::create(model::Object const& model, Patcher & patcher) diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_DifferentTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_DifferentTilde.cpp index 5aee0fca..0ade0c56 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_DifferentTilde.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_DifferentTilde.cpp @@ -30,7 +30,7 @@ namespace kiwi { namespace engine { void DifferentTilde::declare() { - Factory::add("different~", &DifferentTilde::create); + Factory::add("!=~", &DifferentTilde::create); } std::unique_ptr DifferentTilde::create(model::Object const& model, Patcher & patcher) diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Divide.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Divide.cpp index 3dfb6a2c..b0397706 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Divide.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Divide.cpp @@ -30,7 +30,7 @@ namespace kiwi { namespace engine { void Divide::declare() { - Factory::add("divide", &Divide::create); + Factory::add("/", &Divide::create); } std::unique_ptr Divide::create(model::Object const& model, Patcher & patcher) diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_DivideTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_DivideTilde.cpp index 6a6c3be9..77cb653a 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_DivideTilde.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_DivideTilde.cpp @@ -30,7 +30,7 @@ namespace kiwi { namespace engine { void DivideTilde::declare() { - Factory::add("divide~", &DivideTilde::create); + Factory::add("/~", &DivideTilde::create); } std::unique_ptr DivideTilde::create(model::Object const& model, Patcher & patcher) diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Equal.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Equal.cpp index c491f7ee..28b6cb81 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Equal.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Equal.cpp @@ -30,7 +30,7 @@ namespace kiwi { namespace engine { void Equal::declare() { - Factory::add("equal", &Equal::create); + Factory::add("==", &Equal::create); } std::unique_ptr Equal::create(model::Object const& model, Patcher & patcher) diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_EqualTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_EqualTilde.cpp index 3b3aecd4..40c763ce 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_EqualTilde.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_EqualTilde.cpp @@ -30,7 +30,7 @@ namespace kiwi { namespace engine { void EqualTilde::declare() { - Factory::add("equal~", &EqualTilde::create); + Factory::add("==~", &EqualTilde::create); } std::unique_ptr EqualTilde::create(model::Object const& model, Patcher & patcher) diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Greater.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Greater.cpp index 2f538cc6..0bb8ae34 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Greater.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Greater.cpp @@ -30,7 +30,7 @@ namespace kiwi { namespace engine { void Greater::declare() { - Factory::add("greater", &Greater::create); + Factory::add(">", &Greater::create); } std::unique_ptr Greater::create(model::Object const& model, Patcher & patcher) diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_GreaterTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_GreaterTilde.cpp index ee1e4db5..d3f2a97f 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_GreaterTilde.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_GreaterTilde.cpp @@ -30,7 +30,7 @@ namespace kiwi { namespace engine { void GreaterTilde::declare() { - Factory::add("greater~", &GreaterTilde::create); + Factory::add(">~", &GreaterTilde::create); } std::unique_ptr GreaterTilde::create(model::Object const& model, Patcher & patcher) diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Less.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Less.cpp index 85b6f463..ff30cda2 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Less.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Less.cpp @@ -30,7 +30,7 @@ namespace kiwi { namespace engine { void Less::declare() { - Factory::add("less", &Less::create); + Factory::add("<", &Less::create); } std::unique_ptr Less::create(model::Object const& model, Patcher & patcher) diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_LessTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_LessTilde.cpp index 06abdf22..67b7d88d 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_LessTilde.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_LessTilde.cpp @@ -30,7 +30,7 @@ namespace kiwi { namespace engine { void LessTilde::declare() { - Factory::add("less~", &LessTilde::create); + Factory::add("<~", &LessTilde::create); } std::unique_ptr LessTilde::create(model::Object const& model, Patcher & patcher) diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Minus.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Minus.cpp index 295c6acf..ec0da423 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Minus.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Minus.cpp @@ -30,7 +30,7 @@ namespace kiwi { namespace engine { void Minus::declare() { - Factory::add("minus", &Minus::create); + Factory::add("-", &Minus::create); } std::unique_ptr Minus::create(model::Object const& model, Patcher & patcher) diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_MinusTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_MinusTilde.cpp index eb56e89e..793a0e2d 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_MinusTilde.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_MinusTilde.cpp @@ -30,7 +30,7 @@ namespace kiwi { namespace engine { void MinusTilde::declare() { - Factory::add("minus~", &MinusTilde::create); + Factory::add("-~", &MinusTilde::create); } std::unique_ptr MinusTilde::create(model::Object const& model, Patcher & patcher) diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Modulo.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Modulo.cpp index 41ddc648..134b5aca 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Modulo.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Modulo.cpp @@ -32,7 +32,7 @@ namespace kiwi { namespace engine { void Modulo::declare() { - Factory::add("modulo", &Modulo::create); + Factory::add("%", &Modulo::create); } std::unique_ptr Modulo::create(model::Object const& model, Patcher & patcher) diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Plus.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Plus.cpp index a65ec7af..7da379ed 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Plus.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Plus.cpp @@ -31,7 +31,7 @@ namespace kiwi { namespace engine { void Plus::declare() { - Factory::add("plus", &Plus::create); + Factory::add("+", &Plus::create); } std::unique_ptr Plus::create(model::Object const& model, Patcher & patcher) diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_PlusTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_PlusTilde.cpp index 2c9f2f64..3de1412f 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_PlusTilde.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_PlusTilde.cpp @@ -30,7 +30,7 @@ namespace kiwi { namespace engine { void PlusTilde::declare() { - Factory::add("plus~", &PlusTilde::create); + Factory::add("+~", &PlusTilde::create); } std::unique_ptr PlusTilde::create(model::Object const& model, Patcher & patcher) diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Times.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Times.cpp index 3ea172a0..bcf02c7b 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Times.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Times.cpp @@ -30,7 +30,7 @@ namespace kiwi { namespace engine{ void Times::declare() { - Factory::add("times", &Times::create); + Factory::add("*", &Times::create); } std::unique_ptr Times::create(model::Object const& model, Patcher & patcher) diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_TimesTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_TimesTilde.cpp index 808db852..cfd15182 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_TimesTilde.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_TimesTilde.cpp @@ -30,7 +30,7 @@ namespace kiwi { namespace engine { void TimesTilde::declare() { - Factory::add("times~", &TimesTilde::create); + Factory::add("*~", &TimesTilde::create); } std::unique_ptr TimesTilde::create(model::Object const& model, Patcher & patcher) diff --git a/Modules/KiwiModel/KiwiModel_Factory.cpp b/Modules/KiwiModel/KiwiModel_Factory.cpp index 52669b0a..88d72018 100644 --- a/Modules/KiwiModel/KiwiModel_Factory.cpp +++ b/Modules/KiwiModel/KiwiModel_Factory.cpp @@ -19,6 +19,8 @@ ============================================================================== */ +#include + #include #include "KiwiModel_Factory.h" @@ -152,24 +154,60 @@ namespace kiwi return names; } - std::string Factory::sanitizeName(std::string const& name) + std::string Factory::toModelName(std::string const& name) { std::string model_name = "cicm.kiwi.object."; - static const std::string valid_chars("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890_."); - - for(auto const& c : name) + for (char const& c : name) { - if(c == '~') + assert(c != '\\' && "using antislash character in object name"); + + if (uint8_t (c) < 0x20 + || uint8_t (c) == 0x20 + || uint8_t (c) == 0x7f + || uint8_t (c) >= 0x80) { - model_name.append("_tilde"); - continue; + int i = (int) c; + + std::string int_string = "\x5C" + std::to_string(i) + "\x5C"; + + model_name.append(int_string); + } + else + { + model_name.push_back(c); } - - model_name += (valid_chars.find(c) != std::string::npos) ? c : '_'; } return model_name; } + + std::string Factory::toKiwiName(std::string const& model_name) + { + std::string prefix = "cicm.kiwi.object."; + + assert(model_name.find(prefix) == 0); + + std::string kiwi_name = model_name; + + kiwi_name.erase(0, prefix.size()); + + size_t slash_pos = kiwi_name.find('\\'); + + while(slash_pos != std::string::npos) + { + size_t next_slash = kiwi_name.find('\\', slash_pos + 1); + + std::string int_string = kiwi_name.substr(slash_pos + 1, next_slash - slash_pos); + + char c = (char) std::stoi(int_string); + + kiwi_name.replace(slash_pos, next_slash - slash_pos + 1, 1, c); + + slash_pos = kiwi_name.find('\\'); + } + + return kiwi_name; + } } } diff --git a/Modules/KiwiModel/KiwiModel_Factory.h b/Modules/KiwiModel/KiwiModel_Factory.h index f35acc6a..dc7ad6c3 100644 --- a/Modules/KiwiModel/KiwiModel_Factory.h +++ b/Modules/KiwiModel/KiwiModel_Factory.h @@ -164,8 +164,13 @@ namespace kiwi static std::vector getNames(const bool ignore_aliases = false, const bool ignore_internals = true); - //! @internal Returns a sanitized version of the string. - static std::string sanitizeName(std::string const& name); + //! @internal Returns the corresponding model name. Since flip only ascii-7 characters + //! can be used in the datamodel, we define a bijection between name and model name. + static std::string toModelName(std::string const& name); + + //! @internal Returns the corresponding model name. Since flip only ascii-7 characters + //! can be used in the datamodel, we define a bijection between name and model name. + static std::string toKiwiName(std::string const& name); private: // members diff --git a/Modules/KiwiModel/KiwiModel_ObjectClass.cpp b/Modules/KiwiModel/KiwiModel_ObjectClass.cpp index 7b3d5d72..63495ad8 100755 --- a/Modules/KiwiModel/KiwiModel_ObjectClass.cpp +++ b/Modules/KiwiModel/KiwiModel_ObjectClass.cpp @@ -61,7 +61,7 @@ namespace kiwi { namespace model { ObjectClass::ObjectClass(std::string const& name, ctor_t ctor): m_name(name), - m_model_name(Factory::sanitizeName(name)), + m_model_name(Factory::toModelName(name)), m_aliases(), m_params(), m_ctor(ctor), diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Different.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Different.cpp index eadc0501..5decfe8e 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Different.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Different.cpp @@ -35,11 +35,9 @@ namespace kiwi { namespace model { Operator::declare(); } - std::unique_ptr different_class(new ObjectClass("different", + std::unique_ptr different_class(new ObjectClass("!=", &Different::create)); - different_class->addAlias("!="); - flip::Class & different_model = DataModel::declare() .name(different_class->getModelName().c_str()) .inherit(); diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_DifferentTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_DifferentTilde.cpp index 447b061d..36f72c14 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_DifferentTilde.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_DifferentTilde.cpp @@ -35,9 +35,7 @@ namespace kiwi { namespace model { OperatorTilde::declare(); } - std::unique_ptr differenttilde_class(new ObjectClass("different~", &DifferentTilde::create)); - - differenttilde_class->addAlias("!=~"); + std::unique_ptr differenttilde_class(new ObjectClass("!=~", &DifferentTilde::create)); flip::Class & differenttilde_model = DataModel::declare() .name(differenttilde_class->getModelName().c_str()) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Divide.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Divide.cpp index 2f54e8f6..c8e66c45 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Divide.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Divide.cpp @@ -35,11 +35,9 @@ namespace kiwi { namespace model { Operator::declare(); } - std::unique_ptr divide_class(new ObjectClass("divide", + std::unique_ptr divide_class(new ObjectClass("/", &Divide::create)); - divide_class->addAlias("/"); - flip::Class & divide_model = DataModel::declare() .name(divide_class->getModelName().c_str()) .inherit(); diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_DivideTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_DivideTilde.cpp index 57ab9961..988d701c 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_DivideTilde.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_DivideTilde.cpp @@ -35,9 +35,7 @@ namespace kiwi { namespace model { OperatorTilde::declare(); } - std::unique_ptr dividetilde_class(new ObjectClass("divide~", &DivideTilde::create)); - - dividetilde_class->addAlias("/~"); + std::unique_ptr dividetilde_class(new ObjectClass("/~", &DivideTilde::create)); flip::Class & dividetilde_model = DataModel::declare() .name(dividetilde_class->getModelName().c_str()) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Equal.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Equal.cpp index 3d820545..df4a029e 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Equal.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Equal.cpp @@ -35,11 +35,9 @@ namespace kiwi { namespace model { Operator::declare(); } - std::unique_ptr equal_class(new ObjectClass("equal", + std::unique_ptr equal_class(new ObjectClass("==", &Equal::create)); - equal_class->addAlias("=="); - flip::Class & equal_model = DataModel::declare() .name(equal_class->getModelName().c_str()) .inherit(); diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_EqualTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_EqualTilde.cpp index 905f26d7..445a7f4e 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_EqualTilde.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_EqualTilde.cpp @@ -35,9 +35,7 @@ namespace kiwi { namespace model { OperatorTilde::declare(); } - std::unique_ptr equaltilde_class(new ObjectClass("equal~", &EqualTilde::create)); - - equaltilde_class->addAlias("==~"); + std::unique_ptr equaltilde_class(new ObjectClass("==~", &EqualTilde::create)); flip::Class & equaltilde_model = DataModel::declare() .name(equaltilde_class->getModelName().c_str()) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Greater.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Greater.cpp index 29548b2d..7ee09299 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Greater.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Greater.cpp @@ -35,11 +35,9 @@ namespace kiwi { namespace model { Operator::declare(); } - std::unique_ptr greater_class(new ObjectClass("greater", + std::unique_ptr greater_class(new ObjectClass(">", &Greater::create)); - greater_class->addAlias(">"); - flip::Class & greater_model = DataModel::declare() .name(greater_class->getModelName().c_str()) .inherit(); diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_GreaterTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_GreaterTilde.cpp index 3abeba1f..69453471 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_GreaterTilde.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_GreaterTilde.cpp @@ -35,9 +35,7 @@ namespace kiwi { namespace model { OperatorTilde::declare(); } - std::unique_ptr greatertilde_class(new ObjectClass("greater~", &GreaterTilde::create)); - - greatertilde_class->addAlias(">~"); + std::unique_ptr greatertilde_class(new ObjectClass(">~", &GreaterTilde::create)); flip::Class & greatertilde_model = DataModel::declare() .name(greatertilde_class->getModelName().c_str()) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Less.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Less.cpp index dea48678..db8c033c 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Less.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Less.cpp @@ -35,11 +35,9 @@ namespace kiwi { namespace model { Operator::declare(); } - std::unique_ptr less_class(new ObjectClass("less", + std::unique_ptr less_class(new ObjectClass("<", &Less::create)); - less_class->addAlias("<"); - flip::Class & less_model = DataModel::declare() .name(less_class->getModelName().c_str()) .inherit(); diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_LessTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_LessTilde.cpp index 87784431..9da330bd 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_LessTilde.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_LessTilde.cpp @@ -35,9 +35,7 @@ namespace kiwi { namespace model { OperatorTilde::declare(); } - std::unique_ptr lesstilde_class(new ObjectClass("less~", &LessTilde::create)); - - lesstilde_class->addAlias("<~"); + std::unique_ptr lesstilde_class(new ObjectClass("<~", &LessTilde::create)); flip::Class & lesstilde_model = DataModel::declare() .name(lesstilde_class->getModelName().c_str()) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Minus.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Minus.cpp index cc4b70f8..8d2cc08d 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Minus.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Minus.cpp @@ -35,11 +35,9 @@ namespace kiwi { namespace model { Operator::declare(); } - std::unique_ptr minus_class(new ObjectClass("minus", + std::unique_ptr minus_class(new ObjectClass("-", &Minus::create)); - minus_class->addAlias("-"); - flip::Class & minus_model = DataModel::declare() .name(minus_class->getModelName().c_str()) .inherit(); diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_MinusTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_MinusTilde.cpp index c2994737..54023f48 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_MinusTilde.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_MinusTilde.cpp @@ -35,9 +35,7 @@ namespace kiwi { namespace model { OperatorTilde::declare(); } - std::unique_ptr minustilde_class(new ObjectClass("minus~", &MinusTilde::create)); - - minustilde_class->addAlias("-~"); + std::unique_ptr minustilde_class(new ObjectClass("-~", &MinusTilde::create)); flip::Class & plustilde_model = DataModel::declare() .name(minustilde_class->getModelName().c_str()) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Modulo.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Modulo.cpp index aec41130..1d9b8b7d 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Modulo.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Modulo.cpp @@ -35,11 +35,9 @@ namespace kiwi { namespace model { Operator::declare(); } - std::unique_ptr modulo_class(new ObjectClass("modulo", + std::unique_ptr modulo_class(new ObjectClass("%", &Modulo::create)); - modulo_class->addAlias("%"); - flip::Class & modulo_model = DataModel::declare() .name(modulo_class->getModelName().c_str()) .inherit(); diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Plus.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Plus.cpp index 14d7f0f7..84efd844 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Plus.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Plus.cpp @@ -36,11 +36,9 @@ namespace kiwi { namespace model { Operator::declare(); } - std::unique_ptr plus_class(new ObjectClass("plus", + std::unique_ptr plus_class(new ObjectClass("+", &Plus::create)); - plus_class->addAlias("+"); - flip::Class & plus_model = DataModel::declare() .name(plus_class->getModelName().c_str()) .inherit(); diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_PlusTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_PlusTilde.cpp index f40b83f9..4dbd6d08 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_PlusTilde.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_PlusTilde.cpp @@ -36,9 +36,7 @@ namespace kiwi { namespace model { OperatorTilde::declare(); } - std::unique_ptr plustilde_class(new ObjectClass("plus~", &PlusTilde::create)); - - plustilde_class->addAlias("+~"); + std::unique_ptr plustilde_class(new ObjectClass("+~", &PlusTilde::create)); flip::Class & plustilde_model = DataModel::declare() .name(plustilde_class->getModelName().c_str()) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Times.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Times.cpp index 3532fe0b..3a8aca0a 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Times.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Times.cpp @@ -36,11 +36,9 @@ namespace kiwi { namespace model { Operator::declare(); } - std::unique_ptr time_class(new ObjectClass("times", + std::unique_ptr time_class(new ObjectClass("*", &Times::create)); - time_class->addAlias("*"); - flip::Class & time_model = DataModel::declare() .name(time_class->getModelName().c_str()) .inherit(); diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_TimesTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_TimesTilde.cpp index 25fa4d92..9410df6d 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_TimesTilde.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_TimesTilde.cpp @@ -36,9 +36,7 @@ namespace kiwi { namespace model { OperatorTilde::declare(); } - std::unique_ptr timestilde_class(new ObjectClass("times~", &TimesTilde::create)); - - timestilde_class->addAlias("*~"); + std::unique_ptr timestilde_class(new ObjectClass("*~", &TimesTilde::create)); flip::Class & plustilde_model = DataModel::declare() .name(timestilde_class->getModelName().c_str()) diff --git a/Test/Model/test_Factory.cpp b/Test/Model/test_Factory.cpp new file mode 100755 index 00000000..f9579451 --- /dev/null +++ b/Test/Model/test_Factory.cpp @@ -0,0 +1,53 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include "../catch.hpp" + +#include + +using namespace kiwi; + +// ==================================================================================== // +// FACTORY // +// ==================================================================================== // + +TEST_CASE("Model Factory", "[Names]") +{ + SECTION("One special character") + { + std::string kiwi_name = "¨"; + + std::string model_name = model::Factory::toModelName(kiwi_name); + + CHECK(kiwi_name == model::Factory::toKiwiName(model_name)); + } + + SECTION("More complex character chain") + { + std::string kiwi_name = "¨ç*$$sd$sdf$@#2342ééé\\"; + + std::cout << kiwi_name.size() << std::endl; + + std::string model_name = model::Factory::toModelName(kiwi_name); + + CHECK(kiwi_name == model::Factory::toKiwiName(model_name)); + } +} From 393cdb08f9d2d77f468b3696d10879336b0feaed Mon Sep 17 00:00:00 2001 From: jmillot Date: Fri, 24 Nov 2017 18:13:09 +0100 Subject: [PATCH 090/148] fixup Using operator real names instead of aliases. --- Test/Model/test_Factory.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Test/Model/test_Factory.cpp b/Test/Model/test_Factory.cpp index f9579451..71750aca 100755 --- a/Test/Model/test_Factory.cpp +++ b/Test/Model/test_Factory.cpp @@ -42,7 +42,7 @@ TEST_CASE("Model Factory", "[Names]") SECTION("More complex character chain") { - std::string kiwi_name = "¨ç*$$sd$sdf$@#2342ééé\\"; + std::string kiwi_name = "¨ç*$$sd$sdf$@#2342ééé"; std::cout << kiwi_name.size() << std::endl; From 63bda9058587a6f15f6fec5604b9fda2c179668d Mon Sep 17 00:00:00 2001 From: jmillot Date: Fri, 24 Nov 2017 16:15:18 +0100 Subject: [PATCH 091/148] Object <=. --- Client/Source/KiwiApp.cpp | 1 + .../KiwiEngine_LessEqual.cpp | 51 ++++++++++++++++ .../KiwiEngine_Objects/KiwiEngine_LessEqual.h | 45 ++++++++++++++ .../KiwiEngine_Objects/KiwiEngine_Objects.h | 1 + Modules/KiwiModel/KiwiModel_DataModel.cpp | 1 + .../KiwiModel_Objects/KiwiModel_LessEqual.cpp | 58 +++++++++++++++++++ .../KiwiModel_Objects/KiwiModel_LessEqual.h | 46 +++++++++++++++ .../KiwiModel_Objects/KiwiModel_Objects.h | 1 + 8 files changed, 204 insertions(+) create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_LessEqual.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_LessEqual.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_LessEqual.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_LessEqual.h diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index 2ecc50b1..e11512ba 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -178,6 +178,7 @@ namespace kiwi engine::GreaterTilde::declare(); engine::EqualTilde::declare(); engine::DifferentTilde::declare(); + engine::LessEqual::declare(); } void KiwiApp::declareObjectViews() diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_LessEqual.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_LessEqual.cpp new file mode 100644 index 00000000..685cd8f3 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_LessEqual.cpp @@ -0,0 +1,51 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OBJECT LESSEQUAL // + // ================================================================================ // + + void LessEqual::declare() + { + Factory::add("<=", &LessEqual::create); + } + + std::unique_ptr LessEqual::create(model::Object const& model, Patcher & patcher) + { + return std::make_unique(model, patcher); + } + + LessEqual::LessEqual(model::Object const& model, Patcher& patcher): + Operator(model, patcher) + { + } + + double LessEqual::compute(double lhs, double rhs) const + { + return lhs <= rhs ? 1 : 0; + } + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_LessEqual.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_LessEqual.h new file mode 100644 index 00000000..85a1c65c --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_LessEqual.h @@ -0,0 +1,45 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OBJECT LESSEQUAL // + // ================================================================================ // + + class LessEqual : public Operator + { + public: + + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher& patcher); + + LessEqual(model::Object const& model, Patcher& patcher); + + double compute(double lhs, double rhs) const override final; + }; +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h index 3f8e2ed0..ed55fa8d 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h @@ -63,3 +63,4 @@ #include #include #include +#include diff --git a/Modules/KiwiModel/KiwiModel_DataModel.cpp b/Modules/KiwiModel/KiwiModel_DataModel.cpp index 14811a40..07a6c379 100644 --- a/Modules/KiwiModel/KiwiModel_DataModel.cpp +++ b/Modules/KiwiModel/KiwiModel_DataModel.cpp @@ -75,6 +75,7 @@ namespace kiwi model::GreaterTilde::declare(); model::EqualTilde::declare(); model::DifferentTilde::declare(); + model::LessEqual::declare(); } void DataModel::init(std::function declare_object) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_LessEqual.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_LessEqual.cpp new file mode 100755 index 00000000..91092f04 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_LessEqual.cpp @@ -0,0 +1,58 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT LESS // + // ================================================================================ // + + void LessEqual::declare() + { + if (!DataModel::has()) + { + Operator::declare(); + } + + std::unique_ptr lessequal_class(new ObjectClass("<=", + &LessEqual::create)); + + flip::Class & lessequal_model = DataModel::declare() + .name(lessequal_class->getModelName().c_str()) + .inherit(); + + Factory::add(std::move(lessequal_class), lessequal_model); + } + + std::unique_ptr LessEqual::create(std::vector const& args) + { + return std::make_unique(args); + } + + LessEqual::LessEqual(std::vector const& args): + Operator(args) + { + } + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_LessEqual.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_LessEqual.h new file mode 100755 index 00000000..cd12cd6d --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_LessEqual.h @@ -0,0 +1,46 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT LESSEQUAL // + // ================================================================================ // + + class LessEqual : public Operator + { + public: + + LessEqual(flip::Default& d) : Operator(d) {} + + LessEqual(std::vector const& args); + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + }; + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h index 116594c6..a8d1ba01 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h @@ -63,3 +63,4 @@ #include #include #include +#include From 86b23d368ce8c52e4791ec929039fad22b44a776 Mon Sep 17 00:00:00 2001 From: jmillot Date: Fri, 24 Nov 2017 16:24:04 +0100 Subject: [PATCH 092/148] Object <=~. --- Client/Source/KiwiApp.cpp | 1 + .../KiwiEngine_LessEqualTilde.cpp | 51 +++++++++++++++++ .../KiwiEngine_LessEqualTilde.h | 45 +++++++++++++++ .../KiwiEngine_Objects/KiwiEngine_Objects.h | 1 + Modules/KiwiModel/KiwiModel_DataModel.cpp | 1 + .../KiwiModel_LessEqualTilde.cpp | 57 +++++++++++++++++++ .../KiwiModel_LessEqualTilde.h | 45 +++++++++++++++ .../KiwiModel_Objects/KiwiModel_Objects.h | 1 + 8 files changed, 202 insertions(+) create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_LessEqualTilde.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_LessEqualTilde.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_LessEqualTilde.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_LessEqualTilde.h diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index e11512ba..15d02f2d 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -179,6 +179,7 @@ namespace kiwi engine::EqualTilde::declare(); engine::DifferentTilde::declare(); engine::LessEqual::declare(); + engine::LessEqualTilde::declare(); } void KiwiApp::declareObjectViews() diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_LessEqualTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_LessEqualTilde.cpp new file mode 100644 index 00000000..3474d228 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_LessEqualTilde.cpp @@ -0,0 +1,51 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // <=~ // + // ================================================================================ // + + void LessEqualTilde::declare() + { + Factory::add("<=~", &LessEqualTilde::create); + } + + std::unique_ptr LessEqualTilde::create(model::Object const& model, Patcher & patcher) + { + return std::make_unique(model, patcher); + } + + LessEqualTilde::LessEqualTilde(model::Object const& model, Patcher& patcher): + OperatorTilde(model, patcher) + { + } + + void LessEqualTilde::compute(dsp::sample_t & result, dsp::sample_t const& lhs, dsp::sample_t const& rhs) + { + result = lhs <= rhs ? 1 : 0; + } + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_LessEqualTilde.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_LessEqualTilde.h new file mode 100644 index 00000000..1b9d2399 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_LessEqualTilde.h @@ -0,0 +1,45 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // <=~ // + // ================================================================================ // + + class LessEqualTilde : public OperatorTilde + { + public: // methods + + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher & patcher); + + LessEqualTilde(model::Object const& model, Patcher& patcher); + + void compute(dsp::sample_t & result, dsp::sample_t const& lhs, dsp::sample_t const& rhs); + }; + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h index ed55fa8d..ca69658c 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h @@ -64,3 +64,4 @@ #include #include #include +#include diff --git a/Modules/KiwiModel/KiwiModel_DataModel.cpp b/Modules/KiwiModel/KiwiModel_DataModel.cpp index 07a6c379..d09fc2d5 100644 --- a/Modules/KiwiModel/KiwiModel_DataModel.cpp +++ b/Modules/KiwiModel/KiwiModel_DataModel.cpp @@ -76,6 +76,7 @@ namespace kiwi model::EqualTilde::declare(); model::DifferentTilde::declare(); model::LessEqual::declare(); + model::LessEqualTilde::declare(); } void DataModel::init(std::function declare_object) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_LessEqualTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_LessEqualTilde.cpp new file mode 100755 index 00000000..bcc789f6 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_LessEqualTilde.cpp @@ -0,0 +1,57 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT <=~ // + // ================================================================================ // + + void LessEqualTilde::declare() + { + if (!DataModel::has()) + { + OperatorTilde::declare(); + } + + std::unique_ptr lessequaltilde_class(new ObjectClass("<=~", &LessEqualTilde::create)); + + flip::Class & lessequaltilde_model = DataModel::declare() + .name(lessequaltilde_class->getModelName().c_str()) + .inherit(); + + Factory::add(std::move(lessequaltilde_class), lessequaltilde_model); + } + + std::unique_ptr LessEqualTilde::create(std::vector const& args) + { + return std::make_unique(args); + } + + LessEqualTilde::LessEqualTilde(std::vector const& args): + OperatorTilde(args) + { + } + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_LessEqualTilde.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_LessEqualTilde.h new file mode 100755 index 00000000..bf44e74d --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_LessEqualTilde.h @@ -0,0 +1,45 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT <=~ // + // ================================================================================ // + + class LessEqualTilde : public OperatorTilde + { + public: + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + + LessEqualTilde(flip::Default& d): OperatorTilde(d){}; + + LessEqualTilde(std::vector const& args); + }; + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h index a8d1ba01..9d8c5e4b 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h @@ -64,3 +64,4 @@ #include #include #include +#include From 1deb91ea61c9e54505a2e6809d301ae733024b84 Mon Sep 17 00:00:00 2001 From: jmillot Date: Fri, 24 Nov 2017 16:33:48 +0100 Subject: [PATCH 093/148] Object >=. --- Client/Source/KiwiApp.cpp | 1 + .../KiwiEngine_GreaterEqual.cpp | 51 ++++++++++++++++ .../KiwiEngine_GreaterEqual.h | 45 ++++++++++++++ .../KiwiEngine_Objects/KiwiEngine_Objects.h | 1 + Modules/KiwiModel/KiwiModel_DataModel.cpp | 1 + .../KiwiModel_GreaterEqual.cpp | 58 +++++++++++++++++++ .../KiwiModel_GreaterEqual.h | 46 +++++++++++++++ .../KiwiModel_Objects/KiwiModel_Objects.h | 1 + 8 files changed, 204 insertions(+) create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_GreaterEqual.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_GreaterEqual.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_GreaterEqual.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_GreaterEqual.h diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index 15d02f2d..7d6c756c 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -180,6 +180,7 @@ namespace kiwi engine::DifferentTilde::declare(); engine::LessEqual::declare(); engine::LessEqualTilde::declare(); + engine::GreaterEqual::declare(); } void KiwiApp::declareObjectViews() diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_GreaterEqual.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_GreaterEqual.cpp new file mode 100644 index 00000000..4c1dfc4b --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_GreaterEqual.cpp @@ -0,0 +1,51 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OBJECT GREATEREQUAL // + // ================================================================================ // + + void GreaterEqual::declare() + { + Factory::add(">=", &GreaterEqual::create); + } + + std::unique_ptr GreaterEqual::create(model::Object const& model, Patcher & patcher) + { + return std::make_unique(model, patcher); + } + + GreaterEqual::GreaterEqual(model::Object const& model, Patcher& patcher): + Operator(model, patcher) + { + } + + double GreaterEqual::compute(double lhs, double rhs) const + { + return lhs >= rhs ? 1 : 0; + } + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_GreaterEqual.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_GreaterEqual.h new file mode 100644 index 00000000..d61a57ed --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_GreaterEqual.h @@ -0,0 +1,45 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OBJECT GREATEREQUAL // + // ================================================================================ // + + class GreaterEqual : public Operator + { + public: + + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher& patcher); + + GreaterEqual(model::Object const& model, Patcher& patcher); + + double compute(double lhs, double rhs) const override final; + }; +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h index ca69658c..c76c16fa 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h @@ -65,3 +65,4 @@ #include #include #include +#include diff --git a/Modules/KiwiModel/KiwiModel_DataModel.cpp b/Modules/KiwiModel/KiwiModel_DataModel.cpp index d09fc2d5..19c7798c 100644 --- a/Modules/KiwiModel/KiwiModel_DataModel.cpp +++ b/Modules/KiwiModel/KiwiModel_DataModel.cpp @@ -77,6 +77,7 @@ namespace kiwi model::DifferentTilde::declare(); model::LessEqual::declare(); model::LessEqualTilde::declare(); + model::GreaterEqual::declare(); } void DataModel::init(std::function declare_object) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_GreaterEqual.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_GreaterEqual.cpp new file mode 100755 index 00000000..544e666c --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_GreaterEqual.cpp @@ -0,0 +1,58 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT GREATEREQUAL // + // ================================================================================ // + + void GreaterEqual::declare() + { + if (!DataModel::has()) + { + Operator::declare(); + } + + std::unique_ptr greaterequal_class(new ObjectClass(">=", + &GreaterEqual::create)); + + flip::Class & greaterequal_model = DataModel::declare() + .name(greaterequal_class->getModelName().c_str()) + .inherit(); + + Factory::add(std::move(greaterequal_class), greaterequal_model); + } + + std::unique_ptr GreaterEqual::create(std::vector const& args) + { + return std::make_unique(args); + } + + GreaterEqual::GreaterEqual(std::vector const& args): + Operator(args) + { + } + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_GreaterEqual.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_GreaterEqual.h new file mode 100755 index 00000000..7dd769b3 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_GreaterEqual.h @@ -0,0 +1,46 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT GREATEREQUAL // + // ================================================================================ // + + class GreaterEqual : public Operator + { + public: + + GreaterEqual(flip::Default& d) : Operator(d) {} + + GreaterEqual(std::vector const& args); + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + }; + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h index 9d8c5e4b..d732e9ec 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h @@ -65,3 +65,4 @@ #include #include #include +#include From 3af6c5a4e6aefe0554350faae182bbcb65d37dc4 Mon Sep 17 00:00:00 2001 From: jmillot Date: Fri, 24 Nov 2017 17:09:40 +0100 Subject: [PATCH 094/148] Object >=~. --- Client/Source/KiwiApp.cpp | 1 + .../KiwiEngine_GreaterEqualTilde.cpp | 51 +++++++++++++++++ .../KiwiEngine_GreaterEqualTilde.h | 45 +++++++++++++++ .../KiwiEngine_Objects/KiwiEngine_Objects.h | 1 + Modules/KiwiModel/KiwiModel_DataModel.cpp | 1 + .../KiwiModel_GreaterEqualTilde.cpp | 57 +++++++++++++++++++ .../KiwiModel_GreaterEqualTilde.h | 45 +++++++++++++++ .../KiwiModel_Objects/KiwiModel_Objects.h | 1 + 8 files changed, 202 insertions(+) create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_GreaterEqualTilde.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_GreaterEqualTilde.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_GreaterEqualTilde.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_GreaterEqualTilde.h diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index 7d6c756c..243ce843 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -181,6 +181,7 @@ namespace kiwi engine::LessEqual::declare(); engine::LessEqualTilde::declare(); engine::GreaterEqual::declare(); + engine::GreaterEqualTilde::declare(); } void KiwiApp::declareObjectViews() diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_GreaterEqualTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_GreaterEqualTilde.cpp new file mode 100644 index 00000000..c1b8fff4 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_GreaterEqualTilde.cpp @@ -0,0 +1,51 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // >=~ // + // ================================================================================ // + + void GreaterEqualTilde::declare() + { + Factory::add(">=~", &GreaterEqualTilde::create); + } + + std::unique_ptr GreaterEqualTilde::create(model::Object const& model, Patcher & patcher) + { + return std::make_unique(model, patcher); + } + + GreaterEqualTilde::GreaterEqualTilde(model::Object const& model, Patcher& patcher): + OperatorTilde(model, patcher) + { + } + + void GreaterEqualTilde::compute(dsp::sample_t & result, dsp::sample_t const& lhs, dsp::sample_t const& rhs) + { + result = lhs >= rhs ? 1 : 0; + } + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_GreaterEqualTilde.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_GreaterEqualTilde.h new file mode 100644 index 00000000..273e603b --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_GreaterEqualTilde.h @@ -0,0 +1,45 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // >=~ // + // ================================================================================ // + + class GreaterEqualTilde : public OperatorTilde + { + public: // methods + + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher & patcher); + + GreaterEqualTilde(model::Object const& model, Patcher& patcher); + + void compute(dsp::sample_t & result, dsp::sample_t const& lhs, dsp::sample_t const& rhs); + }; + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h index c76c16fa..31e4922d 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h @@ -66,3 +66,4 @@ #include #include #include +#include diff --git a/Modules/KiwiModel/KiwiModel_DataModel.cpp b/Modules/KiwiModel/KiwiModel_DataModel.cpp index 19c7798c..21a0f976 100644 --- a/Modules/KiwiModel/KiwiModel_DataModel.cpp +++ b/Modules/KiwiModel/KiwiModel_DataModel.cpp @@ -78,6 +78,7 @@ namespace kiwi model::LessEqual::declare(); model::LessEqualTilde::declare(); model::GreaterEqual::declare(); + model::GreaterEqualTilde::declare(); } void DataModel::init(std::function declare_object) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_GreaterEqualTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_GreaterEqualTilde.cpp new file mode 100755 index 00000000..d33f3463 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_GreaterEqualTilde.cpp @@ -0,0 +1,57 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT >=~ // + // ================================================================================ // + + void GreaterEqualTilde::declare() + { + if (!DataModel::has()) + { + OperatorTilde::declare(); + } + + std::unique_ptr greaterequal_class(new ObjectClass(">=~", &GreaterEqualTilde::create)); + + flip::Class & greaterequal_model = DataModel::declare() + .name(greaterequal_class->getModelName().c_str()) + .inherit(); + + Factory::add(std::move(greaterequal_class), greaterequal_model); + } + + std::unique_ptr GreaterEqualTilde::create(std::vector const& args) + { + return std::make_unique(args); + } + + GreaterEqualTilde::GreaterEqualTilde(std::vector const& args): + OperatorTilde(args) + { + } + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_GreaterEqualTilde.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_GreaterEqualTilde.h new file mode 100755 index 00000000..0f892801 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_GreaterEqualTilde.h @@ -0,0 +1,45 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT >=~ // + // ================================================================================ // + + class GreaterEqualTilde : public OperatorTilde + { + public: + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + + GreaterEqualTilde(flip::Default& d): OperatorTilde(d){}; + + GreaterEqualTilde(std::vector const& args); + }; + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h index d732e9ec..248b5a1a 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h @@ -66,3 +66,4 @@ #include #include #include +#include From b0f013eddd73c26923d735748b94ea5e66ee0455 Mon Sep 17 00:00:00 2001 From: jean-millot Date: Wed, 22 Nov 2017 18:42:47 +0100 Subject: [PATCH 095/148] Object comment. --- Client/Source/KiwiApp.cpp | 2 + .../KiwiApp_Objects/KiwiApp_CommentView.cpp | 137 ++++++++++++++++++ .../KiwiApp_Objects/KiwiApp_CommentView.h | 85 +++++++++++ .../KiwiApp_Objects/KiwiApp_Objects.h | 1 + .../KiwiEngine_Objects/KiwiEngine_Comment.cpp | 56 +++++++ .../KiwiEngine_Objects/KiwiEngine_Comment.h | 47 ++++++ .../KiwiEngine_Objects/KiwiEngine_Objects.h | 1 + Modules/KiwiModel/KiwiModel_DataModel.cpp | 1 + .../KiwiModel_Objects/KiwiModel_Comment.cpp | 108 ++++++++++++++ .../KiwiModel_Objects/KiwiModel_Comment.h | 58 ++++++++ .../KiwiModel_Objects/KiwiModel_Objects.h | 1 + 11 files changed, 497 insertions(+) create mode 100644 Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_CommentView.cpp create mode 100644 Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_CommentView.h create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Comment.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Comment.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Comment.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Comment.h diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index 243ce843..94b23225 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -182,6 +182,7 @@ namespace kiwi engine::LessEqualTilde::declare(); engine::GreaterEqual::declare(); engine::GreaterEqualTilde::declare(); + engine::Comment::declare(); } void KiwiApp::declareObjectViews() @@ -191,6 +192,7 @@ namespace kiwi ToggleView::declare(); MeterTildeView::declare(); MessageView::declare(); + CommentView::declare(); } void KiwiApp::shutdown() diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_CommentView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_CommentView.cpp new file mode 100644 index 00000000..e6f27c81 --- /dev/null +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_CommentView.cpp @@ -0,0 +1,137 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include +#include + +namespace kiwi { + + // ================================================================================ // + // COMMENT VIEW // + // ================================================================================ // + + void CommentView::declare() + { + Factory::add("comment", &CommentView::create); + } + + std::unique_ptr CommentView::create(model::Object & object_model) + { + return std::make_unique(object_model); + } + + CommentView::CommentView(model::Object & object_model) : + EditableObjectView(object_model) + { + setColour(ObjectView::ColourIds::Background, juce::Colours::transparentWhite); + + juce::Label & label = getLabel(); + + label.setText(object_model.getAttribute("text")[0].getString(), + juce::NotificationType::dontSendNotification); + + label.setColour(juce::Label::backgroundColourId, findColour(ObjectView::ColourIds::Background)); + label.setColour(juce::Label::backgroundWhenEditingColourId, + findColour(ObjectView::ColourIds::Background)); + label.setColour(juce::Label::textColourId, findColour(ObjectView::ColourIds::Text)); + label.setColour(juce::Label::textWhenEditingColourId, findColour(ObjectView::ColourIds::Text)); + + addAndMakeVisible(label); + } + + CommentView::~CommentView() + { + } + + void CommentView::paintOverChildren (juce::Graphics& g) + { + g.setColour (findColour (ObjectView::ColourIds::Outline)); + + drawOutline(g); + } + + void CommentView::resized() + { + getLabel().setBounds(getLocalBounds()); + } + + void CommentView::textEditorTextChanged(juce::TextEditor& editor) + { + setSize(std::max(editor.getTextWidth() + 16, 40), editor.getTextHeight()); + } + + void CommentView::attributeChanged(std::string const& name, tool::Parameter const& param) + { + if (name == "text") + { + getLabel().setText(param[0].getString(), juce::NotificationType::dontSendNotification); + } + } + + void CommentView::textChanged() + { + model::Object & model = getModel(); + + model.setWidth(getWidth()); + + model.setHeight(getHeight()); + + setAttribute("text", tool::Parameter(tool::Parameter::Type::String, + {getLabel().getText().toStdString()})); + } + + juce::TextEditor* CommentView::createdTextEditor() + { + juce::TextEditor * editor = new juce::TextEditor(); + + editor->setBounds(getLocalBounds()); + editor->setBorder(juce::BorderSize(0)); + + + editor->setColour(juce::TextEditor::ColourIds::textColourId, + getLabel().findColour(juce::Label::textWhenEditingColourId)); + + editor->setColour(juce::TextEditor::backgroundColourId, + getLabel().findColour(juce::Label::backgroundWhenEditingColourId)); + + editor->setColour(juce::TextEditor::highlightColourId, + findColour(ObjectView::ColourIds::Highlight, true).withAlpha(0.4f)); + + + editor->setColour(juce::TextEditor::outlineColourId, + juce::Colours::transparentWhite); + + editor->setColour(juce::TextEditor::focusedOutlineColourId, + juce::Colours::transparentWhite); + + editor->setScrollbarsShown(false); + editor->setScrollToShowCursor(true); + editor->setReturnKeyStartsNewLine(true); + editor->setMultiLine(true, true); + editor->setInterceptsMouseClicks(true, false); + + editor->addListener(this); + + return editor; + } +} diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_CommentView.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_CommentView.h new file mode 100644 index 00000000..47f5d28c --- /dev/null +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_CommentView.h @@ -0,0 +1,85 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +#include + +#include + +namespace kiwi { + + // ================================================================================ // + // COMMENT VIEW // + // ================================================================================ // + + //! @brief The view of any textual kiwi object. + class CommentView : public EditableObjectView, + public juce::TextEditor::Listener + { + public: // methods + + // @brief The declaration method. + static void declare(); + + //! @brief Creation method. + static std::unique_ptr create(model::Object & object_model); + + //! @brief Constructor. + CommentView(model::Object & object_model); + + //! @brief Destructor. + ~CommentView(); + + private: // methods + + //! @brief Called when the object is resized. + void resized() override final; + + //! @brief Called when the text is being typed. + //! @details Used to resize in order to keep text visible. + void textEditorTextChanged(juce::TextEditor& editor) override final; + + //! @brief Paints elements over the text editor. + void paintOverChildren (juce::Graphics& g) override final; + + //! @brief Called whenever one of the object's attribute has changed. + void attributeChanged(std::string const& name, tool::Parameter const& param) override final; + + //! @brief Called when the label text has changed. + //! @details Overrides EditableObjectView::textChanged. + void textChanged() override final; + + //! @brief Constructs the label's text editor. + //! @details Overrides EditableOjectView::createTextEditor. + juce::TextEditor* createdTextEditor() override final; + + private: // deleted methods + + CommentView() = delete; + CommentView(CommentView const& other) = delete; + CommentView(CommentView && other) = delete; + CommentView& operator=(CommentView const& other) = delete; + CommentView& operator=(CommentView && other) = delete; + }; +} diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Objects.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Objects.h index abd82c2c..dbc60b64 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Objects.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Objects.h @@ -27,3 +27,4 @@ #include #include #include +#include diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Comment.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Comment.cpp new file mode 100644 index 00000000..d2ec91af --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Comment.cpp @@ -0,0 +1,56 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OBJECT COMMENT // + // ================================================================================ // + + void Comment::declare() + { + Factory::add("comment", &Comment::create); + } + + std::unique_ptr Comment::create(model::Object const& model, Patcher& patcher) + { + return std::make_unique(model, patcher); + } + + Comment::Comment(model::Object const& object_model, Patcher& patcher): + Object(object_model, patcher) + { + } + + + Comment::~Comment() + { + } + + void Comment::receive(size_t index, std::vector const& args) + { + } + +}} + diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Comment.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Comment.h new file mode 100644 index 00000000..24e9161e --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Comment.h @@ -0,0 +1,47 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OBJECT COMMENT // + // ================================================================================ // + + class Comment : public engine::Object + { + public: // methods + + Comment(model::Object const& model, Patcher& patcher); + + ~Comment(); + + void receive(size_t index, std::vector const& args) override final; + + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher& patcher); + }; + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h index 31e4922d..bad16655 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h @@ -67,3 +67,4 @@ #include #include #include +#include diff --git a/Modules/KiwiModel/KiwiModel_DataModel.cpp b/Modules/KiwiModel/KiwiModel_DataModel.cpp index 21a0f976..b8ad5adb 100644 --- a/Modules/KiwiModel/KiwiModel_DataModel.cpp +++ b/Modules/KiwiModel/KiwiModel_DataModel.cpp @@ -79,6 +79,7 @@ namespace kiwi model::LessEqualTilde::declare(); model::GreaterEqual::declare(); model::GreaterEqualTilde::declare(); + model::Comment::declare(); } void DataModel::init(std::function declare_object) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Comment.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Comment.cpp new file mode 100755 index 00000000..8ca1f580 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Comment.cpp @@ -0,0 +1,108 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT COMMENT // + // ================================================================================ // + + void Comment::declare() + { + // Objectclass + std::unique_ptr comment_class(new ObjectClass("comment", &Comment::create)); + + // Parameters + std::unique_ptr param_text(new ParameterClass(tool::Parameter::Type::String)); + + comment_class->addAttribute("text", std::move(param_text)); + + // Flags + comment_class->setFlag(ObjectClass::Flag::DefinedSize); + + // DataModel + flip::Class & comment_model = DataModel::declare() + .name(comment_class->getModelName().c_str()) + .inherit() + .member("comment_text"); + + Factory::add(std::move(comment_class), comment_model); + } + + std::unique_ptr Comment::create(std::vector const& args) + { + return std::make_unique(args); + } + + Comment::Comment(std::vector const& args): + Object(), + m_comment_text("") + { + if (args.size() > 0) + throw Error("comment too many arguments"); + + setMinWidth(20.); + setMinHeight(20.); + setWidth(40); + setHeight(20.); + } + + Comment::Comment(flip::Default& d): + Object(d), + m_comment_text("") + { + } + + void Comment::writeAttribute(std::string const& name, tool::Parameter const& parameter) + { + if (name == "text") + { + m_comment_text = parameter[0].getString(); + } + } + + void Comment::readAttribute(std::string const& name, tool::Parameter & parameter) const + { + std::string const& message = m_comment_text; + + parameter = tool::Parameter(tool::Parameter::Type::String, {message}); + } + + bool Comment::attributeChanged(std::string const& name) const + { + bool changed = false; + + if (name == "text" && m_comment_text.changed()) + { + changed = true; + } + + return changed; + } + + std::string Comment::getIODescription(bool is_inlet, size_t index) const + { + return ""; + } +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Comment.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Comment.h new file mode 100755 index 00000000..88c42b8e --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Comment.h @@ -0,0 +1,58 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT COMMENT // + // ================================================================================ // + + class Comment : public model::Object + { + public: // methods + + Comment(flip::Default& d); + + Comment(std::vector const& args); + + std::string getIODescription(bool is_inlet, size_t index) const override; + + void writeAttribute(std::string const& name, tool::Parameter const& parameter) override final; + + void readAttribute(std::string const& name, tool::Parameter & parameter) const override final; + + bool attributeChanged(std::string const& name) const override final; + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + + private: // members + + flip::String m_comment_text; + }; +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h index 248b5a1a..31eea9fd 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h @@ -67,3 +67,4 @@ #include #include #include +#include From 29206445f8857db40c7f4ed597db53f69e83e538 Mon Sep 17 00:00:00 2001 From: jean-millot Date: Thu, 23 Nov 2017 13:31:04 +0100 Subject: [PATCH 096/148] Object pack, unpack. --- Client/Source/KiwiApp.cpp | 2 + .../KiwiEngine_Objects/KiwiEngine_Objects.h | 2 + .../KiwiEngine_Objects/KiwiEngine_Pack.cpp | 86 +++++++++++++++ .../KiwiEngine_Objects/KiwiEngine_Pack.h | 55 +++++++++ .../KiwiEngine_Objects/KiwiEngine_Unpack.cpp | 104 ++++++++++++++++++ .../KiwiEngine_Objects/KiwiEngine_Unpack.h | 53 +++++++++ Modules/KiwiModel/KiwiModel_DataModel.cpp | 2 + .../KiwiModel_Objects/KiwiModel_Objects.h | 2 + .../KiwiModel_Objects/KiwiModel_Pack.cpp | 99 +++++++++++++++++ .../KiwiModel_Objects/KiwiModel_Pack.h | 51 +++++++++ .../KiwiModel_Objects/KiwiModel_Unpack.cpp | 100 +++++++++++++++++ .../KiwiModel_Objects/KiwiModel_Unpack.h | 47 ++++++++ 12 files changed, 603 insertions(+) create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Pack.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Pack.h create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Unpack.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Unpack.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Pack.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Pack.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Unpack.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Unpack.h diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index 94b23225..4af28f92 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -183,6 +183,8 @@ namespace kiwi engine::GreaterEqual::declare(); engine::GreaterEqualTilde::declare(); engine::Comment::declare(); + engine::Pack::declare(); + engine::Unpack::declare(); } void KiwiApp::declareObjectViews() diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h index bad16655..b0566989 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h @@ -68,3 +68,5 @@ #include #include #include +#include +#include diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Pack.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Pack.cpp new file mode 100644 index 00000000..34851de6 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Pack.cpp @@ -0,0 +1,86 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // PACK // + // ================================================================================ // + + void Pack::declare() + { + Factory::add("pack", &Pack::create); + } + + std::unique_ptr Pack::create(model::Object const& model, Patcher & patcher) + { + return std::make_unique(model, patcher); + } + + Pack::Pack(model::Object const& model, Patcher& patcher) : + Object(model, patcher), + m_list(model.getArguments()) + { + } + + void Pack::output_list() + { + send(0, m_list); + } + + void Pack::receive(size_t index, std::vector const& args) + { + if (args[0].getString() != "bang") + { + switch (m_list[index].getType()) + { + case tool::Atom::Type::Float: + { + m_list[index] = args[0].getFloat(); + break; + } + case tool::Atom::Type::Int: + { + m_list[index] = args[0].getInt(); + break; + } + case tool::Atom::Type::String: + { + m_list[index] = args[0].getString(); + break; + } + case tool::Atom::Type::Null: + { + break; + } + } + } + + if (index == 0 && args[0].isString() && args[0].getString() == "bang") + { + output_list(); + } + } + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Pack.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Pack.h new file mode 100644 index 00000000..b42a08bd --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Pack.h @@ -0,0 +1,55 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // PACK // + // ================================================================================ // + + class Pack : public engine::Object + { + public: + + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher & patcher); + + Pack(model::Object const& model, Patcher& patcher); + + ~Pack() = default; + + void receive(size_t index, std::vector const& args) override; + + private: + + void output_list(); + + private: + + std::vector m_list; + }; + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Unpack.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Unpack.cpp new file mode 100644 index 00000000..a2ea8e1a --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Unpack.cpp @@ -0,0 +1,104 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // UNPACK // + // ================================================================================ // + + void Unpack::declare() + { + Factory::add("unpack", &Unpack::create); + } + + std::unique_ptr Unpack::create(model::Object const& model, Patcher & patcher) + { + return std::make_unique(model, patcher); + } + + Unpack::Unpack(model::Object const& model, Patcher& patcher) : + Object(model, patcher), + m_list(model.getArguments()) + { + } + + void Unpack::output_list() + { + for (int i = m_list.size() - 1; i >= 0; --i) + { + send(i, {m_list[i]}); + } + } + + void Unpack::receive(size_t index, std::vector const& args) + { + if (args[0].getString() == "bang") + { + output_list(); + } + else + { + for (int i = std::max(m_list.size() - 1, args.size() - 1); i >= 0; --i) + { + if (args[i].getString() != "bang") + { + switch (m_list[i].getType()) + { + case tool::Atom::Type::Float: + { + m_list[i] = args[i].getFloat(); + send(i, {m_list[i]}); + break; + } + case tool::Atom::Type::Int: + { + m_list[i] = args[i].getInt(); + send(i, {m_list[i]}); + break; + } + case tool::Atom::Type::String: + { + if (args[i].isString()) + { + m_list[i] = args[i].getString(); + send(i, {m_list[i]}); + } + break; + } + case tool::Atom::Type::Null: + { + break; + } + } + } + else if (i > 0) + { + warning("unpack list element " + std::to_string(i) + " bang not taken into account"); + } + } + } + } + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Unpack.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Unpack.h new file mode 100644 index 00000000..cf58e369 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Unpack.h @@ -0,0 +1,53 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // UNPACK // + // ================================================================================ // + + class Unpack : public engine::Object + { + public: + + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher & patcher); + + Unpack(model::Object const& model, Patcher& patcher); + + ~Unpack() = default; + + void receive(size_t index, std::vector const& args) override; + + void output_list(); + + private: + + std::vector m_list; + }; + +}} diff --git a/Modules/KiwiModel/KiwiModel_DataModel.cpp b/Modules/KiwiModel/KiwiModel_DataModel.cpp index b8ad5adb..02225485 100644 --- a/Modules/KiwiModel/KiwiModel_DataModel.cpp +++ b/Modules/KiwiModel/KiwiModel_DataModel.cpp @@ -80,6 +80,8 @@ namespace kiwi model::GreaterEqual::declare(); model::GreaterEqualTilde::declare(); model::Comment::declare(); + model::Pack::declare(); + model::Unpack::declare(); } void DataModel::init(std::function declare_object) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h index 31eea9fd..37fa5652 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h @@ -68,3 +68,5 @@ #include #include #include +#include +#include diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Pack.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Pack.cpp new file mode 100755 index 00000000..385bc163 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Pack.cpp @@ -0,0 +1,99 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // PACK // + // ================================================================================ // + + void Pack::declare() + { + std::unique_ptr pack_class(new ObjectClass("pack", &Pack::create)); + + flip::Class & pack_model = DataModel::declare() + .name(pack_class->getModelName().c_str()) + .inherit(); + + Factory::add(std::move(pack_class), pack_model); + } + + std::unique_ptr Pack::create(std::vector const& args) + { + return std::make_unique(args); + } + + Pack::Pack(std::vector const& args) + { + pushOutlet({PinType::IType::Control}); + + for(size_t i = 0; i < args.size(); ++i) + { + pushInlet({PinType::IType::Control}); + } + } + + std::string Pack::getIODescription(bool is_inlet, size_t index) const + { + if(!is_inlet) + { + return "Combined list from input"; + } + else if (is_inlet) + { + std::vector const& args = getArguments(); + + std::string type = ""; + + switch (args[index].getType()) + { + case tool::Atom::Type::Float: + { + type = "float"; + break; + } + case tool::Atom::Type::Int: + { + type = "int"; + break; + } + case tool::Atom::Type::String: + { + type = "symbol"; + break; + } + case tool::Atom::Type::Null: + { + type = "void"; + break; + } + } + + return type + "to be element" + std::to_string(index + 1) + " int list"; + } + + return {}; + } + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Pack.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Pack.h new file mode 100755 index 00000000..52744825 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Pack.h @@ -0,0 +1,51 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // PACK // + // ================================================================================ // + + class Pack : public model::Object + { + public: + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + + Pack(flip::Default& d) : model::Object(d) {} + + Pack(std::vector const& args); + + std::string getIODescription(bool is_inlet, size_t index) const override; + + private: // methods + + static std::string getTypeDescription(tool::Atom const& atom); + }; + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Unpack.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Unpack.cpp new file mode 100755 index 00000000..5c89789a --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Unpack.cpp @@ -0,0 +1,100 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // UNPACK // + // ================================================================================ // + + void Unpack::declare() + { + std::unique_ptr unpack_class(new ObjectClass("unpack", &Unpack::create)); + + flip::Class & unpack_model = DataModel::declare() + .name(unpack_class->getModelName().c_str()) + .inherit(); + + Factory::add(std::move(unpack_class), unpack_model); + } + + std::unique_ptr Unpack::create(std::vector const& args) + { + return std::make_unique(args); + } + + Unpack::Unpack(std::vector const& args) + { + pushInlet({PinType::IType::Control}); + + for(size_t i = 0; i < args.size(); ++i) + { + pushOutlet(PinType::IType::Control); + } + } + + std::string Unpack::getIODescription(bool is_inlet, size_t index) const + { + if(is_inlet) + { + return "list to be unpacked"; + } + else + { + std::vector const& args = getArguments(); + + std::string type = ""; + + switch (args[index].getType()) + { + case tool::Atom::Type::Float: + { + type = "float"; + break; + } + case tool::Atom::Type::Int: + { + type = "int"; + break; + } + case tool::Atom::Type::String: + { + type = "symbol"; + break; + } + case tool::Atom::Type::Null: + { + type = "void"; + break; + } + } + + return "element " + std::to_string(index + 1) + " in list of type " + type; + } + + + return {}; + } + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Unpack.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Unpack.h new file mode 100755 index 00000000..a8a40a1f --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Unpack.h @@ -0,0 +1,47 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // UNPACK // + // ================================================================================ // + + class Unpack : public model::Object + { + public: + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + + Unpack(flip::Default& d) : model::Object(d) {} + + Unpack(std::vector const& args); + + std::string getIODescription(bool is_inlet, size_t index) const override; + }; + +}} From 47503d5e5df23d801b0d80bb0a39f6d9a9234fd9 Mon Sep 17 00:00:00 2001 From: jean-millot Date: Thu, 23 Nov 2017 16:17:12 +0100 Subject: [PATCH 097/148] Object random. --- Client/Source/KiwiApp.cpp | 1 + .../KiwiEngine_Objects/KiwiEngine_Objects.h | 1 + .../KiwiEngine_Objects/KiwiEngine_Random.cpp | 110 ++++++++++++++++++ .../KiwiEngine_Objects/KiwiEngine_Random.h | 58 +++++++++ Modules/KiwiModel/KiwiModel_DataModel.cpp | 1 + .../KiwiModel_Objects/KiwiModel_Objects.h | 1 + .../KiwiModel_Objects/KiwiModel_Random.cpp | 94 +++++++++++++++ .../KiwiModel_Objects/KiwiModel_Random.h | 47 ++++++++ 8 files changed, 313 insertions(+) create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Random.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Random.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Random.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Random.h diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index 4af28f92..0453fb98 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -185,6 +185,7 @@ namespace kiwi engine::Comment::declare(); engine::Pack::declare(); engine::Unpack::declare(); + engine::Random::declare(); } void KiwiApp::declareObjectViews() diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h index b0566989..67390769 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h @@ -70,3 +70,4 @@ #include #include #include +#include diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Random.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Random.cpp new file mode 100644 index 00000000..00be1729 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Random.cpp @@ -0,0 +1,110 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // RANDOM // + // ================================================================================ // + + void Random::declare() + { + Factory::add("random", &Random::create); + } + + std::unique_ptr Random::create(model::Object const& model, Patcher & patcher) + { + return std::make_unique(model, patcher); + } + + Random::Random(model::Object const& model, Patcher& patcher): + Object(model, patcher), + m_random_generator(), + m_random_distribution(0, 100) + { + m_random_generator.seed(1); + + std::vector const& args = model.getArguments(); + + if (args.size() > 0 && args[0].isNumber()) + { + setRange(args[0].getInt()); + } + + if (args.size() > 1 && args[1].isNumber()) + { + setSeed(args[1].getInt()); + } + } + + void Random::receive(size_t index, std::vector const& args) + { + if (index == 0) + { + if (args[0].isString() && args[0].getString() == "bang") + { + send(0, {m_random_distribution(m_random_generator)}); + } + else + { + warning("random inlet 1 only understand bang"); + } + } + else if (index == 1) + { + if (args[0].isNumber()) + { + setRange(args[0].getInt()); + } + else + { + warning("random inlet 2 only understand numbers"); + } + } + else if (index == 2) + { + if (args[0].isNumber()) + { + setSeed(args[0].getInt()); + } + else + { + warning("random inlet 2 only understand numbers"); + } + } + } + + void Random::setRange(int range) + { + m_random_distribution.param(std::uniform_int_distribution::param_type(0, std::max(0, range))); + } + + void Random::setSeed(int seed) + { + m_random_generator.seed(); + } +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Random.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Random.h new file mode 100644 index 00000000..cd21fd12 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Random.h @@ -0,0 +1,58 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // RANDOM // + // ================================================================================ // + + class Random : public Object + { + public: // methods + + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher & patcher); + + Random(model::Object const& model, Patcher& patcher); + + void receive(size_t index, std::vector const& args) override final; + + private: // methods + + void setRange(int range); + + void setSeed(int new_seed); + + private: // members + + std::mt19937 m_random_generator; + std::uniform_int_distribution m_random_distribution; + }; + +}} diff --git a/Modules/KiwiModel/KiwiModel_DataModel.cpp b/Modules/KiwiModel/KiwiModel_DataModel.cpp index 02225485..bce02f8b 100644 --- a/Modules/KiwiModel/KiwiModel_DataModel.cpp +++ b/Modules/KiwiModel/KiwiModel_DataModel.cpp @@ -82,6 +82,7 @@ namespace kiwi model::Comment::declare(); model::Pack::declare(); model::Unpack::declare(); + model::Random::declare(); } void DataModel::init(std::function declare_object) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h index 37fa5652..95110939 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h @@ -70,3 +70,4 @@ #include #include #include +#include diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Random.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Random.cpp new file mode 100755 index 00000000..b1e45c5b --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Random.cpp @@ -0,0 +1,94 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // RANDOM // + // ================================================================================ // + + void Random::declare() + { + std::unique_ptr random_class(new ObjectClass("random", &Random::create)); + + flip::Class & random_model = DataModel::declare().name(random_class->getModelName().c_str()).inherit(); + + Factory::add(std::move(random_class), random_model); + } + + std::unique_ptr Random::create(std::vector const& args) + { + return std::make_unique(args); + } + + Random::Random(std::vector const& args) + { + if (args.size() > 2) + { + throw Error("random too many arguments"); + } + + if (args.size() > 1 && !args[1].isNumber()) + { + throw Error("random seed argument must be a number"); + } + + if (args.size() > 0 && !args[0].isNumber()) + { + throw Error("random range argument must be a number"); + } + + pushInlet({PinType::IType::Control}); + pushInlet({PinType::IType::Control}); + pushInlet({PinType::IType::Control}); + + pushOutlet(PinType::IType::Control); + } + + std::string Random::getIODescription(bool is_inlet, size_t index) const + { + if (is_inlet) + { + if (index == 0) + { + return "bang causes random number generation"; + } + else if (index == 1) + { + return "Sets the range"; + } + else if (index == 2) + { + return "Sets the seed"; + } + } + else + { + return "Ouputs ramdom number"; + } + + return ""; + } + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Random.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Random.h new file mode 100755 index 00000000..ab5eb6e7 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Random.h @@ -0,0 +1,47 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // RANDOM // + // ================================================================================ // + + class Random : public model::Object + { + public: + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + + Random(flip::Default& d): model::Object(d){}; + + Random(std::vector const& args); + + std::string getIODescription(bool is_inlet, size_t index) const override; + }; + +}} From 8e079386e39fa9901a0ef1750d268f737bb44ff3 Mon Sep 17 00:00:00 2001 From: jean-millot Date: Thu, 23 Nov 2017 17:25:56 +0100 Subject: [PATCH 098/148] Object scale. --- Client/Source/KiwiApp.cpp | 1 + .../KiwiEngine_Objects/KiwiEngine_Objects.h | 1 + .../KiwiEngine_Objects/KiwiEngine_Scale.cpp | 136 ++++++++++++++++++ .../KiwiEngine_Objects/KiwiEngine_Scale.h | 57 ++++++++ Modules/KiwiModel/KiwiModel_DataModel.cpp | 1 + .../KiwiModel_Objects/KiwiModel_Objects.h | 1 + .../KiwiModel_Objects/KiwiModel_Scale.cpp | 114 +++++++++++++++ .../KiwiModel_Objects/KiwiModel_Scale.h | 47 ++++++ 8 files changed, 358 insertions(+) create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Scale.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Scale.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Scale.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Scale.h diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index 0453fb98..935fa857 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -186,6 +186,7 @@ namespace kiwi engine::Pack::declare(); engine::Unpack::declare(); engine::Random::declare(); + engine::Scale::declare(); } void KiwiApp::declareObjectViews() diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h index 67390769..1ad880ac 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h @@ -71,3 +71,4 @@ #include #include #include +#include diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Scale.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Scale.cpp new file mode 100644 index 00000000..bfb00a55 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Scale.cpp @@ -0,0 +1,136 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // SCALE // + // ================================================================================ // + + void Scale::declare() + { + Factory::add("scale", &Scale::create); + } + + std::unique_ptr Scale::create(model::Object const& model, Patcher & patcher) + { + return std::make_unique(model, patcher); + } + + Scale::Scale(model::Object const& model, Patcher& patcher): + Object(model, patcher) + { + std::vector const& args = model.getArguments(); + + if (args.size() > 3) + { + m_output_high = args[3].getFloat(); + } + + if (args.size() > 2) + { + m_output_low = args[2].getFloat(); + } + + if (args.size() > 1) + { + m_input_high = args[1].getFloat(); + } + + if (args.size() > 0) + { + m_input_low = args[0].getFloat(); + } + } + + void Scale::receive(size_t index, std::vector const& args) + { + if (index == 0) + { + if (args[0].isNumber()) + { + m_value = args[0].getFloat(); + send(0, {scaleValue()}); + } + else if (args[0].isString() && args[0].getString() == "bang") + { + send(0, {scaleValue()}); + } + else + { + warning("scale inlet 1 only understands numbers and bang"); + } + } + else if (index == 1) + { + if (args[0].isNumber()) + { + m_input_low = args[0].getFloat(); + } + else + { + warning("scale inlet 2 only understands numbers"); + } + } + else if(index == 2) + { + if (args[0].isNumber()) + { + m_input_high = args[0].getFloat(); + } + else + { + warning("scale inlet 3 only understands numbers"); + } + } + else if(index == 3) + { + if (args[0].isNumber()) + { + m_output_low = args[0].getFloat(); + } + else + { + warning("scale inlet 4 only understands numbers"); + } + } + else if(index == 4) + { + if (args[0].isNumber()) + { + m_output_high = args[0].getFloat(); + } + else + { + warning("scale inlet 5 only understands numbers"); + } + } + } + + float Scale::scaleValue() + { + return m_output_low + + ((m_output_high - m_output_low) / (m_input_high - m_input_low)) * (m_value - m_input_low); + } +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Scale.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Scale.h new file mode 100644 index 00000000..4a6af120 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Scale.h @@ -0,0 +1,57 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // SCALE // + // ================================================================================ // + + class Scale : public Object + { + public: // methods + + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher & patcher); + + Scale(model::Object const& model, Patcher& patcher); + + void receive(size_t index, std::vector const& args) override final; + + private: + + float scaleValue(); + + private: // members + + double m_value {0.}; + double m_input_low {0.}; + double m_input_high {1.}; + double m_output_low {0.}; + double m_output_high {1.}; + }; + +}} diff --git a/Modules/KiwiModel/KiwiModel_DataModel.cpp b/Modules/KiwiModel/KiwiModel_DataModel.cpp index bce02f8b..7314dc4f 100644 --- a/Modules/KiwiModel/KiwiModel_DataModel.cpp +++ b/Modules/KiwiModel/KiwiModel_DataModel.cpp @@ -83,6 +83,7 @@ namespace kiwi model::Pack::declare(); model::Unpack::declare(); model::Random::declare(); + model::Scale::declare(); } void DataModel::init(std::function declare_object) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h index 95110939..b5439be3 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h @@ -71,3 +71,4 @@ #include #include #include +#include diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Scale.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Scale.cpp new file mode 100755 index 00000000..b6764061 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Scale.cpp @@ -0,0 +1,114 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // SCALE // + // ================================================================================ // + + void Scale::declare() + { + std::unique_ptr scale_class(new ObjectClass("scale", &Scale::create)); + + flip::Class & scale_model = DataModel::declare().name(scale_class->getModelName().c_str()).inherit(); + + Factory::add(std::move(scale_class), scale_model); + } + + std::unique_ptr Scale::create(std::vector const& args) + { + return std::make_unique(args); + } + + Scale::Scale(std::vector const& args) + { + if (args.size() > 4) + { + throw Error("scale too manu arguments"); + } + + if (args.size() > 3 && !args[3].isNumber()) + { + throw Error("scale output high must be a number"); + } + + if (args.size() > 2 && !args[2].isNumber()) + { + throw Error("scale output low must be a number"); + } + + if (args.size() > 1 && !args[1].isNumber()) + { + throw Error("scale intput high must be a number "); + } + + if (args.size() > 0 && !args[0].isNumber()) + { + throw Error("scale input low must be a number"); + } + + pushInlet({PinType::IType::Control}); + pushInlet({PinType::IType::Control}); + pushInlet({PinType::IType::Control}); + pushInlet({PinType::IType::Control}); + pushInlet({PinType::IType::Control}); + + pushOutlet(PinType::IType::Control); + } + + std::string Scale::getIODescription(bool is_inlet, size_t index) const + { + if (is_inlet) + { + if (index == 0) + { + return "Number to be scaled"; + } + else if (index == 1) + { + return "Sets input low value"; + } + else if (index == 2) + { + return "Sets input high value"; + } + else if(index == 3) + { + return "Sets output low value"; + } + else if (index == 4) + { + return "Sets output high value"; + } + } + else + { + return "Ouputs the scaling result"; + } + + return ""; + } + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Scale.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Scale.h new file mode 100755 index 00000000..54b22a6e --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Scale.h @@ -0,0 +1,47 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // SCALE // + // ================================================================================ // + + class Scale : public model::Object + { + public: + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + + Scale(flip::Default& d): model::Object(d){}; + + Scale(std::vector const& args); + + std::string getIODescription(bool is_inlet, size_t index) const override; + }; + +}} From ad8e55b4fe3a126508e02a2f6666cf018bf0fc17 Mon Sep 17 00:00:00 2001 From: jean-millot Date: Mon, 27 Nov 2017 11:18:11 +0100 Subject: [PATCH 099/148] Add shortcut c for comment. --- Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp index 83712f01..4b2e67fd 100755 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp @@ -1871,6 +1871,7 @@ namespace kiwi commands.add(CommandIDs::newToggle); commands.add(CommandIDs::newSlider); commands.add(CommandIDs::newMessage); + commands.add(CommandIDs::newComment); commands.add(CommandIDs::zoomIn); commands.add(CommandIDs::zoomOut); @@ -2017,6 +2018,15 @@ namespace kiwi result.setActive(!isLocked()); break; } + case CommandIDs::newComment: + { + result.setInfo(TRANS("New Comment Box"), + TRANS("Add a new comment"), + CommandCategories::editing, 0); + result.addDefaultKeypress('c', juce::ModifierKeys::noModifiers); + result.setActive(!isLocked()); + break; + } case CommandIDs::newMessage: { result.setInfo(TRANS("New Message Box"), @@ -2097,6 +2107,7 @@ namespace kiwi case CommandIDs::newBang: { createObjectModel("bang", true); break; } case CommandIDs::newToggle: { createObjectModel("toggle", true); break; } case CommandIDs::newSlider: { createObjectModel("slider", true); break; } + case CommandIDs::newComment: { createObjectModel("comment", true); break; } case CommandIDs::newMessage: { createObjectModel("message", true); break; } case CommandIDs::zoomIn: { zoomIn(); break; } From ddd76daa696a9dd4daeead0511eaa6b04d25ff01 Mon Sep 17 00:00:00 2001 From: jean-millot Date: Mon, 4 Dec 2017 11:44:57 +0100 Subject: [PATCH 100/148] Adding object select. --- Client/Source/KiwiApp.cpp | 1 + .../KiwiEngine_Objects/KiwiEngine_Objects.h | 1 + .../KiwiEngine_Objects/KiwiEngine_Select.cpp | 84 +++++++++++++++++ .../KiwiEngine_Objects/KiwiEngine_Select.h | 53 +++++++++++ Modules/KiwiModel/KiwiModel_DataModel.cpp | 1 + .../KiwiModel_Objects/KiwiModel_Objects.h | 1 + .../KiwiModel_Objects/KiwiModel_Select.cpp | 90 +++++++++++++++++++ .../KiwiModel_Objects/KiwiModel_Select.h | 47 ++++++++++ 8 files changed, 278 insertions(+) create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Select.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Select.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Select.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Select.h diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index 935fa857..9aa88ba6 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -187,6 +187,7 @@ namespace kiwi engine::Unpack::declare(); engine::Random::declare(); engine::Scale::declare(); + engine::Select::declare(); } void KiwiApp::declareObjectViews() diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h index 1ad880ac..8e8984c1 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h @@ -72,3 +72,4 @@ #include #include #include +#include diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Select.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Select.cpp new file mode 100644 index 00000000..a345732b --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Select.cpp @@ -0,0 +1,84 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // SELECT // + // ================================================================================ // + + void Select::declare() + { + Factory::add(model, patcher); + } + + Select::Select(model::Object const& model, Patcher& patcher) : + Object(model, patcher), + m_list(model.getArguments()) + { + } + + void Select::receive(size_t index, std::vector const& args) + { + if (index == 0) + { + bool arg_found = false; + + for(size_t i = 0; i != m_list.size() && !arg_found; ++i) + { + if (args[0].isNumber()) + { + if (args[0].getFloat() == m_list[i].getFloat()) + { + send(i, {"bang"}); + arg_found = true; + } + } + else if(args[0].isString()) + { + if (args[0].getString() == m_list[i].getString()) + { + send(i, {"bang}"}); + arg_found = true; + } + } + } + + if (!arg_found) + { + send(m_list.size(), {"bang"}); + } + } + else + { + m_list[index - 1] = args[0]; + } + } + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Select.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Select.h new file mode 100644 index 00000000..f7b5091e --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Select.h @@ -0,0 +1,53 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // SELECT // + // ================================================================================ // + + class Select : public engine::Object + { + public: + + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher & patcher); + + Select(model::Object const& model, Patcher& patcher); + + ~Select() = default; + + void receive(size_t index, std::vector const& args) override; + + private: + + std::vector m_list; + }; + +}} diff --git a/Modules/KiwiModel/KiwiModel_DataModel.cpp b/Modules/KiwiModel/KiwiModel_DataModel.cpp index 7314dc4f..8190798d 100644 --- a/Modules/KiwiModel/KiwiModel_DataModel.cpp +++ b/Modules/KiwiModel/KiwiModel_DataModel.cpp @@ -84,6 +84,7 @@ namespace kiwi model::Unpack::declare(); model::Random::declare(); model::Scale::declare(); + model::Select::declare(); } void DataModel::init(std::function declare_object) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h index b5439be3..9503ca93 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h @@ -72,3 +72,4 @@ #include #include #include +#include diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Select.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Select.cpp new file mode 100755 index 00000000..7b29c6e0 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Select.cpp @@ -0,0 +1,90 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // SELECT // + // ================================================================================ // + + void Select::declare() + { + std::unique_ptr select_class(new ObjectClass("select", &Select::create)); + + flip::Class() + .name(select_class->getModelName().c_str()) + .inherit(); + + Factory::add(args); + } + + Select::Select(std::vector const& args) + { + pushInlet({PinType::IType::Control}); + + for(size_t i = 0; i < args.size(); ++i) + { + pushOutlet(PinType::IType::Control); + pushInlet({PinType::IType::Control}); + } + + pushOutlet(PinType::IType::Control); + } + + std::string Select::getIODescription(bool is_inlet, size_t index) const + { + std::string description = ""; + + if (is_inlet) + { + if (index == 0) + { + description = "value to be tested"; + } + else + { + description = "sets value " + std::to_string(index) + " to be tested"; + } + } + else + { + if (index == getArguments().size()) + { + description = "ouptuts bang if input doesn't match"; + } + else + { + description = "outputs bang if input matches " + getArguments()[index].getString(); + } + } + + return description; + } + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Select.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Select.h new file mode 100755 index 00000000..d233f2ab --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Select.h @@ -0,0 +1,47 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // SELECT // + // ================================================================================ // + + class Select : public model::Object + { + public: + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + + Select(flip::Default& d) : model::Object(d) {} + + Select(std::vector const& args); + + std::string getIODescription(bool is_inlet, size_t index) const override; + }; + +}} From a620f9a754d37ff2ff5f4119690e5e3d93421243 Mon Sep 17 00:00:00 2001 From: jean-millot Date: Mon, 4 Dec 2017 15:43:00 +0100 Subject: [PATCH 101/148] Fix crash in mouse handler. --- .../KiwiApp_Patcher/KiwiApp_PatcherViewMouseHandler.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewMouseHandler.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewMouseHandler.cpp index 3f74ffbd..41337f03 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewMouseHandler.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewMouseHandler.cpp @@ -360,7 +360,7 @@ namespace kiwi } case Action::ObjectEdition: { - if (e.getMouseDownPosition() != e.getPosition()) + if (hit_tester.objectTouched() && e.getMouseDownPosition() != e.getPosition()) { startAction(Action::MoveObject, e); } @@ -368,16 +368,15 @@ namespace kiwi } case Action::SwitchSelection: { - if (e.getMouseDownPosition() != e.getPosition()) + if (hit_tester.objectTouched() && e.getMouseDownPosition() != e.getPosition()) { startAction(Action::MoveObject, e); } - break; } case Action::Selection: { - if (e.getMouseDownPosition() != e.getPosition()) + if (hit_tester.objectTouched() && e.getMouseDownPosition() != e.getPosition()) { startAction(Action::MoveObject, e); } From 4d7d99d9ff0adb4760c7531bf13232a4292fe19e Mon Sep 17 00:00:00 2001 From: jean-millot Date: Wed, 29 Nov 2017 17:53:23 +0100 Subject: [PATCH 102/148] Fix bug server same user connecting from different machines. --- Modules/KiwiServer/KiwiServer_Server.cpp | 68 ++++++++++++++++-------- 1 file changed, 46 insertions(+), 22 deletions(-) diff --git a/Modules/KiwiServer/KiwiServer_Server.cpp b/Modules/KiwiServer/KiwiServer_Server.cpp index 086675a7..86f9e608 100644 --- a/Modules/KiwiServer/KiwiServer_Server.cpp +++ b/Modules/KiwiServer/KiwiServer_Server.cpp @@ -148,11 +148,14 @@ namespace kiwi auto session = m_sessions.find(port.session()); - session->second.unbind(port); - - if (session->second.getConnectedUsers().empty()) + if (session != m_sessions.end()) { - m_sessions.erase(session); + session->second.unbind(port); + + if (session->second.getConnectedUsers().empty()) + { + m_sessions.erase(session); + } } } @@ -295,6 +298,22 @@ namespace kiwi if (authenticateUser(port.user(), port.metadata())) { + // disconnect client if already connected. + + std::set ports = m_document->ports(); + + std::set::iterator port_user = std::find_if(ports.begin(), + ports.end(), + [&port](flip::PortBase * const document_port) + { + return document_port->user() == port.user(); + }); + + if (port_user != ports.end()) + { + m_document->port_factory_remove(**port_user); + } + m_document->port_factory_add(port); m_document->port_greet(port); @@ -329,28 +348,33 @@ namespace kiwi DBG("[server] - User " << std::to_string(port.user()) << " disconnecting from session: " << hexadecimal_convert(m_identifier)); - model::Patcher& patcher = m_document->root(); - - m_document->send_signal_if(patcher.signal_user_disconnect.make(port.user()), - [](flip::PortBase& port) - { - return true; - }); - - m_document->port_factory_remove(port); + std::set ports = m_document->ports(); - if (m_document->ports().empty()) + if (ports.find(&port) != ports.end()) { - if(!m_backend_file.exists()) - { - m_backend_file.create(); - } + model::Patcher& patcher = m_document->root(); - DBG("[server] - Saving session : " << hexadecimal_convert(m_identifier) - << " in file : " - << m_backend_file.getFileName()); + m_document->send_signal_if(patcher.signal_user_disconnect.make(port.user()), + [](flip::PortBase& port) + { + return true; + }); + + m_document->port_factory_remove(port); - save(); + if (m_document->ports().empty()) + { + if(!m_backend_file.exists()) + { + m_backend_file.create(); + } + + DBG("[server] - Saving session : " << hexadecimal_convert(m_identifier) + << " in file : " + << m_backend_file.getFileName()); + + save(); + } } } From d3288020f879c048c82f2f55a4777f19dbf363cb Mon Sep 17 00:00:00 2001 From: jean-millot Date: Thu, 7 Dec 2017 10:56:07 +0100 Subject: [PATCH 103/148] Compiling kiwi for macos-10.7. --- .travis.yml | 1 + CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index cd57af96..e27e0fd7 100755 --- a/.travis.yml +++ b/.travis.yml @@ -77,6 +77,7 @@ matrix: - os: osx compiler: clang++ env: COMPILER=clang++ + osx_image: xcode9.2 install: - git submodule update --init --recursive ThirdParty/Juce ThirdParty/concurrentqueue ThirdParty/Beast diff --git a/CMakeLists.txt b/CMakeLists.txt index e19c49ec..047388b8 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -59,7 +59,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) # IDE Settings #-------------------------------------- -set(CMAKE_OSX_DEPLOYMENT_TARGET 10.8) +set(CMAKE_OSX_DEPLOYMENT_TARGET 10.7) set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LANGUAGE_STANDARD "c++14") set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++") set(CMAKE_OSX_ARCHITECTURES "i386;x86_64") From c35fb271eb6256dfc363628970ad10da566bfc39 Mon Sep 17 00:00:00 2001 From: jean-millot Date: Tue, 12 Dec 2017 13:44:09 +0100 Subject: [PATCH 104/148] Fix message, click when locked. --- .../KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_MessageView.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_MessageView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_MessageView.cpp index 156397d3..ce5ab011 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_MessageView.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_MessageView.cpp @@ -54,7 +54,9 @@ namespace kiwi { label.setColour(juce::Label::backgroundWhenEditingColourId, findColour(ObjectView::ColourIds::Background)); label.setColour(juce::Label::textColourId, findColour(ObjectView::ColourIds::Text)); - label.setColour(juce::Label::textWhenEditingColourId, findColour(ObjectView::ColourIds::Text)); + label.setColour(juce::Label::textWhenEditingColourId, findColour(ObjectView::ColourIds::Text)); + + label.setInterceptsMouseClicks(false, false); addAndMakeVisible(label); } From 2c5fcd67345a55c3f8092991827e1c6e5185fadd Mon Sep 17 00:00:00 2001 From: jean-millot Date: Thu, 7 Dec 2017 12:13:03 +0100 Subject: [PATCH 105/148] Killing server flip saves sessions. --- Modules/KiwiServer/KiwiServer_Server.cpp | 28 ------------------- Modules/KiwiServer/KiwiServer_Server.h | 13 --------- Server/Source/Main.cpp | 34 ++++++++++++++++++++++-- Test/Server/test_Server.cpp | 3 --- 4 files changed, 32 insertions(+), 46 deletions(-) diff --git a/Modules/KiwiServer/KiwiServer_Server.cpp b/Modules/KiwiServer/KiwiServer_Server.cpp index 86f9e608..5b03f6c1 100644 --- a/Modules/KiwiServer/KiwiServer_Server.cpp +++ b/Modules/KiwiServer/KiwiServer_Server.cpp @@ -48,7 +48,6 @@ namespace kiwi const char* Server::kiwi_file_extension = "kiwi"; Server::Server(uint16_t port, std::string const& backend_directory) : - m_running(false), m_backend_directory(backend_directory), m_sessions(), m_socket(*this, port), @@ -74,33 +73,6 @@ namespace kiwi m_socket.process(); } - void Server::run() - { - if(!m_running) - { - flip::RunLoopTimer run_loop ([this] - { - process(); - return m_running.load(); - }, 0.02); - - m_running.store(true); - - run_loop.run(); - } - } - - void Server::stop() - { - m_running.store(false); - std::cout << "[server] - stopped" << std::endl; - } - - bool Server::isRunning() const noexcept - { - return m_running; - } - std::set Server::getSessions() const { std::set sessions; diff --git a/Modules/KiwiServer/KiwiServer_Server.h b/Modules/KiwiServer/KiwiServer_Server.h index b3b0bc89..69d63a93 100644 --- a/Modules/KiwiServer/KiwiServer_Server.h +++ b/Modules/KiwiServer/KiwiServer_Server.h @@ -66,18 +66,6 @@ namespace kiwi //! @brief Process the socket hence process all sessions. void process(); - //! @brief Run the server. - //! @details This will run a loop that call process regularly. - //! @see stop - void run(); - - //! @brief Stops the server. - //! @see Run, isRunning - void stop(); - - //! @brief Returns true if the server is running. - bool isRunning() const noexcept; - //! @brief Returns a list of sessions currenty opened. std::set getSessions() const; @@ -121,7 +109,6 @@ namespace kiwi private: // variables - std::atomic_bool m_running; juce::File m_backend_directory; std::map m_sessions; flip::PortTransportServerTcp m_socket; diff --git a/Server/Source/Main.cpp b/Server/Source/Main.cpp index 4d866a4b..9b813eba 100644 --- a/Server/Source/Main.cpp +++ b/Server/Source/Main.cpp @@ -19,12 +19,19 @@ ============================================================================== */ +#include +#include + +#include + #include #include #include "KiwiServer_CommandLineParser.h" #include +std::atomic server_stopped(false); + void showHelp() { std::cout << "Usage:\n"; @@ -32,11 +39,25 @@ void showHelp() std::cout << " -f set the json configuration file to use (needed). \n"; } +void on_interupt(int signal) +{ + server_stopped.store(true); +} + +void on_terminate(int signal) +{ + server_stopped.store(true); +} + int main(int argc, char const* argv[]) { using namespace kiwi; using nlohmann::json; + std::signal(SIGINT, on_interupt); // interupt, kill -2, Ctrl + C + + std::signal(SIGTERM, on_terminate); // terminate, kill (-15) + CommandLineParser cl_parser(argc, argv); if(cl_parser.hasOption("-h")) @@ -75,11 +96,20 @@ int main(int argc, char const* argv[]) try { - server::Server server(config["port"], config["backend_directory"]); + server::Server kiwi_server(config["port"], config["backend_directory"]); std::cout << "[server] - running on port " << config["port"] << std::endl; - server.run(); + flip::RunLoopTimer run_loop ([&kiwi_server] + { + kiwi_server.process(); + + return !server_stopped.load(); + }, 0.02); + + run_loop.run(); + + std::cout << "[server] - stopped" << std::endl; } catch(std::runtime_error const& e) { diff --git a/Test/Server/test_Server.cpp b/Test/Server/test_Server.cpp index 2d66f5ef..7fe52274 100755 --- a/Test/Server/test_Server.cpp +++ b/Test/Server/test_Server.cpp @@ -96,7 +96,6 @@ TEST_CASE("Server - Server", "[Server, Server]") CHECK(server->getSessions().count(987654)); // Killing server before client is disconnected. - server->stop(); server.reset(nullptr); // Client automatically disconnected from server. @@ -237,8 +236,6 @@ TEST_CASE("Server - Server", "[Server, Server]") while(carrier_1.is_connected() || !server.getSessions().empty()){carrier_1.process(); server.process();} - server.stop(); - juce::File backend ("./server_backend_test"); if (backend.exists()) From 1dc7a103b309dd5c4475b64bcee2d95d9665ff4d Mon Sep 17 00:00:00 2001 From: jmillot Date: Thu, 21 Dec 2017 23:46:15 +0100 Subject: [PATCH 106/148] Handle unexpected disconnection on client side. --- .../KiwiApp_Application/KiwiApp_Instance.cpp | 83 ++++++---- .../KiwiApp_Application/KiwiApp_Instance.h | 2 +- .../KiwiApp_Network/KiwiApp_CarrierSocket.cpp | 109 ++++++------- .../KiwiApp_Network/KiwiApp_CarrierSocket.h | 59 ++++--- .../KiwiApp_PatcherComponent.cpp | 27 ++++ .../KiwiApp_PatcherComponent.h | 40 +++-- .../KiwiApp_PatcherManager.cpp | 153 +++++++++++------- .../KiwiApp_Patcher/KiwiApp_PatcherManager.h | 25 +-- 8 files changed, 300 insertions(+), 198 deletions(-) diff --git a/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp b/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp index f7c1dc6a..69b68a8c 100644 --- a/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp +++ b/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp @@ -69,11 +69,34 @@ namespace kiwi { m_scheduler.process(); - for(auto patcher_manager = m_patcher_managers.begin(); - patcher_manager != m_patcher_managers.end(); - ++patcher_manager) - { - (*patcher_manager)->pull(); + for(auto manager = m_patcher_managers.begin(); manager != m_patcher_managers.end();) + { + bool keep_patcher = true; + + if ((*manager)->isRemote()) + { + (*manager)->pull(); + + if (!(*manager)->isRemote()) + { + keep_patcher + = (*manager)->getFirstWindow().showOkCancelBox(juce::AlertWindow::QuestionIcon, + "Connetion lost", + "Do you want to continue editing document \"" + + (*manager)->getDocumentName() +"\" offline", + "Ok", + "Cancel"); + } + } + + if (!keep_patcher) + { + manager = m_patcher_managers.erase(manager); + } + else + { + ++manager; + } } } @@ -102,7 +125,6 @@ namespace kiwi return false; } - manager.forceCloseAllWindows(); it = m_patcher_managers.erase(it); } else @@ -284,37 +306,36 @@ namespace kiwi return success; } - PatcherManager* Instance::openRemotePatcher(DocumentBrowser::Drive::DocumentSession& session) + void Instance::openRemotePatcher(DocumentBrowser::Drive::DocumentSession& session) { - auto mng_it = getPatcherManagerForSession(session); + auto mng_it = getPatcherManagerForSession(session); + if(mng_it != m_patcher_managers.end()) { PatcherManager& manager = *(mng_it->get()); manager.bringsFirstViewToFront(); - return &manager; - } - - auto manager_uptr = std::make_unique(*this); - - try - { - manager_uptr->connect(session); - } - catch(std::runtime_error &e) - { - KiwiApp::error(e.what()); - return nullptr; + } + else + { + auto manager_uptr = std::make_unique(*this); + + NetworkSettings& network_settings = getAppSettings().network(); + + if (manager_uptr->connect(network_settings.getHost(), network_settings.getSessionPort(), session)) + { + auto manager_it = m_patcher_managers.emplace(m_patcher_managers.end(), std::move(manager_uptr)); + PatcherManager& manager = *(manager_it->get()); + + if(manager.getNumberOfView() == 0) + { + manager.newView(); + } + } + else + { + KiwiApp::error("Failed to connect to the document [" + session.getName() + "]"); + } } - - auto manager_it = m_patcher_managers.emplace(m_patcher_managers.end(), std::move(manager_uptr)); - PatcherManager& manager = *(manager_it->get()); - - if(manager.getNumberOfView() == 0) - { - manager.newView(); - } - - return manager_it->get(); } void Instance::removePatcher(PatcherManager const& patcher_manager) diff --git a/Client/Source/KiwiApp_Application/KiwiApp_Instance.h b/Client/Source/KiwiApp_Application/KiwiApp_Instance.h index 0294623f..9591fad3 100644 --- a/Client/Source/KiwiApp_Application/KiwiApp_Instance.h +++ b/Client/Source/KiwiApp_Application/KiwiApp_Instance.h @@ -98,7 +98,7 @@ namespace kiwi bool closeAllPatcherWindows(); //! @brief Attempt to create a new patcher with document Session informations. - PatcherManager* openRemotePatcher(DocumentBrowser::Drive::DocumentSession& session); + void openRemotePatcher(DocumentBrowser::Drive::DocumentSession& session); //! @brief Brings the Application settings window to front. void showAppSettingsWindow(); diff --git a/Client/Source/KiwiApp_Network/KiwiApp_CarrierSocket.cpp b/Client/Source/KiwiApp_Network/KiwiApp_CarrierSocket.cpp index e724c53e..970f1052 100755 --- a/Client/Source/KiwiApp_Network/KiwiApp_CarrierSocket.cpp +++ b/Client/Source/KiwiApp_Network/KiwiApp_CarrierSocket.cpp @@ -31,99 +31,88 @@ namespace kiwi // CARRIER SOCKET // // ================================================================================ // - CarrierSocket::CarrierSocket(flip::DocumentBase& document, std::string const& host, uint16_t port, uint64_t session_id): - m_transport_socket(document, session_id, host, port) + CarrierSocket::CarrierSocket(flip::DocumentBase& document): + m_transport_socket(nullptr), + m_document(document), + m_state(State::Disconnected), + m_state_func(), + m_transfer_func() { - bindCallBacks(); } - void CarrierSocket::listenStateTransition(flip::CarrierBase::Transition state, flip::CarrierBase::Error error) + void CarrierSocket::onStateTransition(flip::CarrierBase::Transition transition, + flip::CarrierBase::Error error) { - switch(state) + if (transition == flip::CarrierBase::Transition::Disconnected) { - case flip::CarrierBase::Transition::Disconnected: - { - if (m_func_disonnected) {m_func_disonnected();} - break; - } - case flip::CarrierBase::Transition::Connecting: - { - break; - } - case flip::CarrierBase::Transition::Connected: - { - if (m_func_connected){m_func_connected();} - break; - } + m_state = State::Disconnected; } - } - - void CarrierSocket::listenTransferBackEnd(size_t cur, size_t total) - { - if (cur == total) + else if (transition == flip::CarrierBase::Transition::Connecting) { - if (m_func_loaded){m_func_loaded();} + m_state = State::Connecting; + } + else if (transition == flip::CarrierBase::Transition::Connected) + { + m_state = State::Connected; } - } - - void CarrierSocket::listenTransferTransaction(size_t cur, size_t total) - { - } - - void CarrierSocket::listenTransferSignal(size_t cur, size_t total) - { - } - - void CarrierSocket::bindCallBacks() - { - using namespace std::placeholders; // for _1, _2 etc. - - m_transport_socket.listen_state_transition(std::bind(&CarrierSocket::listenStateTransition, - this, _1, _2)); - - m_transport_socket.listen_transfer_backend(std::bind(&CarrierSocket::listenTransferBackEnd, - this, _1, _2)); - - m_transport_socket.listen_transfer_transaction(std::bind(&CarrierSocket::listenTransferTransaction, - this, _1, _2)); - m_transport_socket.listen_transfer_signal(std::bind(&CarrierSocket::listenTransferSignal, - this, _1, _2)); + if (m_state_func) + { + m_state_func(transition, error); + } } - void CarrierSocket::listenDisconnected(std::function func) + void CarrierSocket::onTransferBackend(size_t cur, size_t total) { - m_func_disonnected = func; + if (m_transfer_func) + { + m_transfer_func(cur, total); + } } - void CarrierSocket::listenConnected(std::function func) + void CarrierSocket::listenStateTransition(std::function call_back) { - m_func_connected = func; + m_state_func = call_back; } - void CarrierSocket::listenLoaded(std::function func) + + void CarrierSocket::listenTransferBackend(std::function call_back) { - m_func_loaded = func; + m_transfer_func = call_back; } void CarrierSocket::process() { - m_transport_socket.process(); + if (m_transport_socket != nullptr) + { + m_transport_socket->process(); + } } void CarrierSocket::disconnect() { - m_transport_socket.rebind("", 0); + m_transport_socket.reset(); } bool CarrierSocket::isConnected() const { - return m_transport_socket.is_connected(); + return m_transport_socket != nullptr && m_state == State::Connected; } - void CarrierSocket::connect(std::string const& host, uint16_t port) + void CarrierSocket::connect(std::string const& host, uint16_t port, uint64_t session_id) { - m_transport_socket.rebind(host, port); + m_transport_socket.reset(new flip::CarrierTransportSocketTcp(m_document, session_id, host, port)); + + m_transport_socket->listen_state_transition(std::bind(&CarrierSocket::onStateTransition, + this, + std::placeholders::_1, + std::placeholders::_2)); + + m_transport_socket->listen_transfer_backend(std::bind(&CarrierSocket::onTransferBackend, + this, + std::placeholders::_1, + std::placeholders::_2)); } CarrierSocket::~CarrierSocket() diff --git a/Client/Source/KiwiApp_Network/KiwiApp_CarrierSocket.h b/Client/Source/KiwiApp_Network/KiwiApp_CarrierSocket.h index e4438674..479eabb5 100755 --- a/Client/Source/KiwiApp_Network/KiwiApp_CarrierSocket.h +++ b/Client/Source/KiwiApp_Network/KiwiApp_CarrierSocket.h @@ -34,13 +34,28 @@ namespace kiwi //! @brief Class that encapsulate a TCP socket class CarrierSocket { + public: // classes + + using state_func_t = std::function ; + + using transfer_func_t = std::function ; + + private: // classes + + enum class State + { + Disconnected, + Connecting, + Connected + }; + public: // methods //! @brief Constructor - CarrierSocket(flip::DocumentBase& document, std::string const& host, uint16_t port, uint64_t session_id); + CarrierSocket(flip::DocumentBase& document); // @brief Connects the socket to a remote socket - void connect(std::string const& host, uint16_t port); + void connect(std::string const& host, uint16_t port, uint64_t session_id); //! @brief Stop the socket from processing and disconnect void disconnect(); @@ -51,42 +66,34 @@ namespace kiwi //! @brief Process the socket once void process(); - //! @brief Add a callback to be called once disconnected - void listenDisconnected(std::function func); + //! @brief Callback called when transition changes. + void listenStateTransition(state_func_t call_back); - //! @brief Add a callback to be called on connected - void listenConnected(std::function func); - - //! @brief Add a callback to be called once first load terminated - void listenLoaded(std::function func); + //! @brief Callback called receiving backend informations. + void listenTransferBackend(transfer_func_t call_back); //! @brief Stops processing ~CarrierSocket(); private: // methods - //! @brief Binds the encapsulated socket callbacks - void bindCallBacks(); - - //! @brief Called when connection transition happen - void listenStateTransition(flip::CarrierBase::Transition state, flip::CarrierBase::Error error); - - //! @brief Called during loading process - void listenTransferBackEnd(size_t cur, size_t total); - - //! @brief Called when receiving a transaction - void listenTransferTransaction(size_t cur, size_t total); + //! @brief Called when sockets state changed. + void onStateTransition(flip::CarrierBase::Transition transition, + flip::CarrierBase::Error error); - //! @brief Called when receiving a signal - void listenTransferSignal(size_t cur, size_t total); + //! @brief Called when the socket receives the backend. + //! @details cur represent the portion that has been downloaded yet. total is the total + //! amount of data that needs to be received. + void onTransferBackend(size_t cur, size_t total); private: // members - flip::CarrierTransportSocketTcp m_transport_socket; + std::unique_ptr m_transport_socket; + flip::DocumentBase & m_document; + State m_state; + state_func_t m_state_func; + transfer_func_t m_transfer_func; - std::function m_func_disonnected; - std::function m_func_connected; - std::function m_func_loaded; private: // deleted methods diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherComponent.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherComponent.cpp index 046b5b4a..be018639 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherComponent.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherComponent.cpp @@ -63,6 +63,13 @@ namespace kiwi g.fillAll(juce::Colour(0xff444444)); } + void PatcherToolbar::removeUsersIcon() + { + m_toolbar.removeToolbarItem(0); + m_toolbar.removeToolbarItem(0); + m_toolbar.repaint(); + } + PatcherToolbar::Factory::Factory(PatcherManager& patcher_manager) : m_patcher_manager(patcher_manager) { @@ -287,6 +294,11 @@ namespace kiwi ; } + void PatcherComponent::removeUsersIcon() + { + m_toolbar.removeUsersIcon(); + } + // ================================================================================ // // APPLICATION COMMAND TARGET // // ================================================================================ // @@ -328,6 +340,21 @@ namespace kiwi setVisible(true); } + void PatcherViewWindow::removeUsersIcon() + { + m_patcher_component.removeUsersIcon(); + } + + bool PatcherViewWindow::showOkCancelBox(juce::AlertWindow::AlertIconType icon_type, + std::string const& title, + std::string const& message, + std::string const& button_1, + std::string const& button_2) + { + return juce::AlertWindow::showOkCancelBox(icon_type, title, message, button_1, button_2, this); + } + + PatcherManager& PatcherViewWindow::getPatcherManager() { return m_patcher_component.usePatcherManager(); diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherComponent.h b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherComponent.h index ae9d5cf7..4d0f6901 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherComponent.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherComponent.h @@ -41,7 +41,10 @@ namespace kiwi void resized() override; //! @brief juce::Component::paint - void paint(juce::Graphics& g) override; + void paint(juce::Graphics& g) override; + + //! @brief Removes users icon. + void removeUsersIcon(); private: // classes @@ -49,14 +52,14 @@ namespace kiwi struct Factory : public juce::ToolbarItemFactory { Factory(PatcherManager& patcher_manager); - - enum ItemIds - { - lock_unlock = 1, - zoom_in = 2, - zoom_out = 3, - dsp_on_off = 4, - users = 5, + + enum ItemIds + { + lock_unlock = 1, + zoom_in = 2, + zoom_out = 3, + dsp_on_off = 4, + users = 5, }; void getAllToolbarItemIds(juce::Array& ids) override; @@ -156,7 +159,10 @@ namespace kiwi PatcherManager& usePatcherManager(); //! @brief juce::Component::paint - void paint(juce::Graphics& g) override; + void paint(juce::Graphics& g) override; + + //! @brief Removes the users icon from toolbar; + void removeUsersIcon(); // -------------------------------------------------------------------------------- // // APPLICATION COMMAND TARGET // @@ -182,7 +188,14 @@ namespace kiwi { public: // methods - PatcherViewWindow(PatcherManager& manager, PatcherView& patcherview); + PatcherViewWindow(PatcherManager& manager, PatcherView& patcherview); + + //! @brief Shows an modal window asking for user input. + bool showOkCancelBox(juce::AlertWindow::AlertIconType icon_type, + std::string const& title, + std::string const& message, + std::string const& button_1, + std::string const& button_2); void closeButtonPressed() override; @@ -190,7 +203,10 @@ namespace kiwi PatcherManager& getPatcherManager(); //! @brief returns the PatcherView. - PatcherView& getPatcherView(); + PatcherView& getPatcherView(); + + //! @brief Removes the connected users icon. Called once patcher disconnected. + void removeUsersIcon(); private: // variables diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.cpp index 7884c7f1..94ba05f6 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.cpp @@ -51,7 +51,7 @@ namespace kiwi m_document(model::DataModel::use(), *this, m_validator, m_instance.getUserId(), 'cicm', 'kpat'), m_file(), - m_socket(), + m_socket(m_document), m_need_saving_flag(false), m_session(nullptr) { @@ -59,7 +59,8 @@ namespace kiwi } PatcherManager::~PatcherManager() - { + { + forceCloseAllWindows(); disconnect(); } @@ -77,22 +78,51 @@ namespace kiwi { if (isRemote()) { - m_socket->process(); + m_socket.process(); model::DocumentManager::pull(getPatcher()); } } + + void PatcherManager::onStateTransition(flip::CarrierBase::Transition transition, + flip::CarrierBase::Error error) + { + if (transition == flip::CarrierBase::Transition::Disconnected) + { + model::Patcher & patcher = getPatcher(); + + patcher.setName(m_session->getName()); + model::DocumentManager::commit(patcher); + + m_session->useDrive().removeListener(*this); + m_session = nullptr; + + m_connected_users.clear(); + + m_listeners.call(&Listener::connectedUserChanged, *this); + + flip::Collection & views = getPatcher().useSelfUser().getViews(); + + for(auto & view : views) + { + view.entity().use().removeUsersIcon(); + + view.entity().use().updateWindowTitle(); + } + } + } void PatcherManager::disconnect() { if (isRemote()) - { - m_socket.reset(); - m_session->useDrive().removeListener(*this); - m_session = nullptr; + { + m_socket.disconnect(); } - } + } + - void PatcherManager::connect(DocumentBrowser::Drive::DocumentSession& session) + bool PatcherManager::connect(std::string const& host, + uint16_t port, + DocumentBrowser::Drive::DocumentSession& session) { disconnect(); @@ -122,54 +152,53 @@ namespace kiwi m_connected_users.clear(); m_connected_users.insert(users.begin(), users.end()); m_listeners.call(&Listener::connectedUserChanged, *this); - }); - - const auto& network_settings = getAppSettings().network(); - - std::unique_ptr socket(new CarrierSocket(m_document, - network_settings.getHost(), - network_settings.getSessionPort(), - session.getSessionId())); - - const auto init_time = std::chrono::steady_clock::now(); - - const std::chrono::duration time_out(2); - - while(!socket->isConnected() && std::chrono::steady_clock::now() - init_time < time_out) - { - socket->process(); - } - - if (socket->isConnected()) - { - bool loaded = false; - - socket->listenLoaded([&loaded](){loaded = true;}); - - while(!loaded) - { - socket->process(); - } - - socket->listenLoaded(std::function()); - } - else - { - throw std::runtime_error("Failed to connect to the document"); - } - - m_socket = std::move(socket); - - m_session = &session; - - m_session->useDrive().addListener(*this); - - model::DocumentManager::pull(patcher); - - patcher.useSelfUser(); - model::DocumentManager::commit(patcher); - - patcher.entity().use().sendLoadbang(); + }); + + m_socket.connect(host, port, session.getSessionId()); + + bool patcher_loaded = false; + + m_socket.listenTransferBackend([&patcher_loaded](size_t cur, size_t total) + { + patcher_loaded = cur == total; + + }); + + const auto init_time = std::chrono::steady_clock::now(); + + const std::chrono::duration time_out(2); + + while(!m_socket.isConnected() && std::chrono::steady_clock::now() - init_time < time_out) + { + m_socket.process(); + } + + while(!patcher_loaded && m_socket.isConnected()) + { + m_socket.process(); + } + + if (m_socket.isConnected() && patcher_loaded) + { + m_session = &session; + + m_session->useDrive().addListener(*this); + + m_socket.listenStateTransition([this](flip::CarrierBase::Transition state, + flip::CarrierBase::Error error) + { + onStateTransition(state, error); + }); + + model::DocumentManager::pull(patcher); + + patcher.useSelfUser(); + model::DocumentManager::commit(patcher); + + patcher.entity().use().sendLoadbang(); + } + + return m_socket.isConnected() && patcher_loaded; } void PatcherManager::readDocument() @@ -216,7 +245,7 @@ namespace kiwi bool PatcherManager::isRemote() const noexcept { - return m_socket != nullptr; + return m_socket.isConnected(); } uint64_t PatcherManager::getSessionId() const noexcept @@ -226,7 +255,7 @@ namespace kiwi std::string PatcherManager::getDocumentName() const { - return m_session ? m_session->getName() : ""; + return isRemote() ? m_session->getName() : getPatcher().getName(); } void PatcherManager::newView() @@ -416,6 +445,12 @@ namespace kiwi } return false; + } + + PatcherViewWindow & PatcherManager::getFirstWindow() + { + auto first_view = getPatcher().useSelfUser().getViews().begin(); + return (*first_view).entity().use(); } void PatcherManager::bringsFirstViewToFront() diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.h b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.h index 44da8a96..43d3bfc3 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.h @@ -38,7 +38,8 @@ namespace kiwi { class Instance; - class PatcherView; + class PatcherView; + class PatcherViewWindow; // ================================================================================ // // PATCHER MANAGER // @@ -62,7 +63,7 @@ namespace kiwi ~PatcherManager(); //! @brief Try to connect this patcher to a remote server. - void connect(DocumentBrowser::Drive::DocumentSession& session); + bool connect(std::string const& host, uint16_t port, DocumentBrowser::Drive::DocumentSession& session); //! @brief Pull changes from server if it is remote. void pull(); @@ -114,12 +115,12 @@ namespace kiwi //! @brief Brings the first patcher view to front. void bringsFirstViewToFront(); - //! @brief Force all windows to close without asking user to save document. - void forceCloseAllWindows(); - //! @brief Attempt to close all document windows, after asking user to save them if needed. //! @return True if all document have been closed, false if the user cancel the action. - bool askAllWindowsToClose(); + bool askAllWindowsToClose(); + + //! @brief Returns the first window of the patcher manager. + PatcherViewWindow & getFirstWindow(); //! @brief Close the window that contains a given patcherview. //! @details if it's the last patcher view, it will ask the user the save the document before closing if needed. @@ -138,9 +139,15 @@ namespace kiwi void documentChanged(DocumentBrowser::Drive::DocumentSession& doc) override; //! @brief Called when a document session has been removed. - void documentRemoved(DocumentBrowser::Drive::DocumentSession& doc) override; + void documentRemoved(DocumentBrowser::Drive::DocumentSession& doc) override; + + //! @brief Force all windows to close without asking user to save document. + void forceCloseAllWindows(); - private: + private: + + //! @internal Called from socket process to notify changing state. + void onStateTransition(flip::CarrierBase::Transition transition, flip::CarrierBase::Error error); //! @internal Write data into file. void writeDocument(); @@ -182,7 +189,7 @@ namespace kiwi model::PatcherValidator m_validator; flip::Document m_document; juce::File m_file; - std::unique_ptr m_socket; + CarrierSocket m_socket; bool m_need_saving_flag; DocumentBrowser::Drive::DocumentSession* m_session; From 9145efcb5fc562e4bac253263896d4a37a673aca Mon Sep 17 00:00:00 2001 From: jmillot Date: Wed, 13 Dec 2017 15:34:33 +0100 Subject: [PATCH 107/148] Checking latest release at lauch time. --- Client/Source/KiwiApp.cpp | 28 +++++++++++++++++- Client/Source/KiwiApp.h | 7 +++-- Client/Source/KiwiApp_Network/KiwiApp_Api.cpp | 29 +++++++++++++++++++ Client/Source/KiwiApp_Network/KiwiApp_Api.h | 4 +++ 4 files changed, 65 insertions(+), 3 deletions(-) diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index 9aa88ba6..3b008794 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -115,7 +115,9 @@ namespace kiwi m_api.reset(new Api(*m_api_controller)); m_instance = std::make_unique(); - m_command_manager->registerAllCommandsForTarget(this); + m_command_manager->registerAllCommandsForTarget(this); + + checkLatestRelease(); #if JUCE_MAC juce::PopupMenu macMainMenuPopup; @@ -322,6 +324,30 @@ namespace kiwi KiwiApp::use().m_api_controller->logout(); KiwiApp::commandStatusChanged(); } + } + + void KiwiApp::checkLatestRelease() + { + std::string current_version = getApplicationVersion().toStdString(); + + Api::CallbackFn on_success = [current_version](std::string const& latest_version) + { + KiwiApp::useInstance().useScheduler().schedule([current_version, latest_version]() + { + if (current_version.compare(latest_version) < 0) + { + juce::AlertWindow::showMessageBoxAsync(juce::AlertWindow::QuestionIcon, + "New release available" , + "Upgrading required to access remote documents.\n\n Please visit:\n https://github.com/Musicoll/Kiwi/releases"); + } + }); + }; + + Api::ErrorCallback on_fail =[](Api::Error error) + { + }; + + useApi().getLatestRelease(on_success, on_fail); } void KiwiApp::addApiConnectStatusListener(ApiConnectStatusListener& listener) diff --git a/Client/Source/KiwiApp.h b/Client/Source/KiwiApp.h index 25808887..5b6f099c 100644 --- a/Client/Source/KiwiApp.h +++ b/Client/Source/KiwiApp.h @@ -34,7 +34,7 @@ namespace ProjectInfo { const char* const projectName = "Kiwi"; - const char* const versionString = "0.1.0"; + const char* const versionString = "v0.1.0"; const int versionNumber = 0x010; } @@ -245,7 +245,10 @@ namespace kiwi void declareEngineObjects(); //! @internal Initializes gui specific objects. - void declareObjectViews(); + void declareObjectViews(); + + //! @internal Checks if current Kiwi version is the latest. Show popup if version not up to date. + void checkLatestRelease(); private: // members diff --git a/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp b/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp index 9f2eb7f3..99361daf 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp +++ b/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp @@ -27,6 +27,7 @@ namespace kiwi const std::string Api::Endpoint::login {Api::Endpoint::root + "/login"}; const std::string Api::Endpoint::documents {Api::Endpoint::root + "/documents"}; const std::string Api::Endpoint::users {Api::Endpoint::root + "/users"}; + const std::string Api::Endpoint::releases {Api::Endpoint::root + "/releases"}; std::string Api::Endpoint::document(std::string const& document_id) { @@ -228,6 +229,34 @@ namespace kiwi storeFuture(session->PutAsync(std::move(callback))); } + void Api::getLatestRelease(CallbackFn success_cb, ErrorCallback error_cb) + { + auto session = makeSession(Endpoint::releases + "/latest"); + + auto cb = [success = std::move(success_cb), + fail = std::move(error_cb)](Response res) + { + if (!res.error + && hasJsonHeader(res) + && res.result() == beast::http::status::ok) + { + const auto j = json::parse(res.body); + + if(j.is_object() && j.count("tag_name")) + { + std::string latest_release = j["tag_name"]; + success(latest_release); + } + } + else + { + fail(res); + } + }; + + storeFuture(session->GetAsync(std::move(cb))); + } + bool Api::hasJsonHeader(Response const& res) { return (res[beast::http::field::content_type] == "application/json; charset=utf-8"); diff --git a/Client/Source/KiwiApp_Network/KiwiApp_Api.h b/Client/Source/KiwiApp_Network/KiwiApp_Api.h index 3127b5d0..c8d1b185 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_Api.h +++ b/Client/Source/KiwiApp_Network/KiwiApp_Api.h @@ -103,6 +103,9 @@ namespace kiwi std::string const& new_name, Callback callback); + //! @brief Retrieves Kiwi's latest release as a string. ex: v0.1.0 + void getLatestRelease(CallbackFn success_cb, ErrorCallback error_cb); + public: // helper methods template @@ -120,6 +123,7 @@ namespace kiwi static const std::string login; static const std::string documents; static const std::string users; + static const std::string releases; static std::string document(std::string const& document_id); static std::string user(std::string const& user_id); From b5ef91b0ba3c8272e00dc32f85f3ffbb49719839 Mon Sep 17 00:00:00 2001 From: jmillot Date: Wed, 13 Dec 2017 16:11:13 +0100 Subject: [PATCH 108/148] Rejecting flip connection if data model differs. --- .../KiwiApp_Network/KiwiApp_CarrierSocket.cpp | 7 +++++-- .../Source/KiwiApp_Network/KiwiApp_CarrierSocket.h | 2 +- .../KiwiApp_Patcher/KiwiApp_PatcherManager.cpp | 7 +++++-- Modules/KiwiServer/KiwiServer_Server.cpp | 7 +++---- Test/Server/test_Server.cpp | 13 +++++++------ 5 files changed, 21 insertions(+), 15 deletions(-) diff --git a/Client/Source/KiwiApp_Network/KiwiApp_CarrierSocket.cpp b/Client/Source/KiwiApp_Network/KiwiApp_CarrierSocket.cpp index 970f1052..5792a403 100755 --- a/Client/Source/KiwiApp_Network/KiwiApp_CarrierSocket.cpp +++ b/Client/Source/KiwiApp_Network/KiwiApp_CarrierSocket.cpp @@ -100,9 +100,12 @@ namespace kiwi return m_transport_socket != nullptr && m_state == State::Connected; } - void CarrierSocket::connect(std::string const& host, uint16_t port, uint64_t session_id) + void CarrierSocket::connect(std::string const& host, + uint16_t port, + uint64_t session_id, + std::string & metadata) { - m_transport_socket.reset(new flip::CarrierTransportSocketTcp(m_document, session_id, host, port)); + m_transport_socket.reset(new flip::CarrierTransportSocketTcp(m_document, session_id, metadata, host, port)); m_transport_socket->listen_state_transition(std::bind(&CarrierSocket::onStateTransition, this, diff --git a/Client/Source/KiwiApp_Network/KiwiApp_CarrierSocket.h b/Client/Source/KiwiApp_Network/KiwiApp_CarrierSocket.h index 479eabb5..045f58ca 100755 --- a/Client/Source/KiwiApp_Network/KiwiApp_CarrierSocket.h +++ b/Client/Source/KiwiApp_Network/KiwiApp_CarrierSocket.h @@ -55,7 +55,7 @@ namespace kiwi CarrierSocket(flip::DocumentBase& document); // @brief Connects the socket to a remote socket - void connect(std::string const& host, uint16_t port, uint64_t session_id); + void connect(std::string const& host, uint16_t port, uint64_t session_id, std::string & metadata); //! @brief Stop the socket from processing and disconnect void disconnect(); diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.cpp index 94ba05f6..d50f317f 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.cpp @@ -26,7 +26,8 @@ #include #include -#include +#include +#include #include #include @@ -154,7 +155,9 @@ namespace kiwi m_listeners.call(&Listener::connectedUserChanged, *this); }); - m_socket.connect(host, port, session.getSessionId()); + std::string metadata = KIWI_MODEL_VERSION_STRING; + + m_socket.connect(host, port, session.getSessionId(), metadata); bool patcher_loaded = false; diff --git a/Modules/KiwiServer/KiwiServer_Server.cpp b/Modules/KiwiServer/KiwiServer_Server.cpp index 5b03f6c1..556c5427 100644 --- a/Modules/KiwiServer/KiwiServer_Server.cpp +++ b/Modules/KiwiServer/KiwiServer_Server.cpp @@ -28,6 +28,7 @@ #include #include +#include namespace kiwi { @@ -254,11 +255,9 @@ namespace kiwi m_document->commit(); } - bool Server::Session::authenticateUser(uint64_t user, std::string metadate) const + bool Server::Session::authenticateUser(uint64_t user, std::string metadata) const { - // @todo check token received in port metadata - - return true; + return metadata == KIWI_MODEL_VERSION_STRING; } void Server::Session::bind(flip::PortBase & port) diff --git a/Test/Server/test_Server.cpp b/Test/Server/test_Server.cpp index 7fe52274..09826dae 100755 --- a/Test/Server/test_Server.cpp +++ b/Test/Server/test_Server.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -43,7 +44,7 @@ TEST_CASE("Server - Server", "[Server, Server]") // Initializing document flip::Document document (kiwi::model::DataModel::use (), 123456789, 'appl', 'gui '); - flip::CarrierTransportSocketTcp carrier (document, 987654, "localhost", 9191); + flip::CarrierTransportSocketTcp carrier (document, 987654, KIWI_MODEL_VERSION_STRING, "localhost", 9191); // Client/Document connecting to server. while(!carrier.is_connected() || server.getSessions().empty()) @@ -83,7 +84,7 @@ TEST_CASE("Server - Server", "[Server, Server]") // Initializing document. flip::Document document (kiwi::model::DataModel::use (), 123456789, 'appl', 'gui '); - flip::CarrierTransportSocketTcp carrier (document, 987654, "localhost", 9191); + flip::CarrierTransportSocketTcp carrier (document, 987654, KIWI_MODEL_VERSION_STRING, "localhost", 9191); // Client/Document connecting to server. while(!carrier.is_connected() || server->getSessions().empty()) @@ -120,10 +121,10 @@ TEST_CASE("Server - Server", "[Server, Server]") // Initializing documents. flip::Document document_1 (kiwi::model::DataModel::use (), 123456789, 'appl', 'gui '); - flip::CarrierTransportSocketTcp carrier_1 (document_1, 987654, "localhost", 9191); + flip::CarrierTransportSocketTcp carrier_1 (document_1, 987654, KIWI_MODEL_VERSION_STRING, "localhost", 9191); flip::Document document_2 (kiwi::model::DataModel::use (), 123456789, 'appl', 'gui '); - flip::CarrierTransportSocketTcp carrier_2 (document_2, 987655, "localhost", 9191); + flip::CarrierTransportSocketTcp carrier_2 (document_2, 987655, KIWI_MODEL_VERSION_STRING, "localhost", 9191); // Client/Document connecting to server. while(!carrier_1.is_connected() || !carrier_2.is_connected() || server.getSessions().size() != 2) @@ -165,7 +166,7 @@ TEST_CASE("Server - Server", "[Server, Server]") // Initializing client 1 flip::Document document_1 (kiwi::model::DataModel::use (), 1, 'appl', 'gui '); - flip::CarrierTransportSocketTcp carrier_1 (document_1, 1234, "localhost", 9191); + flip::CarrierTransportSocketTcp carrier_1 (document_1, 1234, KIWI_MODEL_VERSION_STRING, "localhost", 9191); kiwi::model::Patcher& patcher_1 = document_1.root(); @@ -185,7 +186,7 @@ TEST_CASE("Server - Server", "[Server, Server]") // Initializing client 2 flip::Document document_2 (kiwi::model::DataModel::use (), 2, 'appl', 'gui '); - flip::CarrierTransportSocketTcp carrier_2 (document_2, 1234, "localhost", 9191); + flip::CarrierTransportSocketTcp carrier_2 (document_2, 1234, KIWI_MODEL_VERSION_STRING, "localhost", 9191); kiwi::model::Patcher& patcher_2 = document_2.root(); From b9da525ef630929acd8ab7d9add6d319d14777ca Mon Sep 17 00:00:00 2001 From: jmillot Date: Thu, 21 Dec 2017 22:33:29 +0100 Subject: [PATCH 109/148] Objects number and number~. --- Client/Source/KiwiApp.cpp | 8 +- .../KiwiApp_EditableObjectView.cpp | 15 +- .../KiwiApp_EditableObjectView.h | 9 +- .../KiwiApp_NumberTildeView.cpp | 65 ++++++++ .../KiwiApp_Objects/KiwiApp_NumberTildeView.h | 66 ++++++++ .../KiwiApp_Objects/KiwiApp_NumberView.cpp | 136 ++++++++++++++++ .../KiwiApp_Objects/KiwiApp_NumberView.h | 97 +++++++++++ .../KiwiApp_NumberViewBase.cpp | 152 ++++++++++++++++++ .../KiwiApp_Objects/KiwiApp_NumberViewBase.h | 96 +++++++++++ .../KiwiApp_Objects/KiwiApp_Objects.h | 2 + .../KiwiApp_PatcherViewMouseHandler.cpp | 8 +- .../KiwiEngine_Objects/KiwiEngine_Number.cpp | 107 ++++++++++++ .../KiwiEngine_Objects/KiwiEngine_Number.h | 56 +++++++ .../KiwiEngine_NumberTilde.cpp | 84 ++++++++++ .../KiwiEngine_NumberTilde.h | 62 +++++++ .../KiwiEngine_Objects/KiwiEngine_Objects.h | 4 +- Modules/KiwiModel/KiwiModel_DataModel.cpp | 4 +- .../KiwiModel_Objects/KiwiModel_Number.cpp | 100 ++++++++++++ .../KiwiModel_Objects/KiwiModel_Number.h | 54 +++++++ .../KiwiModel_NumberTilde.cpp | 97 +++++++++++ .../KiwiModel_Objects/KiwiModel_NumberTilde.h | 47 ++++++ .../KiwiModel_Objects/KiwiModel_Objects.h | 4 +- 22 files changed, 1259 insertions(+), 14 deletions(-) create mode 100644 Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_NumberTildeView.cpp create mode 100644 Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_NumberTildeView.h create mode 100644 Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_NumberView.cpp create mode 100644 Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_NumberView.h create mode 100644 Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_NumberViewBase.cpp create mode 100644 Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_NumberViewBase.h create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Number.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Number.h create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_NumberTilde.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_NumberTilde.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Number.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Number.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_NumberTilde.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_NumberTilde.h diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index 3b008794..861aa874 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -189,7 +189,9 @@ namespace kiwi engine::Unpack::declare(); engine::Random::declare(); engine::Scale::declare(); - engine::Select::declare(); + engine::Select::declare(); + engine::Number::declare(); + engine::NumberTilde::declare(); } void KiwiApp::declareObjectViews() @@ -199,7 +201,9 @@ namespace kiwi ToggleView::declare(); MeterTildeView::declare(); MessageView::declare(); - CommentView::declare(); + CommentView::declare(); + NumberView::declare(); + NumberTildeView::declare(); } void KiwiApp::shutdown() diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_EditableObjectView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_EditableObjectView.cpp index b3887573..8a632287 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_EditableObjectView.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_EditableObjectView.cpp @@ -29,7 +29,8 @@ namespace kiwi { EditableObjectView::EditableObjectView(model::Object & object_model) : ObjectView(object_model), - m_label(*this), + m_label(*this), + m_editable(true), m_listeners() { } @@ -37,10 +38,18 @@ namespace kiwi { EditableObjectView::~EditableObjectView() { } + + void EditableObjectView::setEditable(bool editable) + { + m_editable = editable; + } void EditableObjectView::edit() - { - m_label.showEditor(); + { + if (m_editable) + { + m_label.showEditor(); + } } void EditableObjectView::labelTextChanged (juce::Label* label) diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_EditableObjectView.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_EditableObjectView.h index e2601c93..7353cc31 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_EditableObjectView.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_EditableObjectView.h @@ -92,7 +92,11 @@ namespace kiwi protected: // methods //! @brief Returns the label created by the editable object. - juce::Label & getLabel(); + juce::Label & getLabel(); + + //! @brief Sets the editable object view as editable or not. + //! @details Editable object is editable by default. + void setEditable(bool editable); private: // methods @@ -116,7 +120,8 @@ namespace kiwi private: // members - Label m_label; + Label m_label; + bool m_editable; tool::Listeners m_listeners; private: // deleted methods diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_NumberTildeView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_NumberTildeView.cpp new file mode 100644 index 00000000..2ff4766f --- /dev/null +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_NumberTildeView.cpp @@ -0,0 +1,65 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { + + // ================================================================================ // + // NUMBER TILDE VIEW // + // ================================================================================ // + + void NumberTildeView::declare() + { + Factory::add("number~", &NumberTildeView::create); + } + + std::unique_ptr NumberTildeView::create(model::Object & object_model) + { + return std::make_unique(object_model); + } + + NumberTildeView::NumberTildeView(model::Object & object_model) : + NumberViewBase(object_model) + { + setEditable(false); + setIconColour(findColour(ObjectView::ColourIds::Active)); + setInterceptsMouseClicks(false, false); + } + + void NumberTildeView::parameterChanged(std::string const& name, tool::Parameter const& param) + { + if (name == "value") + { + setDisplayNumber(param[0].getFloat()); + } + } + + void NumberTildeView::displayNumberChanged(double new_number) + { + } + + NumberTildeView::~NumberTildeView() + { + } +} + diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_NumberTildeView.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_NumberTildeView.h new file mode 100644 index 00000000..aa043fbe --- /dev/null +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_NumberTildeView.h @@ -0,0 +1,66 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { + + // ================================================================================ // + // NUMBER TILDE VIEW // + // ================================================================================ // + + //! @brief The view of any textual kiwi object. + class NumberTildeView : public NumberViewBase + { + public: // methods + + // @brief The declaration method. + static void declare(); + + //! @brief Creation method. + static std::unique_ptr create(model::Object & object_model); + + //! @brief Constructor. + NumberTildeView(model::Object & object_model); + + //! @brief Destructor. + ~NumberTildeView(); + + private: // methods + + //! @brief Called when the displayed number has just changed. + void displayNumberChanged(double new_number) override final; + + //! @brief Called whenever one of the object's attribute has changed. + void parameterChanged(std::string const& name, tool::Parameter const& param) override final; + + private: // deleted methods + + NumberTildeView() = delete; + NumberTildeView(NumberTildeView const&) = delete; + NumberTildeView(NumberTildeView && other) = delete; + NumberTildeView& operator=(NumberTildeView const& other) = delete; + NumberTildeView& operator=(NumberTildeView && other) = delete; + }; +} + diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_NumberView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_NumberView.cpp new file mode 100644 index 00000000..5c6bb194 --- /dev/null +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_NumberView.cpp @@ -0,0 +1,136 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include +#include + +namespace kiwi { + + // ================================================================================ // + // NUMBER VIEW // + // ================================================================================ // + + void NumberView::declare() + { + Factory::add("number", &NumberView::create); + } + + std::unique_ptr NumberView::create(model::Object & object_model) + { + return std::make_unique(object_model); + } + + NumberView::NumberView(model::Object & object_model) : + NumberViewBase(object_model), + m_output_message(object_model.getSignal<>(model::Message::Signal::outputMessage)), + m_sensitivity(1), + m_mouse_info() + { + setIconColour(findColour(ObjectView::ColourIds::Outline)); + setInterceptsMouseClicks(true, true); + } + + NumberView::~NumberView() + { + } + + void NumberView::mouseDoubleClick(juce::MouseEvent const& e) + { + getLabel().showEditor(); + } + + void NumberView::mouseDown(juce::MouseEvent const& e) + { + e.source.enableUnboundedMouseMovement(true, true); + + m_mouse_info.m_mouse_down_value = getDisplayNumber(); + m_mouse_info.m_mouse_down_y = e.y; + + if (e.mods.isAltDown()) + { + m_mouse_info.m_is_alt_down = true; + m_mouse_info.m_alt_down_value = getDisplayNumber(); + m_mouse_info.m_alt_down_y = e.y; + } + } + + void NumberView::mouseDrag(juce::MouseEvent const& e) + { + if (e.getDistanceFromDragStartY() != 0) + { + double new_value = 0; + + if (!m_mouse_info.m_is_alt_down && e.mods.isAltDown()) + { + m_mouse_info.m_is_alt_down = true; + m_mouse_info.m_alt_down_value = getDisplayNumber(); + m_mouse_info.m_alt_down_y = e.y; + } + else if(m_mouse_info.m_is_alt_down && !e.mods.isAltDown()) + { + m_mouse_info.m_mouse_down_value = getDisplayNumber(); + m_mouse_info.m_mouse_down_y = e.y; + m_mouse_info.m_is_alt_down = false; + m_mouse_info.m_is_alt_down = 0; + m_mouse_info.m_alt_down_y = 0; + } + + if (e.mods.isAltDown()) + { + new_value = m_mouse_info.m_alt_down_value - (m_sensitivity * (e.y - m_mouse_info.m_alt_down_y)) / 100.; + } + else + { + new_value = m_mouse_info.m_mouse_down_value - m_sensitivity * (e.y - m_mouse_info.m_mouse_down_y); + } + + setParameter("value", tool::Parameter(tool::Parameter::Type::Float, {new_value})); + m_output_message(); + repaint(); + } + } + + void NumberView::mouseUp(juce::MouseEvent const& e) + { + m_mouse_info.m_mouse_down_value = 0; + m_mouse_info.m_mouse_down_y = 0; + m_mouse_info.m_is_alt_down = false; + m_mouse_info.m_alt_down_value = 0; + m_mouse_info.m_alt_down_y = 0; + } + + void NumberView::parameterChanged(std::string const& name, tool::Parameter const& param) + { + if (name == "value") + { + setDisplayNumber(param[0].getFloat()); + } + } + + void NumberView::displayNumberChanged(double number) + { + setParameter("value", tool::Parameter(tool::Parameter::Type::Float, {number})); + m_output_message(); + } +} + diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_NumberView.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_NumberView.h new file mode 100644 index 00000000..11a456f8 --- /dev/null +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_NumberView.h @@ -0,0 +1,97 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +#include + +namespace kiwi { + + // ================================================================================ // + // NUMBER VIEW // + // ================================================================================ // + + //! @brief The view of any textual kiwi object. + class NumberView : public NumberViewBase + { + private: // members + + struct MouseInfo + { + double m_mouse_down_value = 0; + int m_mouse_down_y = 0; + bool m_is_alt_down = false; + double m_alt_down_value = 0; + int m_alt_down_y = 0; + }; + + public: // methods + + // @brief The declaration method. + static void declare(); + + //! @brief Creation method. + static std::unique_ptr create(model::Object & object_model); + + //! @brief Constructor. + NumberView(model::Object & object_model); + + //! @brief Destructor. + ~NumberView(); + + private: // methods + + //! @brief Stores the initial value before draging. + void mouseDown(juce::MouseEvent const& e) override final; + + //! @brief Increment value depending on mouse position. + void mouseDrag(juce::MouseEvent const& e) override final; + + //! @brief Resets mouse information. + void mouseUp(juce::MouseEvent const& e) override final; + + //! @brief Edits the label. + void mouseDoubleClick(juce::MouseEvent const& e) override final; + + //! @brief Called whenever one of the object's attribute has changed. + void parameterChanged(std::string const& name, tool::Parameter const& param) override final; + + //! @brief Sets the parameter value. + void displayNumberChanged(double number) override final; + + private: // members + + flip::Signal<> & m_output_message; + int m_sensitivity; + MouseInfo m_mouse_info; + + private: // deleted methods + + NumberView() = delete; + NumberView(NumberView const& other) = delete; + NumberView(NumberView && other) = delete; + NumberView& operator=(NumberView const& other) = delete; + NumberView& operator=(NumberView && other) = delete; + }; +} + diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_NumberViewBase.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_NumberViewBase.cpp new file mode 100644 index 00000000..f62d1400 --- /dev/null +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_NumberViewBase.cpp @@ -0,0 +1,152 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include +#include + +namespace kiwi { + + // ================================================================================ // + // NUMBER VIEW BASE // + // ================================================================================ // + + NumberViewBase::NumberViewBase(model::Object & object_model) : + EditableObjectView(object_model), + m_value(0), + m_indent(9), + m_icon_colour(findColour (ObjectView::ColourIds::Outline)) + { + juce::Label & label = getLabel(); + + label.setText("0.", juce::NotificationType::dontSendNotification); + + label.setColour(juce::Label::backgroundColourId, findColour(ObjectView::ColourIds::Background)); + label.setColour(juce::Label::backgroundWhenEditingColourId, + findColour(ObjectView::ColourIds::Background)); + label.setColour(juce::Label::textColourId, findColour(ObjectView::ColourIds::Text)); + label.setColour(juce::Label::textWhenEditingColourId, findColour(ObjectView::ColourIds::Text)); + label.setMinimumHorizontalScale(1); + label.setInterceptsMouseClicks(false, false); + + addAndMakeVisible(label); + } + + NumberViewBase::~NumberViewBase() + { + } + + void NumberViewBase::paint(juce::Graphics & g) + { + g.fillAll(findColour(ObjectView::ColourIds::Background)); + } + + void NumberViewBase::paintOverChildren (juce::Graphics& g) + { + g.setColour (findColour (ObjectView::ColourIds::Outline)); + + drawOutline(g); + + juce::Path corner; + + g.setColour(m_icon_colour); + + juce::Rectangle triangle_bounds = getLocalBounds().withWidth(m_indent - 4).withHeight(getHeight() - 8).translated(2, 4); + + corner.addTriangle(triangle_bounds.getTopLeft().toFloat(), + triangle_bounds.getTopRight().toFloat() + juce::Point(0, (triangle_bounds.getHeight() / 2.)), + triangle_bounds.getBottomLeft().toFloat()); + + g.fillPath(corner); + } + + void NumberViewBase::resized() + { + juce::Rectangle label_bounds = getLocalBounds(); + label_bounds.removeFromLeft(m_indent); + getLabel().setBounds(label_bounds); + } + + void NumberViewBase::setIconColour(juce::Colour colour) + { + m_icon_colour = colour; + } + + double NumberViewBase::getDisplayNumber() const + { + return m_value; + } + + void NumberViewBase::setDisplayNumber(double number) + { + m_value = number; + + juce::String display_value(std::to_string(m_value)); + + display_value = display_value.trimCharactersAtEnd("0"); + + getLabel().setText(display_value, juce::NotificationType::dontSendNotification); + } + + void NumberViewBase::textChanged() + { + m_value = getLabel().getText().getFloatValue(); + + displayNumberChanged(m_value); + } + + juce::TextEditor* NumberViewBase::createdTextEditor() + { + juce::TextEditor * editor = new juce::TextEditor(); + + editor->setBounds(getLocalBounds()); + editor->setBorder(juce::BorderSize(0)); + + + editor->setColour(juce::TextEditor::ColourIds::textColourId, + getLabel().findColour(juce::Label::textWhenEditingColourId)); + + editor->setColour(juce::TextEditor::backgroundColourId, + getLabel().findColour(juce::Label::backgroundWhenEditingColourId)); + + editor->setColour(juce::TextEditor::highlightColourId, + findColour(ObjectView::ColourIds::Highlight, true).withAlpha(0.4f)); + + + editor->setColour(juce::TextEditor::outlineColourId, + juce::Colours::transparentWhite); + + editor->setColour(juce::TextEditor::focusedOutlineColourId, + juce::Colours::transparentWhite); + + editor->setScrollbarsShown(false); + editor->setScrollToShowCursor(true); + editor->setReturnKeyStartsNewLine(false); + editor->setMultiLine(true, false); + editor->setInterceptsMouseClicks(true, false); + + editor->setInputFilter(new juce::TextEditor::LengthAndCharacterRestriction(-1, "0123456789.-"), true); + + return editor; + } +} + diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_NumberViewBase.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_NumberViewBase.h new file mode 100644 index 00000000..8a03f84f --- /dev/null +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_NumberViewBase.h @@ -0,0 +1,96 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +#include + +namespace kiwi { + + // ================================================================================ // + // NUMBER VIEW BASE // + // ================================================================================ // + + //! @brief The view of any textual kiwi object. + class NumberViewBase : public EditableObjectView + { + public: // methods + + //! @brief Constructor. + NumberViewBase(model::Object & object_model); + + //! @brief Destructor. + ~NumberViewBase(); + + protected: // methods. + + //! @brief Sets the displayed text and call repaint. + void setDisplayNumber(double number); + + //! @brief Returns the displayed text as a number. + double getDisplayNumber() const; + + //! @brief Sets the triangle icon colour. + //! @details By default colour is outline colour. + void setIconColour(juce::Colour colour); + + private: // methods + + //! @brief Overrides this method to react to a change in display number. + virtual void displayNumberChanged(double number) = 0; + + private: // methods + + //! @brief Called when the object is resized. + void resized() override final; + + //! @brief Draw the background of the number object. + void paint(juce::Graphics& g) override final; + + //! @brief Paints elements over the text editor. + void paintOverChildren (juce::Graphics& g) override final; + + //! @brief Called when the label text has changed. + //! @details Overrides EditableObjectView::textChanged. + void textChanged() override final; + + //! @brief Constructs the label's text editor. + //! @details Overrides EditableOjectView::createTextEditor. + juce::TextEditor* createdTextEditor() override final; + + private: // members + + double m_value; + int m_indent; + juce::Colour m_icon_colour; + + private: // deleted methods + + NumberViewBase() = delete; + NumberViewBase(NumberViewBase const& other) = delete; + NumberViewBase(NumberViewBase && other) = delete; + NumberViewBase& operator=(NumberViewBase const& other) = delete; + NumberViewBase& operator=(NumberViewBase && other) = delete; + }; +} + diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Objects.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Objects.h index dbc60b64..ed8ccb35 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Objects.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_Objects.h @@ -28,3 +28,5 @@ #include #include #include +#include +#include diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewMouseHandler.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewMouseHandler.cpp index 41337f03..94abd1d3 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewMouseHandler.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherViewMouseHandler.cpp @@ -544,13 +544,13 @@ namespace kiwi { if(hit_tester.getZone() == HitTester::Zone::Inside) { - if(e.mods.isAltDown()) + if (e.mods.isCommandDown()) { - startAction(Action::CopyOnDrag, e); + startAction(Action::Object, e); } - else if (e.mods.isCommandDown()) + else if(e.mods.isAltDown()) { - startAction(Action::Object, e); + startAction(Action::CopyOnDrag, e); } else { diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Number.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Number.cpp new file mode 100644 index 00000000..e23738f0 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Number.cpp @@ -0,0 +1,107 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OBJECT NUMBER // + // ================================================================================ // + + void Number::declare() + { + Factory::add("number", &Number::create); + } + + std::unique_ptr Number::create(model::Object const& model, Patcher& patcher) + { + return std::make_unique(model, patcher); + } + + Number::Number(model::Object const& object_model, Patcher& patcher): + Object(object_model, patcher), + m_value(object_model.getParameter("value")[0].getFloat()), + m_connection(object_model.getSignal<>(model::Number::Signal::OutputValue) + .connect(std::bind(&Number::outputValue, this))) + { + } + + void Number::parameterChanged(std::string const& name, tool::Parameter const& parameter) + { + if (name == "value") + { + m_value = parameter[0].getFloat(); + } + } + + void Number::outputValue() + { + defer([this]() + { + send(0, {m_value}); + + }); + } + + void Number::receive(size_t index, std::vector const& args) + { + if (index == 0 && !args.empty()) + { + if (args[0].isNumber()) + { + send(0, {args[0].getFloat()}); + setParameter("value", tool::Parameter(tool::Parameter::Type::Float, {args[0].getFloat()})); + } + else if (args[0].isString()) + { + if (args[0].getString() == "bang") + { + outputValue(); + } + else if(args[0].getString() == "set") + { + if (args.size() > 1 && args[1].isNumber()) + { + setParameter("value", tool::Parameter(tool::Parameter::Type::Float, {args[1].getFloat()})); + } + else + { + warning("number, \"set\" must be followed by a number"); + } + } + else + { + warning("number doesn't understand symbol " + args[0].getString()); + } + } + else + { + warning("number doesn't understand " + args[0].getString()); + } + } + } + +}} + diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Number.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Number.h new file mode 100644 index 00000000..90d1ced6 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Number.h @@ -0,0 +1,56 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OBJECT NUMBER // + // ================================================================================ // + + class Number : public engine::Object + { + public: // methods + + Number(model::Object const& model, Patcher& patcher); + + void parameterChanged(std::string const& name, tool::Parameter const& param) override final; + + void receive(size_t index, std::vector const& args) override final; + + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher& patcher); + + private: // methods + + void outputValue(); + + private: // members + + double m_value; + flip::SignalConnection m_connection; + }; + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_NumberTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_NumberTilde.cpp new file mode 100644 index 00000000..7d9305e7 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_NumberTilde.cpp @@ -0,0 +1,84 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OBJECT NUMBER TILDE // + // ================================================================================ // + + void NumberTilde::declare() + { + Factory::add("number~", &NumberTilde::create); + } + + std::unique_ptr NumberTilde::create(model::Object const& model, Patcher& patcher) + { + return std::make_unique(model, patcher); + } + + NumberTilde::NumberTilde(model::Object const& object_model, Patcher& patcher): + AudioObject(object_model, patcher), + tool::Scheduler<>::Timer(patcher.getScheduler()), + m_value(object_model.getParameter("value")[0].getFloat()), + m_interval(100) + { + } + + void NumberTilde::perform(dsp::Buffer const& input, dsp::Buffer& output) + { + m_value.store(input[0][input[0].size() - 1]); + } + + void NumberTilde::prepare(dsp::Processor::PrepareInfo const& infos) + { + if(infos.inputs[0]) + { + setPerformCallBack(this, &NumberTilde::perform); + } + + startTimer(std::chrono::milliseconds(m_interval)); + } + + void NumberTilde::release() + { + stopTimer(); + } + + void NumberTilde::timerCallBack() + { + double current_value = m_value.load(); + + setParameter("value", tool::Parameter(tool::Parameter::Type::Float, {current_value})); + + send(0,{current_value}); + } + + void NumberTilde::receive(size_t index, std::vector const& args) + { + } +}} + diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_NumberTilde.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_NumberTilde.h new file mode 100644 index 00000000..7a3e99c1 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_NumberTilde.h @@ -0,0 +1,62 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OBJECT NUMBER TILDE // + // ================================================================================ // + + class NumberTilde : public engine::AudioObject, tool::Scheduler<>::Timer + { + public: // methods + + NumberTilde(model::Object const& model, Patcher& patcher); + + void perform(dsp::Buffer const& intput, dsp::Buffer& output); + + void prepare(dsp::Processor::PrepareInfo const& infos) override final; + + void release() override final; + + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher& patcher); + + private: // methods + + void timerCallBack() override final; + + void receive(size_t index, std::vector const& args) override final; + + private: // members + + std::atomic m_value; + size_t m_interval; + }; + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h index 8e8984c1..ba1bb5c0 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h @@ -72,4 +72,6 @@ #include #include #include -#include +#include +#include +#include diff --git a/Modules/KiwiModel/KiwiModel_DataModel.cpp b/Modules/KiwiModel/KiwiModel_DataModel.cpp index 8190798d..50ba1eb0 100644 --- a/Modules/KiwiModel/KiwiModel_DataModel.cpp +++ b/Modules/KiwiModel/KiwiModel_DataModel.cpp @@ -84,7 +84,9 @@ namespace kiwi model::Unpack::declare(); model::Random::declare(); model::Scale::declare(); - model::Select::declare(); + model::Select::declare(); + model::Number::declare(); + model::NumberTilde::declare(); } void DataModel::init(std::function declare_object) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Number.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Number.cpp new file mode 100755 index 00000000..871bbbfb --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Number.cpp @@ -0,0 +1,100 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT NUMBER // + // ================================================================================ // + + void Number::declare() + { + std::unique_ptr number_class(new ObjectClass("number", + &Number::create)); + // parameters + std::unique_ptr param_value(new ParameterClass(tool::Parameter::Type::Float)); + + number_class->addParameter("value", std::move(param_value)); + + + // flags + number_class->setFlag(ObjectClass::Flag::ResizeWidth); + number_class->setFlag(ObjectClass::Flag::DefinedSize); + + // data model + + flip::Class & number_model = DataModel::declare() + .name(number_class->getModelName().c_str()) + .inherit(); + + Factory::add(std::move(number_class), number_model); + } + + std::unique_ptr Number::create(std::vector const& args) + { + return std::make_unique(args); + } + + Number::Number(std::vector const& args): + Object() + { + if (!args.empty()) + { + throw Error("number doesn't take any arguments"); + } + + addSignal<>(Signal::OutputValue, *this); + + setMinWidth(20.); + setMinHeight(20.); + setWidth(50.); + setHeight(20.); + pushInlet({PinType::IType::Control}); + pushOutlet(PinType::IType::Control); + } + + Number::Number(flip::Default& d): + Object(d) + { + addSignal<>(Signal::OutputValue, *this); + } + + std::string Number::getIODescription(bool is_inlet, size_t index) const + { + if (is_inlet && index == 0) + { + return "Sets number value."; + } + else if(!is_inlet && index == 0) + { + return "Outputs number value"; + } + else + { + return ""; + } + } +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Number.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Number.h new file mode 100755 index 00000000..78bd421a --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Number.h @@ -0,0 +1,54 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT NUMBER // + // ================================================================================ // + + class Number : public model::Object + { + public: // enum + + enum Signal : SignalKey + { + OutputValue + }; + + public: // methods + + Number(flip::Default& d); + + Number(std::vector const& args); + + std::string getIODescription(bool is_inlet, size_t index) const override; + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + }; +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_NumberTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_NumberTilde.cpp new file mode 100755 index 00000000..1cbf5e4b --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_NumberTilde.cpp @@ -0,0 +1,97 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT NUMBER TILDE // + // ================================================================================ // + + void NumberTilde::declare() + { + std::unique_ptr numbertilde_class(new ObjectClass("number~", + &NumberTilde::create)); + // parameters + std::unique_ptr param_value(new ParameterClass(tool::Parameter::Type::Float)); + + numbertilde_class->addParameter("value", std::move(param_value)); + + + // flags + numbertilde_class->setFlag(ObjectClass::Flag::ResizeWidth); + numbertilde_class->setFlag(ObjectClass::Flag::DefinedSize); + + // data model + + flip::Class & numbertilde_model = DataModel::declare() + .name(numbertilde_class->getModelName().c_str()) + .inherit(); + + Factory::add(std::move(numbertilde_class), numbertilde_model); + } + + std::unique_ptr NumberTilde::create(std::vector const& args) + { + return std::make_unique(args); + } + + NumberTilde::NumberTilde(std::vector const& args): + Object() + { + if (!args.empty()) + { + throw Error("number tilde doesn't take any arguments"); + } + + setMinWidth(20.); + setMinHeight(20.); + setWidth(50.); + setHeight(20.); + pushInlet({PinType::IType::Signal}); + pushOutlet(PinType::IType::Control); + } + + NumberTilde::NumberTilde(flip::Default& d): + Object(d) + { + } + + std::string NumberTilde::getIODescription(bool is_inlet, size_t index) const + { + if (is_inlet && index == 0) + { + return "Input signal"; + } + else if(!is_inlet && index == 0) + { + return "Ouputs input signal value every interval"; + } + else + { + return ""; + } + } +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_NumberTilde.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_NumberTilde.h new file mode 100755 index 00000000..5eb870c2 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_NumberTilde.h @@ -0,0 +1,47 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT NUMBER TILDE // + // ================================================================================ // + + class NumberTilde : public model::Object + { + public: // methods + + NumberTilde(flip::Default& d); + + NumberTilde(std::vector const& args); + + std::string getIODescription(bool is_inlet, size_t index) const override; + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + }; +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h index 9503ca93..dc64b096 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h @@ -72,4 +72,6 @@ #include #include #include -#include +#include +#include +#include From 39157a6f956a9b140630aff4101cf64cc09651f2 Mon Sep 17 00:00:00 2001 From: jean-millot Date: Mon, 18 Dec 2017 20:34:23 +0100 Subject: [PATCH 110/148] Enable data model conversion. --- .../KiwiApp_Application/KiwiApp_Instance.cpp | 37 +++++---- .../KiwiApp_PatcherManager.cpp | 73 ++++++++++++----- .../KiwiApp_Patcher/KiwiApp_PatcherManager.h | 4 +- .../KiwiModel_Converter.cpp | 55 +++++++++++++ .../KiwiModel_Converter.h | 47 +++++++++++ Modules/KiwiModel/KiwiModel_Def.h | 2 +- Modules/KiwiServer/KiwiServer_Server.cpp | 82 +++++++++++++------ Modules/KiwiServer/KiwiServer_Server.h | 6 +- 8 files changed, 235 insertions(+), 71 deletions(-) create mode 100755 Modules/KiwiModel/KiwiModel_Converters/KiwiModel_Converter.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Converters/KiwiModel_Converter.h diff --git a/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp b/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp index 69b68a8c..08e8c1fb 100644 --- a/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp +++ b/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp @@ -177,29 +177,36 @@ namespace kiwi } bool Instance::openFile(juce::File const& file) - { + { + bool open_succeeded = false; + if(file.hasFileExtension("kiwi")) - { - auto manager_it = m_patcher_managers.emplace(m_patcher_managers.end(), - new PatcherManager(*this)); - - PatcherManager& manager = *(manager_it->get()); - - manager.loadFromFile(file); - - if(manager.getNumberOfView() == 0) - { - manager.newView(); + { + std::unique_ptr patcher_manager(new PatcherManager(*this)); + + if (patcher_manager->loadFromFile(file)) + { + auto manager_it = m_patcher_managers.emplace(m_patcher_managers.end(), + std::move(patcher_manager)); + + open_succeeded = true; + + if((*manager_it)->getNumberOfView() == 0) + { + (*manager_it)->newView(); + } + } + else + { + KiwiApp::error("Can't open document. Version is not up to date. Please download latest Kiwi version."); } - - return true; } else { KiwiApp::error("can't open file (bad file extension)"); } - return false; + return open_succeeded; } void Instance::askUserToOpenPatcherDocument() diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.cpp index d50f317f..8df46e3d 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.cpp @@ -27,7 +27,8 @@ #include #include -#include +#include +#include #include #include @@ -204,36 +205,66 @@ namespace kiwi return m_socket.isConnected() && patcher_loaded; } - void PatcherManager::readDocument() - { + bool PatcherManager::readDocument() + { + bool loading_succeeded = false; + flip::DataProviderFile provider(m_file.getFullPathName().toStdString().c_str()); flip::BackEndIR back_end; - back_end.register_backend(); - back_end.read(provider); - - m_document.read(back_end); + back_end.register_backend(); - m_need_saving_flag = false; + if (back_end.read(provider)) + { + if (model::Converter::process(back_end)) + { + try + { + m_document.read(back_end); + } + catch (...) + { + return false; + } + + m_need_saving_flag = false; + loading_succeeded = true; + } + } + + return loading_succeeded; } - void PatcherManager::loadFromFile(juce::File const& file) - { + bool PatcherManager::loadFromFile(juce::File const& file) + { + bool success = false; + if (file.hasFileExtension("kiwi")) { m_file = file; - readDocument(); - - model::Patcher& patcher = getPatcher(); - - patcher.useSelfUser(); - patcher.setName(file.getFileNameWithoutExtension().toStdString()); - - model::DocumentManager::commit(patcher); - - patcher.entity().use().sendLoadbang(); - } + if (readDocument()) + { + model::Patcher& patcher = getPatcher(); + + patcher.useSelfUser(); + patcher.setName(file.getFileNameWithoutExtension().toStdString()); + + try + { + model::DocumentManager::commit(patcher); + } + catch (...) + { + return false; + } + + patcher.entity().use().sendLoadbang(); + success = true; + } + } + + return success; } model::Patcher& PatcherManager::getPatcher() diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.h b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.h index 43d3bfc3..597a6ab9 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.h @@ -69,7 +69,7 @@ namespace kiwi void pull(); //! @brief Load patcher datas from file. - void loadFromFile(juce::File const& file); + bool loadFromFile(juce::File const& file); //! @brief Save the document. //! @details Returns true if saving document succeeded false otherwise. @@ -153,7 +153,7 @@ namespace kiwi void writeDocument(); //! @internal Reads data from file. - void readDocument(); + bool readDocument(); //! @internal If the patcher is remote, tries to disconnect it. void disconnect(); diff --git a/Modules/KiwiModel/KiwiModel_Converters/KiwiModel_Converter.cpp b/Modules/KiwiModel/KiwiModel_Converters/KiwiModel_Converter.cpp new file mode 100755 index 00000000..42de6529 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Converters/KiwiModel_Converter.cpp @@ -0,0 +1,55 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // CONVERTER // + // ================================================================================ // + + bool Converter::process(flip::BackEndIR & backend) + { + bool success = false; + + process_rollback(backend); + + std::string current_version(KIWI_MODEL_VERSION_STRING); + + if (current_version.compare(backend.version) >= 0) + { + if (backend.version.compare("v1") >= 0) + { + success = true; + } + } + + return success; + } + + void Converter::process_rollback(flip::BackEndIR & backend) + { + } +}} diff --git a/Modules/KiwiModel/KiwiModel_Converters/KiwiModel_Converter.h b/Modules/KiwiModel/KiwiModel_Converters/KiwiModel_Converter.h new file mode 100755 index 00000000..c41dede8 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Converters/KiwiModel_Converter.h @@ -0,0 +1,47 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // CONVERTER // + // ================================================================================ // + + //! @brief Converts a document's backend representation to meet current version representation. + class Converter + { + public: // methods + + //! @brief Tries converting current data model version. + //! @details Returns true if the conversion was successful, false otherwise. Call this function + //! after reading from data provider. + static bool process(flip::BackEndIR & backend); + + private: // methods + + //! @brief Rollbacks depecrated revisions. + static void process_rollback(flip::BackEndIR & backend); + }; +}} diff --git a/Modules/KiwiModel/KiwiModel_Def.h b/Modules/KiwiModel/KiwiModel_Def.h index 93960b61..60292373 100644 --- a/Modules/KiwiModel/KiwiModel_Def.h +++ b/Modules/KiwiModel/KiwiModel_Def.h @@ -21,4 +21,4 @@ #pragma once -#define KIWI_MODEL_VERSION_STRING "v0.1.0" +#define KIWI_MODEL_VERSION_STRING "v1" diff --git a/Modules/KiwiServer/KiwiServer_Server.cpp b/Modules/KiwiServer/KiwiServer_Server.cpp index 556c5427..bdafb1f4 100644 --- a/Modules/KiwiServer/KiwiServer_Server.cpp +++ b/Modules/KiwiServer/KiwiServer_Server.cpp @@ -29,6 +29,7 @@ #include #include +#include namespace kiwi { @@ -98,21 +99,38 @@ namespace kiwi .withFileExtension(kiwi_file_extension); } - void Server::createSession(uint64_t session_id) - { - const auto session_file = getSessionFile(session_id); - - m_sessions.insert(std::make_pair(session_id, Session(session_id, session_file))); - } - void Server::onConnected(flip::PortBase & port) { + uint64_t session_id = port.session(); + if(m_sessions.find(port.session()) == m_sessions.end()) { - createSession(port.session()); + juce::File session_file = getSessionFile(port.session()); + + DBG("[server] - creating new session for session_id : " << hexadecimal_convert(session_id)); + + auto session = m_sessions.insert(std::make_pair(session_id, Session(session_id, session_file))); + + if (session_file.exists()) + { + DBG("[server] - loading session file for session_id : " << hexadecimal_convert(session_id)); + + if (!(*session.first).second.load()) + { + DBG("[server] - opening document document session : " << hexadecimal_convert(session_id) << " failed"); + + m_sessions.erase(session_id); + + throw std::runtime_error("loading session failed."); + } + } + + (*session.first).second.bind(port); + } + else + { + m_sessions.find(port.session())->second.bind(port); } - - m_sessions.find(port.session())->second.bind(port); } void Server::onDisconnected(flip::PortBase & port) @@ -196,24 +214,11 @@ namespace kiwi , m_signal_connections() , m_backend_file(backend_file) { - DBG("[server] - creating new session for session_id : " << hexadecimal_convert(m_identifier)); - model::Patcher& patcher = m_document->root(); auto cnx = patcher.signal_get_connected_users.connect(std::bind(&Server::Session::sendConnectedUsers, this)); m_signal_connections.emplace_back(std::move(cnx)); - - if (m_backend_file.exists()) - { - DBG("[server] - loading session file for session_id : " << hexadecimal_convert(m_identifier)); - - load(); - } - else - { - DBG("[server] - initializing with empty document for session_id : " << hexadecimal_convert(m_identifier)); - } } Server::Session::~Session() @@ -243,16 +248,39 @@ namespace kiwi backend.write(consumer); } - void Server::Session::load() + bool Server::Session::load() { + bool success = false; + flip::BackEndIR backend; backend.register_backend(); flip::DataProviderFile provider(m_backend_file.getFullPathName().toStdString().c_str()); - backend.read(provider); - m_document->read(backend); - m_document->commit(); + try + { + backend.read(provider); + } + catch (...) + { + return false; + } + + if (model::Converter::process(backend)) + { + try + { + m_document->read(backend); + m_document->commit(); + success = true; + } + catch(...) + { + return false; + } + } + + return success; } bool Server::Session::authenticateUser(uint64_t user, std::string metadata) const diff --git a/Modules/KiwiServer/KiwiServer_Server.h b/Modules/KiwiServer/KiwiServer_Server.h index 69d63a93..fd0ae9e6 100644 --- a/Modules/KiwiServer/KiwiServer_Server.h +++ b/Modules/KiwiServer/KiwiServer_Server.h @@ -74,10 +74,6 @@ namespace kiwi private: // methods - //! @brief Creates a new session for server. - //! @details Will load the document if there's a corresponding file in backend directory. - void createSession(uint64_t session_id); - //! @brief Called when a user connects to a document. void onConnected(flip::PortBase & port); @@ -153,7 +149,7 @@ namespace kiwi void save() const; //! @brief Loads the document from designated backend file. - void load(); + bool load(); //! @brief Binds user to session. void bind(flip::PortBase & port); From 00dbc7244eb764979081171111ad1bb8961dd8f4 Mon Sep 17 00:00:00 2001 From: jmillot Date: Thu, 21 Dec 2017 22:14:06 +0100 Subject: [PATCH 111/148] Using github draft to publish binaries. --- .travis.yml | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++-- appveyor.yml | 30 +++++++++++++++++++++-------- 2 files changed, 74 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index e27e0fd7..4af73803 100755 --- a/.travis.yml +++ b/.travis.yml @@ -63,16 +63,41 @@ matrix: - mkdir Kiwi - mv Build/Release/KiwiBuild/Kiwi Kiwi/Kiwi - tar zcvf Kiwi_linux.tar.gz Kiwi/ + - mkdir Kiwi_Server + - mv Build/Release/KiwiBuild/Server Kiwi_Server/Server + - tar zcvf Kiwi_Server_linux.tar.gz Kiwi_Server/ deploy: provider: releases api_key: secure: atcBDMdJNzUGiUYSqQu/URg8mfvRk9b78tvj1eHKCeDXSTP0Y1UvI5YpmTx8SkUXp23QH4sgp0tKTFB98FbRojR4IL2NW+KZDG1o5BxZ4HYJ4hdCXXXhzeujcn2AjQzRJ9f8uodX/7Pfa19jGlovj1Tl9ZJ9jIfyyvcxlJXkTN9+CDlkkcpLNU64c4B+CclS8aLPbIKqvLmIy3fphzzkJoKN5rnE4EvKrIkJBPEib1WIY8K7W8boCwghsGBs04MwRZwidKIjPSPgbYpmGPspfKpu0W8mKMirdGEVt4rzpm+Dl9wMa/5Qsyc6afYfS4p3PZOfBio0mtVrPz4+4VXy/Ad+FDNnvxUy9776D0pSv2iBrdHhqs6n1vG0uT4uhbGtvwJR3BBbo6+TmEKakRgp+uRhYEvGy/EO0OkcKrOVLsrZ/akj8O+KOSROrz2VYfxmDTxtUi8K51vW3pJhcGsEsN1FkcJfef/pvxGLK5i0qEZWoyCyA4YMPNDWFFiuBadPTujIGJ/iDmwouzalV9F0vKOIFvP9IuZ1FHLOyEzhyoBS3l1NNpQUz+HNgupTVYSREH1qPXUHg3B5BdFpEJpOjU/P8gwG4npcNxX/5XvigFFiTeEN+eV4xcBVLcg+SsumeswIqi5Tvm+mzYyqz3wj628ddWxgGiPFSfySI4tz6lg= - file: Kiwi_linux.tar.gz + file: + - Kiwi_linux.tar.gz + - Kiwi_Server_linux.tar.gz skip_cleanup: true + draft: false + prerelease: false on: repo: Musicoll/Kiwi tags: true + branch: master + + deploy: + provider: releases + api_key: + secure: atcBDMdJNzUGiUYSqQu/URg8mfvRk9b78tvj1eHKCeDXSTP0Y1UvI5YpmTx8SkUXp23QH4sgp0tKTFB98FbRojR4IL2NW+KZDG1o5BxZ4HYJ4hdCXXXhzeujcn2AjQzRJ9f8uodX/7Pfa19jGlovj1Tl9ZJ9jIfyyvcxlJXkTN9+CDlkkcpLNU64c4B+CclS8aLPbIKqvLmIy3fphzzkJoKN5rnE4EvKrIkJBPEib1WIY8K7W8boCwghsGBs04MwRZwidKIjPSPgbYpmGPspfKpu0W8mKMirdGEVt4rzpm+Dl9wMa/5Qsyc6afYfS4p3PZOfBio0mtVrPz4+4VXy/Ad+FDNnvxUy9776D0pSv2iBrdHhqs6n1vG0uT4uhbGtvwJR3BBbo6+TmEKakRgp+uRhYEvGy/EO0OkcKrOVLsrZ/akj8O+KOSROrz2VYfxmDTxtUi8K51vW3pJhcGsEsN1FkcJfef/pvxGLK5i0qEZWoyCyA4YMPNDWFFiuBadPTujIGJ/iDmwouzalV9F0vKOIFvP9IuZ1FHLOyEzhyoBS3l1NNpQUz+HNgupTVYSREH1qPXUHg3B5BdFpEJpOjU/P8gwG4npcNxX/5XvigFFiTeEN+eV4xcBVLcg+SsumeswIqi5Tvm+mzYyqz3wj628ddWxgGiPFSfySI4tz6lg= + file: + - Kiwi_linux.tar.gz + - Kiwi_Server_linux.tar.gz + skip_cleanup: true + draft: true + prerelease: false + name: ${TRAVIS_TAG} + tag_name: ${TRAVIS_TAG} + on: + repo: Musicoll/Kiwi + tags: true + condition: $TRAVIS_BRANCH != "master" - os: osx compiler: clang++ @@ -103,13 +128,38 @@ matrix: - mkdir Kiwi - mv Build/Release/KiwiBuild/Release/Kiwi.app Kiwi/Kiwi.app - zip -r Kiwi_macos.zip Kiwi + - mkdir Kiwi_Server + - mv Build/Release/KiwiBuild/Release/Server Kiwi_Server/Server + - zip -r Kiwi_Server_macos.zip Kiwi_Server + + deploy: + provider: releases + api_key: + secure: atcBDMdJNzUGiUYSqQu/URg8mfvRk9b78tvj1eHKCeDXSTP0Y1UvI5YpmTx8SkUXp23QH4sgp0tKTFB98FbRojR4IL2NW+KZDG1o5BxZ4HYJ4hdCXXXhzeujcn2AjQzRJ9f8uodX/7Pfa19jGlovj1Tl9ZJ9jIfyyvcxlJXkTN9+CDlkkcpLNU64c4B+CclS8aLPbIKqvLmIy3fphzzkJoKN5rnE4EvKrIkJBPEib1WIY8K7W8boCwghsGBs04MwRZwidKIjPSPgbYpmGPspfKpu0W8mKMirdGEVt4rzpm+Dl9wMa/5Qsyc6afYfS4p3PZOfBio0mtVrPz4+4VXy/Ad+FDNnvxUy9776D0pSv2iBrdHhqs6n1vG0uT4uhbGtvwJR3BBbo6+TmEKakRgp+uRhYEvGy/EO0OkcKrOVLsrZ/akj8O+KOSROrz2VYfxmDTxtUi8K51vW3pJhcGsEsN1FkcJfef/pvxGLK5i0qEZWoyCyA4YMPNDWFFiuBadPTujIGJ/iDmwouzalV9F0vKOIFvP9IuZ1FHLOyEzhyoBS3l1NNpQUz+HNgupTVYSREH1qPXUHg3B5BdFpEJpOjU/P8gwG4npcNxX/5XvigFFiTeEN+eV4xcBVLcg+SsumeswIqi5Tvm+mzYyqz3wj628ddWxgGiPFSfySI4tz6lg= + file: + - Kiwi_macos.zip + - Kiwi_Server_macos.zip + skip_cleanup: true + draft: false + prerelease: false + on: + repo: Musicoll/Kiwi + tags: true + branch: master deploy: provider: releases api_key: secure: atcBDMdJNzUGiUYSqQu/URg8mfvRk9b78tvj1eHKCeDXSTP0Y1UvI5YpmTx8SkUXp23QH4sgp0tKTFB98FbRojR4IL2NW+KZDG1o5BxZ4HYJ4hdCXXXhzeujcn2AjQzRJ9f8uodX/7Pfa19jGlovj1Tl9ZJ9jIfyyvcxlJXkTN9+CDlkkcpLNU64c4B+CclS8aLPbIKqvLmIy3fphzzkJoKN5rnE4EvKrIkJBPEib1WIY8K7W8boCwghsGBs04MwRZwidKIjPSPgbYpmGPspfKpu0W8mKMirdGEVt4rzpm+Dl9wMa/5Qsyc6afYfS4p3PZOfBio0mtVrPz4+4VXy/Ad+FDNnvxUy9776D0pSv2iBrdHhqs6n1vG0uT4uhbGtvwJR3BBbo6+TmEKakRgp+uRhYEvGy/EO0OkcKrOVLsrZ/akj8O+KOSROrz2VYfxmDTxtUi8K51vW3pJhcGsEsN1FkcJfef/pvxGLK5i0qEZWoyCyA4YMPNDWFFiuBadPTujIGJ/iDmwouzalV9F0vKOIFvP9IuZ1FHLOyEzhyoBS3l1NNpQUz+HNgupTVYSREH1qPXUHg3B5BdFpEJpOjU/P8gwG4npcNxX/5XvigFFiTeEN+eV4xcBVLcg+SsumeswIqi5Tvm+mzYyqz3wj628ddWxgGiPFSfySI4tz6lg= - file: Kiwi_macos.zip + file: + - Kiwi_macos.zip + - Kiwi_Server_macos.zip skip_cleanup: true + draft: true + prerelease: false + name: ${TRAVIS_TAG} + tag_name: ${TRAVIS_TAG} on: repo: Musicoll/Kiwi tags: true + condition: $TRAVIS_BRANCH != "master" diff --git a/appveyor.yml b/appveyor.yml index 04c2198c..de588193 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -28,6 +28,7 @@ install: - set KIWI_BOOST_LIB_x64=C:\Libraries\boost_1_63_0\lib64-msvc-14.0 - set KIWI_BOOST_LIB_WIN32=C:\Libraries\boost_1_63_0\lib32-msvc-14.0 - cd %APPVEYOR_BUILD_FOLDER% + - if "%APPVEYOR_REPO_BRANCH%"=="master" (set KIWI_DEPLOY=release) else (set KIWI_DEPLOY=draft) build_script: - python .\Scripts\configure.py -c %CONFIGURATION% -p %PLATFORM% @@ -36,19 +37,32 @@ build_script: after_build: - set BUILD_DIR=%APPVEYOR_BUILD_FOLDER%\Build\Release\%PLATFORM%\KiwiBuild\%CONFIGURATION% - 7z a Kiwi_%PLATFORM%.zip %BUILD_DIR%\Kiwi.exe %BUILD_DIR%\*.dll + - 7z a Kiwi_Server_%PLATFORM%.zip %BUILD_DIR%\Server.exe artifacts: - path: '*.zip' deploy: - provider: GitHub - auth_token: - secure: ZtKK8yOVkgIf+6Vm0jQLCbjCjuTiln3w2k/xMHI/kgardyCVtZ6plKI5O8lR3NNY - artifact: /.*\.zip/ - draft: false - prerelease: false - on: - appveyor_repo_tag: true + - provider: GitHub + release: $(APPVEYOR_REPO_TAG_NAME) + auth_token: + secure: ZtKK8yOVkgIf+6Vm0jQLCbjCjuTiln3w2k/xMHI/kgardyCVtZ6plKI5O8lR3NNY + artifact: /.*\.zip/ + draft: true + prerelease: false + on: + appveyor_repo_tag: true + KIWI_DEPLOY: 'draft' + + - provider: GitHub + auth_token: + secure: ZtKK8yOVkgIf+6Vm0jQLCbjCjuTiln3w2k/xMHI/kgardyCVtZ6plKI5O8lR3NNY + artifact: /.*\.zip/ + draft: false + prerelease: false + on: + appveyor_repo_tag: true + KIWI_DEPLOY: 'release' #---------------------------------# # notifications # From 24083d8827370ef1821c9cbe13ba79b9e57ab74e Mon Sep 17 00:00:00 2001 From: jmillot Date: Thu, 4 Jan 2018 15:46:38 +0100 Subject: [PATCH 112/148] Adding hub object. --- Client/Source/KiwiApp.cpp | 3 +- .../KiwiEngine_Objects/KiwiEngine_Hub.cpp | 70 +++++++++++ .../KiwiEngine_Objects/KiwiEngine_Hub.h | 49 ++++++++ .../KiwiEngine_Objects/KiwiEngine_Objects.h | 3 +- Modules/KiwiModel/KiwiModel_DataModel.cpp | 3 +- .../KiwiModel_Objects/KiwiModel_Hub.cpp | 111 ++++++++++++++++++ .../KiwiModel_Objects/KiwiModel_Hub.h | 59 ++++++++++ .../KiwiModel_Objects/KiwiModel_Objects.h | 3 +- 8 files changed, 297 insertions(+), 4 deletions(-) create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Hub.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Hub.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Hub.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Hub.h diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index 861aa874..bb304aa1 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -191,7 +191,8 @@ namespace kiwi engine::Scale::declare(); engine::Select::declare(); engine::Number::declare(); - engine::NumberTilde::declare(); + engine::NumberTilde::declare(); + engine::Hub::declare(); } void KiwiApp::declareObjectViews() diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Hub.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Hub.cpp new file mode 100644 index 00000000..b3831aac --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Hub.cpp @@ -0,0 +1,70 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OBJECT HUB // + // ================================================================================ // + + void Hub::declare() + { + Factory::add("hub", &Hub::create); + } + + std::unique_ptr Hub::create(model::Object const& model, Patcher& patcher) + { + return std::make_unique(model, patcher); + } + + Hub::Hub(model::Object const& object_model, Patcher& patcher): + Object(object_model, patcher) + { + } + + + Hub::~Hub() + { + } + + void Hub::attributeChanged(std::string const& name, tool::Parameter const& parameter) + { + if (name == "message") + { + send(0,{tool::AtomHelper::parse(parameter[0].getString())}); + } + } + + void Hub::receive(size_t index, std::vector const& args) + { + if (index == 0 && !args.empty()) + { + setAttribute("message", tool::Parameter(tool::Parameter::Type::String, {tool::AtomHelper::toString(args)})); + } + } + +}} + diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Hub.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Hub.h new file mode 100644 index 00000000..bcf44ecf --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Hub.h @@ -0,0 +1,49 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // OBJECT HUB // + // ================================================================================ // + + class Hub : public engine::Object + { + public: // methods + + Hub(model::Object const& model, Patcher& patcher); + + ~Hub(); + + void attributeChanged(std::string const& name, tool::Parameter const& param) override final; + + void receive(size_t index, std::vector const& args) override final; + + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher& patcher); + }; + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h index ba1bb5c0..bea5918a 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h @@ -74,4 +74,5 @@ #include #include #include -#include +#include +#include diff --git a/Modules/KiwiModel/KiwiModel_DataModel.cpp b/Modules/KiwiModel/KiwiModel_DataModel.cpp index 50ba1eb0..24d515d8 100644 --- a/Modules/KiwiModel/KiwiModel_DataModel.cpp +++ b/Modules/KiwiModel/KiwiModel_DataModel.cpp @@ -86,7 +86,8 @@ namespace kiwi model::Scale::declare(); model::Select::declare(); model::Number::declare(); - model::NumberTilde::declare(); + model::NumberTilde::declare(); + model::Hub::declare(); } void DataModel::init(std::function declare_object) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Hub.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Hub.cpp new file mode 100755 index 00000000..68097e2a --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Hub.cpp @@ -0,0 +1,111 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT HUB // + // ================================================================================ // + + void Hub::declare() + { + // Objectclass + std::unique_ptr hub_class(new ObjectClass("hub", &Hub::create)); + + // Parameters + std::unique_ptr param_message(new ParameterClass(tool::Parameter::Type::String)); + + hub_class->addAttribute("message", std::move(param_message)); + + // DataModel + flip::Class & hub_model = DataModel::declare() + .name(hub_class->getModelName().c_str()) + .inherit() + .member, &Hub::m_message>("message"); + + Factory::add(std::move(hub_class), hub_model); + } + + std::unique_ptr Hub::create(std::vector const& args) + { + return std::make_unique(args); + } + + Hub::Hub(std::vector const& args): + Object(), + m_message() + { + if (args.size() > 0) + throw Error("message too many arguments"); + + pushInlet({PinType::IType::Control}); + pushOutlet(PinType::IType::Control); + } + + Hub::Hub(flip::Default& d): + Object(d), + m_message() + { + } + + void Hub::writeAttribute(std::string const& name, tool::Parameter const& parameter) + { + if (name == "message") + { + m_message.send(parameter[0].getString()); + } + } + + void Hub::readAttribute(std::string const& name, tool::Parameter & parameter) const + { + if (name == "message") + { + m_message.get([¶meter](bool forward_flag, std::string received_message) + { + parameter = tool::Parameter(tool::Parameter::Type::String, {received_message}); + }); + } + } + + bool Hub::attributeChanged(std::string const& name) const + { + return name == "message" && m_message.changed(); + } + + std::string Hub::getIODescription(bool is_inlet, size_t index) const + { + if (is_inlet && index == 0) + { + return "Sends message to all users"; + } + else if(!is_inlet && index == 0) + { + return "Outputs message received from other users"; + } + else + { + return ""; + } + } +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Hub.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Hub.h new file mode 100755 index 00000000..6e8963cf --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Hub.h @@ -0,0 +1,59 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // OBJECT HUB // + // ================================================================================ // + + class Hub : public model::Object + { + public: // methods + + Hub(flip::Default& d); + + Hub(std::vector const& args); + + std::string getIODescription(bool is_inlet, size_t index) const override; + + void writeAttribute(std::string const& name, tool::Parameter const& parameter) override final; + + void readAttribute(std::string const& name, tool::Parameter & parameter) const override final; + + bool attributeChanged(std::string const& name) const override final; + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + + private: // members + + flip::Message m_message; + + }; +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h index dc64b096..279da018 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h @@ -74,4 +74,5 @@ #include #include #include -#include +#include +#include From 068022002004d33a9063e80a3b21c3f563d1e953 Mon Sep 17 00:00:00 2001 From: jmillot Date: Thu, 11 Jan 2018 18:52:12 +0100 Subject: [PATCH 113/148] Adapting kiwi code to new node server registration. --- Client/Source/KiwiApp.cpp | 2 +- Client/Source/KiwiApp.h | 2 +- .../Source/KiwiApp_Auth/KiwiApp_AuthPanel.cpp | 6 ++--- Client/Source/KiwiApp_Network/KiwiApp_Api.cpp | 27 ++++++++----------- Client/Source/KiwiApp_Network/KiwiApp_Api.h | 2 +- .../KiwiApp_Network/KiwiApp_ApiController.cpp | 12 +++------ .../KiwiApp_Network/KiwiApp_ApiController.h | 2 +- Server/Source/Main.cpp | 6 ++--- 8 files changed, 25 insertions(+), 34 deletions(-) diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index 861aa874..295475a8 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -309,7 +309,7 @@ namespace kiwi void KiwiApp::signup(std::string const& username, std::string const& email, std::string const& password, - std::function success_callback, + std::function success_callback, Api::ErrorCallback error_callback) { auto& api_controller = *KiwiApp::use().m_api_controller; diff --git a/Client/Source/KiwiApp.h b/Client/Source/KiwiApp.h index 5b6f099c..89654a04 100644 --- a/Client/Source/KiwiApp.h +++ b/Client/Source/KiwiApp.h @@ -112,7 +112,7 @@ namespace kiwi static void signup(std::string const& username, std::string const& email, std::string const& password, - std::function success_callback, + std::function success_callback, Api::ErrorCallback error_callback); //! @brief Returns the current user diff --git a/Client/Source/KiwiApp_Auth/KiwiApp_AuthPanel.cpp b/Client/Source/KiwiApp_Auth/KiwiApp_AuthPanel.cpp index 1a790914..11494a99 100644 --- a/Client/Source/KiwiApp_Auth/KiwiApp_AuthPanel.cpp +++ b/Client/Source/KiwiApp_Auth/KiwiApp_AuthPanel.cpp @@ -147,11 +147,11 @@ namespace kiwi showOverlay(); - auto success_callback = [this]() + auto success_callback = [this](std::string message) { - KiwiApp::useInstance().useScheduler().schedule([this]() { + KiwiApp::useInstance().useScheduler().schedule([this, message]() { - showSuccessOverlay("Registering success !"); + showSuccessOverlay(message); KiwiApp::useInstance().useScheduler().schedule([this]() { diff --git a/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp b/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp index 99361daf..4b147bc0 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp +++ b/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp @@ -108,7 +108,7 @@ namespace kiwi void Api::signup(std::string const& username, std::string const& email, std::string const& password, - CallbackFn success_cb, + CallbackFn success_cb, ErrorCallback error_cb) { assert(!username.empty()); @@ -132,24 +132,19 @@ namespace kiwi { const auto j = json::parse(res.body); - if(j.is_object() && j.count("user")) + if(j.is_object() && j.count("message")) { - User user(j["user"]); - - if(user.isValid()) - { - success(std::move(user)); - } - else - { - fail({res.result_int(), "Failed to parse result"}); - } - - return; + success(j["message"]); + } + else + { + fail({res.result_int(), "Failed to parse result"}); } } - - fail(res); + else + { + fail(res); + } }; storeFuture(session->PostAsync(std::move(cb))); diff --git a/Client/Source/KiwiApp_Network/KiwiApp_Api.h b/Client/Source/KiwiApp_Network/KiwiApp_Api.h index c8d1b185..01f9c230 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_Api.h +++ b/Client/Source/KiwiApp_Network/KiwiApp_Api.h @@ -86,7 +86,7 @@ namespace kiwi void signup(std::string const& username, std::string const& email, std::string const& password, - CallbackFn success_cb, + CallbackFn success_cb, ErrorCallback error_cb); //! @brief Make an async API request to get a list of documents diff --git a/Client/Source/KiwiApp_Network/KiwiApp_ApiController.cpp b/Client/Source/KiwiApp_Network/KiwiApp_ApiController.cpp index 7b8305b2..77d57de8 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_ApiController.cpp +++ b/Client/Source/KiwiApp_Network/KiwiApp_ApiController.cpp @@ -115,18 +115,14 @@ namespace kiwi void ApiController::signup(std::string const& username, std::string const& email, std::string const& password, - std::function success_callback, + std::function success_callback, Api::ErrorCallback error_callback) { - auto success_cb = [this, success_callback = std::move(success_callback)](Api::User user){ + auto success_cb = [this, success_callback = std::move(success_callback)](std::string message){ auto& scheduler = KiwiApp::useInstance().useScheduler(); - scheduler.schedule([this, success_callback, user](){ - - m_auth_user.resetWith(user); - m_listeners.call(&ApiConnectStatusListener::authUserChanged, m_auth_user); - - success_callback(); + scheduler.schedule([this, success_callback, message](){ + success_callback(message); }); }; diff --git a/Client/Source/KiwiApp_Network/KiwiApp_ApiController.h b/Client/Source/KiwiApp_Network/KiwiApp_ApiController.h index 45cf205b..de6f5984 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_ApiController.h +++ b/Client/Source/KiwiApp_Network/KiwiApp_ApiController.h @@ -73,7 +73,7 @@ namespace kiwi void signup(std::string const& username, std::string const& email, std::string const& password, - std::function success_cb, + std::function success_cb, Api::ErrorCallback error_cb); //! @brief Log-out the user. diff --git a/Server/Source/Main.cpp b/Server/Source/Main.cpp index 9b813eba..c548cfc5 100644 --- a/Server/Source/Main.cpp +++ b/Server/Source/Main.cpp @@ -66,7 +66,7 @@ int main(int argc, char const* argv[]) return 0; } - juce::File configuration_file(cl_parser.getOption("-f")); + juce::File configuration_file("./" + cl_parser.getOption("-f")); if(!configuration_file.exists()) { @@ -96,9 +96,9 @@ int main(int argc, char const* argv[]) try { - server::Server kiwi_server(config["port"], config["backend_directory"]); + server::Server kiwi_server(config["session_port"], config["backend_directory"]); - std::cout << "[server] - running on port " << config["port"] << std::endl; + std::cout << "[server] - running on port " << config["session_port"] << std::endl; flip::RunLoopTimer run_loop ([&kiwi_server] { From 26413fd71123d58c5ae86c77db8a695df9519bdd Mon Sep 17 00:00:00 2001 From: jmillot Date: Fri, 12 Jan 2018 19:42:28 +0100 Subject: [PATCH 114/148] Adapting Kiwi to handle reset password request. --- .../Source/KiwiApp_Auth/KiwiApp_AuthPanel.cpp | 172 ++++++++++++++++-- .../Source/KiwiApp_Auth/KiwiApp_AuthPanel.h | 29 +++ .../KiwiApp_FormComponent.cpp | 91 ++++++++- .../KiwiApp_FormComponent.h | 43 ++++- Client/Source/KiwiApp_Network/KiwiApp_Api.cpp | 68 +++++++ Client/Source/KiwiApp_Network/KiwiApp_Api.h | 9 + 6 files changed, 390 insertions(+), 22 deletions(-) diff --git a/Client/Source/KiwiApp_Auth/KiwiApp_AuthPanel.cpp b/Client/Source/KiwiApp_Auth/KiwiApp_AuthPanel.cpp index 11494a99..91d6b640 100644 --- a/Client/Source/KiwiApp_Auth/KiwiApp_AuthPanel.cpp +++ b/Client/Source/KiwiApp_Auth/KiwiApp_AuthPanel.cpp @@ -31,22 +31,128 @@ namespace kiwi // ================================================================================ // LoginForm::LoginForm() - : FormComponent("login", "login...") + : FormComponent("Login", "login...") { - addField(); + setState(State::Login); + } + + void LoginForm::setState(State state) + { + clearFields(); - addField("username", - KiwiApp::getCurrentUser().getName(), - "Username or Email"); + m_state = state; - addField("password", "", "Password"); + switch (state) + { + case State::Login: + { + addField(); + + addField("username", + KiwiApp::getCurrentUser().getName(), + "Username or Email"); + + addField("password", "", "Password"); + + addField("remember_me", + "Remember me", + getAppSettings().network().getRememberUserFlag()); + + addField("forgot_pass", + "Forgot password ?", + [this]() + { + setState(State::Request); + showAlert("Enter email to request reset token", AlertBox::Type::Info); + }); + + setSubmitText("Login"); + + break; + } + case State::Request: + { + addField(); + + addField("email", "", "Email"); + addField("already_have", + "Already have token ?", + [this]() + { + setState(State::Reset); + showAlert("Enter reset token.", AlertBox::Type::Info); + }); + + setSubmitText("Send"); + + break; + } + case State::Reset: + { + addField(); + + addField("token", "", "Token"); + addField("newpass", "", "New Password"); + + setSubmitText("Send"); + + break; + } + } - addField("remember_me", - "Remember me", - getAppSettings().network().getRememberUserFlag()); + setSize(getWidth(), getBestHeight()); } - void LoginForm::onUserSubmit() + void LoginForm::performPassReset() + { + auto success_callback = [this](std::string const& message) + { + KiwiApp::useInstance().useScheduler().schedule([this]() { + setState(State::Login); + showAlert("Password reset. Try login again.", AlertBox::Type::Info); + }); + }; + + auto error_callback = [this](Api::Error error) + { + std::string error_message = error.getMessage(); + + KiwiApp::useInstance().useScheduler().schedule([this, error_message]() { + showAlert(error_message, AlertBox::Type::Error); + }); + }; + + const std::string token = getFieldValue("token").toString().toStdString(); + const std::string newpass = getFieldValue("newpass").toString().toStdString(); + + KiwiApp::useApi().resetPassword(token, newpass, success_callback, error_callback); + } + + void LoginForm::performPassRequest() + { + auto success_callback = [this](std::string const& message) + { + KiwiApp::useInstance().useScheduler().schedule([this]() { + setState(State::Reset); + showAlert("Reset token sent. Check your email.", AlertBox::Type::Info); + }); + }; + + auto error_callback = [this](Api::Error error) + { + std::string error_message = error.getMessage(); + + KiwiApp::useInstance().useScheduler().schedule([this, error_message]() { + showAlert(error_message, AlertBox::Type::Error); + }); + }; + + const std::string email = getFieldValue("email").toString().toStdString(); + + KiwiApp::useApi().requestPasswordToken(email, success_callback, error_callback); + } + + void LoginForm::performLogin() { const auto username = getFieldValue("username").toString(); const auto password = getFieldValue("password").toString(); @@ -98,12 +204,56 @@ namespace kiwi std::move(error_callback)); } + void LoginForm::onUserSubmit() + { + switch (m_state) + { + case State::Login: + { + performLogin(); + break; + } + case State::Request: + { + performPassRequest(); + break; + } + case State::Reset: + { + performPassReset(); + break; + } + } + } + + void LoginForm::onUserCancelled() + { + switch(m_state) + { + case State::Login: + { + dismiss(); + break; + } + case State::Request: + { + setState(State::Login); + break; + } + case State::Reset: + { + setState(State::Login); + break; + } + } + } + // ================================================================================ // // SIGNUP FORM // // ================================================================================ // SignUpForm::SignUpForm() - : FormComponent("register", "register...") + : FormComponent("Register", "register...") { addField(); addField("username", "", "Username"); diff --git a/Client/Source/KiwiApp_Auth/KiwiApp_AuthPanel.h b/Client/Source/KiwiApp_Auth/KiwiApp_AuthPanel.h index a6c8e5f7..f8152c0d 100644 --- a/Client/Source/KiwiApp_Auth/KiwiApp_AuthPanel.h +++ b/Client/Source/KiwiApp_Auth/KiwiApp_AuthPanel.h @@ -31,6 +31,15 @@ namespace kiwi class LoginForm : public FormComponent { + private: // classes + + enum class State + { + Login, + Request, + Reset + }; + public: // methods //! @brief Constructor. @@ -42,8 +51,28 @@ namespace kiwi private: // methods + //! @brief Sends login request to server. + void performLogin(); + + //! @brief Sends password token request to server. + void performPassReset(); + + //! @brief Sends password reset request to server. + void performPassRequest(); + + //! @brief When submit button clicked. Reaction depends on current state. void onUserSubmit() override; + //! @brief When cancel button is clicked depends on current state. + void onUserCancelled() override; + + //! @brief Change the form state. + void setState(State state); + + private: // members + + State m_state; + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(LoginForm) }; diff --git a/Client/Source/KiwiApp_Components/KiwiApp_FormComponent.cpp b/Client/Source/KiwiApp_Components/KiwiApp_FormComponent.cpp index fe439939..52be4090 100644 --- a/Client/Source/KiwiApp_Components/KiwiApp_FormComponent.cpp +++ b/Client/Source/KiwiApp_Components/KiwiApp_FormComponent.cpp @@ -280,6 +280,47 @@ namespace kiwi return 20; } + // ================================================================================ // + // FIELD TEXT BUTTON // + // ================================================================================ // + + FormComponent::Field::TextButton::TextButton(std::string const& name, + std::string const& button_text, + std::function call_back): + Field(name), + m_button(button_text), + m_value(), + m_call_back(call_back) + { + m_button.addListener(this); + addAndMakeVisible(m_button); + } + + FormComponent::Field::TextButton::~TextButton() + { + m_button.removeListener(this); + } + + void FormComponent::Field::TextButton::resized() + { + m_button.changeWidthToFitText(getHeight()); + } + + juce::Value& FormComponent::Field::TextButton::getValue() + { + return m_value; + } + + int FormComponent::Field::TextButton::getPreferedHeight() + { + return 30; + } + + void FormComponent::Field::TextButton::buttonClicked(juce::Button *) + { + m_call_back(); + } + // ================================================================================ // // KIWI LOGO FIELD // // ================================================================================ // @@ -319,10 +360,10 @@ namespace kiwi FormComponent::FormComponent(std::string const& submit_button_text, std::string const& overlay_text) - : m_submit_button_text(submit_button_text) - , m_overlay_text(overlay_text) - , m_submit_btn(m_submit_button_text) + : m_overlay_text(overlay_text) + , m_submit_btn(submit_button_text) , m_cancel_btn(TRANS("Cancel")) + , m_alert_height(50) { addAndMakeVisible(m_submit_btn); addAndMakeVisible(m_cancel_btn); @@ -357,8 +398,7 @@ namespace kiwi if(m_alert_box) { - const int alert_height = 50; - m_alert_box->setBounds(r.removeFromTop(alert_height)); + m_alert_box->setBounds(r.removeFromTop(m_alert_height)); } r.reduce(10, 10); @@ -416,6 +456,12 @@ namespace kiwi } } + void FormComponent::setSubmitText(std::string const& submit_text) + { + m_submit_btn.setButtonText(submit_text); + repaint(); + } + bool FormComponent::hasOverlay() { return (m_overlay != nullptr); @@ -429,19 +475,17 @@ namespace kiwi removeChildComponent(m_alert_box.get()); } - const int alert_height = 50; - - m_alert_box.reset(new AlertBox(message, type, true, [this, alert_height](){ + m_alert_box.reset(new AlertBox(message, type, true, [this](){ removeChildComponent(m_alert_box.get()); m_alert_box.reset(); - setBounds(getBounds().withHeight(getHeight() - alert_height)); + setBounds(getBounds().withHeight(getHeight() - m_alert_height)); })); addAndMakeVisible(*m_alert_box); if(!was_showing) { - setBounds(getBounds().withHeight(getHeight() + alert_height)); + setBounds(getBounds().withHeight(getHeight() + m_alert_height)); } else { @@ -477,6 +521,33 @@ namespace kiwi } } + void FormComponent::clearFields() + { + for(auto field = m_fields.begin(); field != m_fields.end();) + { + removeChildComponent((*field).get()); + field = m_fields.erase(field); + } + repaint(); + } + + void FormComponent::removeField(std::string const& name) + { + for(auto field = m_fields.begin(); field != m_fields.end();) + { + if ((*field)->getName() == name) + { + removeChildComponent((*field).get()); + field = m_fields.erase(field); + } + else + { + ++field; + } + } + repaint(); + } + juce::Value FormComponent::getFieldValue(std::string const& name) { for(auto& field : m_fields) diff --git a/Client/Source/KiwiApp_Components/KiwiApp_FormComponent.h b/Client/Source/KiwiApp_Components/KiwiApp_FormComponent.h index a6e0bcba..14cee3c9 100644 --- a/Client/Source/KiwiApp_Components/KiwiApp_FormComponent.h +++ b/Client/Source/KiwiApp_Components/KiwiApp_FormComponent.h @@ -103,6 +103,12 @@ namespace kiwi //! @brief Returns a field Value. juce::Value getFieldValue(std::string const& name); + //! @brief Remove fields by name. + void removeField(std::string const& name); + + //! @brief Remove all fields. + void clearFields(); + //! @brief Show an Alert on the top of the form; void showAlert(std::string const& message, AlertBox::Type type = AlertBox::Type::Error); @@ -116,6 +122,9 @@ namespace kiwi //! @brief Hide overlay void hideOverlay(); + //! @brief Changes the submit button text + void setSubmitText(std::string const& submit_text); + //! @brief Returns true if the overlay component is visible. bool hasOverlay(); @@ -145,7 +154,6 @@ namespace kiwi private: // variables - std::string m_submit_button_text; std::string m_overlay_text; juce::TextButton m_submit_btn, m_cancel_btn; @@ -154,6 +162,8 @@ namespace kiwi std::vector> m_fields; + int m_alert_height; + class OverlayComp; friend class OverlayComp; Component::SafePointer m_overlay; @@ -173,6 +183,7 @@ namespace kiwi class Password; class ToggleButton; class KiwiLogo; + class TextButton; Field(std::string name); @@ -245,6 +256,35 @@ namespace kiwi juce::ToggleButton m_button; }; + // ================================================================================ // + // TEXT BUTTON FIELD // + // ================================================================================ // + + class FormComponent::Field::TextButton : public Field, public juce::Button::Listener + { + public: + + TextButton(std::string const& name, + std::string const& buton_text, + std::function call_back); + + ~TextButton(); + + juce::Value& getValue() override final; + + int getPreferedHeight() override final; + + void resized() override; + + void buttonClicked(juce::Button *) override final; + + private: + + juce::TextButton m_button; + juce::Value m_value; + std::function m_call_back; + }; + // ================================================================================ // // KIWI LOGO FIELD // // ================================================================================ // @@ -269,6 +309,7 @@ namespace kiwi juce::Value m_useless_value; }; + // ================================================================================ // // FORM COMPONENT - template definitions // // ================================================================================ // diff --git a/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp b/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp index 4b147bc0..25114fd6 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp +++ b/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp @@ -252,6 +252,74 @@ namespace kiwi storeFuture(session->GetAsync(std::move(cb))); } + void Api::requestPasswordToken(std::string const& user_mail, CallbackFn success_cb, ErrorCallback error_cb) + { + auto session = makeSession(Endpoint::users + "/passtoken"); + + session->setPayload({ + {"email", user_mail} + }); + + auto cb = [success = std::move(success_cb), + fail = std::move(error_cb)](Response res) + { + if (!res.error + && hasJsonHeader(res) + && res.result() == beast::http::status::ok) + { + const auto j = json::parse(res.body); + + if(j.is_object() && j.count("message")) + { + std::string message = j["message"]; + success(message); + } + } + else + { + fail(res); + } + }; + + storeFuture(session->PostAsync(std::move(cb))); + } + + void Api::resetPassword(std::string const& token, + std::string const& newpass, + CallbackFn success_cb, + ErrorCallback error_cb) + { + auto session = makeSession(Endpoint::users + "/passreset"); + + session->setPayload({ + {"token", token}, + {"newpass", newpass} + }); + + auto cb = [success = std::move(success_cb), + fail = std::move(error_cb)](Response res) + { + if (!res.error + && hasJsonHeader(res) + && res.result() == beast::http::status::ok) + { + const auto j = json::parse(res.body); + + if(j.is_object() && j.count("message")) + { + std::string message = j["message"]; + success(message); + } + } + else + { + fail(res); + } + }; + + storeFuture(session->PostAsync(std::move(cb))); + } + bool Api::hasJsonHeader(Response const& res) { return (res[beast::http::field::content_type] == "application/json; charset=utf-8"); diff --git a/Client/Source/KiwiApp_Network/KiwiApp_Api.h b/Client/Source/KiwiApp_Network/KiwiApp_Api.h index 01f9c230..79f6200f 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_Api.h +++ b/Client/Source/KiwiApp_Network/KiwiApp_Api.h @@ -106,6 +106,15 @@ namespace kiwi //! @brief Retrieves Kiwi's latest release as a string. ex: v0.1.0 void getLatestRelease(CallbackFn success_cb, ErrorCallback error_cb); + //! @brief Requests a reset token to the server. + void requestPasswordToken(std::string const& user_mail, CallbackFn success_cb, ErrorCallback error_cb); + + //! @brief Sends reset request token to the server. + void resetPassword(std::string const& token, + std::string const& newpass, + CallbackFn success_cb, + ErrorCallback error_cb); + public: // helper methods template From 06d52267cfa3334fb7444152ae05c51dc019a7ed Mon Sep 17 00:00:00 2001 From: jean-millot Date: Mon, 15 Jan 2018 16:14:55 +0100 Subject: [PATCH 115/148] Adding object mtof. --- Client/Source/KiwiApp.cpp | 3 +- .../KiwiEngine_Objects/KiwiEngine_Mtof.cpp | 64 +++++++++++++++ .../KiwiEngine_Objects/KiwiEngine_Mtof.h | 47 +++++++++++ .../KiwiEngine_Objects/KiwiEngine_Objects.h | 3 +- Modules/KiwiModel/KiwiModel_DataModel.cpp | 3 +- .../KiwiModel_Objects/KiwiModel_Mtof.cpp | 78 +++++++++++++++++++ .../KiwiModel_Objects/KiwiModel_Mtof.h | 47 +++++++++++ .../KiwiModel_Objects/KiwiModel_Objects.h | 3 +- 8 files changed, 244 insertions(+), 4 deletions(-) create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Mtof.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Mtof.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Mtof.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Mtof.h diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index 10c695c0..5b5cde31 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -192,7 +192,8 @@ namespace kiwi engine::Select::declare(); engine::Number::declare(); engine::NumberTilde::declare(); - engine::Hub::declare(); + engine::Hub::declare(); + engine::Mtof::declare(); } void KiwiApp::declareObjectViews() diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Mtof.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Mtof.cpp new file mode 100644 index 00000000..079a99e0 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Mtof.cpp @@ -0,0 +1,64 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // MTOF // + // ================================================================================ // + + void Mtof::declare() + { + Factory::add("mtof", &Mtof::create); + } + + std::unique_ptr Mtof::create(model::Object const& model, Patcher & patcher) + { + return std::make_unique(model, patcher); + } + + Mtof::Mtof(model::Object const& model, Patcher& patcher) : + Object(model, patcher) + { + } + + void Mtof::receive(size_t index, std::vector const& args) + { + if (index == 0 && !args.empty()) + { + if (args[0].isNumber()) + { + send(0, {440. * std::pow(2., (args[0].getFloat() - 69) / 12.)}); + } + else + { + warning("mtof inlet 1 doesn't understand " + args[0].getString()); + } + + } + } + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Mtof.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Mtof.h new file mode 100644 index 00000000..85d62502 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Mtof.h @@ -0,0 +1,47 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // MTOF // + // ================================================================================ // + + class Mtof : public engine::Object + { + public: + + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher & patcher); + + Mtof(model::Object const& model, Patcher& patcher); + + Mtof() = default; + + void receive(size_t index, std::vector const& args) override; + }; + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h index bea5918a..a5df019c 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h @@ -75,4 +75,5 @@ #include #include #include -#include +#include +#include diff --git a/Modules/KiwiModel/KiwiModel_DataModel.cpp b/Modules/KiwiModel/KiwiModel_DataModel.cpp index 24d515d8..15354eb7 100644 --- a/Modules/KiwiModel/KiwiModel_DataModel.cpp +++ b/Modules/KiwiModel/KiwiModel_DataModel.cpp @@ -87,7 +87,8 @@ namespace kiwi model::Select::declare(); model::Number::declare(); model::NumberTilde::declare(); - model::Hub::declare(); + model::Hub::declare(); + model::Mtof::declare(); } void DataModel::init(std::function declare_object) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Mtof.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Mtof.cpp new file mode 100755 index 00000000..386211bc --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Mtof.cpp @@ -0,0 +1,78 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // MTOF // + // ================================================================================ // + + void Mtof::declare() + { + std::unique_ptr mtof_class(new ObjectClass("mtof", &Mtof::create)); + + flip::Class & mtof_model = DataModel::declare() + .name(mtof_class->getModelName().c_str()) + .inherit(); + + Factory::add(std::move(mtof_class), mtof_model); + } + + std::unique_ptr Mtof::create(std::vector const& args) + { + return std::make_unique(args); + } + + Mtof::Mtof(std::vector const& args) + { + if (!args.empty()) + throw Error("mtof doesn't take any argument"); + + pushInlet({PinType::IType::Control}); + pushOutlet(PinType::IType::Control); + } + + std::string Mtof::getIODescription(bool is_inlet, size_t index) const + { + std::string description = ""; + + if (is_inlet) + { + if (index == 0) + { + description = "midi note to convert"; + } + } + else + { + if (index == 0) + { + description = "ouputs converted midi note"; + } + } + + return description; + } + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Mtof.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Mtof.h new file mode 100755 index 00000000..3e77bfe9 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Mtof.h @@ -0,0 +1,47 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // MTOF // + // ================================================================================ // + + class Mtof : public model::Object + { + public: + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + + Mtof(flip::Default& d) : model::Object(d) {} + + Mtof(std::vector const& args); + + std::string getIODescription(bool is_inlet, size_t index) const override; + }; + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h index 279da018..63991b89 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h @@ -75,4 +75,5 @@ #include #include #include -#include +#include +#include From 4d076cc9c4bb173f943fcab7f5e650ee9675395c Mon Sep 17 00:00:00 2001 From: jean-millot Date: Mon, 15 Jan 2018 17:46:07 +0100 Subject: [PATCH 116/148] Object send. --- Client/Source/KiwiApp.cpp | 3 +- .../KiwiEngine_Objects/KiwiEngine_Objects.h | 3 +- .../KiwiEngine_Objects/KiwiEngine_Send.cpp | 55 ++++++++++++++ .../KiwiEngine_Objects/KiwiEngine_Send.h | 52 +++++++++++++ Modules/KiwiModel/KiwiModel_DataModel.cpp | 3 +- .../KiwiModel_Objects/KiwiModel_Objects.h | 3 +- .../KiwiModel_Objects/KiwiModel_Send.cpp | 76 +++++++++++++++++++ .../KiwiModel_Objects/KiwiModel_Send.h | 47 ++++++++++++ 8 files changed, 238 insertions(+), 4 deletions(-) create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Send.cpp create mode 100644 Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Send.h create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Send.cpp create mode 100755 Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Send.h diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index 5b5cde31..0489bb0a 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -193,7 +193,8 @@ namespace kiwi engine::Number::declare(); engine::NumberTilde::declare(); engine::Hub::declare(); - engine::Mtof::declare(); + engine::Mtof::declare(); + engine::Send::declare(); } void KiwiApp::declareObjectViews() diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h index a5df019c..dca288df 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Objects.h @@ -76,4 +76,5 @@ #include #include #include -#include +#include +#include diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Send.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Send.cpp new file mode 100644 index 00000000..129b21f2 --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Send.cpp @@ -0,0 +1,55 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // SEND // + // ================================================================================ // + + void Send::declare() + { + Factory::add("send", &Send::create); + } + + std::unique_ptr Send::create(model::Object const& model, Patcher & patcher) + { + return std::make_unique(model, patcher); + } + + Send::Send(model::Object const& model, Patcher& patcher) : + Object(model, patcher), + m_beacon(patcher.getBeacon(model.getArguments()[0].getString())) + { + } + + void Send::receive(size_t index, std::vector const& args) + { + if (index == 0 && !args.empty()) + { + m_beacon.dispatch(args); + } + } + +}} diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Send.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Send.h new file mode 100644 index 00000000..bf2e22fb --- /dev/null +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Send.h @@ -0,0 +1,52 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include +#include + +namespace kiwi { namespace engine { + + // ================================================================================ // + // SEND // + // ================================================================================ // + + class Send : public engine::Object + { + public: + + static void declare(); + + static std::unique_ptr create(model::Object const& model, Patcher & patcher); + + Send(model::Object const& model, Patcher& patcher); + + Send() = default; + + void receive(size_t index, std::vector const& args) override; + + private: + + tool::Beacon& m_beacon; + }; + +}} diff --git a/Modules/KiwiModel/KiwiModel_DataModel.cpp b/Modules/KiwiModel/KiwiModel_DataModel.cpp index 15354eb7..40ceb00a 100644 --- a/Modules/KiwiModel/KiwiModel_DataModel.cpp +++ b/Modules/KiwiModel/KiwiModel_DataModel.cpp @@ -88,7 +88,8 @@ namespace kiwi model::Number::declare(); model::NumberTilde::declare(); model::Hub::declare(); - model::Mtof::declare(); + model::Mtof::declare(); + model::Send::declare(); } void DataModel::init(std::function declare_object) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h index 63991b89..8ec00922 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Objects.h @@ -76,4 +76,5 @@ #include #include #include -#include +#include +#include diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Send.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Send.cpp new file mode 100755 index 00000000..21be2967 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Send.cpp @@ -0,0 +1,76 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // SEND // + // ================================================================================ // + + void Send::declare() + { + std::unique_ptr send_class(new ObjectClass("send", &Send::create)); + + flip::Class & send_model = DataModel::declare() + .name(send_class->getModelName().c_str()) + .inherit(); + + Factory::add(std::move(send_class), send_model); + } + + std::unique_ptr Send::create(std::vector const& args) + { + return std::make_unique(args); + } + + Send::Send(std::vector const& args) + { + if (args.empty()) + throw Error("send requires one argument"); + + if (args.size() > 1) + throw Error("send requires only one argument"); + + if (args.size() == 1 && !args[0].isString()) + throw Error("send argument must be a symbol"); + + pushInlet({PinType::IType::Control}); + } + + std::string Send::getIODescription(bool is_inlet, size_t index) const + { + std::string description = ""; + + if (is_inlet) + { + if (index == 0) + { + description = "message to send to corresponding receive objects"; + } + } + + return description; + } + +}} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Send.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Send.h new file mode 100755 index 00000000..44323170 --- /dev/null +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Send.h @@ -0,0 +1,47 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include + +namespace kiwi { namespace model { + + // ================================================================================ // + // SEND // + // ================================================================================ // + + class Send : public model::Object + { + public: + + static void declare(); + + static std::unique_ptr create(std::vector const& args); + + Send(flip::Default& d) : model::Object(d) {} + + Send(std::vector const& args); + + std::string getIODescription(bool is_inlet, size_t index) const override; + }; + +}} From 7bdf7bccee2188ec6400e78851f05044f3e76e3e Mon Sep 17 00:00:00 2001 From: jean-millot Date: Mon, 22 Jan 2018 15:04:03 +0100 Subject: [PATCH 117/148] Checking outlet/inlet types in validator. --- Modules/KiwiModel/KiwiModel_PatcherValidator.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Modules/KiwiModel/KiwiModel_PatcherValidator.cpp b/Modules/KiwiModel/KiwiModel_PatcherValidator.cpp index 81793b16..f1adf7a3 100755 --- a/Modules/KiwiModel/KiwiModel_PatcherValidator.cpp +++ b/Modules/KiwiModel/KiwiModel_PatcherValidator.cpp @@ -73,8 +73,15 @@ namespace kiwi { if(!link.isSenderValid() || !link.isReceiverValid()) { - flip_VALIDATION_FAILED ("Creating link to non existing object"); - } + flip_VALIDATION_FAILED ("Creating link to non existing object"); + } + + PinType outlet_type = link.getSenderObject().getOutlet(link.getSenderIndex()).getType(); + + if (!link.getReceiverObject().getInlet(link.getReceiverIndex()).hasType(outlet_type)) + { + flip_VALIDATION_FAILED("Link creation type mismatch between outlet and inlet"); + } } } } From 61ea0373d6efc580296a8edd35cc4273df621701 Mon Sep 17 00:00:00 2001 From: jean-millot Date: Mon, 8 Jan 2018 18:11:24 +0100 Subject: [PATCH 118/148] Removing unused columns from console. --- .../KiwiApp_Application/KiwiApp_Console.cpp | 24 +------------------ .../KiwiApp_Application/KiwiApp_Console.h | 5 +--- 2 files changed, 2 insertions(+), 27 deletions(-) diff --git a/Client/Source/KiwiApp_Application/KiwiApp_Console.cpp b/Client/Source/KiwiApp_Application/KiwiApp_Console.cpp index 38121fd6..337c734d 100644 --- a/Client/Source/KiwiApp_Application/KiwiApp_Console.cpp +++ b/Client/Source/KiwiApp_Application/KiwiApp_Console.cpp @@ -44,25 +44,12 @@ namespace kiwi juce::TableHeaderComponent* header = new juce::TableHeaderComponent(); - header->addColumn(juce::String("ID"), - Column::Id, 30, 20, 50, - juce::TableHeaderComponent::defaultFlags, -1); - - header->addColumn(juce::String("Type"), - Column::Type, 30, 20, 50, - juce::TableHeaderComponent::defaultFlags, -1); - - header->addColumn(juce::String("Object"), - Column::Object, 60, 20, 10000, - juce::TableHeaderComponent::defaultFlags, -1); - header->addColumn(juce::String("Message"), Column::Message, 100, 40, 10000, juce::TableHeaderComponent::defaultFlags, -1); header->setStretchToFitActive(false); - header->setColumnVisible(1, false); - header->setColumnVisible(2, false); + header->setColumnVisible(1, true); header->addListener(this); m_table.setWantsKeyboardFocus(true); @@ -291,12 +278,6 @@ namespace kiwi switch (columnId) { - case Column::Object: - { - // todo - break; - } - case Column::Message: { auto repeat_times = pair.second; @@ -345,9 +326,6 @@ namespace kiwi // column. int ConsoleContent::getColumnAutoSizeWidth(int columnId) { - if(columnId == Column::Id) - return 30; - int widest = 32; sConsoleHistory history = getHistory(); diff --git a/Client/Source/KiwiApp_Application/KiwiApp_Console.h b/Client/Source/KiwiApp_Application/KiwiApp_Console.h index 9c444c6b..b5a359bd 100644 --- a/Client/Source/KiwiApp_Application/KiwiApp_Console.h +++ b/Client/Source/KiwiApp_Application/KiwiApp_Console.h @@ -146,10 +146,7 @@ namespace kiwi //! @internal Column type enum Column { - Id = 1, - Type = 2, - Object = 3, - Message = 4 + Message = 1 }; //! @internal copy selected rows content. From a1bbd69ffc03e3030ca5f85c81e6a73a08ea0128 Mon Sep 17 00:00:00 2001 From: jmillot Date: Tue, 16 Jan 2018 21:44:56 +0100 Subject: [PATCH 119/148] Cancelling all pending request when Kiwi quits. --- Client/Source/KiwiApp.cpp | 3 +- Client/Source/KiwiApp_Network/KiwiApp_Api.cpp | 50 +++++-- Client/Source/KiwiApp_Network/KiwiApp_Api.h | 9 +- Modules/KiwiNetwork/KiwiHttp/KiwiHttp.h | 17 +-- Modules/KiwiNetwork/KiwiHttp/KiwiHttp.hpp | 131 ++++++++---------- .../KiwiNetwork/KiwiHttp/KiwiHttp_Session.cpp | 53 +++++-- .../KiwiNetwork/KiwiHttp/KiwiHttp_Session.h | 31 +++-- Test/Network/test_Http.cpp | 4 +- 8 files changed, 171 insertions(+), 127 deletions(-) diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index 0489bb0a..478971ae 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -214,7 +214,8 @@ namespace kiwi #if JUCE_MAC juce::MenuBarModel::setMacMainMenu(nullptr); #endif - + + m_api->cancelPendingRequest(); m_api.reset(); m_api_controller.reset(); m_settings.reset(); diff --git a/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp b/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp index 25114fd6..df504772 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp +++ b/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp @@ -54,6 +54,16 @@ namespace kiwi } + void Api::cancelPendingRequest() + { + for(auto & session : m_pending_requests) + { + session->cancel(); + } + + m_pending_requests.clear(); + } + // ================================================================================ // // API REQUESTS // // ================================================================================ // @@ -102,7 +112,8 @@ namespace kiwi fail(res); }; - storeFuture(session->PostAsync(std::move(cb))); + session->PostAsync(std::move(cb)); + storeSession(std::move(session)); } void Api::signup(std::string const& username, @@ -147,7 +158,8 @@ namespace kiwi } }; - storeFuture(session->PostAsync(std::move(cb))); + session->GetAsync(std::move(cb)); + storeSession(std::move(session)); } void Api::getDocuments(std::function callback) @@ -173,7 +185,9 @@ namespace kiwi }; auto session = makeSession(Endpoint::documents); - storeFuture(session->GetAsync(std::move(cb))); + + session->GetAsync(std::move(cb)); + storeSession(std::move(session)); } void Api::createDocument(std::string const& document_name, @@ -208,7 +222,8 @@ namespace kiwi }); } - storeFuture(session->PostAsync(std::move(cb))); + session->PostAsync(std::move(cb)); + storeSession(std::move(session)); } void Api::renameDocument(std::string document_id, std::string const& new_name, @@ -221,7 +236,8 @@ namespace kiwi {"name", new_name} }); - storeFuture(session->PutAsync(std::move(callback))); + session->PutAsync(std::move(callback)); + storeSession(std::move(session)); } void Api::getLatestRelease(CallbackFn success_cb, ErrorCallback error_cb) @@ -249,7 +265,8 @@ namespace kiwi } }; - storeFuture(session->GetAsync(std::move(cb))); + session->GetAsync(std::move(cb)); + storeSession(std::move(session)); } void Api::requestPasswordToken(std::string const& user_mail, CallbackFn success_cb, ErrorCallback error_cb) @@ -281,7 +298,8 @@ namespace kiwi } }; - storeFuture(session->PostAsync(std::move(cb))); + session->PostAsync(std::move(cb)); + storeSession(std::move(session)); } void Api::resetPassword(std::string const& token, @@ -317,7 +335,8 @@ namespace kiwi } }; - storeFuture(session->PostAsync(std::move(cb))); + session->PostAsync(std::move(cb)); + storeSession(std::move(session)); } bool Api::hasJsonHeader(Response const& res) @@ -343,18 +362,21 @@ namespace kiwi return std::move(session); } - void Api::storeFuture(std::future && future) + void Api::storeSession(std::unique_ptr session) { - for(std::future& f : m_pending_requests) + for(auto it = m_pending_requests.begin(); it != m_pending_requests.end();) { - if(f.wait_for(std::chrono::seconds(0)) == std::future_status::ready) + if (!(*it)->isPending()) + { + it = m_pending_requests.erase(it); + } + else { - f = std::move(future); - return; + ++it; } } - m_pending_requests.emplace_back(std::move(future)); + m_pending_requests.emplace_back(std::move(session)); } // ================================================================================ // diff --git a/Client/Source/KiwiApp_Network/KiwiApp_Api.h b/Client/Source/KiwiApp_Network/KiwiApp_Api.h index 79f6200f..23b755ed 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_Api.h +++ b/Client/Source/KiwiApp_Network/KiwiApp_Api.h @@ -69,6 +69,9 @@ namespace kiwi //! @brief Destructor ~Api(); + //! @brief Cancel pending execution. + void cancelPendingRequest(); + public: // requests //! @brief Attempt to log-in the user. @@ -142,15 +145,15 @@ namespace kiwi std::unique_ptr makeSession(std::string const& endpoint, bool add_auth = true); //! @internal Store the async future response in a vector - void storeFuture(std::future && future); + void storeSession(std::unique_ptr session); //! @internal Check if the response header has a JSON content-type static bool hasJsonHeader(Response const& res); private: // variables - Api::Controller& m_controller; - std::vector> m_pending_requests; + Api::Controller& m_controller; + std::vector> m_pending_requests; private: // deleted methods diff --git a/Modules/KiwiNetwork/KiwiHttp/KiwiHttp.h b/Modules/KiwiNetwork/KiwiHttp/KiwiHttp.h index 42ccf663..9d8f3ec7 100644 --- a/Modules/KiwiNetwork/KiwiHttp/KiwiHttp.h +++ b/Modules/KiwiNetwork/KiwiHttp/KiwiHttp.h @@ -77,7 +77,7 @@ namespace kiwi { namespace network { namespace http { // QUERY // // ================================================================================ // - template + template class Query { public: // methods @@ -90,9 +90,12 @@ namespace kiwi { namespace network { namespace http { //! @brief Destructor. ~Query(); - //! @brief Write the request and get the response. - template - Response writeRequest(); + //! @brief Process the underlying service. + //! @details Returns if the request terminated and response can be returned. + bool process(); + + //! @brief Returns the reponse of the query. + Response const& getResponse() const; private: // methods @@ -102,18 +105,15 @@ namespace kiwi { namespace network { namespace http { void handleTimeout(beast::error_code const& error); //! @internal - template void connect(Response& response, beast::error_code const& error, tcp::resolver::iterator iterator); //! @internal - template void write(Response& response, beast::error_code const& error); //! @internal - template void read(Response& response, beast::error_code const& error); @@ -123,13 +123,14 @@ namespace kiwi { namespace network { namespace http { private: // members std::unique_ptr> m_request; + Response m_response; Error m_error; - Timeout m_timeout; std::string m_port; boost::asio::io_service m_io_service; tcp::socket m_socket; boost::asio::steady_timer m_timer; + tcp::resolver m_resolver; beast::flat_buffer m_buffer; private: // deleted methods diff --git a/Modules/KiwiNetwork/KiwiHttp/KiwiHttp.hpp b/Modules/KiwiNetwork/KiwiHttp/KiwiHttp.hpp index fc1c46b1..6e71438e 100644 --- a/Modules/KiwiNetwork/KiwiHttp/KiwiHttp.hpp +++ b/Modules/KiwiNetwork/KiwiHttp/KiwiHttp.hpp @@ -33,7 +33,11 @@ namespace kiwi { namespace network { namespace http { std::string port, Timeout timeout) { - return Query(std::move(request), port, timeout).template writeRequest(); + Query query(std::move(request), port, timeout); + + while(!query.process()){} + + return query.getResponse(); } template @@ -43,12 +47,13 @@ namespace kiwi { namespace network { namespace http { std::function)> callback, Timeout timeout) { - auto query = std::make_unique>(std::move(request), port, timeout); + auto query = std::make_unique>(std::move(request), port, timeout); - return std::async(std::launch::async, [query = std::move(query), cb = std::move(callback)]() { - - return cb(query->template writeRequest()); + return std::async(std::launch::async, [query = std::move(query), cb = std::move(callback)]() + { + while(!query->process()){} + return cb(query->getResponse()); }); } @@ -56,86 +61,75 @@ namespace kiwi { namespace network { namespace http { // HTTP QUERY // // ================================================================================ // - template - Query::Query(std::unique_ptr> request, - std::string port, - Timeout timeout) + template + Query::Query(std::unique_ptr> request, + std::string port, + Timeout timeout) : m_request(std::move(request)) - , m_error() - , m_timeout(timeout) + , m_response() , m_port(port) , m_io_service() , m_socket(m_io_service) , m_timer(m_io_service) + , m_resolver(m_io_service) , m_buffer() { - ; - } - - template - Query::~Query() - { - ; - } - - template - template - Response - Query::writeRequest() - { - if (m_timeout > Timeout(0)) + if (timeout > Timeout(0)) { - m_timer.expires_from_now(m_timeout); + m_timer.expires_from_now(timeout); - m_timer.async_wait([this](Error const& error) { + m_timer.async_wait([this](Error const& error) + { handleTimeout(error); }); } - tcp::resolver resolver(m_io_service); - const std::string host = m_request->at(beast::http::field::host).to_string(); - Response response; - - resolver.async_resolve({host, m_port}, [this, &response](Error const& error, - tcp::resolver::iterator iterator) { - connect(response, error, iterator); + m_resolver.async_resolve({host, m_port}, [this](Error const& error, + tcp::resolver::iterator iterator) + { + connect(m_response, error, iterator); }); m_io_service.reset(); - - // block here until error or success - while(!m_error && m_io_service.run_one()) - { - ; - } - - response.error = m_error; - - return std::move(response); - }; + } + + template + Query::~Query() + { + ; + } - template - void - Query::handleTimeout(Error const& error) + template + bool Query::process() + { + return !m_io_service.run_one() || !m_response.error; + } + + template + Response const& Query::getResponse() const + { + return m_response; + } + + template + void Query::handleTimeout(Error const& error) { m_io_service.stop(); m_socket.shutdown(tcp::socket::shutdown_both, m_error); - m_error = boost::asio::error::basic_errors::timed_out; + m_response.error = boost::asio::error::basic_errors::timed_out; } - template - template - void - Query::connect(Response& response, - Error const& error, - tcp::resolver::iterator iterator) + template + void Query::connect(Response& response, + Error const& error, + tcp::resolver::iterator iterator) { if (error) { - m_error = error; + m_response.error = error; } else { @@ -146,15 +140,13 @@ namespace kiwi { namespace network { namespace http { } } - template - template - void - Query::write(Response& response, - beast::error_code const& error) + template + void Query::write(Response& response, + beast::error_code const& error) { if (error) { - m_error = error; + m_response.error = error; } else { @@ -164,11 +156,9 @@ namespace kiwi { namespace network { namespace http { } } - template - template - void - Query::read(Response& response, - Error const& error) + template + void Query::read(Response& response, + Error const& error) { if (error) { @@ -182,9 +172,8 @@ namespace kiwi { namespace network { namespace http { } } - template - void - Query::shutdown(Error const& error) + template + void Query::shutdown(Error const& error) { m_io_service.stop(); diff --git a/Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Session.cpp b/Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Session.cpp index 6105995c..9159bfed 100644 --- a/Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Session.cpp +++ b/Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Session.cpp @@ -97,6 +97,8 @@ namespace kiwi { namespace network { namespace http { , m_payload() , m_body() , m_timeout(0) + , m_future() + , m_keep_processing(false) , m_req_header() { ; @@ -137,14 +139,24 @@ namespace kiwi { namespace network { namespace http { m_payload = std::move(payload); } + bool Session::isPending() + { + return m_future.valid() && m_future.wait_for(std::chrono::seconds(0)) != std::future_status::ready; + } + + void Session::cancel() + { + m_keep_processing = false; + } + Session::Response Session::Get() { return makeResponse(beast::http::verb::get); } - Session::AsyncResponse Session::GetAsync(Callback callback) + void Session::GetAsync(Callback callback) { - return makeResponse(beast::http::verb::get, std::move(callback)); + makeResponse(beast::http::verb::get, std::move(callback)); } Session::Response Session::Post() @@ -152,9 +164,9 @@ namespace kiwi { namespace network { namespace http { return makeResponse(beast::http::verb::post); } - Session::AsyncResponse Session::PostAsync(Callback callback) + void Session::PostAsync(Callback callback) { - return makeResponse(beast::http::verb::post, std::move(callback)); + makeResponse(beast::http::verb::post, std::move(callback)); } Session::Response Session::Put() @@ -162,9 +174,9 @@ namespace kiwi { namespace network { namespace http { return makeResponse(beast::http::verb::put); } - Session::AsyncResponse Session::PutAsync(Callback callback) + void Session::PutAsync(Callback callback) { - return makeResponse(beast::http::verb::put, std::move(callback)); + makeResponse(beast::http::verb::put, std::move(callback)); } Session::Response Session::Delete() @@ -172,12 +184,12 @@ namespace kiwi { namespace network { namespace http { return makeResponse(beast::http::verb::delete_); } - Session::AsyncResponse Session::DeleteAsync(Callback callback) + void Session::DeleteAsync(Callback callback) { - return makeResponse(beast::http::verb::delete_, std::move(callback)); + makeResponse(beast::http::verb::delete_, std::move(callback)); } - std::unique_ptr> Session::makeQuery() + std::unique_ptr> Session::makeQuery() { const auto makeTarget = [this]() { @@ -215,20 +227,33 @@ namespace kiwi { namespace network { namespace http { } request->prepare_payload(); - return std::make_unique>(std::move(request), m_port, m_timeout); + return std::make_unique>(std::move(request), m_port, m_timeout); } Session::Response Session::makeResponse(beast::http::verb verb) { m_req_header.method(verb); - return std::move(makeQuery()->writeRequest()); + + auto query = makeQuery(); + + while(!query->process()){} + + return query->getResponse(); } - Session::AsyncResponse Session::makeResponse(beast::http::verb verb, Session::Callback && callback) + void Session::makeResponse(beast::http::verb verb, Session::Callback && callback) { m_req_header.method(verb); - return std::async(std::launch::async, [query = makeQuery(), cb = std::move(callback)]() { - return cb(std::move(query->writeRequest())); + + m_future = std::async(std::launch::async, [this, query = makeQuery(), cb = std::move(callback)]() + { + while(m_keep_processing) + { + if (query->process()) + { + cb(query->getResponse()); + } + } }); } diff --git a/Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Session.h b/Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Session.h index 84b223c7..be9871d7 100644 --- a/Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Session.h +++ b/Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Session.h @@ -113,31 +113,36 @@ namespace kiwi { namespace network { namespace http { void setPayload(Payload && payload); void setBody(Body && body); + bool isPending(); + void cancel(); + Response Get(); - AsyncResponse GetAsync(Callback callback); + void GetAsync(Callback callback); Response Post(); - AsyncResponse PostAsync(Callback callback); + void PostAsync(Callback callback); Response Put(); - AsyncResponse PutAsync(Callback callback); + void PutAsync(Callback callback); Response Delete(); - AsyncResponse DeleteAsync(Callback callback); + void DeleteAsync(Callback callback); private: // variables - std::unique_ptr> makeQuery(); + std::unique_ptr> makeQuery(); Response makeResponse(beast::http::verb verb); - AsyncResponse makeResponse(beast::http::verb verb, Callback && callback); - - std::string m_port; - std::string m_target; - Parameters m_parameters; - Payload m_payload; - Body m_body; - Timeout m_timeout; + void makeResponse(beast::http::verb verb, Callback && callback); + + std::string m_port; + std::string m_target; + Parameters m_parameters; + Payload m_payload; + Body m_body; + Timeout m_timeout; + std::future m_future; + std::atomic m_keep_processing; beast::http::request_header<> m_req_header; }; diff --git a/Test/Network/test_Http.cpp b/Test/Network/test_Http.cpp index 36b87092..3e70f842 100755 --- a/Test/Network/test_Http.cpp +++ b/Test/Network/test_Http.cpp @@ -93,12 +93,10 @@ TEST_CASE("Network - Http Session", "[Network, Http]") session.setHost("httpbin.org"); session.setTarget("/get"); - auto future = session.GetAsync([](http::Session::Response response) { + session.GetAsync([](http::Session::Response response) { REQUIRE(!response.error); CHECK(response.result() == beast::http::status::ok); }); - - future.get(); } SECTION("Session GetAsync with Parameters") From 85981ef2bff225cf333aac3e9ac69d37a0ca78e1 Mon Sep 17 00:00:00 2001 From: jmillot Date: Tue, 23 Jan 2018 22:34:17 +0100 Subject: [PATCH 120/148] Fixup Kiwi network. --- Client/Source/KiwiApp_Network/KiwiApp_Api.cpp | 3 +- Modules/KiwiNetwork/KiwiHttp/KiwiHttp.h | 11 +-- Modules/KiwiNetwork/KiwiHttp/KiwiHttp.hpp | 89 +++++++++---------- .../KiwiNetwork/KiwiHttp/KiwiHttp_Session.cpp | 3 +- 4 files changed, 49 insertions(+), 57 deletions(-) diff --git a/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp b/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp index df504772..a7575b64 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp +++ b/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp @@ -141,6 +141,7 @@ namespace kiwi && hasJsonHeader(res) && res.result() == beast::http::status::ok) { + const auto j = json::parse(res.body); if(j.is_object() && j.count("message")) @@ -158,7 +159,7 @@ namespace kiwi } }; - session->GetAsync(std::move(cb)); + session->PostAsync(std::move(cb)); storeSession(std::move(session)); } diff --git a/Modules/KiwiNetwork/KiwiHttp/KiwiHttp.h b/Modules/KiwiNetwork/KiwiHttp/KiwiHttp.h index 9d8f3ec7..41f80b70 100644 --- a/Modules/KiwiNetwork/KiwiHttp/KiwiHttp.h +++ b/Modules/KiwiNetwork/KiwiHttp/KiwiHttp.h @@ -105,17 +105,13 @@ namespace kiwi { namespace network { namespace http { void handleTimeout(beast::error_code const& error); //! @internal - void connect(Response& response, - beast::error_code const& error, - tcp::resolver::iterator iterator); + void connect(tcp::resolver::iterator iterator); //! @internal - void write(Response& response, - beast::error_code const& error); + void write(); //! @internal - void read(Response& response, - beast::error_code const& error); + void read(); //! @internal void shutdown(beast::error_code const& error); @@ -124,7 +120,6 @@ namespace kiwi { namespace network { namespace http { std::unique_ptr> m_request; Response m_response; - Error m_error; std::string m_port; boost::asio::io_service m_io_service; diff --git a/Modules/KiwiNetwork/KiwiHttp/KiwiHttp.hpp b/Modules/KiwiNetwork/KiwiHttp/KiwiHttp.hpp index 6e71438e..b76712ed 100644 --- a/Modules/KiwiNetwork/KiwiHttp/KiwiHttp.hpp +++ b/Modules/KiwiNetwork/KiwiHttp/KiwiHttp.hpp @@ -81,6 +81,7 @@ namespace kiwi { namespace network { namespace http { m_timer.async_wait([this](Error const& error) { handleTimeout(error); + }); } @@ -89,7 +90,14 @@ namespace kiwi { namespace network { namespace http { m_resolver.async_resolve({host, m_port}, [this](Error const& error, tcp::resolver::iterator iterator) { - connect(m_response, error, iterator); + if (error) + { + shutdown(error); + } + else + { + connect(iterator); + } }); m_io_service.reset(); @@ -104,7 +112,7 @@ namespace kiwi { namespace network { namespace http { template bool Query::process() { - return !m_io_service.run_one() || !m_response.error; + return !m_io_service.run_one() || m_response.error; } template @@ -116,60 +124,48 @@ namespace kiwi { namespace network { namespace http { template void Query::handleTimeout(Error const& error) { - m_io_service.stop(); - - m_socket.shutdown(tcp::socket::shutdown_both, m_error); - m_response.error = boost::asio::error::basic_errors::timed_out; + shutdown(boost::asio::error::basic_errors::timed_out); } template - void Query::connect(Response& response, - Error const& error, - tcp::resolver::iterator iterator) + void Query::connect(tcp::resolver::iterator iterator) { - if (error) - { - m_response.error = error; - } - else - { - boost::asio::async_connect(m_socket, iterator, [this, &response](Error const& error, - tcp::resolver::iterator i) { - this->write(response, error); - }); - } + boost::asio::async_connect(m_socket, iterator, [this](Error const& error, + tcp::resolver::iterator i) { + if (error) + { + shutdown(error); + } + else + { + write(); + } + }); } template - void Query::write(Response& response, - beast::error_code const& error) + void Query::write() { - if (error) + beast::http::async_write(m_socket, *m_request, [this](Error const& error) { - m_response.error = error; - } - else - { - beast::http::async_write(m_socket, *m_request, [this, &response](Error const& error) { - read(response, error); - }); - } + if (error) + { + shutdown(error); + } + else + { + read(); + } + }); } template - void Query::read(Response& response, - Error const& error) + void Query::read() { - if (error) - { - m_error = error; - } - else + beast::http::async_read(m_socket, m_buffer, m_response, [this](Error const& error) { - beast::http::async_read(m_socket, m_buffer, response, [this](Error const& error) { - shutdown(error); - }); - } + shutdown(error); + }); } template @@ -179,12 +175,11 @@ namespace kiwi { namespace network { namespace http { if (error) { - m_error = error; - } - else - { - m_socket.shutdown(tcp::socket::shutdown_both, m_error); + m_response.error = error; } + + boost::system::error_code ec; + m_socket.shutdown(tcp::socket::shutdown_both, ec); } }}} // namespace kiwi::network::http diff --git a/Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Session.cpp b/Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Session.cpp index 9159bfed..ba378126 100644 --- a/Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Session.cpp +++ b/Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Session.cpp @@ -98,7 +98,7 @@ namespace kiwi { namespace network { namespace http { , m_body() , m_timeout(0) , m_future() - , m_keep_processing(false) + , m_keep_processing(true) , m_req_header() { ; @@ -252,6 +252,7 @@ namespace kiwi { namespace network { namespace http { if (query->process()) { cb(query->getResponse()); + m_keep_processing = false; } } }); From f4eaa7b27beb7b5367e0a09962384b48b5a22a5a Mon Sep 17 00:00:00 2001 From: jmillot Date: Thu, 25 Jan 2018 18:49:36 +0100 Subject: [PATCH 121/148] Updating Kiwi to handle new doc info. --- .../KiwiApp_DocumentBrowserView.cpp | 355 +++++++++++++++--- .../KiwiApp_DocumentBrowserView.h | 90 ++++- Client/Source/KiwiApp_Network/KiwiApp_Api.cpp | 44 ++- Client/Source/KiwiApp_Network/KiwiApp_Api.h | 10 + .../KiwiApp_DocumentBrowser.cpp | 118 +++++- .../KiwiApp_Network/KiwiApp_DocumentBrowser.h | 26 ++ 6 files changed, 551 insertions(+), 92 deletions(-) diff --git a/Client/Source/KiwiApp_Application/KiwiApp_DocumentBrowserView.cpp b/Client/Source/KiwiApp_Application/KiwiApp_DocumentBrowserView.cpp index 5126b794..a8a226fa 100644 --- a/Client/Source/KiwiApp_Application/KiwiApp_DocumentBrowserView.cpp +++ b/Client/Source/KiwiApp_Application/KiwiApp_DocumentBrowserView.cpp @@ -99,7 +99,9 @@ namespace kiwi // DOCUMENT SESSION VIEW // // ================================================================================ // - DocumentBrowserView::DriveView::RowElem::RowElem(DriveView& drive_view, std::string const& name) : + DocumentBrowserView::DriveView::RowElem::RowElem(DriveView& drive_view, + std::string const& name, + std::string const& tooltip) : m_drive_view(drive_view), m_name(name), m_open_btn("open", std::unique_ptr(juce::Drawable::createFromImageData(binary_data::images::open_png, binary_data::images::open_png_size)), ImageButton::ButtonStyle::ImageFitted), @@ -107,7 +109,7 @@ namespace kiwi binary_data::images::kiwi_filetype_png_size)), m_row(-1) { - addMouseListener(this, true); + setTooltip(tooltip); m_open_btn.setCommand(std::bind(&DriveView::openDocument, &m_drive_view, m_row)); m_open_btn.setSize(40, 40); @@ -129,26 +131,22 @@ namespace kiwi removeMouseListener(this); } - void DocumentBrowserView::DriveView::RowElem::update(std::string const& name, int row, bool now_selected) + void DocumentBrowserView::DriveView::RowElem::update(std::string const& name, + std::string const& tooltip, + int row, + bool now_selected) { - if(row != m_row) - { - m_row = row; - m_open_btn.setCommand(std::bind(&DriveView::openDocument, &m_drive_view, m_row)); - } + setTooltip(tooltip); - if(name != m_name) - { - m_name = name; - m_name_label.setText(m_name, juce::NotificationType::dontSendNotification); - } + m_row = row; + m_open_btn.setCommand(std::bind(&DriveView::openDocument, &m_drive_view, m_row)); - if(m_selected != now_selected) - { - m_selected = now_selected; - m_open_btn.setVisible(m_selected); - repaint(); - } + m_name = name; + m_name_label.setText(m_name, juce::NotificationType::dontSendNotification); + + m_selected = now_selected; + m_open_btn.setVisible(m_selected); + repaint(); } void DocumentBrowserView::DriveView::RowElem::paint(juce::Graphics& g) @@ -191,31 +189,82 @@ namespace kiwi repaint(); } - void DocumentBrowserView::DriveView::RowElem::mouseDown(juce::MouseEvent const& e) + void DocumentBrowserView::DriveView::RowElem::showPopup() { - m_select_row_on_mouse_up = false; + juce::PopupMenu m; + + m.addItem(1, "Rename"); + m.addItem(2, m_drive_view.getTrashMode() ? "Restore" : "Delete"); + + DriveView::SortType current_sort = m_drive_view.getSortType(); + + juce::PopupMenu sort_menu; + sort_menu.addItem(3, "Name", + current_sort != DriveView::SortType::name, + current_sort == DriveView::SortType::name); + + sort_menu.addItem(4, "Created at", + current_sort != DriveView::SortType::creationDate, + current_sort == DriveView::SortType::creationDate); + + sort_menu.addItem(5, "Created by", + current_sort != DriveView::SortType::author, + current_sort == DriveView::SortType::author); + + m.addSubMenu("Sort by", sort_menu); - if(isEnabled()) + int result = m.show(); + + switch(result) { - if(!m_selected) + case 1: // rename + { + m_name_label.showEditor(); + break; + } + case 2: // delete/Restore + { + if (!m_drive_view.getTrashMode()) + { + m_drive_view.deleteDocumentForRow(m_row); + } + else + { + m_drive_view.restoreDocumentForRow(m_row); + } + break; + } + case 3: // sort by name { - m_drive_view.selectRowsBasedOnModifierKeys(m_row, e.mods, false); + m_drive_view.setSortType(DriveView::SortType::name); + break; } - else + case 4: // sort by creation date { - m_select_row_on_mouse_up = true; + m_drive_view.setSortType(DriveView::SortType::creationDate); + break; + } + case 5: + { + m_drive_view.setSortType(DriveView::SortType::author); } } } - void DocumentBrowserView::DriveView::RowElem::mouseUp(juce::MouseEvent const& e) + void DocumentBrowserView::DriveView::RowElem::mouseDown(juce::MouseEvent const& e) { - if(m_select_row_on_mouse_up && e.mouseWasClicked() && isEnabled()) + m_drive_view.selectRow(m_row); + + if (e.mods.isPopupMenu()) { - m_drive_view.selectRowsBasedOnModifierKeys(m_row, e.mods, true); + showPopup(); } } + void DocumentBrowserView::DriveView::RowElem::mouseUp(juce::MouseEvent const& e) + { + } + void DocumentBrowserView::DriveView::RowElem::mouseDoubleClick(juce::MouseEvent const& event) { m_drive_view.listBoxItemDoubleClicked(m_row, event); @@ -226,6 +275,8 @@ namespace kiwi if(label == &m_name_label) { m_drive_view.renameDocumentForRow(m_row, m_name_label.getText().toStdString()); + + m_name_label.setText(m_name, juce::NotificationType::dontSendNotification); } } @@ -238,31 +289,78 @@ namespace kiwi // BROWSER DRIVE VIEW HEADER // // ================================================================================ // - DocumentBrowserView::DriveView::Header::Header(juce::ListBox& listbox, DocumentBrowser::Drive& drive) : - m_listbox(listbox), - m_drive(drive), - m_refresh_btn("refresh", std::unique_ptr(juce::Drawable::createFromImageData(binary_data::images::refresh_png, binary_data::images::refresh_png_size))), - m_create_document_btn("create", std::unique_ptr(juce::Drawable::createFromImageData(binary_data::images::plus_png, binary_data::images::plus_png_size))), + DocumentBrowserView::DriveView::Header::Header(DocumentBrowserView::DriveView& drive_view): + m_drive_view(drive_view), + m_refresh_btn("refresh", + std::unique_ptr + (juce::Drawable::createFromImageData(binary_data::images::refresh_png, + binary_data::images::refresh_png_size))), + m_create_document_btn("create", + std::unique_ptr + (juce::Drawable::createFromImageData(binary_data::images::plus_png, + binary_data::images::plus_png_size))), + m_trash_btn("trash", + std::unique_ptr + (juce::Drawable::createFromImageData(binary_data::images::trash_png, + binary_data::images::trash_png_size))), + m_search_bar(), + m_folder_bounds(), + m_label("drive_name", m_drive_view.getDriveName()), m_folder_img(juce::ImageCache::getFromMemory(binary_data::images::folder_png, binary_data::images::folder_png_size)) { - m_create_document_btn.setCommand(std::bind(&DocumentBrowser::Drive::createNewDocument, &m_drive)); + m_label.setFont(m_label.getFont().withHeight(20)); + m_label.setEditable(false); + m_label.setColour(juce::Label::textColourId, juce::Colours::whitesmoke); + addAndMakeVisible(m_label); + + m_search_bar.setPopupMenuEnabled(false); + addAndMakeVisible(m_search_bar); + + m_create_document_btn.setCommand([this](){m_drive_view.createDocument();}); m_create_document_btn.setSize(40, 40); m_create_document_btn.setTooltip("Create a new patcher on this drive"); m_create_document_btn.setColour(ImageButton::ColourIds::textColourId, juce::Colours::whitesmoke); addAndMakeVisible(m_create_document_btn); - m_refresh_btn.setCommand(std::bind(&DocumentBrowser::Drive::refresh, &m_drive)); + m_refresh_btn.setCommand([this](){m_drive_view.refresh();}); m_refresh_btn.setSize(40, 40); m_refresh_btn.setTooltip("Refresh Document list"); m_refresh_btn.setColour(ImageButton::ColourIds::textColourId, juce::Colours::whitesmoke); addAndMakeVisible(m_refresh_btn); + + m_trash_btn.setCommand([this]() + { + m_trash_btn.setAlpha(!m_drive_view.getTrashMode() ? 1. : 0.5); + m_drive_view.setTrashMode(!m_drive_view.getTrashMode()); + + }); + m_trash_btn.setAlpha(m_drive_view.getTrashMode() ? 1. : 0.5); + m_trash_btn.setSize(40, 40); + m_trash_btn.setTooltip("Display trashed documents"); + addAndMakeVisible(m_trash_btn); + } void DocumentBrowserView::DriveView::Header::resized() { - m_refresh_btn.setTopRightPosition(getWidth(), 5); - m_create_document_btn.setTopRightPosition(m_refresh_btn.getX(), 5); + const auto bounds = getLocalBounds(); + + m_folder_bounds = bounds.withRight(getHeight()).reduced(10); + + m_trash_btn.setTopRightPosition(getWidth(), 5); + m_refresh_btn.setTopRightPosition(m_trash_btn.getX(), 5); + m_create_document_btn.setTopRightPosition(m_refresh_btn.getX(), 5); + + int text_width = m_label.getFont().getStringWidth(m_label.getText()); + + int remaining_width = std::max(0, m_create_document_btn.getX() - m_folder_bounds.getRight()); + + m_label.setBounds(bounds.withX(m_folder_bounds.getRight() + 5).withWidth(std::min(text_width, remaining_width / 2))); + + m_search_bar.setBounds(bounds.withX(m_label.getBounds().getRight()) + .withRight(m_create_document_btn.getX()) + .reduced(0, 13)); } void DocumentBrowserView::DriveView::Header::paint(juce::Graphics& g) @@ -272,20 +370,10 @@ namespace kiwi g.fillAll(color); - const auto bounds = getLocalBounds(); - - const auto folder_img_bounds = bounds.withRight(getHeight()).reduced(10); - - g.drawImage(m_folder_img, folder_img_bounds.toFloat(), + g.drawImage(m_folder_img, m_folder_bounds.toFloat(), juce::RectanglePlacement::yMid, false); - g.setColour(juce::Colours::whitesmoke); - g.setFont(18); - g.drawFittedText(m_drive.getName(), - bounds - .withLeft(folder_img_bounds.getRight() + 10) - .withRight(m_create_document_btn.getX() - 5), - juce::Justification::centredLeft, 1); + const auto bounds = getLocalBounds(); g.setColour(color.darker(0.3)); g.drawHorizontalLine(bounds.getBottom() - 1, 0, getWidth()); @@ -293,7 +381,11 @@ namespace kiwi void DocumentBrowserView::DriveView::Header::mouseDown(juce::MouseEvent const& e) { - m_listbox.getModel()->backgroundClicked(e); + m_drive_view.getModel()->backgroundClicked(e); + } + + void DocumentBrowserView::DriveView::Header::textEditorReturnKeyPressed(juce::TextEditor & text_editor) + { } // ================================================================================ // @@ -302,22 +394,30 @@ namespace kiwi DocumentBrowserView::DriveView::DriveView(DocumentBrowser::Drive& drive) : juce::ListBox("document list", this), - m_drive(drive) + m_drive(drive), + m_trash_mode(false), + m_sorter() { m_drive.addListener(*this); setMultipleSelectionEnabled(false); - setRowSelectedOnMouseDown(true); + setRowSelectedOnMouseDown(false); setRowHeight(40); - auto* header = new Header(*this, m_drive); + auto* header = new Header(*this); header->setSize(getWidth(), 50); setHeaderComponent(header); getViewport()->setScrollBarThickness(10); juce::ListBox::setColour(juce::ListBox::backgroundColourId, juce::Colour(0xFFD4D4D4)); - updateContent(); + m_drive.setSort([sorter = m_sorter](DocumentBrowser::Drive::DocumentSession const& l_hs, + DocumentBrowser::Drive::DocumentSession const& r_hs) + { + return sorter.compare(l_hs, r_hs); + }); + + update(); } DocumentBrowserView::DriveView::~DriveView() @@ -325,15 +425,57 @@ namespace kiwi m_drive.removeListener(*this); } + bool DocumentBrowserView::DriveView::Comp::compare(DocumentBrowser::Drive::DocumentSession const& l_hs, + DocumentBrowser::Drive::DocumentSession const& r_hs) const + { + bool type_ordered = false; + + switch(m_type) + { + case SortType::name: + { + type_ordered = l_hs.getName() < r_hs.getName(); + break; + } + case SortType::author: + { + type_ordered = l_hs.getAuthor() < r_hs.getAuthor(); + break; + } + case SortType::creationDate: + { + type_ordered = l_hs.getCreationDate() < r_hs.getCreationDate(); + break; + } + } + + bool trash_order = (m_trashed_first && l_hs.isTrashed() > r_hs.isTrashed()) + || (!m_trashed_first && l_hs.isTrashed() < r_hs.isTrashed()); + + return trash_order + || (l_hs.isTrashed() == r_hs.isTrashed() && type_ordered); + } + void DocumentBrowserView::DriveView::driveChanged() { - updateContent(); - repaint(); + update(); } int DocumentBrowserView::DriveView::getNumRows() { - return m_drive.getDocuments().size(); + int num_rows = 0; + + auto const& documents = m_drive.getDocuments(); + + num_rows = std::count_if(documents.begin(), + documents.end(), + [trash_mode = m_trash_mode] + (std::unique_ptr const& doc) + { + return trash_mode ? doc->isTrashed() : !doc->isTrashed(); + }); + + return num_rows; } void DocumentBrowserView::DriveView::paintListBoxItem(int rowNumber, juce::Graphics& g, @@ -342,6 +484,76 @@ namespace kiwi ; } + std::string const& DocumentBrowserView::DriveView::getDriveName() const + { + return m_drive.getName(); + } + + void DocumentBrowserView::DriveView::refresh() + { + m_drive.refresh(); + } + + void DocumentBrowserView::DriveView::createDocument() + { + m_drive.createNewDocument(); + } + + void DocumentBrowserView::DriveView::setTrashMode(bool trash_mode) + { + m_trash_mode = trash_mode; + + m_sorter.m_trashed_first = m_trash_mode; + + m_drive.setSort([sorter = m_sorter](DocumentBrowser::Drive::DocumentSession const& l_hs, + DocumentBrowser::Drive::DocumentSession const& r_hs) + { + return sorter.compare(l_hs, r_hs); + }); + } + + DocumentBrowserView::DriveView::SortType DocumentBrowserView::DriveView::getSortType() const + { + return m_sorter.m_type; + } + + void DocumentBrowserView::DriveView::setSortType(SortType sort_type) + { + m_sorter.m_type = sort_type; + + m_drive.setSort([sorter = m_sorter](DocumentBrowser::Drive::DocumentSession const& l_hs, + DocumentBrowser::Drive::DocumentSession const& r_hs) + { + return sorter.compare(l_hs, r_hs); + + }); + } + + bool DocumentBrowserView::DriveView::getTrashMode() const + { + return m_trash_mode; + } + + void DocumentBrowserView::DriveView::update() + { + updateContent(); + repaint(); + } + + std::string DocumentBrowserView::DriveView::createDocumentToolTip(DocumentBrowser::Drive::DocumentSession const& doc) + { + std::string tooltip = "name: " + doc.getName() + "\n" + + "created by: " + doc.getAuthor() + "\n" + + "created at: " + doc.getCreationDate() + "\n"; + + if (doc.isTrashed()) + { + tooltip += "trashed at: " + doc.getTrashedDate(); + } + + return tooltip; + } + juce::Component* DocumentBrowserView::DriveView::refreshComponentForRow(int row, bool selected, juce::Component* c) { @@ -359,10 +571,13 @@ namespace kiwi { if(c == nullptr) { - c = new RowElem(*this, documents[row]->getName()); + c = new RowElem(*this, documents[row]->getName(), createDocumentToolTip(*documents[row])); } - static_cast(c)->update(documents[row]->getName(), row, selected); + static_cast(c)->update(documents[row]->getName(), + createDocumentToolTip(*documents[row]), + row, + selected); } return c; @@ -394,6 +609,26 @@ namespace kiwi } } + void DocumentBrowserView::DriveView::restoreDocumentForRow(int row) + { + auto & documents = m_drive.getDocuments(); + + if (row < documents.size()) + { + documents[row]->untrash(); + } + } + + void DocumentBrowserView::DriveView::deleteDocumentForRow(int row) + { + auto & documents = m_drive.getDocuments(); + + if (row < documents.size()) + { + documents[row]->trash(); + } + } + void DocumentBrowserView::DriveView::renameDocumentForRow(int row, std::string const& new_name) { auto& documents = m_drive.getDocuments(); diff --git a/Client/Source/KiwiApp_Application/KiwiApp_DocumentBrowserView.h b/Client/Source/KiwiApp_Application/KiwiApp_DocumentBrowserView.h index 5cb23d1c..0298d7b4 100644 --- a/Client/Source/KiwiApp_Application/KiwiApp_DocumentBrowserView.h +++ b/Client/Source/KiwiApp_Application/KiwiApp_DocumentBrowserView.h @@ -77,7 +77,25 @@ namespace kiwi public juce::ListBoxModel, public DocumentBrowser::Drive::Listener { - public: + private: // classes + + enum class SortType + { + name, + author, + creationDate + }; + + struct Comp + { + bool compare(DocumentBrowser::Drive::DocumentSession const& l_hs, + DocumentBrowser::Drive::DocumentSession const& r_hs) const; + + SortType m_type = SortType::creationDate; + bool m_trashed_first = false; + }; + + public: // methods //! @brief Constructor. DriveView(DocumentBrowser::Drive& drive); @@ -122,6 +140,41 @@ namespace kiwi //! @brief Make an API call to rename the remote document void renameDocumentForRow(int row, std::string const& new_name); + //! @brief Moves a document to trash. + void deleteDocumentForRow(int row); + + //! @brief Restore a trashed document. + void restoreDocumentForRow(int row); + + private: // methods + + //! @brief Resort content and call update content. + void update(); + + //! @brief Returns the drive name. + std::string const& getDriveName() const; + + //! @brief Refresh document list. + void refresh(); + + //! @brief Creates a new document. + void createDocument(); + + //! @brief Returns the current sorting parameter. + SortType getSortType() const; + + //! @brief Changes the sort parameter and sorts. + void setSortType(SortType sort_type); + + // @brief Set the trash mode. + void setTrashMode(bool trash_mode); + + //! @brief Get current mode trash or default. + bool getTrashMode() const; + + //! @brief Creates document info tooltip. + std::string createDocumentToolTip(DocumentBrowser::Drive::DocumentSession const& doc); + private: // classes class Header; @@ -130,18 +183,21 @@ namespace kiwi private: // members DocumentBrowser::Drive& m_drive; + bool m_trash_mode; + Comp m_sorter; }; // ================================================================================ // // BROWSER DRIVE VIEW HEADER // // ================================================================================ // - class DocumentBrowserView::DriveView::Header : public juce::Component + class DocumentBrowserView::DriveView::Header : public juce::Component, + public juce::TextEditor::Listener { public: // methods //! @brief Constructor - Header(juce::ListBox& listbox, DocumentBrowser::Drive& drive); + Header(DocumentBrowserView::DriveView& drive_view); //! @brief Destructor ~Header() = default; @@ -155,25 +211,33 @@ namespace kiwi //! @brief juce::Component::mouseDown void mouseDown(juce::MouseEvent const& event) override; + //! @brief overrides texteditor listener. + void textEditorReturnKeyPressed(juce::TextEditor & text_editor) override final; + private: // members - juce::ListBox& m_listbox; - DocumentBrowser::Drive& m_drive; - ImageButton m_refresh_btn; - ImageButton m_create_document_btn; - const juce::Image m_folder_img; + DocumentBrowserView::DriveView& m_drive_view; + ImageButton m_refresh_btn; + ImageButton m_create_document_btn; + ImageButton m_trash_btn; + juce::TextEditor m_search_bar; + juce::Rectangle m_folder_bounds; + juce::Label m_label; + const juce::Image m_folder_img; }; // ================================================================================ // // BROWSER DRIVE VIEW ROW ELEM // // ================================================================================ // - class DocumentBrowserView::DriveView::RowElem : public juce::Component, juce::Label::Listener + class DocumentBrowserView::DriveView::RowElem : public juce::Component, + public juce::SettableTooltipClient, + public juce::Label::Listener { public: // methods //! @brief Constructor. - RowElem(DriveView& drive_view, std::string const& name); + RowElem(DriveView& drive_view, std::string const& name, std::string const& tooltip); //! @brief Destructor. ~RowElem(); @@ -206,7 +270,11 @@ namespace kiwi void labelTextChanged(juce::Label* label_text_that_has_changed) override; //! @brief Update the document session - void update(std::string const& name, int row, bool now_selected); + void update(std::string const& name, std::string const& tooltip, int row, bool now_selected); + + private: // methods + + void showPopup(); private: // variables diff --git a/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp b/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp index a7575b64..fbc0b5d3 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp +++ b/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp @@ -241,6 +241,30 @@ namespace kiwi storeSession(std::move(session)); } + void Api::untrashDocument(std::string document_id, Callback callback) + { + auto session = makeSession(Endpoint::document(document_id)); + + session->setPayload({ + {"trashed", false} + }); + + session->PutAsync(std::move(callback)); + storeSession(std::move(session)); + } + + void Api::trashDocument(std::string document_id, Callback callback) + { + auto session = makeSession(Endpoint::document(document_id)); + + session->setPayload({ + {"trashed", true} + }); + + session->PutAsync(std::move(callback)); + storeSession(std::move(session)); + } + void Api::getLatestRelease(CallbackFn success_cb, ErrorCallback error_cb) { auto session = makeSession(Endpoint::releases + "/latest"); @@ -355,7 +379,7 @@ namespace kiwi const AuthUser& user = m_controller.getAuthUser(); - if(add_auth && !user.isLoggedIn()) + if(add_auth && user.isLoggedIn()) { session->setAuthorization("JWT " + user.getToken()); } @@ -553,14 +577,30 @@ namespace kiwi j = json{ {"_id", doc._id}, {"name", doc.name}, - {"session_id", session_id_converter.str()} + {"session_id", session_id_converter.str()}, + {"createdBy", doc.author_name}, + {"createdAt", doc.creation_date}, }; + + if (doc.trashed) + { + j.at("trashed") = true; + j.at("trash_date") = doc.trashed_date; + } + else + { + j.at("trashed") = false; + } } void from_json(json const& j, Api::Document& doc) { doc._id = Api::getJsonValue(j, "_id"); doc.name = Api::getJsonValue(j, "name"); + doc.author_name = Api::getJsonValue(j.at("createdBy"), "username"); + doc.creation_date = Api::getJsonValue(j, "createdAt"); + doc.trashed = Api::getJsonValue(j, "trashed"); + doc.trashed_date = doc.trashed ? Api::getJsonValue(j, "trashedDate") : ""; doc.session_id = 0ul; if(j.count("session_id")) diff --git a/Client/Source/KiwiApp_Network/KiwiApp_Api.h b/Client/Source/KiwiApp_Network/KiwiApp_Api.h index 23b755ed..1f5e442a 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_Api.h +++ b/Client/Source/KiwiApp_Network/KiwiApp_Api.h @@ -106,6 +106,12 @@ namespace kiwi std::string const& new_name, Callback callback); + //! @brief Moves a document to trash. + void trashDocument(std::string document_id, Callback callback); + + //! @brief Moves document out of the trash. + void untrashDocument(std::string document_id, Callback callback); + //! @brief Retrieves Kiwi's latest release as a string. ex: v0.1.0 void getLatestRelease(CallbackFn success_cb, ErrorCallback error_cb); @@ -300,6 +306,10 @@ namespace kiwi std::string _id = "0"; std::string name = ""; + std::string author_name = ""; + std::string creation_date = ""; + bool trashed = false; + std::string trashed_date = ""; uint64_t session_id = 0ul; //! @brief Returns true if the Document match another Document diff --git a/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp b/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp index 0ef218a6..29639ba7 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp +++ b/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp @@ -137,7 +137,11 @@ namespace kiwi DocumentBrowser::Drive::Drive(std::string const& name, uint16_t session_port) : m_session_port(session_port), - m_name(name) + m_name(name), + m_sort([](DocumentSession const& l_hs, DocumentSession const& r_hs) + { + return l_hs.getName() < r_hs.getName(); + }) { ; }; @@ -173,6 +177,21 @@ namespace kiwi return m_name; } + void DocumentBrowser::Drive::setSort(Comp comp) + { + m_sort = comp; + + std::sort(m_documents.begin(), + m_documents.end(), + [comp](std::unique_ptr const& l_hs, + std::unique_ptr const& r_hs) + { + return comp(*l_hs, *r_hs); + }); + + m_listeners.call(&Listener::driveChanged); + } + void DocumentBrowser::Drive::createNewDocument() { KiwiApp::useApi().createDocument("", [this](Api::Response res, Api::Document document) { @@ -186,16 +205,9 @@ namespace kiwi } else { - juce::MessageManager::callAsync([this, document]() { - - auto it = m_documents.emplace(m_documents.end(), - std::make_unique(*this, - std::move(document))); - - m_listeners.call(&Listener::documentAdded, *(it->get())); - m_listeners.call(&Listener::driveChanged); - - (*it)->open(); + juce::MessageManager::callAsync([this]() + { + refresh(); }); } }); @@ -267,11 +279,12 @@ namespace kiwi else { // name is currently the only document field that can change. - if(new_doc->getName() != (*it)->getName()) + if(new_doc->getName() != (*it)->getName() + || new_doc->isTrashed() != (*it)->isTrashed()) { - (*it)->m_document.name = new_doc->getName(); - auto& doc = *(it->get()); + (*it)->m_document = new_doc->m_document; + auto& doc = *(it->get()); m_listeners.call(&Listener::documentChanged, doc); changed = true; } @@ -280,6 +293,15 @@ namespace kiwi if(changed) { + std::sort(m_documents.begin(), + m_documents.end(), + [this](std::unique_ptr const& l_hs, + std::unique_ptr const& r_hs) + { + return m_sort(*l_hs, *r_hs); + + }); + m_listeners.call(&Listener::driveChanged); } } @@ -333,6 +355,62 @@ namespace kiwi return m_drive; } + std::string const& DocumentBrowser::Drive::DocumentSession::getCreationDate() const + { + return m_document.creation_date; + } + + std::string const& DocumentBrowser::Drive::DocumentSession::getAuthor() const + { + return m_document.author_name; + } + + bool DocumentBrowser::Drive::DocumentSession::isTrashed() const + { + return m_document.trashed; + } + + std::string const& DocumentBrowser::Drive::DocumentSession::getTrashedDate() const + { + return m_document.trashed_date; + } + + void DocumentBrowser::Drive::DocumentSession::untrash() + { + KiwiApp::useApi().untrashDocument(m_document._id, [this](Api::Response res) + { + if(res.error) + { + KiwiApp::error(res.error.message()); + } + else + { + KiwiApp::useInstance().useScheduler().schedule([this]() + { + m_drive.refresh(); + }); + } + }); + } + + void DocumentBrowser::Drive::DocumentSession::trash() + { + KiwiApp::useApi().trashDocument(m_document._id, [this](Api::Response res) { + + if(res.error) + { + KiwiApp::error(res.error.message()); + } + else + { + KiwiApp::useInstance().useScheduler().schedule([this]() + { + m_drive.refresh(); + }); + } + }); + } + void DocumentBrowser::Drive::DocumentSession::rename(std::string const& new_name) { if(new_name.empty()) @@ -340,17 +418,19 @@ namespace kiwi return; } - KiwiApp::useApi().renameDocument(m_document._id, new_name, [](Api::Response res) { + KiwiApp::useApi().renameDocument(m_document._id, new_name, [this](Api::Response res) { - if(!res.error) + if(res.error) { - std::cout << "document update failed, err: " + res.error.message() << '\n'; + KiwiApp::error(res.error.message()); } else { - std::cout << "document successfully updated\n"; + KiwiApp::useInstance().useScheduler().schedule([this]() + { + m_drive.refresh(); + }); } - }); } diff --git a/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.h b/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.h index c78a66e7..1698611a 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.h +++ b/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.h @@ -125,6 +125,10 @@ namespace kiwi using DocumentSessions = std::vector>; + private: + + using Comp = std::function; + public: // methods Drive(std::string const& name, uint16_t session_port); @@ -152,6 +156,9 @@ namespace kiwi //! @brief Creates and opens a new document on this drive. void createNewDocument(); + //! @brief Changes the way documents are sorted. + void setSort(Comp comp); + //! @brief Returns the documents. DocumentSessions const& getDocuments() const; @@ -174,6 +181,7 @@ namespace kiwi std::string m_name = "Drive"; DocumentSessions m_documents; tool::Listeners m_listeners; + Comp m_sort; friend class DocumentBrowser; }; @@ -233,6 +241,24 @@ namespace kiwi //! @brief Rename the document. void rename(std::string const& new_name); + //! @brief Move the document to trash. + void trash(); + + // @brief Moves document out of the trash. + void untrash(); + + //! @brief Returns the date creation as a string. + std::string const& getCreationDate() const; + + //! @brief Returns the author's username. + std::string const& getAuthor() const; + + //! @brief Returns true if document is trashed + bool isTrashed() const; + + //! @brief Returns trashed date as string. + std::string const& getTrashedDate() const; + //! @brief Returns true if the DocumentSession match another DocumentSession //! @details this operator uses the session_id field to compare. bool operator==(DocumentSession const& other_doc) const; From d211eb75ddcc232cb2583a899f0ea91fba5918f1 Mon Sep 17 00:00:00 2001 From: jmillot Date: Tue, 23 Jan 2018 23:39:23 +0100 Subject: [PATCH 122/148] Adding last opened date info. --- .../KiwiApp_DocumentBrowserView.cpp | 138 +++++++++++------- .../KiwiApp_DocumentBrowserView.h | 21 ++- Client/Source/KiwiApp_Network/KiwiApp_Api.cpp | 45 +++++- Client/Source/KiwiApp_Network/KiwiApp_Api.h | 11 ++ .../KiwiApp_DocumentBrowser.cpp | 39 ++++- .../KiwiApp_Network/KiwiApp_DocumentBrowser.h | 10 ++ .../KiwiApp_PatcherManager.cpp | 13 +- Modules/KiwiServer/KiwiServer_Server.cpp | 24 ++- Modules/KiwiServer/KiwiServer_Server.h | 8 +- Server/Source/Main.cpp | 4 +- Test/Server/test_Server.cpp | 34 +++-- 11 files changed, 258 insertions(+), 89 deletions(-) diff --git a/Client/Source/KiwiApp_Application/KiwiApp_DocumentBrowserView.cpp b/Client/Source/KiwiApp_Application/KiwiApp_DocumentBrowserView.cpp index a8a226fa..48073fb4 100644 --- a/Client/Source/KiwiApp_Application/KiwiApp_DocumentBrowserView.cpp +++ b/Client/Source/KiwiApp_Application/KiwiApp_DocumentBrowserView.cpp @@ -193,23 +193,38 @@ namespace kiwi { juce::PopupMenu m; - m.addItem(1, "Rename"); - m.addItem(2, m_drive_view.getTrashMode() ? "Restore" : "Delete"); + if (!m_drive_view.getTrashMode()) + { + m.addItem(1, "Rename"); + m.addItem(2, "Delete"); + } + else + { + m.addItem(3, "Restore"); + } - DriveView::SortType current_sort = m_drive_view.getSortType(); + DriveView::DataType current_sort = m_drive_view.getSortType(); juce::PopupMenu sort_menu; - sort_menu.addItem(3, "Name", - current_sort != DriveView::SortType::name, - current_sort == DriveView::SortType::name); + sort_menu.addItem(4, "Name", + current_sort != DriveView::DataType::name, + current_sort == DriveView::DataType::name); + + sort_menu.addItem(5, "Created at", + current_sort != DriveView::DataType::creationDate, + current_sort == DriveView::DataType::creationDate); - sort_menu.addItem(4, "Created at", - current_sort != DriveView::SortType::creationDate, - current_sort == DriveView::SortType::creationDate); + sort_menu.addItem(6, "Created by", + current_sort != DriveView::DataType::author, + current_sort == DriveView::DataType::author); - sort_menu.addItem(5, "Created by", - current_sort != DriveView::SortType::author, - current_sort == DriveView::SortType::author); + sort_menu.addItem(7, "Last opened at", + current_sort != DriveView::DataType::openedDate, + current_sort == DriveView::DataType::openedDate); + + sort_menu.addItem(8, "Last opened by", + current_sort != DriveView::DataType::openedUser, + current_sort == DriveView::DataType::openedUser); m.addSubMenu("Sort by", sort_menu); @@ -222,31 +237,40 @@ namespace kiwi m_name_label.showEditor(); break; } - case 2: // delete/Restore + case 2: // delete + { + m_drive_view.deleteDocumentForRow(m_row); + break; + } + case 3: // restore + { + m_drive_view.restoreDocumentForRow(m_row); + break; + } + case 4: // sort by name + { + m_drive_view.setSortType(DriveView::DataType::name); + break; + } + case 5: // sort by creation date { - if (!m_drive_view.getTrashMode()) - { - m_drive_view.deleteDocumentForRow(m_row); - } - else - { - m_drive_view.restoreDocumentForRow(m_row); - } + m_drive_view.setSortType(DriveView::DataType::creationDate); break; } - case 3: // sort by name + case 6: // sort by author { - m_drive_view.setSortType(DriveView::SortType::name); + m_drive_view.setSortType(DriveView::DataType::author); break; } - case 4: // sort by creation date + case 7: { - m_drive_view.setSortType(DriveView::SortType::creationDate); + m_drive_view.setSortType(DriveView::DataType::openedDate); break; } - case 5: + case 8: { - m_drive_view.setSortType(DriveView::SortType::author); + m_drive_view.setSortType(DriveView::DataType::openedUser); + break; } } } @@ -303,7 +327,6 @@ namespace kiwi std::unique_ptr (juce::Drawable::createFromImageData(binary_data::images::trash_png, binary_data::images::trash_png_size))), - m_search_bar(), m_folder_bounds(), m_label("drive_name", m_drive_view.getDriveName()), m_folder_img(juce::ImageCache::getFromMemory(binary_data::images::folder_png, @@ -314,10 +337,11 @@ namespace kiwi m_label.setColour(juce::Label::textColourId, juce::Colours::whitesmoke); addAndMakeVisible(m_label); - m_search_bar.setPopupMenuEnabled(false); - addAndMakeVisible(m_search_bar); - - m_create_document_btn.setCommand([this](){m_drive_view.createDocument();}); + m_create_document_btn.setCommand([this]() + { + if (!m_drive_view.getTrashMode()) + m_drive_view.createDocument(); + }); m_create_document_btn.setSize(40, 40); m_create_document_btn.setTooltip("Create a new patcher on this drive"); m_create_document_btn.setColour(ImageButton::ColourIds::textColourId, juce::Colours::whitesmoke); @@ -331,9 +355,10 @@ namespace kiwi m_trash_btn.setCommand([this]() { - m_trash_btn.setAlpha(!m_drive_view.getTrashMode() ? 1. : 0.5); - m_drive_view.setTrashMode(!m_drive_view.getTrashMode()); - + bool new_trash_mode = !m_drive_view.getTrashMode(); + m_drive_view.setTrashMode(new_trash_mode); + m_trash_btn.setAlpha(new_trash_mode ? 1. : 0.5); + m_create_document_btn.setAlpha(new_trash_mode ? 0.5 : 1.); }); m_trash_btn.setAlpha(m_drive_view.getTrashMode() ? 1. : 0.5); m_trash_btn.setSize(40, 40); @@ -352,15 +377,9 @@ namespace kiwi m_refresh_btn.setTopRightPosition(m_trash_btn.getX(), 5); m_create_document_btn.setTopRightPosition(m_refresh_btn.getX(), 5); - int text_width = m_label.getFont().getStringWidth(m_label.getText()); - int remaining_width = std::max(0, m_create_document_btn.getX() - m_folder_bounds.getRight()); - m_label.setBounds(bounds.withX(m_folder_bounds.getRight() + 5).withWidth(std::min(text_width, remaining_width / 2))); - - m_search_bar.setBounds(bounds.withX(m_label.getBounds().getRight()) - .withRight(m_create_document_btn.getX()) - .reduced(0, 13)); + m_label.setBounds(bounds.withX(m_folder_bounds.getRight() + 5).withWidth(remaining_width)); } void DocumentBrowserView::DriveView::Header::paint(juce::Graphics& g) @@ -384,8 +403,10 @@ namespace kiwi m_drive_view.getModel()->backgroundClicked(e); } - void DocumentBrowserView::DriveView::Header::textEditorReturnKeyPressed(juce::TextEditor & text_editor) + void DocumentBrowserView::DriveView::Header::setText(std::string const& text) { + m_label.setText(text, juce::NotificationType::dontSendNotification); + repaint(); } // ================================================================================ // @@ -432,19 +453,29 @@ namespace kiwi switch(m_type) { - case SortType::name: + case DataType::name: { type_ordered = l_hs.getName() < r_hs.getName(); break; } - case SortType::author: + case DataType::author: { type_ordered = l_hs.getAuthor() < r_hs.getAuthor(); break; } - case SortType::creationDate: + case DataType::creationDate: + { + type_ordered = l_hs.getCreationDate() > r_hs.getCreationDate(); + break; + } + case DataType::openedDate: + { + type_ordered = l_hs.getOpenedDate() > r_hs.getOpenedDate(); + break; + } + case DataType::openedUser: { - type_ordered = l_hs.getCreationDate() < r_hs.getCreationDate(); + type_ordered = l_hs.getOpenedUser() < r_hs.getOpenedUser(); break; } } @@ -512,12 +543,12 @@ namespace kiwi }); } - DocumentBrowserView::DriveView::SortType DocumentBrowserView::DriveView::getSortType() const + DocumentBrowserView::DriveView::DataType DocumentBrowserView::DriveView::getSortType() const { return m_sorter.m_type; } - void DocumentBrowserView::DriveView::setSortType(SortType sort_type) + void DocumentBrowserView::DriveView::setSortType(DataType sort_type) { m_sorter.m_type = sort_type; @@ -536,6 +567,7 @@ namespace kiwi void DocumentBrowserView::DriveView::update() { + dynamic_cast(getHeaderComponent())->setText(getDriveName()); updateContent(); repaint(); } @@ -543,12 +575,14 @@ namespace kiwi std::string DocumentBrowserView::DriveView::createDocumentToolTip(DocumentBrowser::Drive::DocumentSession const& doc) { std::string tooltip = "name: " + doc.getName() + "\n" - + "created by: " + doc.getAuthor() + "\n" - + "created at: " + doc.getCreationDate() + "\n"; + + "created by : " + doc.getAuthor() + "\n" + + "created at : " + doc.getCreationDate() + "\n" + + "last opened at : " + doc.getOpenedDate() + "\n" + + "last opened by : " + doc.getOpenedUser(); if (doc.isTrashed()) { - tooltip += "trashed at: " + doc.getTrashedDate(); + tooltip += "\ntrashed at : " + doc.getTrashedDate(); } return tooltip; diff --git a/Client/Source/KiwiApp_Application/KiwiApp_DocumentBrowserView.h b/Client/Source/KiwiApp_Application/KiwiApp_DocumentBrowserView.h index 0298d7b4..98fc6eb4 100644 --- a/Client/Source/KiwiApp_Application/KiwiApp_DocumentBrowserView.h +++ b/Client/Source/KiwiApp_Application/KiwiApp_DocumentBrowserView.h @@ -79,11 +79,13 @@ namespace kiwi { private: // classes - enum class SortType + enum class DataType { name, author, - creationDate + creationDate, + openedDate, + openedUser }; struct Comp @@ -91,7 +93,7 @@ namespace kiwi bool compare(DocumentBrowser::Drive::DocumentSession const& l_hs, DocumentBrowser::Drive::DocumentSession const& r_hs) const; - SortType m_type = SortType::creationDate; + DataType m_type = DataType::creationDate; bool m_trashed_first = false; }; @@ -161,10 +163,10 @@ namespace kiwi void createDocument(); //! @brief Returns the current sorting parameter. - SortType getSortType() const; + DataType getSortType() const; //! @brief Changes the sort parameter and sorts. - void setSortType(SortType sort_type); + void setSortType(DataType sort_type); // @brief Set the trash mode. void setTrashMode(bool trash_mode); @@ -191,8 +193,7 @@ namespace kiwi // BROWSER DRIVE VIEW HEADER // // ================================================================================ // - class DocumentBrowserView::DriveView::Header : public juce::Component, - public juce::TextEditor::Listener + class DocumentBrowserView::DriveView::Header : public juce::Component { public: // methods @@ -211,8 +212,8 @@ namespace kiwi //! @brief juce::Component::mouseDown void mouseDown(juce::MouseEvent const& event) override; - //! @brief overrides texteditor listener. - void textEditorReturnKeyPressed(juce::TextEditor & text_editor) override final; + //! @brief Sets the text diaplyed by the header bar. + void setText(std::string const& text); private: // members @@ -220,7 +221,6 @@ namespace kiwi ImageButton m_refresh_btn; ImageButton m_create_document_btn; ImageButton m_trash_btn; - juce::TextEditor m_search_bar; juce::Rectangle m_folder_bounds; juce::Label m_label; const juce::Image m_folder_img; @@ -288,6 +288,5 @@ namespace kiwi int m_row; bool m_selected; bool m_mouseover = false; - bool m_select_row_on_mouse_up = false; }; } diff --git a/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp b/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp index fbc0b5d3..565a3655 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp +++ b/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp @@ -265,6 +265,32 @@ namespace kiwi storeSession(std::move(session)); } + void Api::getOpenToken(std::string document_id, + CallbackFn success_cb, + ErrorCallback error_cb) + { + auto session = makeSession(Endpoint::document(document_id) + "/opentoken"); + + auto callback = [success = std::move(success_cb), + fail = std::move(error_cb)](Response res) + { + if (!res.error + && hasJsonHeader(res) + && res.result() == beast::http::status::ok) + { + const auto j = json::parse(res.body); + success(j["token"]); + } + else + { + fail(res); + } + }; + + session->GetAsync(std::move(callback)); + storeSession(std::move(session)); + } + void Api::getLatestRelease(CallbackFn success_cb, ErrorCallback error_cb) { auto session = makeSession(Endpoint::releases + "/latest"); @@ -364,6 +390,17 @@ namespace kiwi storeSession(std::move(session)); } + std::string Api::convertDate(std::string const& date) + { + std::string result = date; + + result.replace(result.find_first_of("T"), 1 , " "); + result.replace(result.find_first_of("Z"), 1 , " "); + result.append("GMT"); + + return result; + } + bool Api::hasJsonHeader(Response const& res) { return (res[beast::http::field::content_type] == "application/json; charset=utf-8"); @@ -580,6 +617,8 @@ namespace kiwi {"session_id", session_id_converter.str()}, {"createdBy", doc.author_name}, {"createdAt", doc.creation_date}, + {"lastOpenedAt", doc.opened_date}, + {"lastModdifyBy", doc.opened_user} }; if (doc.trashed) @@ -598,9 +637,11 @@ namespace kiwi doc._id = Api::getJsonValue(j, "_id"); doc.name = Api::getJsonValue(j, "name"); doc.author_name = Api::getJsonValue(j.at("createdBy"), "username"); - doc.creation_date = Api::getJsonValue(j, "createdAt"); + doc.creation_date = Api::convertDate(Api::getJsonValue(j, "createdAt")); + doc.opened_date = Api::convertDate(Api::getJsonValue(j, "lastOpenedAt")); + doc.opened_user = Api::getJsonValue(j.at("lastOpenedBy"), "username"); doc.trashed = Api::getJsonValue(j, "trashed"); - doc.trashed_date = doc.trashed ? Api::getJsonValue(j, "trashedDate") : ""; + doc.trashed_date = doc.trashed ? Api::convertDate(Api::getJsonValue(j, "trashedDate")) : ""; doc.session_id = 0ul; if(j.count("session_id")) diff --git a/Client/Source/KiwiApp_Network/KiwiApp_Api.h b/Client/Source/KiwiApp_Network/KiwiApp_Api.h index 1f5e442a..fd4f407b 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_Api.h +++ b/Client/Source/KiwiApp_Network/KiwiApp_Api.h @@ -112,6 +112,11 @@ namespace kiwi //! @brief Moves document out of the trash. void untrashDocument(std::string document_id, Callback callback); + //! @brief Returns the open token used to open document. + void getOpenToken(std::string document_id, + CallbackFn success_cb, + ErrorCallback error_cb); + //! @brief Retrieves Kiwi's latest release as a string. ex: v0.1.0 void getLatestRelease(CallbackFn success_cb, ErrorCallback error_cb); @@ -132,6 +137,10 @@ namespace kiwi return json.count(key) ? json.at(key).get() : default_value; } + //! @brief Converts an ISO 8601 received by server. + //! @details Output format is %Y-%m-%d %H:%M:%S + static std::string convertDate(std::string const& date); + private: // methods //! @brief Kiwi API Endpoints @@ -310,6 +319,8 @@ namespace kiwi std::string creation_date = ""; bool trashed = false; std::string trashed_date = ""; + std::string opened_date = ""; + std::string opened_user = ""; uint64_t session_id = 0ul; //! @brief Returns true if the Document match another Document diff --git a/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp b/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp index 29639ba7..9be300f9 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp +++ b/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp @@ -280,7 +280,8 @@ namespace kiwi { // name is currently the only document field that can change. if(new_doc->getName() != (*it)->getName() - || new_doc->isTrashed() != (*it)->isTrashed()) + || new_doc->isTrashed() != (*it)->isTrashed() + || new_doc->getOpenedDate() != (*it)->getOpenedDate()) { (*it)->m_document = new_doc->m_document; @@ -330,7 +331,8 @@ namespace kiwi DocumentBrowser::Drive::DocumentSession::DocumentSession(DocumentBrowser::Drive& parent, Api::Document document) : m_drive(parent), - m_document(std::move(document)) + m_document(std::move(document)), + m_open_token("") { } @@ -375,6 +377,21 @@ namespace kiwi return m_document.trashed_date; } + std::string const& DocumentBrowser::Drive::DocumentSession::getOpenedDate() const + { + return m_document.opened_date; + } + + std::string const& DocumentBrowser::Drive::DocumentSession::getOpenedUser() const + { + return m_document.opened_user; + } + + std::string const& DocumentBrowser::Drive::DocumentSession::getOpenToken() const + { + return m_open_token; + } + void DocumentBrowser::Drive::DocumentSession::untrash() { KiwiApp::useApi().untrashDocument(m_document._id, [this](Api::Response res) @@ -446,6 +463,22 @@ namespace kiwi void DocumentBrowser::Drive::DocumentSession::open() { - KiwiApp::useInstance().openRemotePatcher(*this); + auto success = [this](std::string const& token) + { + m_open_token = token; + + KiwiApp::useInstance().useScheduler().schedule([this]() + { + KiwiApp::useInstance().openRemotePatcher(*this); + m_drive.refresh(); + }); + }; + + auto error = [this](Api::Error er) + { + KiwiApp::error(er.getMessage()); + }; + + KiwiApp::useApi().getOpenToken(m_document._id, success, error); } } diff --git a/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.h b/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.h index 1698611a..866c17a2 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.h +++ b/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.h @@ -235,6 +235,9 @@ namespace kiwi //! @brief Returns the session id of the document. uint64_t getSessionId() const; + //! @brief Returns the open token of the document. + std::string const& getOpenToken() const; + //! @brief Returns the drive that holds this document. DocumentBrowser::Drive const& useDrive() const; @@ -259,6 +262,12 @@ namespace kiwi //! @brief Returns trashed date as string. std::string const& getTrashedDate() const; + //! @brief Returns the last modification date. + std::string const& getOpenedDate() const; + + //! @brief Returns the user that modified document last. + std::string const& getOpenedUser() const; + //! @brief Returns true if the DocumentSession match another DocumentSession //! @details this operator uses the session_id field to compare. bool operator==(DocumentSession const& other_doc) const; @@ -267,6 +276,7 @@ namespace kiwi DocumentBrowser::Drive& m_drive; Api::Document m_document; + std::string m_open_token; friend class DocumentBrowser::Drive; }; diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.cpp index 8df46e3d..717f6d29 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.cpp @@ -19,7 +19,9 @@ ============================================================================== */ -#include +#include + +#include #include #include @@ -42,7 +44,9 @@ #include namespace kiwi -{ +{ + using json = nlohmann::json; + // ================================================================================ // // PATCHER MANAGER // // ================================================================================ // @@ -156,7 +160,10 @@ namespace kiwi m_listeners.call(&Listener::connectedUserChanged, *this); }); - std::string metadata = KIWI_MODEL_VERSION_STRING; + json j; + j["model_version"] = KIWI_MODEL_VERSION_STRING; + j["open_token"] = session.getOpenToken(); + std::string metadata = j.dump(); m_socket.connect(host, port, session.getSessionId(), metadata); diff --git a/Modules/KiwiServer/KiwiServer_Server.cpp b/Modules/KiwiServer/KiwiServer_Server.cpp index bdafb1f4..cf30427a 100644 --- a/Modules/KiwiServer/KiwiServer_Server.cpp +++ b/Modules/KiwiServer/KiwiServer_Server.cpp @@ -19,7 +19,9 @@ ============================================================================== */ -#include "KiwiServer_Server.h" +#include + +#include #include @@ -39,6 +41,8 @@ namespace kiwi // SERVER // // ================================================================================ // + using json = nlohmann::json; + std::string hexadecimal_convert(uint64_t hexa_decimal) { std::stringstream converter; @@ -49,8 +53,11 @@ namespace kiwi const char* Server::kiwi_file_extension = "kiwi"; - Server::Server(uint16_t port, std::string const& backend_directory) : + Server::Server(uint16_t port, + std::string const& backend_directory, + std::string const& open_token) : m_backend_directory(backend_directory), + m_open_token(open_token), m_sessions(), m_socket(*this, port), m_ports() @@ -109,7 +116,8 @@ namespace kiwi DBG("[server] - creating new session for session_id : " << hexadecimal_convert(session_id)); - auto session = m_sessions.insert(std::make_pair(session_id, Session(session_id, session_file))); + auto session = m_sessions.insert(std::make_pair(session_id, + Session(session_id, session_file, m_open_token))); if (session_file.exists()) { @@ -203,16 +211,20 @@ namespace kiwi , m_document(std::move(other.m_document)) , m_signal_connections(std::move(other.m_signal_connections)) , m_backend_file(std::move(other.m_backend_file)) + , m_token(other.m_token) { ; } - Server::Session::Session(uint64_t identifier, juce::File const& backend_file) + Server::Session::Session(uint64_t identifier, + juce::File const& backend_file, + std::string const& token) : m_identifier(identifier) , m_validator(new model::PatcherValidator()) , m_document(new flip::DocumentServer(model::DataModel::use(), *m_validator, m_identifier)) , m_signal_connections() , m_backend_file(backend_file) + , m_token(token) { model::Patcher& patcher = m_document->root(); @@ -285,7 +297,9 @@ namespace kiwi bool Server::Session::authenticateUser(uint64_t user, std::string metadata) const { - return metadata == KIWI_MODEL_VERSION_STRING; + const auto j = json::parse(metadata); + return j["model_version"] == KIWI_MODEL_VERSION_STRING + && j["open_token"] == m_token; } void Server::Session::bind(flip::PortBase & port) diff --git a/Modules/KiwiServer/KiwiServer_Server.h b/Modules/KiwiServer/KiwiServer_Server.h index fd0ae9e6..55dc097e 100644 --- a/Modules/KiwiServer/KiwiServer_Server.h +++ b/Modules/KiwiServer/KiwiServer_Server.h @@ -57,7 +57,9 @@ namespace kiwi //! @brief Constructor. //! @details Initializes socket and creates backend directory if not there. - Server(uint16_t port, std::string const& backend_directory); + Server(uint16_t port, + std::string const& backend_directory, + std::string const& open_token); //! @brief Destructor. //! @details Disconnect all users and clean sessions. onDisconnected will be called for all port. @@ -106,6 +108,7 @@ namespace kiwi private: // variables juce::File m_backend_directory; + std::string m_open_token; std::map m_sessions; flip::PortTransportServerTcp m_socket; std::set m_ports; @@ -136,7 +139,7 @@ namespace kiwi //! @brief Constructor //! @details Constructor will load the document if file exists. backend_file is //! the file in which the session will save and load document. - Session(uint64_t identifier, juce::File const& backend_file); + Session(uint64_t identifier, juce::File const& backend_file, std::string const& token); //! @brief Destructor. //! @details Unbinds all documents and ports. @@ -176,6 +179,7 @@ namespace kiwi std::unique_ptr m_document; std::vector m_signal_connections; juce::File m_backend_file; + std::string m_token; private: // deleted methods diff --git a/Server/Source/Main.cpp b/Server/Source/Main.cpp index c548cfc5..8002f8ed 100644 --- a/Server/Source/Main.cpp +++ b/Server/Source/Main.cpp @@ -96,7 +96,9 @@ int main(int argc, char const* argv[]) try { - server::Server kiwi_server(config["session_port"], config["backend_directory"]); + server::Server kiwi_server(config["session_port"], + config["backend_directory"], + config["open_token"]); std::cout << "[server] - running on port " << config["session_port"] << std::endl; diff --git a/Test/Server/test_Server.cpp b/Test/Server/test_Server.cpp index 09826dae..beba7b24 100755 --- a/Test/Server/test_Server.cpp +++ b/Test/Server/test_Server.cpp @@ -23,6 +23,8 @@ #include +#include + #include #include #include @@ -36,15 +38,25 @@ using namespace kiwi; // SERVER // // ==================================================================================== // +std::string token = "token"; + +std::string getMetaData() +{ + nlohmann::json j; + j["model_version"] = KIWI_MODEL_VERSION_STRING; + j["open_token"] = token; + return j.dump(); +} + TEST_CASE("Server - Server", "[Server, Server]") { SECTION("Simple Connection - Deconnection") { - kiwi::server::Server server(9191, "./server_backend_test"); + kiwi::server::Server server(9191, "./server_backend_test", token); // Initializing document flip::Document document (kiwi::model::DataModel::use (), 123456789, 'appl', 'gui '); - flip::CarrierTransportSocketTcp carrier (document, 987654, KIWI_MODEL_VERSION_STRING, "localhost", 9191); + flip::CarrierTransportSocketTcp carrier (document, 987654, getMetaData(), "localhost", 9191); // Client/Document connecting to server. while(!carrier.is_connected() || server.getSessions().empty()) @@ -80,11 +92,13 @@ TEST_CASE("Server - Server", "[Server, Server]") SECTION("Simple Connection - Server Killed") { - std::unique_ptr server(new kiwi::server::Server(9191, "./server_backend_test")); + std::unique_ptr server(new kiwi::server::Server(9191, + "./server_backend_test", + token)); // Initializing document. flip::Document document (kiwi::model::DataModel::use (), 123456789, 'appl', 'gui '); - flip::CarrierTransportSocketTcp carrier (document, 987654, KIWI_MODEL_VERSION_STRING, "localhost", 9191); + flip::CarrierTransportSocketTcp carrier (document, 987654, getMetaData(), "localhost", 9191); // Client/Document connecting to server. while(!carrier.is_connected() || server->getSessions().empty()) @@ -117,14 +131,14 @@ TEST_CASE("Server - Server", "[Server, Server]") SECTION("One user connecting to multiple document") { - kiwi::server::Server server(9191, "./server_backend_test"); + kiwi::server::Server server(9191, "./server_backend_test", token); // Initializing documents. flip::Document document_1 (kiwi::model::DataModel::use (), 123456789, 'appl', 'gui '); - flip::CarrierTransportSocketTcp carrier_1 (document_1, 987654, KIWI_MODEL_VERSION_STRING, "localhost", 9191); + flip::CarrierTransportSocketTcp carrier_1 (document_1, 987654, getMetaData(), "localhost", 9191); flip::Document document_2 (kiwi::model::DataModel::use (), 123456789, 'appl', 'gui '); - flip::CarrierTransportSocketTcp carrier_2 (document_2, 987655, KIWI_MODEL_VERSION_STRING, "localhost", 9191); + flip::CarrierTransportSocketTcp carrier_2 (document_2, 987655, getMetaData(), "localhost", 9191); // Client/Document connecting to server. while(!carrier_1.is_connected() || !carrier_2.is_connected() || server.getSessions().size() != 2) @@ -162,11 +176,11 @@ TEST_CASE("Server - Server", "[Server, Server]") SECTION("Multiple connections") { - kiwi::server::Server server(9191, "./server_backend_test"); + kiwi::server::Server server(9191, "./server_backend_test", token); // Initializing client 1 flip::Document document_1 (kiwi::model::DataModel::use (), 1, 'appl', 'gui '); - flip::CarrierTransportSocketTcp carrier_1 (document_1, 1234, KIWI_MODEL_VERSION_STRING, "localhost", 9191); + flip::CarrierTransportSocketTcp carrier_1 (document_1, 1234, getMetaData(), "localhost", 9191); kiwi::model::Patcher& patcher_1 = document_1.root(); @@ -186,7 +200,7 @@ TEST_CASE("Server - Server", "[Server, Server]") // Initializing client 2 flip::Document document_2 (kiwi::model::DataModel::use (), 2, 'appl', 'gui '); - flip::CarrierTransportSocketTcp carrier_2 (document_2, 1234, KIWI_MODEL_VERSION_STRING, "localhost", 9191); + flip::CarrierTransportSocketTcp carrier_2 (document_2, 1234, getMetaData(), "localhost", 9191); kiwi::model::Patcher& patcher_2 = document_2.root(); From e50e16ffef0162b44470273be964c69d6b44b40e Mon Sep 17 00:00:00 2001 From: jmillot Date: Mon, 22 Jan 2018 22:57:39 +0100 Subject: [PATCH 123/148] Handle denied request in Kiwi side. --- .../KiwiApp_DocumentBrowser.cpp | 71 +++++++++++++++++-- .../KiwiApp_Network/KiwiApp_DocumentBrowser.h | 3 + 2 files changed, 68 insertions(+), 6 deletions(-) diff --git a/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp b/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp index 9be300f9..509c1dd9 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp +++ b/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp @@ -115,6 +115,19 @@ namespace kiwi m_distant_drive->refresh(); } + void DocumentBrowser::handleDeniedRequest() + { + if (KiwiApp::getCurrentUser().isLoggedIn()) + { + KiwiApp::logout(); + KiwiApp::error("Session has expired. Please login."); + } + else + { + KiwiApp::error("Request denied. Please login."); + } + } + void DocumentBrowser::userLoggedIn(Api::AuthUser const& user) { m_distant_drive->setName(user.getName()); @@ -196,7 +209,11 @@ namespace kiwi { KiwiApp::useApi().createDocument("", [this](Api::Response res, Api::Document document) { - if(res.error) + if (res.result() == beast::http::status::forbidden) + { + DocumentBrowser::handleDeniedRequest(); + } + else if(res.error) { juce::MessageManager::callAsync([message = res.error.message()](){ KiwiApp::error("Error: can't create document"); @@ -311,7 +328,14 @@ namespace kiwi { KiwiApp::useApi().getDocuments([this](Api::Response res, Api::Documents docs) { - if(res.error) + if (res.result() == beast::http::status::forbidden) + { + KiwiApp::useInstance().useScheduler().schedule([]() + { + DocumentBrowser::handleDeniedRequest(); + }); + } + else if(res.error) { KiwiApp::error("Kiwi API error: can't get documents => " + res.error.message()); } @@ -396,7 +420,14 @@ namespace kiwi { KiwiApp::useApi().untrashDocument(m_document._id, [this](Api::Response res) { - if(res.error) + if (res.result() == beast::http::status::forbidden) + { + KiwiApp::useInstance().useScheduler().schedule([]() + { + DocumentBrowser::handleDeniedRequest(); + }); + } + else if(res.error) { KiwiApp::error(res.error.message()); } @@ -414,7 +445,15 @@ namespace kiwi { KiwiApp::useApi().trashDocument(m_document._id, [this](Api::Response res) { - if(res.error) + if (res.result() == beast::http::status::forbidden) + { + KiwiApp::useInstance().useScheduler().schedule([]() + { + DocumentBrowser::handleDeniedRequest(); + + }); + } + else if(res.error) { KiwiApp::error(res.error.message()); } @@ -437,7 +476,14 @@ namespace kiwi KiwiApp::useApi().renameDocument(m_document._id, new_name, [this](Api::Response res) { - if(res.error) + if (res.result() == beast::http::status::forbidden) + { + KiwiApp::useInstance().useScheduler().schedule([]() + { + DocumentBrowser::handleDeniedRequest(); + }); + } + else if(res.error) { KiwiApp::error(res.error.message()); } @@ -476,7 +522,20 @@ namespace kiwi auto error = [this](Api::Error er) { - KiwiApp::error(er.getMessage()); + if (er.getStatusCode() == static_cast(beast::http::status::forbidden)) + { + KiwiApp::useInstance().useScheduler().schedule([]() + { + DocumentBrowser::handleDeniedRequest(); + }); + } + else + { + KiwiApp::useInstance().useScheduler().schedule([er]() + { + KiwiApp::error(er.getMessage()); + }); + } }; KiwiApp::useApi().getOpenToken(m_document._id, success, error); diff --git a/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.h b/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.h index 866c17a2..239ee2bc 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.h +++ b/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.h @@ -80,6 +80,9 @@ namespace kiwi private: // methods + //! @brief Handles request that denied by server. + static void handleDeniedRequest(); + void networkSettingsChanged(NetworkSettings const&, const juce::Identifier& id) override; void userLoggedIn(Api::AuthUser const&) override; From f761620c2feb7f6e397490050a0e6548b4f45562 Mon Sep 17 00:00:00 2001 From: jmillot Date: Thu, 25 Jan 2018 18:51:31 +0100 Subject: [PATCH 124/148] Review document name management and saving. --- ChangeLog.txt | 6 + .../KiwiApp_Application/KiwiApp_Instance.cpp | 64 +++-- .../KiwiApp_Application/KiwiApp_Instance.h | 5 +- .../KiwiApp_PatcherComponent.cpp | 1 - .../KiwiApp_PatcherManager.cpp | 253 ++++++++++-------- .../KiwiApp_Patcher/KiwiApp_PatcherManager.h | 30 ++- .../KiwiApp_Patcher/KiwiApp_PatcherView.cpp | 45 ---- .../KiwiApp_Patcher/KiwiApp_PatcherView.h | 3 - Modules/KiwiModel/KiwiModel_Patcher.cpp | 18 +- Modules/KiwiModel/KiwiModel_Patcher.h | 13 +- 10 files changed, 214 insertions(+), 224 deletions(-) create mode 100644 ChangeLog.txt diff --git a/ChangeLog.txt b/ChangeLog.txt new file mode 100644 index 00000000..7f8b4313 --- /dev/null +++ b/ChangeLog.txt @@ -0,0 +1,6 @@ +Model changelog: +v1 -> v2: +- Added object hub +- Added object mtof +- Added object send +- name removed from document. diff --git a/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp b/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp index 08e8c1fb..a2cc06a2 100644 --- a/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp +++ b/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp @@ -39,7 +39,7 @@ namespace kiwi // INSTANCE // // ================================================================================ // - size_t Instance::m_untitled_patcher_index(0); + size_t Instance::m_untitled_patcher_index(1); Instance::Instance() : m_scheduler(), @@ -152,28 +152,19 @@ namespace kiwi } void Instance::newPatcher() - { - auto manager_it = m_patcher_managers.emplace(m_patcher_managers.end(), new PatcherManager(*this)); - - PatcherManager& manager = *(manager_it->get()); - model::Patcher& patcher = manager.getPatcher(); - - const size_t next_untitled = getNextUntitledNumberAndIncrement(); - std::string patcher_name = "Untitled"; - - if(next_untitled > 0) - { - patcher_name += " " + std::to_string(next_untitled); - } + { + std::string patcher_name = "Untitled " + + std::to_string(getNextUntitledNumberAndIncrement()); - patcher.setName(patcher_name); + PatcherManager & manager = (*m_patcher_managers.emplace(m_patcher_managers.end(), + new PatcherManager(*this, patcher_name))->get()); if(manager.getNumberOfView() == 0) { manager.newView(); } - model::DocumentManager::commit(patcher); + model::DocumentManager::commit(manager.getPatcher()); } bool Instance::openFile(juce::File const& file) @@ -182,24 +173,35 @@ namespace kiwi if(file.hasFileExtension("kiwi")) { - std::unique_ptr patcher_manager(new PatcherManager(*this)); + auto manager_it = getPatcherManagerForFile(file); - if (patcher_manager->loadFromFile(file)) + if (manager_it == m_patcher_managers.end()) { - auto manager_it = m_patcher_managers.emplace(m_patcher_managers.end(), - std::move(patcher_manager)); + std::string patcher_name = file.getFileNameWithoutExtension().toStdString(); - open_succeeded = true; + std::unique_ptr patcher_manager (new PatcherManager(*this, patcher_name)); - if((*manager_it)->getNumberOfView() == 0) + if (patcher_manager->loadFromFile(file)) { - (*manager_it)->newView(); + auto manager_it = m_patcher_managers.emplace(m_patcher_managers.end(), + std::move(patcher_manager)); + + open_succeeded = true; + + if((*manager_it)->getNumberOfView() == 0) + { + (*manager_it)->newView(); + } + } + else + { + KiwiApp::error("Can't open document. Version is not up to date. Please download latest Kiwi version."); } } else { - KiwiApp::error("Can't open document. Version is not up to date. Please download latest Kiwi version."); - } + (*manager_it)->bringsFirstViewToFront(); + } } else { @@ -324,7 +326,7 @@ namespace kiwi } else { - auto manager_uptr = std::make_unique(*this); + auto manager_uptr = std::make_unique(*this, session.getName()); NetworkSettings& network_settings = getAppSettings().network(); @@ -363,6 +365,16 @@ namespace kiwi }; return std::find_if(m_patcher_managers.begin(), m_patcher_managers.end(), find_fn); + } + + Instance::PatcherManagers::iterator Instance::getPatcherManagerForFile(juce::File const& file) + { + const auto find_it = [&file](std::unique_ptr const& manager_uptr) + { + return (!manager_uptr->isRemote() && file == manager_uptr->getSelectedFile()); + }; + + return std::find_if(m_patcher_managers.begin(), m_patcher_managers.end(), find_it); } Instance::PatcherManagers::iterator Instance::getPatcherManagerForSession(DocumentBrowser::Drive::DocumentSession& session) diff --git a/Client/Source/KiwiApp_Application/KiwiApp_Instance.h b/Client/Source/KiwiApp_Application/KiwiApp_Instance.h index 9591fad3..5e5df988 100644 --- a/Client/Source/KiwiApp_Application/KiwiApp_Instance.h +++ b/Client/Source/KiwiApp_Application/KiwiApp_Instance.h @@ -135,7 +135,10 @@ namespace kiwi PatcherManagers::iterator getPatcherManager(PatcherManager const& manager); //! @internal get the given patcher manager iterator. - PatcherManagers::iterator getPatcherManagerForSession(DocumentBrowser::Drive::DocumentSession& session); + PatcherManagers::iterator getPatcherManagerForSession(DocumentBrowser::Drive::DocumentSession& session); + + //! @internal gets patcher manager currently associated to file. + Instance::PatcherManagers::iterator getPatcherManagerForFile(juce::File const& file); //! @internal Returns the next untitled number based on current documents size_t getNextUntitledNumberAndIncrement(); diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherComponent.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherComponent.cpp index be018639..4d47746b 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherComponent.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherComponent.cpp @@ -258,7 +258,6 @@ namespace kiwi setSize(600, 400); addAndMakeVisible(&patcherview.getViewport(), true); - patcherview.updateWindowTitle(); KiwiApp::bindToCommandManager(this); KiwiApp::bindToKeyMapping(this); diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.cpp index 717f6d29..8940db43 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.cpp @@ -51,7 +51,8 @@ namespace kiwi // PATCHER MANAGER // // ================================================================================ // - PatcherManager::PatcherManager(Instance& instance) : + PatcherManager::PatcherManager(Instance& instance, std::string const& name) : + m_name(name), m_instance(instance), m_validator(), m_document(model::DataModel::use(), *this, m_validator, @@ -94,11 +95,6 @@ namespace kiwi { if (transition == flip::CarrierBase::Transition::Disconnected) { - model::Patcher & patcher = getPatcher(); - - patcher.setName(m_session->getName()); - model::DocumentManager::commit(patcher); - m_session->useDrive().removeListener(*this); m_session = nullptr; @@ -111,9 +107,11 @@ namespace kiwi for(auto & view : views) { view.entity().use().removeUsersIcon(); - - view.entity().use().updateWindowTitle(); } + + setNeedSaving(true); + + updateTitleBars(); } } @@ -206,6 +204,12 @@ namespace kiwi patcher.useSelfUser(); model::DocumentManager::commit(patcher); + setName(session.getName()); + + setNeedSaving(false); + + updateTitleBars(); + patcher.entity().use().sendLoadbang(); } @@ -234,7 +238,6 @@ namespace kiwi return false; } - m_need_saving_flag = false; loading_succeeded = true; } } @@ -255,7 +258,6 @@ namespace kiwi model::Patcher& patcher = getPatcher(); patcher.useSelfUser(); - patcher.setName(file.getFileNameWithoutExtension().toStdString()); try { @@ -266,6 +268,12 @@ namespace kiwi return false; } + setName(file.getFileNameWithoutExtension().toStdString()); + + setNeedSaving(false); + + updateTitleBars(); + patcher.entity().use().sendLoadbang(); success = true; } @@ -296,7 +304,7 @@ namespace kiwi std::string PatcherManager::getDocumentName() const { - return isRemote() ? m_session->getName() : getPatcher().getName(); + return m_name; } void PatcherManager::newView() @@ -337,7 +345,7 @@ namespace kiwi bool PatcherManager::needsSaving() const noexcept { - return !isRemote() && m_need_saving_flag; + return m_need_saving_flag && !isRemote(); } void PatcherManager::writeDocument() @@ -345,71 +353,73 @@ namespace kiwi flip::BackEndIR back_end = m_document.write(); flip::DataConsumerFile consumer(m_file.getFullPathName().toStdString().c_str()); back_end.write(consumer); - m_need_saving_flag = false; } bool PatcherManager::saveDocument() - { - if (needsSaving()) - { - if (m_file.existsAsFile()) - { - writeDocument(); - } - else - { - auto directory = juce::File::getSpecialLocation(juce::File::userHomeDirectory); - - juce::FileChooser saveFileChooser("Save file", directory, "*.kiwi"); - - if (saveFileChooser.browseForFileToSave(true)) - { - m_file = saveFileChooser.getResult(); - - writeDocument(); - - model::Patcher& patcher = getPatcher(); - patcher.setName(m_file.getFileNameWithoutExtension().toStdString()); - model::DocumentManager::commit(patcher); - } - } + { + bool saved = false; + + if (needsSaving() && m_file.existsAsFile()) + { + saved = true; + + writeDocument(); + } + else if(needsSaving() || (!needsSaving() && !m_file.existsAsFile())) + { + auto directory = juce::File::getSpecialLocation(juce::File::userHomeDirectory); + + juce::FileChooser saveFileChooser("Save file", directory, "*.kiwi"); + + if ((saved = saveFileChooser.browseForFileToSave(true))) + { + m_file = saveFileChooser.getResult(); + + writeDocument(); + + setName(m_file.getFileNameWithoutExtension().toStdString()); + + updateTitleBars(); + } + } + + if (saved) + { + setNeedSaving(false); + updateTitleBars(); } - return !m_need_saving_flag; + return saved; } - juce::FileBasedDocument::SaveResult PatcherManager::saveIfNeededAndUserAgrees() - { - if (! needsSaving()) - { - return juce::FileBasedDocument::savedOk; - } - - auto& patcher = getPatcher(); - - const std::string document_name = patcher.getName(); - - const int r = juce::AlertWindow::showYesNoCancelBox(juce::AlertWindow::QuestionIcon, - TRANS("Closing document..."), - TRANS("Do you want to save the changes to \"") - + document_name + "\"?", - TRANS("Save"), - TRANS("Discard changes"), - TRANS("Cancel")); - - // save changes - if(r == 1) - { - return (saveDocument()) ? juce::FileBasedDocument::savedOk : juce::FileBasedDocument::failedToWriteToFile; - } - - // discard changes - if(r == 2) - { - return juce::FileBasedDocument::savedOk; - } - - return juce::FileBasedDocument::userCancelledSave; + bool PatcherManager::saveIfNeededAndUserAgrees() + { + bool user_cancelled = false; + + if (needsSaving()) + { + const int r = juce::AlertWindow::showYesNoCancelBox(juce::AlertWindow::QuestionIcon, + TRANS("Closing document..."), + TRANS("Do you want to save the changes to \"") + + m_name + "\"?", + TRANS("Save"), + TRANS("Discard changes"), + TRANS("Cancel")); + + if (r == 0) // cancel button + { + user_cancelled = true; + } + else if(r == 1) // save button + { + if (!saveDocument()) + { + user_cancelled = true; + } + } + } + + return user_cancelled; } void PatcherManager::forceCloseAllWindows() @@ -442,7 +452,7 @@ namespace kiwi { bool need_saving = m_need_saving_flag && (number_of_views <= 1); - if(!need_saving || (need_saving && saveIfNeededAndUserAgrees() == juce::FileBasedDocument::savedOk)) + if(!need_saving || (need_saving && !saveIfNeededAndUserAgrees())) { it = user.removeView(*it); model::DocumentManager::commit(patcher); @@ -458,7 +468,7 @@ namespace kiwi return success; } - bool PatcherManager::closePatcherViewWindow(PatcherView& patcher_view) + void PatcherManager::closePatcherViewWindow(PatcherView& patcher_view) { auto& patcher = getPatcher(); auto& user = patcher.useSelfUser(); @@ -470,22 +480,13 @@ namespace kiwi return !view.removed(); }); - bool need_saving = m_need_saving_flag && (number_of_views <= 1); - - for(auto& view : views) - { - if(&view == &patcher_view_m) - { - if(!need_saving || saveIfNeededAndUserAgrees() == juce::FileBasedDocument::savedOk) - { - user.removeView(patcher_view_m); - model::DocumentManager::commit(patcher); - return true; - } - } + bool need_saving = m_need_saving_flag && (number_of_views <= 1); + + if (!need_saving || (need_saving && !saveIfNeededAndUserAgrees())) + { + user.removeView(patcher_view_m); + model::DocumentManager::commit(patcher); } - - return false; } PatcherViewWindow & PatcherManager::getFirstWindow() @@ -521,26 +522,9 @@ namespace kiwi void PatcherManager::documentChanged(DocumentBrowser::Drive::DocumentSession& doc) { if(m_session && (m_session == &doc)) - { - for(auto& view : getPatcher().useSelfUser().getViews()) - { - auto& patcherview = view.entity().use(); - patcherview.updateWindowTitle(); - } - } - } - - void PatcherManager::documentRemoved(DocumentBrowser::Drive::DocumentSession& doc) - { - if(m_session && (m_session == &doc)) - { - disconnect(); - - for(auto& view : getPatcher().useSelfUser().getViews()) - { - auto& patcherview = view.entity().use(); - patcherview.updateWindowTitle(); - } + { + setName(doc.getName()); + updateTitleBars(); } } @@ -570,7 +554,9 @@ namespace kiwi if(patcher.resident() && (patcher.objectsChanged() || patcher.linksChanged())) { - m_need_saving_flag = true; + setNeedSaving(true); + + updateTitleBars(); } } @@ -588,6 +574,11 @@ namespace kiwi if(view.added()) { createPatcherWindow(patcher, user, view); + } + + if(view.lockChanged()) + { + updateTitleBar(view); } notifyPatcherView(patcher, user, view); @@ -599,6 +590,48 @@ namespace kiwi } } } + } + + void PatcherManager::updateTitleBar(model::Patcher::View & view) + { + PatcherViewWindow & patcher_window = view.entity().use(); + + bool is_locked = view.getLock(); + + std::string title = (isRemote() ? "[Remote] " : "") + + m_name + + (is_locked ? "" : " (edit)"); + + if(juce::ComponentPeer* peer = patcher_window.getPeer()) + { + if (!peer->setDocumentEditedStatus(needsSaving())) + if (needsSaving()) + title += " *"; + + peer->setRepresentedFile(getSelectedFile()); + } + + patcher_window.setName(title); + } + + void PatcherManager::updateTitleBars() + { + flip::Collection & views = getPatcher().useSelfUser().getViews(); + + for(auto & view : views) + { + updateTitleBar(view); + } + } + + void PatcherManager::setNeedSaving(bool need_saving) + { + m_need_saving_flag = need_saving; + } + + void PatcherManager::setName(std::string const& name) + { + m_name = name; } void PatcherManager::createPatcherWindow(model::Patcher& patcher, @@ -608,8 +641,8 @@ namespace kiwi if(user.getId() == m_document.user()) { auto& patcherview = view.entity().emplace(*this, m_instance, patcher, view); - view.entity().emplace(*this, patcherview); - patcherview.updateWindowTitle(); + view.entity().emplace(*this, patcherview); + updateTitleBar(view); } } diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.h b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.h index 597a6ab9..181a121a 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.h @@ -57,7 +57,7 @@ namespace kiwi public: // methods //! @brief Constructor. - PatcherManager(Instance& instance); + PatcherManager(Instance& instance, std::string const& name); //! @brief Destructor. ~PatcherManager(); @@ -124,7 +124,7 @@ namespace kiwi //! @brief Close the window that contains a given patcherview. //! @details if it's the last patcher view, it will ask the user the save the document before closing if needed. - bool closePatcherViewWindow(PatcherView& patcherview); + void closePatcherViewWindow(PatcherView& patcherview); //! @brief Add a listener. void addListener(Listener& listener); @@ -136,10 +136,7 @@ namespace kiwi void documentAdded(DocumentBrowser::Drive::DocumentSession& doc) override; //! @brief Called when a document session changed. - void documentChanged(DocumentBrowser::Drive::DocumentSession& doc) override; - - //! @brief Called when a document session has been removed. - void documentRemoved(DocumentBrowser::Drive::DocumentSession& doc) override; + void documentChanged(DocumentBrowser::Drive::DocumentSession& doc) override; //! @brief Force all windows to close without asking user to save document. void forceCloseAllWindows(); @@ -180,11 +177,26 @@ namespace kiwi model::Patcher::User const& user, model::Patcher::View& view); - //! @internal Save document if needed and if user agrees. - juce::FileBasedDocument::SaveResult saveIfNeededAndUserAgrees(); + //! @internal Save document if needed and if user agrees. + //! returns true if user wants to continue editing. + bool saveIfNeededAndUserAgrees(); + + //! @internal Updates the title bar of specific view. + void updateTitleBar(model::Patcher::View & view); + + //! @internal Updates windows title bars according to remote state, + //! need saving flag, name and selected file. + void updateTitleBars(); + + //! @internal Sets the need saving flags. Updates title bar if requested. + void setNeedSaving(bool need_saving); + + //! @internal Sets the patcher manager's name. Updates title bar if requested. + void setName(std::string const& name); private: // members - + + std::string m_name; Instance& m_instance; model::PatcherValidator m_validator; flip::Document m_document; diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp index 4b2e67fd..8bd93bfe 100755 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.cpp @@ -1031,11 +1031,6 @@ namespace kiwi } } - if(!view.removed() && patcher.nameChanged()) - { - updateWindowTitle(); - } - if(!view.removed() && &view == &m_view_model) { checkViewInfos(view); @@ -1073,11 +1068,6 @@ namespace kiwi updateParameters(patcher); if(view.removed()) {} - - if(patcher.resident() && (patcher.objectsChanged() || patcher.linksChanged())) - { - updateWindowTitle(); - } } void PatcherView::updateParameters(model::Patcher const& patcher_model) @@ -1102,39 +1092,6 @@ namespace kiwi } } - void PatcherView::updateWindowTitle() const - { - PatcherViewWindow* window = findParentComponentOfClass(); - if(window) - { - juce::String title; - - if(!m_manager.isRemote()) - { - title = m_patcher_model.getName(); - const bool edited = m_manager.needsSaving(); - - juce::File kiwi_file = m_manager.getSelectedFile(); - - if(juce::ComponentPeer* peer = window->getPeer()) - { - if (!peer->setDocumentEditedStatus(edited)) - if (edited) - title << "*"; - - peer->setRepresentedFile(kiwi_file); - } - } - else - { - title = "[Remote] " + m_manager.getDocumentName(); - } - - std::string new_name = title.toStdString() + (isLocked() ? "" : " (edit) "); - window->setName(new_name); - } - } - void PatcherView::checkViewInfos(model::Patcher::View& view) { if(&view == &m_view_model && !view.removed()) @@ -1155,8 +1112,6 @@ namespace kiwi m_viewport.resetObjectsArea(); } - updateWindowTitle(); - repaint(); KiwiApp::commandStatusChanged(); } diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.h b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.h index cac8e7c6..07892d6e 100755 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherView.h @@ -124,9 +124,6 @@ namespace kiwi //! @brief Returns true if an object if being edited. bool isEditingObject() const; - //! @internal Update the patcher window title. - void updateWindowTitle() const; - // ================================================================================ // // COMPONENT // // ================================================================================ // diff --git a/Modules/KiwiModel/KiwiModel_Patcher.cpp b/Modules/KiwiModel/KiwiModel_Patcher.cpp index aeed7293..017e6b8d 100755 --- a/Modules/KiwiModel/KiwiModel_Patcher.cpp +++ b/Modules/KiwiModel/KiwiModel_Patcher.cpp @@ -43,8 +43,7 @@ namespace kiwi .name("cicm.kiwi.Patcher") .member("objects") .member("links") - .member("users") - .member("patcher_name"); + .member("users"); } // ================================================================================ // @@ -237,21 +236,6 @@ namespace kiwi return m_users.changed(); } - bool Patcher::nameChanged() const noexcept - { - return m_patcher_name.changed(); - } - - std::string Patcher::getName() const - { - return !m_patcher_name.removed() ? static_cast(m_patcher_name) : "Untitled"; - } - - void Patcher::setName(std::string const& new_name) - { - m_patcher_name = new_name; - } - Patcher::Objects const& Patcher::getObjects() const noexcept { return m_objects; diff --git a/Modules/KiwiModel/KiwiModel_Patcher.h b/Modules/KiwiModel/KiwiModel_Patcher.h index acfc28ba..f7ef3ded 100755 --- a/Modules/KiwiModel/KiwiModel_Patcher.h +++ b/Modules/KiwiModel/KiwiModel_Patcher.h @@ -93,15 +93,6 @@ namespace kiwi //! @brief Returns true if a User has been added, removed or changed. bool usersChanged() const noexcept; - //! @brief Returns true if the Patcher name changed. - bool nameChanged() const noexcept; - - //! @brief Returns the Patcher name. - std::string getName() const; - - //! @brief Sets the Patcher name. - void setName(std::string const& new_name); - //! @brief Gets the objects. Objects const& getObjects() const noexcept; @@ -169,12 +160,10 @@ namespace kiwi private: // members Objects m_objects; - Links m_links; + Links m_links; Users m_users; - flip::String m_patcher_name; - private: // deleted methods Patcher(Patcher const&) = delete; From d5bf033f528943e757f6915ec029724cf1254a13 Mon Sep 17 00:00:00 2001 From: jean-millot Date: Wed, 24 Jan 2018 16:08:57 +0100 Subject: [PATCH 125/148] Display connected users' name. --- Client/Source/KiwiApp_Network/KiwiApp_Api.cpp | 38 +++++++++++++++ Client/Source/KiwiApp_Network/KiwiApp_Api.h | 5 ++ .../KiwiApp_PatcherComponent.cpp | 46 +++++++++++++++++-- .../KiwiApp_PatcherComponent.h | 14 ++++-- 4 files changed, 95 insertions(+), 8 deletions(-) diff --git a/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp b/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp index 565a3655..e1c243de 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp +++ b/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp @@ -163,6 +163,44 @@ namespace kiwi storeSession(std::move(session)); } + void Api::getUsers(std::unordered_set const& user_ids, + CallbackFn success_cb, + ErrorCallback error_cb) + { + auto cb = + [success = std::move(success_cb), fail = std::move(error_cb)] + (Response res) + { + if (!res.error + && hasJsonHeader(res) + && res.result() == beast::http::status::ok) + { + success(json::parse(res.body)); + } + else + { + fail(res); + } + }; + + auto session = makeSession(Endpoint::users); + + json j_users; + + for(uint64_t const& user_id : user_ids) + { + std::ostringstream result; + result << std::hex << std::uppercase << user_id; + + j_users.push_back(result.str()); + } + + session->setParameters({{"ids", j_users.dump()}}); + + session->GetAsync(std::move(cb)); + storeSession(std::move(session)); + } + void Api::getDocuments(std::function callback) { auto cb = [callback = std::move(callback)](Response res) diff --git a/Client/Source/KiwiApp_Network/KiwiApp_Api.h b/Client/Source/KiwiApp_Network/KiwiApp_Api.h index fd4f407b..ea47d38e 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_Api.h +++ b/Client/Source/KiwiApp_Network/KiwiApp_Api.h @@ -21,6 +21,8 @@ #pragma once +#include + #include #include @@ -92,6 +94,9 @@ namespace kiwi CallbackFn success_cb, ErrorCallback error_cb); + //! @brief Returns a list of users, retrieved with user ids. + void getUsers(std::unordered_set const& user_ids, CallbackFn sucess_cb, ErrorCallback error_cb); + //! @brief Make an async API request to get a list of documents void getDocuments(std::function callback); diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherComponent.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherComponent.cpp index 4d47746b..5208e4a0 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherComponent.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherComponent.cpp @@ -160,7 +160,8 @@ namespace kiwi PatcherManager& patcher_manager) : ToolbarItemComponent (toolbarItemId, "Custom Toolbar Item", false) , m_patcher_manager(patcher_manager) - , m_users(m_patcher_manager.getNumberOfUsers()) + , m_users() + , m_user_nb(m_patcher_manager.getNumberOfUsers()) , m_users_img(juce::ImageCache::getFromMemory(binary_data::images::users_png, binary_data::images::users_png_size)) , m_flash_alpha(0.f) @@ -177,8 +178,32 @@ namespace kiwi { if(&manager == &m_patcher_manager) { - m_users = m_patcher_manager.getNumberOfUsers(); + m_user_nb = manager.getNumberOfUsers(); + startFlashing(); + + auto success = [this](Api::Users users) + { + KiwiApp::useInstance().useScheduler().schedule([this, users]() + { + m_users.clear(); + + for(Api::User const& user : users) + { + m_users.push_back(user.getName()); + } + }); + }; + + auto fail = [this](Api::Error error) + { + KiwiApp::useInstance().useScheduler().schedule([this, error]() + { + m_users.clear(); + }); + }; + + KiwiApp::useApi().getUsers(m_patcher_manager.getConnectedUsers(), success, fail); } } @@ -202,7 +227,7 @@ namespace kiwi g.fillEllipse(label_bounds.expanded(2).toFloat()); g.setColour(juce::Colours::whitesmoke); - g.drawText(std::to_string(m_users), label_bounds, juce::Justification::centred); + g.drawText(std::to_string(m_user_nb), label_bounds, juce::Justification::centred); } bool PatcherToolbar::UsersItemComponent::getToolbarItemSizes(int toolbarDepth, bool isVertical, @@ -233,6 +258,21 @@ namespace kiwi repaint(); } + void PatcherToolbar::UsersItemComponent::mouseDown(juce::MouseEvent const& e) + { + if (m_users.size() > 0) + { + juce::PopupMenu m; + + for(std::string const& username : m_users) + { + m.addItem(1, username, false, false); + } + + m.showAt(this); + } + } + void PatcherToolbar::UsersItemComponent::timerCallback() { // Reduce the alpha level of the flash slightly so it fades out diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherComponent.h b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherComponent.h index 4d0f6901..c2bc7f83 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherComponent.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherComponent.h @@ -117,7 +117,10 @@ namespace kiwi void startFlashing(); //! @brief Stops this component flashing. - void stopFlashing(); + void stopFlashing(); + + //! @brief Displays the list of usernames. + void mouseDown(juce::MouseEvent const& e) override final; private: // methods @@ -126,10 +129,11 @@ namespace kiwi private: // variables - PatcherManager& m_patcher_manager; - size_t m_users; - const juce::Image m_users_img; - float m_flash_alpha = 0.f; + PatcherManager& m_patcher_manager; + std::vector m_users; + size_t m_user_nb; + const juce::Image m_users_img; + float m_flash_alpha = 0.f; }; // ================================================================================ // From c3c1436a91a5ef34030115d8dcc6773b09d34cc2 Mon Sep 17 00:00:00 2001 From: jmillot Date: Wed, 24 Jan 2018 21:33:20 +0100 Subject: [PATCH 126/148] Update the way latest release is handled. --- Client/Source/KiwiApp.cpp | 4 ++-- Client/Source/KiwiApp_Network/KiwiApp_Api.cpp | 10 +++++----- Client/Source/KiwiApp_Network/KiwiApp_Api.h | 6 +++--- .../KiwiApp_Patcher/KiwiApp_PatcherManager.cpp | 1 + Modules/KiwiServer/KiwiServer_Server.cpp | 17 ++++++++++++----- Modules/KiwiServer/KiwiServer_Server.h | 10 ++++++++-- Server/Source/Main.cpp | 3 ++- Test/Server/test_Server.cpp | 11 +++++++---- 8 files changed, 40 insertions(+), 22 deletions(-) diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index 478971ae..c04267df 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -342,7 +342,7 @@ namespace kiwi { KiwiApp::useInstance().useScheduler().schedule([current_version, latest_version]() { - if (current_version.compare(latest_version) < 0) + if (current_version.compare(latest_version) != 0) { juce::AlertWindow::showMessageBoxAsync(juce::AlertWindow::QuestionIcon, "New release available" , @@ -355,7 +355,7 @@ namespace kiwi { }; - useApi().getLatestRelease(on_success, on_fail); + useApi().getRelease(on_success, on_fail); } void KiwiApp::addApiConnectStatusListener(ApiConnectStatusListener& listener) diff --git a/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp b/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp index e1c243de..b3b45f56 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp +++ b/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp @@ -27,7 +27,7 @@ namespace kiwi const std::string Api::Endpoint::login {Api::Endpoint::root + "/login"}; const std::string Api::Endpoint::documents {Api::Endpoint::root + "/documents"}; const std::string Api::Endpoint::users {Api::Endpoint::root + "/users"}; - const std::string Api::Endpoint::releases {Api::Endpoint::root + "/releases"}; + const std::string Api::Endpoint::release {Api::Endpoint::root + "/release"}; std::string Api::Endpoint::document(std::string const& document_id) { @@ -329,9 +329,9 @@ namespace kiwi storeSession(std::move(session)); } - void Api::getLatestRelease(CallbackFn success_cb, ErrorCallback error_cb) + void Api::getRelease(CallbackFn success_cb, ErrorCallback error_cb) { - auto session = makeSession(Endpoint::releases + "/latest"); + auto session = makeSession(Endpoint::release); auto cb = [success = std::move(success_cb), fail = std::move(error_cb)](Response res) @@ -342,9 +342,9 @@ namespace kiwi { const auto j = json::parse(res.body); - if(j.is_object() && j.count("tag_name")) + if(j.is_object() && j.count("release")) { - std::string latest_release = j["tag_name"]; + std::string latest_release = j["release"]; success(latest_release); } } diff --git a/Client/Source/KiwiApp_Network/KiwiApp_Api.h b/Client/Source/KiwiApp_Network/KiwiApp_Api.h index ea47d38e..76e0fbe0 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_Api.h +++ b/Client/Source/KiwiApp_Network/KiwiApp_Api.h @@ -122,8 +122,8 @@ namespace kiwi CallbackFn success_cb, ErrorCallback error_cb); - //! @brief Retrieves Kiwi's latest release as a string. ex: v0.1.0 - void getLatestRelease(CallbackFn success_cb, ErrorCallback error_cb); + //! @brief Retrieve version of kiwi compatible with the api server. + void getRelease(CallbackFn success_cb, ErrorCallback error_cb); //! @brief Requests a reset token to the server. void requestPasswordToken(std::string const& user_mail, CallbackFn success_cb, ErrorCallback error_cb); @@ -155,7 +155,7 @@ namespace kiwi static const std::string login; static const std::string documents; static const std::string users; - static const std::string releases; + static const std::string release; static std::string document(std::string const& document_id); static std::string user(std::string const& user_id); diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.cpp index 8940db43..f389270b 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.cpp @@ -161,6 +161,7 @@ namespace kiwi json j; j["model_version"] = KIWI_MODEL_VERSION_STRING; j["open_token"] = session.getOpenToken(); + j["kiwi_version"] = KiwiApp::getApp()->getApplicationVersion().toStdString(); std::string metadata = j.dump(); m_socket.connect(host, port, session.getSessionId(), metadata); diff --git a/Modules/KiwiServer/KiwiServer_Server.cpp b/Modules/KiwiServer/KiwiServer_Server.cpp index cf30427a..437b555a 100644 --- a/Modules/KiwiServer/KiwiServer_Server.cpp +++ b/Modules/KiwiServer/KiwiServer_Server.cpp @@ -55,9 +55,11 @@ namespace kiwi Server::Server(uint16_t port, std::string const& backend_directory, - std::string const& open_token) : + std::string const& open_token, + std::string const& kiwi_version) : m_backend_directory(backend_directory), m_open_token(open_token), + m_kiwi_version(kiwi_version), m_sessions(), m_socket(*this, port), m_ports() @@ -116,8 +118,9 @@ namespace kiwi DBG("[server] - creating new session for session_id : " << hexadecimal_convert(session_id)); - auto session = m_sessions.insert(std::make_pair(session_id, - Session(session_id, session_file, m_open_token))); + auto session = m_sessions + .insert(std::make_pair(session_id, + Session(session_id, session_file, m_open_token, m_kiwi_version))); if (session_file.exists()) { @@ -212,19 +215,22 @@ namespace kiwi , m_signal_connections(std::move(other.m_signal_connections)) , m_backend_file(std::move(other.m_backend_file)) , m_token(other.m_token) + , m_kiwi_version(other.m_kiwi_version) { ; } Server::Session::Session(uint64_t identifier, juce::File const& backend_file, - std::string const& token) + std::string const& token, + std::string const& kiwi_version) : m_identifier(identifier) , m_validator(new model::PatcherValidator()) , m_document(new flip::DocumentServer(model::DataModel::use(), *m_validator, m_identifier)) , m_signal_connections() , m_backend_file(backend_file) , m_token(token) + , m_kiwi_version(kiwi_version) { model::Patcher& patcher = m_document->root(); @@ -299,7 +305,8 @@ namespace kiwi { const auto j = json::parse(metadata); return j["model_version"] == KIWI_MODEL_VERSION_STRING - && j["open_token"] == m_token; + && j["open_token"] == m_token + && j["kiwi_version"] == m_kiwi_version; } void Server::Session::bind(flip::PortBase & port) diff --git a/Modules/KiwiServer/KiwiServer_Server.h b/Modules/KiwiServer/KiwiServer_Server.h index 55dc097e..003cfbae 100644 --- a/Modules/KiwiServer/KiwiServer_Server.h +++ b/Modules/KiwiServer/KiwiServer_Server.h @@ -59,7 +59,8 @@ namespace kiwi //! @details Initializes socket and creates backend directory if not there. Server(uint16_t port, std::string const& backend_directory, - std::string const& open_token); + std::string const& open_token, + std::string const& kiwi_version); //! @brief Destructor. //! @details Disconnect all users and clean sessions. onDisconnected will be called for all port. @@ -109,6 +110,7 @@ namespace kiwi juce::File m_backend_directory; std::string m_open_token; + std::string m_kiwi_version; std::map m_sessions; flip::PortTransportServerTcp m_socket; std::set m_ports; @@ -139,7 +141,10 @@ namespace kiwi //! @brief Constructor //! @details Constructor will load the document if file exists. backend_file is //! the file in which the session will save and load document. - Session(uint64_t identifier, juce::File const& backend_file, std::string const& token); + Session(uint64_t identifier, + juce::File const& backend_file, + std::string const& token, + std::string const& kiwi_version); //! @brief Destructor. //! @details Unbinds all documents and ports. @@ -180,6 +185,7 @@ namespace kiwi std::vector m_signal_connections; juce::File m_backend_file; std::string m_token; + std::string m_kiwi_version; private: // deleted methods diff --git a/Server/Source/Main.cpp b/Server/Source/Main.cpp index 8002f8ed..ed2e0fb4 100644 --- a/Server/Source/Main.cpp +++ b/Server/Source/Main.cpp @@ -98,7 +98,8 @@ int main(int argc, char const* argv[]) { server::Server kiwi_server(config["session_port"], config["backend_directory"], - config["open_token"]); + config["open_token"], + config["kiwi_version"]); std::cout << "[server] - running on port " << config["session_port"] << std::endl; diff --git a/Test/Server/test_Server.cpp b/Test/Server/test_Server.cpp index beba7b24..1fd5e8aa 100755 --- a/Test/Server/test_Server.cpp +++ b/Test/Server/test_Server.cpp @@ -39,12 +39,14 @@ using namespace kiwi; // ==================================================================================== // std::string token = "token"; +std::string kiwi_version = "v0.1.0"; std::string getMetaData() { nlohmann::json j; j["model_version"] = KIWI_MODEL_VERSION_STRING; j["open_token"] = token; + j["kiwi_version"] = kiwi_version; return j.dump(); } @@ -52,7 +54,7 @@ TEST_CASE("Server - Server", "[Server, Server]") { SECTION("Simple Connection - Deconnection") { - kiwi::server::Server server(9191, "./server_backend_test", token); + kiwi::server::Server server(9191, "./server_backend_test", token, kiwi_version); // Initializing document flip::Document document (kiwi::model::DataModel::use (), 123456789, 'appl', 'gui '); @@ -94,7 +96,8 @@ TEST_CASE("Server - Server", "[Server, Server]") { std::unique_ptr server(new kiwi::server::Server(9191, "./server_backend_test", - token)); + token, + kiwi_version)); // Initializing document. flip::Document document (kiwi::model::DataModel::use (), 123456789, 'appl', 'gui '); @@ -131,7 +134,7 @@ TEST_CASE("Server - Server", "[Server, Server]") SECTION("One user connecting to multiple document") { - kiwi::server::Server server(9191, "./server_backend_test", token); + kiwi::server::Server server(9191, "./server_backend_test", token, kiwi_version); // Initializing documents. flip::Document document_1 (kiwi::model::DataModel::use (), 123456789, 'appl', 'gui '); @@ -176,7 +179,7 @@ TEST_CASE("Server - Server", "[Server, Server]") SECTION("Multiple connections") { - kiwi::server::Server server(9191, "./server_backend_test", token); + kiwi::server::Server server(9191, "./server_backend_test", token, kiwi_version); // Initializing client 1 flip::Document document_1 (kiwi::model::DataModel::use (), 1, 'appl', 'gui '); From 992f479b825808604e2a2af1a95e9cc373be7639 Mon Sep 17 00:00:00 2001 From: jmillot Date: Thu, 25 Jan 2018 17:42:21 +0100 Subject: [PATCH 127/148] upload-download-duplicate. --- .../KiwiApp_DocumentBrowserView.cpp | 95 +++++++++++++++++++ .../KiwiApp_DocumentBrowserView.h | 9 ++ Client/Source/KiwiApp_Network/KiwiApp_Api.cpp | 51 ++++++++++ Client/Source/KiwiApp_Network/KiwiApp_Api.h | 12 +++ .../KiwiApp_DocumentBrowser.cpp | 78 +++++++++++++++ .../KiwiApp_Network/KiwiApp_DocumentBrowser.h | 12 +++ .../KiwiNetwork/KiwiHttp/KiwiHttp_Session.cpp | 12 ++- .../KiwiNetwork/KiwiHttp/KiwiHttp_Session.h | 4 +- Modules/KiwiServer/KiwiServer_Server.cpp | 28 ++++++ Modules/KiwiServer/KiwiServer_Server.h | 5 + 10 files changed, 300 insertions(+), 6 deletions(-) diff --git a/Client/Source/KiwiApp_Application/KiwiApp_DocumentBrowserView.cpp b/Client/Source/KiwiApp_Application/KiwiApp_DocumentBrowserView.cpp index 48073fb4..b7685516 100644 --- a/Client/Source/KiwiApp_Application/KiwiApp_DocumentBrowserView.cpp +++ b/Client/Source/KiwiApp_Application/KiwiApp_DocumentBrowserView.cpp @@ -19,6 +19,12 @@ ============================================================================== */ +#include +#include +#include + +#include + #include #include "KiwiApp_DocumentBrowserView.h" @@ -197,12 +203,16 @@ namespace kiwi { m.addItem(1, "Rename"); m.addItem(2, "Delete"); + m.addItem(10, "Upload"); + m.addItem(11, "Duplicate"); } else { m.addItem(3, "Restore"); } + m.addItem(9, "Download"); + DriveView::DataType current_sort = m_drive_view.getSortType(); juce::PopupMenu sort_menu; @@ -272,6 +282,21 @@ namespace kiwi m_drive_view.setSortType(DriveView::DataType::openedUser); break; } + case 9: // download document + { + m_drive_view.downloadDocumentForRow(m_row); + break; + } + case 10: // upload document + { + m_drive_view.uploadDocument(); + break; + } + case 11: // duplicate document + { + m_drive_view.duplicateDocumentForRow(m_row); + break; + } } } @@ -672,6 +697,76 @@ namespace kiwi } } + void DocumentBrowserView::DriveView::duplicateDocumentForRow(int row) + { + auto& documents = m_drive.getDocuments(); + + if(row < documents.size()) + { + documents[row]->duplicate(); + } + } + + void DocumentBrowserView::DriveView::uploadDocument() + { + auto directory = juce::File::getSpecialLocation(juce::File::userHomeDirectory); + + juce::FileChooser file_chooser("Upload file", directory, "*.kiwi"); + + if(file_chooser.browseForFileToOpen()) + { + juce::File result = file_chooser.getResult(); + + // Test that document is a valid kiwi document. + flip::DataProviderFile provider(result.getFullPathName().toStdString().c_str()); + flip::BackEndIR back_end; + + back_end.register_backend(); + + std::string current_version(KIWI_MODEL_VERSION_STRING); + + if (back_end.read(provider) && current_version.compare(back_end.version) == 0) + { + juce::MemoryBlock buffer; + result.loadFileAsData(buffer); + + std::string data((char *) buffer.getData(), buffer.getSize() / sizeof(char)); + + m_drive.uploadDocument(result.getFileNameWithoutExtension().toStdString(), + data); + } + else + { + KiwiApp::error("Not a valid Kiwi file"); + } + } + } + + void DocumentBrowserView::DriveView::downloadDocumentForRow(int row) + { + auto& document = m_drive.getDocuments()[row]; + + auto directory = juce::File::getSpecialLocation(juce::File::userHomeDirectory); + + juce::File suggest_file = + directory.getChildFile(juce::String(document->getName())).withFileExtension("kiwi"); + + juce::FileChooser saveFileChooser("Download file", suggest_file, "*.kiwi"); + + if (saveFileChooser.browseForFileToSave(true)) + { + juce::File result = saveFileChooser.getResult(); + + document->download([result](std::string const& content) + { + if(result.create().wasOk()) + { + result.replaceWithData(content.data(), content.size() * sizeof(char)); + } + }); + } + } + void DocumentBrowserView::DriveView::listBoxItemDoubleClicked(int row, juce::MouseEvent const& e) { openDocument(row); diff --git a/Client/Source/KiwiApp_Application/KiwiApp_DocumentBrowserView.h b/Client/Source/KiwiApp_Application/KiwiApp_DocumentBrowserView.h index 98fc6eb4..e56eceea 100644 --- a/Client/Source/KiwiApp_Application/KiwiApp_DocumentBrowserView.h +++ b/Client/Source/KiwiApp_Application/KiwiApp_DocumentBrowserView.h @@ -139,9 +139,18 @@ namespace kiwi //! @brief Opens document for the given row. void openDocument(int row); + //! @brief Make an API call to duplicate the document on server side. + void duplicateDocumentForRow(int row); + //! @brief Make an API call to rename the remote document void renameDocumentForRow(int row, std::string const& new_name); + //! @brief Makes an API call to upload a document. + void uploadDocument(); + + //! @brief Makes an API call to download the remote document. + void downloadDocumentForRow(int row); + //! @brief Moves a document to trash. void deleteDocumentForRow(int row); diff --git a/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp b/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp index b3b45f56..d03f2518 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp +++ b/Client/Source/KiwiApp_Network/KiwiApp_Api.cpp @@ -265,6 +265,47 @@ namespace kiwi storeSession(std::move(session)); } + void Api::uploadDocument(std::string const& name, + std::string const& data, + std::string const& kiwi_version, + std::function callback) + { + auto cb = [callback = std::move(callback)](Response res) + { + if (!res.error + && res.result() == beast::http::status::ok + && hasJsonHeader(res)) + { + auto j = json::parse(res.body); + + if(j.is_object()) + { + // parse object as a document + callback(std::move(res), j); + return; + } + } + + callback(std::move(res), {}); + }; + + auto session = makeSession(Endpoint::documents + "/upload"); + + session->setParameters({{"name", name}, {"kiwi_version", kiwi_version}}); + session->setBody(data); + + session->PostAsync(std::move(cb)); + storeSession(std::move(session)); + } + + void Api::duplicateDocument(std::string const& document_id, Callback callback) + { + auto session = makeSession(Endpoint::document(document_id) + "/clone"); + + session->PostAsync(std::move(callback)); + storeSession(std::move(session)); + } + void Api::renameDocument(std::string document_id, std::string const& new_name, Callback callback) { @@ -329,6 +370,16 @@ namespace kiwi storeSession(std::move(session)); } + void Api::downloadDocument(std::string document_id, Callback callback) + { + auto session = makeSession(Endpoint::document(document_id) + "/download"); + + session->setParameters({{"alt", "download"}}); + + session->GetAsync(std::move(callback)); + storeSession(std::move(session)); + } + void Api::getRelease(CallbackFn success_cb, ErrorCallback error_cb) { auto session = makeSession(Endpoint::release); diff --git a/Client/Source/KiwiApp_Network/KiwiApp_Api.h b/Client/Source/KiwiApp_Network/KiwiApp_Api.h index 76e0fbe0..1a68cfcf 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_Api.h +++ b/Client/Source/KiwiApp_Network/KiwiApp_Api.h @@ -105,6 +105,15 @@ namespace kiwi void createDocument(std::string const& document_name, std::function callback); + //! @brief Uploads a document to the server. + void uploadDocument(std::string const& name, + std::string const& data, + std::string const& kiwi_version, + std::function callback); + + //! @brief Duplicates a document on server side. + void duplicateDocument(std::string const& document_id, Callback callback); + //! @brief Rename a document asynchronously. //! @param callback The callback method that will be called when the request is completed. void renameDocument(std::string document_id, @@ -122,6 +131,9 @@ namespace kiwi CallbackFn success_cb, ErrorCallback error_cb); + //! @brief Make an async API request to download a document. + void downloadDocument(std::string document_id, Callback success_cb); + //! @brief Retrieve version of kiwi compatible with the api server. void getRelease(CallbackFn success_cb, ErrorCallback error_cb); diff --git a/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp b/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp index 509c1dd9..ced99626 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp +++ b/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp @@ -205,6 +205,34 @@ namespace kiwi m_listeners.call(&Listener::driveChanged); } + void DocumentBrowser::Drive::uploadDocument(std::string const& name, std::string const& data) + { + KiwiApp::useApi().uploadDocument(name, + data, + KiwiApp::use().getApplicationVersion().toStdString(), + [this](Api::Response res, Api::Document document) + { + if (res.result() == beast::http::status::forbidden) + { + DocumentBrowser::handleDeniedRequest(); + } + else if(res.error) + { + juce::MessageManager::callAsync([message = res.error.message()](){ + KiwiApp::error("Error: can't create document"); + KiwiApp::error("=> " + message); + }); + } + else + { + juce::MessageManager::callAsync([this]() + { + refresh(); + }); + } + }); + } + void DocumentBrowser::Drive::createNewDocument() { KiwiApp::useApi().createDocument("", [this](Api::Response res, Api::Document document) { @@ -467,6 +495,31 @@ namespace kiwi }); } + void DocumentBrowser::Drive::DocumentSession::duplicate() + { + KiwiApp::useApi().duplicateDocument(m_document._id, [this](Api::Response res) { + + if (res.result() == beast::http::status::forbidden) + { + KiwiApp::useInstance().useScheduler().schedule([]() + { + DocumentBrowser::handleDeniedRequest(); + }); + } + else if(res.error) + { + KiwiApp::error(res.error.message()); + } + else + { + KiwiApp::useInstance().useScheduler().schedule([this]() + { + m_drive.refresh(); + }); + } + }); + } + void DocumentBrowser::Drive::DocumentSession::rename(std::string const& new_name) { if(new_name.empty()) @@ -497,6 +550,31 @@ namespace kiwi }); } + void DocumentBrowser::Drive::DocumentSession::download(std::function callback) + { + KiwiApp::useApi().downloadDocument(m_document._id, + [this, cb = std::move(callback)](Api::Response res) + { + + if (res.result() == beast::http::status::forbidden) + { + KiwiApp::useInstance().useScheduler().schedule([]() + { + DocumentBrowser::handleDeniedRequest(); + + }); + } + else if(res.error) + { + KiwiApp::error(res.error.message()); + } + else + { + KiwiApp::useInstance().useScheduler().schedule(std::bind(cb, res.body)); + } + }); + } + bool DocumentBrowser::Drive::DocumentSession::operator==(DocumentSession const& other_doc) const { return (&m_drive == &other_doc.useDrive()) && (m_document == other_doc.m_document); diff --git a/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.h b/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.h index 239ee2bc..95b9e4ab 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.h +++ b/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.h @@ -156,6 +156,10 @@ namespace kiwi //! @brief Returns the name of this drive. std::string const& getName() const; + //! @brief Uploads a document. + //! @detail data is represented as a string + void uploadDocument(std::string const& name, std::string const& data); + //! @brief Creates and opens a new document on this drive. void createNewDocument(); @@ -247,12 +251,20 @@ namespace kiwi //! @brief Rename the document. void rename(std::string const& new_name); + //! @brief Duplicates the document on server side. + void duplicate(); + //! @brief Move the document to trash. void trash(); // @brief Moves document out of the trash. void untrash(); + //! @brief Called to download the document. + //! @details download is asynchronous and callback is called on the main thread + //! if request succeed. + void download(std::function callback); + //! @brief Returns the date creation as a string. std::string const& getCreationDate() const; diff --git a/Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Session.cpp b/Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Session.cpp index ba378126..14c5dc3d 100644 --- a/Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Session.cpp +++ b/Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Session.cpp @@ -80,10 +80,9 @@ namespace kiwi { namespace network { namespace http { // BODY // // ================================================================================ // - Body::Body(std::string body) - : content(std::move(body)) + Body::Body(std::string const& body) + : content(body) { - } // ================================================================================ // @@ -139,6 +138,11 @@ namespace kiwi { namespace network { namespace http { m_payload = std::move(payload); } + void Session::setBody(std::string const& content) + { + m_body.content = content; + } + bool Session::isPending() { return m_future.valid() && m_future.wait_for(std::chrono::seconds(0)) != std::future_status::ready; @@ -219,7 +223,7 @@ namespace kiwi { namespace network { namespace http { const auto content_type = req[beast::http::field::content_type]; if(content_type.empty()) { - request->set(beast::http::field::content_type, "text/plain"); + request->set(beast::http::field::content_type, "application/octet-stream"); } request->body = std::move(m_body.content); diff --git a/Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Session.h b/Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Session.h index be9871d7..4a8922f2 100644 --- a/Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Session.h +++ b/Modules/KiwiNetwork/KiwiHttp/KiwiHttp_Session.h @@ -83,7 +83,7 @@ namespace kiwi { namespace network { namespace http { public: Body() = default; - Body(std::string body); + Body(std::string const& body); std::string content; }; @@ -111,7 +111,7 @@ namespace kiwi { namespace network { namespace http { void setParameters(Parameters && parameters); void setPayload(Payload && payload); - void setBody(Body && body); + void setBody(std::string const& content); bool isPending(); void cancel(); diff --git a/Modules/KiwiServer/KiwiServer_Server.cpp b/Modules/KiwiServer/KiwiServer_Server.cpp index 437b555a..434f87ef 100644 --- a/Modules/KiwiServer/KiwiServer_Server.cpp +++ b/Modules/KiwiServer/KiwiServer_Server.cpp @@ -72,6 +72,11 @@ namespace kiwi { m_backend_directory.createDirectory(); } + + if(!createEmptyDocument()) + { + throw std::runtime_error("Failed to create empty document"); + } } Server::~Server() @@ -102,6 +107,29 @@ namespace kiwi return session != m_sessions.end() ? session->second.getConnectedUsers() : std::set(); } + bool Server::createEmptyDocument() + { + juce::File empty_file = m_backend_directory.getChildFile("empty").withFileExtension(".kiwi"); + + if (!empty_file.exists()) + { + if (empty_file.create().wasOk()) + { + model::PatcherValidator validator; + flip::DocumentServer empty_document(model::DataModel::use(), validator, 0); + + empty_document.commit(); + + flip::BackEndIR backend(empty_document.write()); + flip::DataConsumerFile consumer(empty_file.getFullPathName().toStdString().c_str()); + + backend.write(consumer); + } + } + + return empty_file.exists(); + } + juce::File Server::getSessionFile(uint64_t session_id) const { return m_backend_directory.getChildFile(juce::String(hexadecimal_convert(session_id))) diff --git a/Modules/KiwiServer/KiwiServer_Server.h b/Modules/KiwiServer/KiwiServer_Server.h index 003cfbae..d04dfd30 100644 --- a/Modules/KiwiServer/KiwiServer_Server.h +++ b/Modules/KiwiServer/KiwiServer_Server.h @@ -86,6 +86,11 @@ namespace kiwi //! @brief Get the path for a given session. juce::File getSessionFile(uint64_t session_id) const; + //! @brief Creates and empy document. + //! @details Used by node to retrieve empty if document not yet opened. + //! Returns true if the empty document exists. + bool createEmptyDocument(); + private: // methods // PortFactoryListener From 9f82f6271c2d8b05bd66e50f9a23126bf1673b27 Mon Sep 17 00:00:00 2001 From: jmillot Date: Sat, 27 Jan 2018 02:01:26 +0100 Subject: [PATCH 128/148] Improving connection user experience. --- Client/Source/KiwiApp.cpp | 51 ++++--- Client/Source/KiwiApp.h | 16 +-- .../KiwiApp_DocumentBrowserView.cpp | 119 +++++++++------- .../KiwiApp_DocumentBrowserView.h | 38 +++--- .../KiwiApp_Application/KiwiApp_Instance.cpp | 74 +++++----- .../KiwiApp_Application/KiwiApp_Instance.h | 11 +- .../KiwiApp_SettingsPanel.cpp | 78 +++++++++-- .../KiwiApp_SettingsPanel.h | 22 ++- Client/Source/KiwiApp_General/KiwiApp_IDs.h | 2 +- .../KiwiApp_StoredSettings.cpp | 127 ++++++++++-------- .../KiwiApp_General/KiwiApp_StoredSettings.h | 24 ++-- .../KiwiApp_Network/KiwiApp_ApiController.cpp | 28 ---- .../KiwiApp_Network/KiwiApp_ApiController.h | 22 --- .../KiwiApp_DocumentBrowser.cpp | 122 ++++------------- .../KiwiApp_Network/KiwiApp_DocumentBrowser.h | 76 ++--------- .../KiwiApp_Patcher/KiwiApp_PatcherManager.h | 8 +- .../KiwiApp_Ressources/KiwiApp_BinaryData.cpp | 16 ++- .../KiwiApp_Ressources/KiwiApp_BinaryData.h | 2 +- .../BinaryRes/Settings/network.settings | 4 +- 19 files changed, 402 insertions(+), 438 deletions(-) diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index c04267df..f8588269 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -27,7 +27,8 @@ #include #include #include -#include +#include +#include namespace kiwi { @@ -107,7 +108,9 @@ namespace kiwi m_command_manager = std::make_unique(); - m_settings = std::make_unique(); + m_settings = std::make_unique(); + + m_settings->network().addListener(*this); m_menu_model.reset(new MainMenuModel()); @@ -306,8 +309,15 @@ namespace kiwi std::function success_callback, Api::ErrorCallback error_callback) { - auto& api_controller = *KiwiApp::use().m_api_controller; - api_controller.login(name_or_email, password, std::move(success_callback), std::move(error_callback)); + auto& api_controller = *KiwiApp::use().m_api_controller; + + auto success = [cb = std::move(success_callback)]() + { + KiwiApp::useInstance().login(); + cb(); + }; + + api_controller.login(name_or_email, password, std::move(success), std::move(error_callback)); } void KiwiApp::signup(std::string const& username, @@ -326,12 +336,10 @@ namespace kiwi } void KiwiApp::logout() - { - if(useInstance().logout()) - { - KiwiApp::use().m_api_controller->logout(); - KiwiApp::commandStatusChanged(); - } + { + useInstance().logout(); + KiwiApp::use().m_api_controller->logout(); + KiwiApp::commandStatusChanged(); } void KiwiApp::checkLatestRelease() @@ -356,16 +364,19 @@ namespace kiwi }; useApi().getRelease(on_success, on_fail); - } - - void KiwiApp::addApiConnectStatusListener(ApiConnectStatusListener& listener) - { - KiwiApp::use().m_api_controller->addListener(listener); - } - - void KiwiApp::removeApiConnectStatusListener(ApiConnectStatusListener& listener) - { - KiwiApp::use().m_api_controller->removeListener(listener); + } + + void KiwiApp::networkSettingsChanged(NetworkSettings const& settings, juce::Identifier const& id) + { + if (id == Ids::server_address) + { + logout(); + + m_api_controller->setHost(settings.getHost()); + m_api_controller->setPort(settings.getApiPort()); + + checkLatestRelease(); + } } uint64_t KiwiApp::userID() diff --git a/Client/Source/KiwiApp.h b/Client/Source/KiwiApp.h index 89654a04..db6c281b 100644 --- a/Client/Source/KiwiApp.h +++ b/Client/Source/KiwiApp.h @@ -44,7 +44,8 @@ namespace kiwi // KiWi APPLICATION // // ================================================================================ // - class KiwiApp : public juce::JUCEApplication + class KiwiApp : public juce::JUCEApplication, + public NetworkSettings::Listener { public: // methods @@ -121,14 +122,6 @@ namespace kiwi //! @brief Log-out the user static void logout(); - //! @brief Adds an api connect status listener. - //! @see ApiConnectStatusListener - static void addApiConnectStatusListener(ApiConnectStatusListener& listener); - - //! @brief Removes an api connect status listener. - //! @see ApiConnectStatusListener - static void removeApiConnectStatusListener(ApiConnectStatusListener& listener); - //! @brief Get the current running engine instance. static engine::Instance& useEngineInstance(); @@ -248,7 +241,10 @@ namespace kiwi void declareObjectViews(); //! @internal Checks if current Kiwi version is the latest. Show popup if version not up to date. - void checkLatestRelease(); + void checkLatestRelease(); + + // @brief Handles changes of server address. + void networkSettingsChanged(NetworkSettings const& settings, juce::Identifier const& ids) override final; private: // members diff --git a/Client/Source/KiwiApp_Application/KiwiApp_DocumentBrowserView.cpp b/Client/Source/KiwiApp_Application/KiwiApp_DocumentBrowserView.cpp index b7685516..ea356479 100644 --- a/Client/Source/KiwiApp_Application/KiwiApp_DocumentBrowserView.cpp +++ b/Client/Source/KiwiApp_Application/KiwiApp_DocumentBrowserView.cpp @@ -39,49 +39,27 @@ namespace kiwi // DOCUMENT BROWSER // // ================================================================================ // - DocumentBrowserView::DocumentBrowserView(DocumentBrowser& browser) : + DocumentBrowserView::DocumentBrowserView(DocumentBrowser& browser, bool enabled) : m_browser(browser) { setSize(1, 1); - m_browser.addListener(*this); - for(auto* drive : m_browser.getDrives()) - { - driveAdded(*drive); - } - setSize(200, 300); - } - - DocumentBrowserView::~DocumentBrowserView() - { - m_browser.removeListener(*this); - } - - void DocumentBrowserView::driveAdded(DocumentBrowser::Drive& drive) - { + DocumentBrowser::Drive & drive = *m_browser.getDrive(); + auto drive_view = std::make_unique(drive); drive_view->setSize(getWidth(), drive_view->getHeight()); addAndMakeVisible(drive_view.get()); m_drives.emplace_back(std::move(drive_view)); + resized(); - } - - void DocumentBrowserView::driveRemoved(DocumentBrowser::Drive const& drive) - { - const auto drive_view_it = std::find_if(m_drives.begin(), m_drives.end(), [&drive](std::unique_ptr const& drive_view){ - return (*drive_view.get() == drive); - }); - if(drive_view_it != m_drives.end()) - { - removeChildComponent((*drive_view_it).get()); - m_drives.erase(drive_view_it); - } + setSize(200, 300); + + setEnabled(enabled); } - void DocumentBrowserView::driveChanged(DocumentBrowser::Drive const& drive) + DocumentBrowserView::~DocumentBrowserView() { - resized(); } void DocumentBrowserView::resized() @@ -101,6 +79,14 @@ namespace kiwi ; } + void DocumentBrowserView::enablementChanged() + { + for(auto & drive : m_drives) + { + drive->setEnabled(isEnabled()); + } + } + // ================================================================================ // // DOCUMENT SESSION VIEW // // ================================================================================ // @@ -355,8 +341,12 @@ namespace kiwi m_folder_bounds(), m_label("drive_name", m_drive_view.getDriveName()), m_folder_img(juce::ImageCache::getFromMemory(binary_data::images::folder_png, - binary_data::images::folder_png_size)) + binary_data::images::folder_png_size)), + m_disable_folder_img(m_folder_img) { + m_folder_img.duplicateIfShared(); + m_disable_folder_img.multiplyAllAlphas(0.5); + m_label.setFont(m_label.getFont().withHeight(20)); m_label.setEditable(false); m_label.setColour(juce::Label::textColourId, juce::Colours::whitesmoke); @@ -392,6 +382,30 @@ namespace kiwi } + void DocumentBrowserView::DriveView::Header::enablementChanged() + { + if (isEnabled()) + { + m_refresh_btn.setCommand([this](){m_drive_view.refresh();}); + m_refresh_btn.setAlpha(1); + + m_create_document_btn.setCommand([this]() + { + if (!m_drive_view.getTrashMode()) + m_drive_view.createDocument(); + }); + m_create_document_btn.setAlpha(1); + } + else + { + m_refresh_btn.setCommand([](){}); + m_refresh_btn.setAlpha(0.5); + + m_create_document_btn.setCommand([](){}); + m_create_document_btn.setAlpha(0.5); + } + } + void DocumentBrowserView::DriveView::Header::resized() { const auto bounds = getLocalBounds(); @@ -414,8 +428,16 @@ namespace kiwi g.fillAll(color); - g.drawImage(m_folder_img, m_folder_bounds.toFloat(), - juce::RectanglePlacement::yMid, false); + if (isEnabled()) + { + g.drawImage(m_folder_img, m_folder_bounds.toFloat(), + juce::RectanglePlacement::yMid, false); + } + else + { + g.drawImage(m_disable_folder_img, m_folder_bounds.toFloat(), + juce::RectanglePlacement::yMid, false); + } const auto bounds = getLocalBounds(); @@ -442,6 +464,7 @@ namespace kiwi juce::ListBox("document list", this), m_drive(drive), m_trash_mode(false), + m_enabled(true), m_sorter() { m_drive.addListener(*this); @@ -512,6 +535,12 @@ namespace kiwi || (l_hs.isTrashed() == r_hs.isTrashed() && type_ordered); } + void DocumentBrowserView::DriveView::enablementChanged() + { + getHeaderComponent()->setEnabled(isEnabled()); + update(); + } + void DocumentBrowserView::DriveView::driveChanged() { update(); @@ -521,15 +550,18 @@ namespace kiwi { int num_rows = 0; - auto const& documents = m_drive.getDocuments(); - - num_rows = std::count_if(documents.begin(), - documents.end(), - [trash_mode = m_trash_mode] - (std::unique_ptr const& doc) + if (isEnabled()) { - return trash_mode ? doc->isTrashed() : !doc->isTrashed(); - }); + auto const& documents = m_drive.getDocuments(); + + num_rows = std::count_if(documents.begin(), + documents.end(), + [trash_mode = m_trash_mode] + (std::unique_ptr const& doc) + { + return trash_mode ? doc->isTrashed() : !doc->isTrashed(); + }); + } return num_rows; } @@ -771,9 +803,4 @@ namespace kiwi { openDocument(row); } - - bool DocumentBrowserView::DriveView::operator==(DocumentBrowser::Drive const& other_drive) const - { - return (m_drive == other_drive); - } } diff --git a/Client/Source/KiwiApp_Application/KiwiApp_DocumentBrowserView.h b/Client/Source/KiwiApp_Application/KiwiApp_DocumentBrowserView.h index e56eceea..3d4d496e 100644 --- a/Client/Source/KiwiApp_Application/KiwiApp_DocumentBrowserView.h +++ b/Client/Source/KiwiApp_Application/KiwiApp_DocumentBrowserView.h @@ -32,31 +32,26 @@ namespace kiwi // DOCUMENT BROWSER VIEW // // ================================================================================ // - class DocumentBrowserView : public juce::Component, public DocumentBrowser::Listener + class DocumentBrowserView : public juce::Component { public: // methods //! @brief Constructor. - DocumentBrowserView(DocumentBrowser& browser); + DocumentBrowserView(DocumentBrowser& browser, bool enabled); //! @brief Destructor. ~DocumentBrowserView(); - //! @brief Called when the document list changed. - void driveAdded(DocumentBrowser::Drive& drive) override; - - //! @brief Called when a drive changed. - void driveChanged(DocumentBrowser::Drive const& drive) override; - - //! @brief Called when the document list changed. - void driveRemoved(DocumentBrowser::Drive const& drive) override; - //! @brief Called when resized. void resized() override; //! @brief juce::Component::paint void paint(juce::Graphics& g) override; + private: // methods + + void enablementChanged() override final; + private: // nested classes class DriveView; @@ -112,6 +107,12 @@ namespace kiwi //! @details Called when one or more document has been changed / removed or added. void driveChanged() override; + //! @brief Disable the display of document and their modification. + void disable(); + + //! @brief Enable the display of documents and their modification. + void enable(); + //! @brief Returns the number of items in the list. int getNumRows() override; @@ -133,9 +134,6 @@ namespace kiwi //! @brief Called when the user double-clicking on a row. void listBoxItemDoubleClicked(int row, juce::MouseEvent const& e) override; - //! @brief Returns true if the two drive view refer to the same drive. - bool operator==(DocumentBrowser::Drive const& other_drive) const; - //! @brief Opens document for the given row. void openDocument(int row); @@ -159,6 +157,9 @@ namespace kiwi private: // methods + //! @brief Hides document liste and disable some interactions. + void enablementChanged() override final; + //! @brief Resort content and call update content. void update(); @@ -194,7 +195,9 @@ namespace kiwi private: // members DocumentBrowser::Drive& m_drive; + std::string m_name; bool m_trash_mode; + bool m_enabled; Comp m_sorter; }; @@ -224,6 +227,10 @@ namespace kiwi //! @brief Sets the text diaplyed by the header bar. void setText(std::string const& text); + private: // methods + + void enablementChanged() override final; + private: // members DocumentBrowserView::DriveView& m_drive_view; @@ -232,7 +239,8 @@ namespace kiwi ImageButton m_trash_btn; juce::Rectangle m_folder_bounds; juce::Label m_label; - const juce::Image m_folder_img; + juce::Image m_folder_img; + juce::Image m_disable_folder_img; }; // ================================================================================ // diff --git a/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp b/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp index a2cc06a2..d241af5e 100644 --- a/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp +++ b/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp @@ -44,7 +44,8 @@ namespace kiwi Instance::Instance() : m_scheduler(), m_instance(std::make_unique(), m_scheduler), - m_browser(), + m_browser(KiwiApp::getCurrentUser().isLoggedIn() ? KiwiApp::getCurrentUser().getName(): "logged out", + 1000), m_console_history(std::make_shared(m_instance)), m_last_opened_file(juce::File::getSpecialLocation(juce::File::userHomeDirectory)) { @@ -104,36 +105,44 @@ namespace kiwi { const auto& user = KiwiApp::getCurrentUser(); return user.isLoggedIn() ? user.getIdAsInt() : flip::Ref::User::Offline; - } + } + + void Instance::login() + { + m_browser.setDriveName(KiwiApp::getCurrentUser().getName()); + + m_windows[std::size_t(WindowId::DocumentBrowser)]->getContentComponent()->setEnabled(true); + } - bool Instance::logout() - { - bool user_agreed = false; - - for(auto it = m_patcher_managers.begin(); it != m_patcher_managers.end();) - { - auto& manager = *it->get(); - if(manager.isRemote()) - { - if(!user_agreed) - { - user_agreed = juce::AlertWindow::showOkCancelBox(juce::AlertWindow::WarningIcon, - TRANS("Are you about to logout."), - TRANS("All patchers connected to this account will be closed...")); - - if(!user_agreed) - return false; - } - - it = m_patcher_managers.erase(it); - } - else - { - it++; - } - } - - return true; + void Instance::logout() + { + m_browser.setDriveName("logged out"); + + for(auto manager = m_patcher_managers.begin(); manager != m_patcher_managers.end();) + { + if ((*manager)->isRemote()) + { + bool keep_patcher + = (*manager)->getFirstWindow().showOkCancelBox(juce::AlertWindow::QuestionIcon, + "User logged out", + "Do you want to continue editing document \"" + + (*manager)->getDocumentName() +"\" offline", + "Ok", + "Cancel"); + + if (!keep_patcher) + { + manager = m_patcher_managers.erase(manager); + } + else + { + (*manager)->disconnect(); + ++manager; + } + } + } + + m_windows[std::size_t(WindowId::DocumentBrowser)]->getContentComponent()->setEnabled(false); } engine::Instance& Instance::useEngineInstance() @@ -424,7 +433,8 @@ namespace kiwi { showWindowWithId(WindowId::DocumentBrowser, [&browser = m_browser](){ return std::make_unique("Document Browser", - std::make_unique(browser), + std::make_unique(browser, + KiwiApp::getCurrentUser().isLoggedIn()), true, false, "document_browser_window"); }); } @@ -443,7 +453,7 @@ namespace kiwi showWindowWithId(WindowId::ApplicationSettings, [](){ return std::make_unique("Application settings", std::make_unique(), - true, true, "application_settings_window"); + false, true, "application_settings_window"); }); } diff --git a/Client/Source/KiwiApp_Application/KiwiApp_Instance.h b/Client/Source/KiwiApp_Application/KiwiApp_Instance.h index 5e5df988..f2588328 100644 --- a/Client/Source/KiwiApp_Application/KiwiApp_Instance.h +++ b/Client/Source/KiwiApp_Application/KiwiApp_Instance.h @@ -61,11 +61,14 @@ namespace kiwi void timerCallback() override final; //! @brief Get the user ID of the Instance. - uint64_t getUserId() const noexcept; - - //! @brief Close all remote patchers. - bool logout(); + uint64_t getUserId() const noexcept; + + //! @brief Enables the document browser view. + void login(); + //! @brief Close all remote patchers and disable document browser view. + void logout(); + //! @brief create a new patcher window. void newPatcher(); diff --git a/Client/Source/KiwiApp_Application/KiwiApp_SettingsPanel.cpp b/Client/Source/KiwiApp_Application/KiwiApp_SettingsPanel.cpp index 1b2c3230..c2da9fc8 100644 --- a/Client/Source/KiwiApp_Application/KiwiApp_SettingsPanel.cpp +++ b/Client/Source/KiwiApp_Application/KiwiApp_SettingsPanel.cpp @@ -19,8 +19,10 @@ ============================================================================== */ -#include "KiwiApp_SettingsPanel.h" -#include "../KiwiApp.h" +#include +#include +#include +#include namespace kiwi { @@ -28,26 +30,76 @@ namespace kiwi // SETTINGS PANEL // // ================================================================================ // - SettingsPanel::SettingsPanel() : juce::PropertyPanel("Application settings") - { - auto& net_config = getAppSettings().network(); + SettingsPanel::SettingsPanel(): + m_settings(getAppSettings().network().getServerAddress()), + m_pannel("Application settings"), + m_apply_button("apply"), + m_reset_button("reset") + { juce::Array props { - new juce::TextPropertyComponent(net_config.getHostValue(), "Host", 20, false), - new juce::TextPropertyComponent(net_config.getApiPortValue(), "API Port", 5, false), - new juce::TextPropertyComponent(net_config.getSessionPortValue(), "Session Port", 5, false), - new juce::TextPropertyComponent(net_config.getRefreshIntervalValue(), "Refresh interval time", 5, false) + new juce::TextPropertyComponent(m_settings + .getPropertyAsValue(Ids::host, nullptr),"Host", 20,false), + new juce::TextPropertyComponent(m_settings + .getPropertyAsValue(Ids::api_port, nullptr), "API Port", 5, false), + new juce::TextPropertyComponent(m_settings + .getPropertyAsValue(Ids::session_port, nullptr), "Session Port", 5, false) }; - addSection("Network config", props, true, 0); - - setSize(300, 400); + m_pannel.addSection("Network config", props, true, 0); + + m_apply_button.setButtonText("Apply"); + m_reset_button.setButtonText("Reset"); + + m_apply_button.addListener(this); + m_reset_button.addListener(this); + + setSize(400, m_pannel.getTotalContentHeight() + 50); + + addAndMakeVisible(m_pannel); + addAndMakeVisible(m_apply_button); + addAndMakeVisible(m_reset_button); } SettingsPanel::~SettingsPanel() { - clear(); + m_pannel.clear(); + } + + void SettingsPanel::resized() + { + juce::Rectangle bounds = getLocalBounds(); + + m_pannel.setBounds(bounds.withHeight(m_pannel.getTotalContentHeight())); + + m_apply_button.setBounds(bounds + .withPosition(m_pannel.getX() + 10, m_pannel.getBottom() + 10) + .withHeight(30)); + + m_apply_button.changeWidthToFitText(); + + m_reset_button.setBounds(m_apply_button.getBounds().withLeft(m_apply_button.getRight() + 10)); + + m_reset_button.changeWidthToFitText(); + } + + void SettingsPanel::buttonClicked(juce::Button * button) + { + if (button->getName() == "apply") + { + getAppSettings().network().setServerAddress(m_settings[Ids::host].toString().toStdString(), + m_settings[Ids::api_port].operator int(), + m_settings[Ids::session_port].operator int()); + } + else if(button->getName() == "reset") + { + NetworkSettings & network = getAppSettings().network(); + + network.resetToDefault(); + + m_settings.copyPropertiesFrom(network.getServerAddress(), nullptr); + } } } diff --git a/Client/Source/KiwiApp_Application/KiwiApp_SettingsPanel.h b/Client/Source/KiwiApp_Application/KiwiApp_SettingsPanel.h index c9fec8d9..8093a58e 100644 --- a/Client/Source/KiwiApp_Application/KiwiApp_SettingsPanel.h +++ b/Client/Source/KiwiApp_Application/KiwiApp_SettingsPanel.h @@ -30,14 +30,30 @@ namespace kiwi // ================================================================================ // //! @brief A Panel Component that shows application's settings. - class SettingsPanel : public juce::PropertyPanel + class SettingsPanel : public juce::Component, + public juce::Button::Listener { public: // classes //! @brief Constructor. - SettingsPanel(); + SettingsPanel(); //! @brief Destructor. - ~SettingsPanel(); + ~SettingsPanel(); + + private: // methods + + //! @brief Resized methods called when resized. + void resized() override final; + + //! @brief Called when apply or reset button is clicked. + void buttonClicked(juce::Button * button) override final; + + private: // members + + juce::ValueTree m_settings; + juce::PropertyPanel m_pannel; + juce::TextButton m_apply_button; + juce::TextButton m_reset_button; }; } diff --git a/Client/Source/KiwiApp_General/KiwiApp_IDs.h b/Client/Source/KiwiApp_General/KiwiApp_IDs.h index 3074b01f..c1b426dd 100644 --- a/Client/Source/KiwiApp_General/KiwiApp_IDs.h +++ b/Client/Source/KiwiApp_General/KiwiApp_IDs.h @@ -37,8 +37,8 @@ namespace kiwi DECLARE_ID(host); DECLARE_ID(api_port); DECLARE_ID(session_port); - DECLARE_ID(refresh_interval); DECLARE_ID(remember_me); + DECLARE_ID(server_address); DECLARE_ID(NETWORK_CONFIG); diff --git a/Client/Source/KiwiApp_General/KiwiApp_StoredSettings.cpp b/Client/Source/KiwiApp_General/KiwiApp_StoredSettings.cpp index 5088e4ac..9c0a8f66 100644 --- a/Client/Source/KiwiApp_General/KiwiApp_StoredSettings.cpp +++ b/Client/Source/KiwiApp_General/KiwiApp_StoredSettings.cpp @@ -105,7 +105,7 @@ namespace kiwi NetworkSettings::NetworkSettings() : m_settings(Ids::NETWORK_CONFIG) { - resetToDefault(); + resetToDefault(); m_settings.addListener(this); } @@ -117,7 +117,8 @@ namespace kiwi void NetworkSettings::resetToDefault() { m_settings.removeAllChildren(nullptr); - m_settings.removeAllProperties(nullptr); + m_settings.removeAllProperties(nullptr); + m_settings.removeAllChildren(nullptr); std::unique_ptr xml(nullptr); @@ -125,31 +126,60 @@ namespace kiwi binary_data::settings::network_settings_size); xml.reset(juce::XmlDocument::parse(str)); - assert(xml != nullptr); - - // load default settings - m_settings = juce::ValueTree::fromXml(*xml); - } - - bool NetworkSettings::readFromXml(juce::XmlElement const& xml) - { - if(xml.hasTagName(m_settings.getType().toString())) - { - const auto new_settings(juce::ValueTree::fromXml(xml)); - - for(int i = new_settings.getNumProperties(); --i >= 0;) - { - const auto key = new_settings.getPropertyName(i); - if(m_settings.hasProperty(key)) - { - m_settings.setProperty(key, new_settings.getProperty(key), nullptr); - } - } - - return true; + assert(xml != nullptr); + + juce::ValueTree tree = juce::ValueTree::fromXml(*xml); + + if (tree.hasProperty(Ids::remember_me)) + { + m_settings.setProperty(Ids::remember_me, tree.getProperty(Ids::remember_me), nullptr); + } + + juce::ValueTree server_tree = tree.getChildWithName(Ids::server_address).createCopy(); + + if (server_tree.isValid()) + { + m_settings.addChild(server_tree, 0, nullptr); } - - return false; + } + + juce::ValueTree NetworkSettings::getServerAddress() + { + return m_settings.getChildWithName(Ids::server_address).createCopy(); + } + + void NetworkSettings::setServerAddress(std::string const& host, uint16_t api_port, uint16_t session_port) + { + juce::ValueTree tree(Ids::server_address); + tree.setProperty(Ids::host, juce::String(host), nullptr); + tree.setProperty(Ids::api_port, api_port, nullptr); + tree.setProperty(Ids::session_port, session_port, nullptr); + + m_settings.removeChild(m_settings.getChildWithName(Ids::server_address), nullptr); + m_settings.addChild(tree, 0, nullptr); + } + + void NetworkSettings::readFromXml(juce::XmlElement const& xml) + { + if(xml.hasTagName(m_settings.getType().toString())) + { + const auto new_settings(juce::ValueTree::fromXml(xml)); + + if (new_settings.hasProperty(Ids::remember_me)) + { + m_settings.setProperty(Ids::remember_me, + new_settings.getProperty(Ids::remember_me), + nullptr); + } + + juce::ValueTree server_tree = new_settings.getChildWithName(Ids::server_address).createCopy(); + + if (server_tree.isValid()) + { + m_settings.removeChild(m_settings.getChildWithName(Ids::server_address), nullptr); + m_settings.addChild(server_tree, 0, nullptr); + } + } } juce::ValueTree& NetworkSettings::use() @@ -159,47 +189,21 @@ namespace kiwi std::string NetworkSettings::getHost() const { - return m_settings.getProperty(Ids::host).toString().toStdString(); - } - - juce::Value NetworkSettings::getHostValue() - { - return m_settings.getPropertyAsValue(Ids::host, nullptr); + return m_settings.getChildWithName(Ids::server_address).getProperty(Ids::host).toString().toStdString(); } uint16_t NetworkSettings::getApiPort() const { - int port = m_settings.getProperty(Ids::api_port); + int port = m_settings.getChildWithName(Ids::server_address).getProperty(Ids::api_port); return static_cast(port); } - juce::Value NetworkSettings::getApiPortValue() - { - return m_settings.getPropertyAsValue(Ids::api_port, nullptr); - } - uint16_t NetworkSettings::getSessionPort() const { - int port = m_settings.getProperty(Ids::session_port); + int port = m_settings.getChildWithName(Ids::server_address).getProperty(Ids::session_port); return static_cast(port); } - juce::Value NetworkSettings::getSessionPortValue() - { - return m_settings.getPropertyAsValue(Ids::session_port, nullptr); - } - - uint16_t NetworkSettings::getRefreshInterval() const - { - int time = m_settings.getProperty(Ids::refresh_interval); - return static_cast(time); - } - - juce::Value NetworkSettings::getRefreshIntervalValue() - { - return m_settings.getPropertyAsValue(Ids::refresh_interval, nullptr); - } - void NetworkSettings::setRememberUserFlag(bool remember_me) { m_settings.setProperty(Ids::remember_me, remember_me, nullptr); @@ -223,6 +227,11 @@ namespace kiwi void NetworkSettings::valueTreePropertyChanged(juce::ValueTree&, juce::Identifier const& id) { m_listeners.call(&Listener::networkSettingsChanged, *this, id); + } + + void NetworkSettings::valueTreeChildAdded(juce::ValueTree& parent, juce::ValueTree& child) + { + m_listeners.call(&Listener::networkSettingsChanged, *this, child.getType()); } // ================================================================================ // @@ -261,10 +270,10 @@ namespace kiwi m_property_files.emplace_back(createPropsFile("kiwi_settings")); // Try to reload User settings - std::unique_ptr xml(getGlobalProperties().getXmlValue("Network Settings")); - if(xml) - { - m_network.readFromXml(*xml); + std::unique_ptr xml(getGlobalProperties().getXmlValue("Network Settings")); + if (xml) + { + m_network.readFromXml(*xml); } } diff --git a/Client/Source/KiwiApp_General/KiwiApp_StoredSettings.h b/Client/Source/KiwiApp_General/KiwiApp_StoredSettings.h index e325f6b1..30b76e57 100644 --- a/Client/Source/KiwiApp_General/KiwiApp_StoredSettings.h +++ b/Client/Source/KiwiApp_General/KiwiApp_StoredSettings.h @@ -46,35 +46,29 @@ namespace kiwi ~NetworkSettings(); //! @brief Reset to default settings values - void resetToDefault(); + void resetToDefault(); + + //! @brief Sets the server adress. + void setServerAddress(std::string const& host, uint16_t api_port, uint16_t session_port); + + //! @brief Retrieves a copy of the server adress info. + juce::ValueTree getServerAddress(); //! @brief Restore settings with an xml. - bool readFromXml(juce::XmlElement const& xml); + void readFromXml(juce::XmlElement const& xml); //! @brief Returns the Host as a string std::string getHost() const; - //! @brief Returns the Host as a juce::Value - juce::Value getHostValue(); - //! @brief Returns the api port as an integer uint16_t getApiPort() const; - //! @brief Returns the api port as a juce::Value - juce::Value getApiPortValue(); - //! @brief Returns the session port as an integer uint16_t getSessionPort() const; - //! @brief Returns the session port as a juce::Value - juce::Value getSessionPortValue(); - //! @brief Returns the session port as an integer uint16_t getRefreshInterval() const; - //! @brief Returns the session port as a juce::Value - juce::Value getRefreshIntervalValue(); - void setRememberUserFlag(bool remember_me); bool getRememberUserFlag() const; @@ -101,7 +95,7 @@ namespace kiwi juce::ValueTree& use(); void valueTreePropertyChanged(juce::ValueTree&, juce::Identifier const&) override; - void valueTreeChildAdded(juce::ValueTree&, juce::ValueTree&) override {} + void valueTreeChildAdded(juce::ValueTree& parent, juce::ValueTree& child) override; void valueTreeChildRemoved(juce::ValueTree&, juce::ValueTree&, int) override {} void valueTreeChildOrderChanged(juce::ValueTree&, int, int) override {} void valueTreeParentChanged(juce::ValueTree&) override {} diff --git a/Client/Source/KiwiApp_Network/KiwiApp_ApiController.cpp b/Client/Source/KiwiApp_Network/KiwiApp_ApiController.cpp index 77d57de8..ba3820e9 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_ApiController.cpp +++ b/Client/Source/KiwiApp_Network/KiwiApp_ApiController.cpp @@ -34,15 +34,12 @@ namespace kiwi setHost(settings.getHost()); setPort(settings.getApiPort()); - settings.addListener(*this); - restoreAuthUserProfile(); } ApiController::~ApiController() { auto& settings = getAppSettings().network(); - settings.removeListener(*this); if(!settings.getRememberUserFlag()) { @@ -69,29 +66,6 @@ namespace kiwi return false; } - void ApiController::networkSettingsChanged(NetworkSettings const& settings, - juce::Identifier const& id) - { - if(id == Ids::host) - { - setHost(settings.getHost()); - } - else if(id == Ids::api_port) - { - setPort(settings.getApiPort()); - } - } - - void ApiController::addListener(ApiConnectStatusListener& listener) - { - m_listeners.add(listener); - } - - void ApiController::removeListener(ApiConnectStatusListener& listener) - { - m_listeners.remove(listener); - } - void ApiController::login(std::string const& name_or_email, std::string const& password, std::function success_callback, @@ -103,7 +77,6 @@ namespace kiwi scheduler.schedule([this, success_callback, user](){ m_auth_user.resetWith(user); - m_listeners.call(&ApiConnectStatusListener::userLoggedIn, m_auth_user); success_callback(); }); @@ -133,6 +106,5 @@ namespace kiwi void ApiController::logout() { Api::Controller::clearToken(); - m_listeners.call(&ApiConnectStatusListener::userLoggedOut, getAuthUser()); } } diff --git a/Client/Source/KiwiApp_Network/KiwiApp_ApiController.h b/Client/Source/KiwiApp_Network/KiwiApp_ApiController.h index de6f5984..c8c68a01 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_ApiController.h +++ b/Client/Source/KiwiApp_Network/KiwiApp_ApiController.h @@ -28,18 +28,9 @@ namespace kiwi { - struct ApiConnectStatusListener - { - virtual ~ApiConnectStatusListener() {} - - virtual void userLoggedIn(Api::AuthUser const&) = 0; - virtual void userLoggedOut(Api::AuthUser const&) = 0; - virtual void authUserChanged(Api::AuthUser const&) = 0; - }; class ApiController : public Api::Controller - , private NetworkSettings::Listener { public: // methods @@ -51,12 +42,6 @@ namespace kiwi //! If false, the user profile will be saved whithout the token. ~ApiController(); - //! @brief Adds a listener. - void addListener(ApiConnectStatusListener& listener); - - //! @brief Removes a listener. - void removeListener(ApiConnectStatusListener& listener); - //! @brief Attempt to log the client api user in (Async). //! @param name_or_email The name or email of the user. //! @param password The user password. @@ -84,12 +69,5 @@ namespace kiwi bool saveAuthUserProfile() const; bool restoreAuthUserProfile(); - - //! @brief Called when the network settings has changed. - void networkSettingsChanged(NetworkSettings const&, juce::Identifier const&) override; - - private: // variables - - tool::Listeners m_listeners; }; } diff --git a/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp b/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp index ced99626..b43df53e 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp +++ b/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.cpp @@ -34,85 +34,34 @@ namespace kiwi // DOCUMENT BROWSER // // ================================================================================ // - DocumentBrowser::DocumentBrowser() : - m_distant_drive(nullptr) - { - auto& settings = getAppSettings().network(); - settings.addListener(*this); - - m_distant_drive.reset(new Drive("Remote Drive", settings.getSessionPort())); - - int time = settings.getRefreshInterval(); - if(time > 0) + DocumentBrowser::DocumentBrowser(std::string const& drive_name, int refresh_time) : + m_distant_drive(new Drive(drive_name)), + m_refresh_time(refresh_time) + { + if(m_refresh_time > 0) { - start(time); + startTimer(m_refresh_time); } - - authUserChanged(KiwiApp::getCurrentUser()); - KiwiApp::addApiConnectStatusListener(*this); } DocumentBrowser::~DocumentBrowser() - { - KiwiApp::removeApiConnectStatusListener(*this); - getAppSettings().network().removeListener(*this); - stop(); - } - - void DocumentBrowser::start(const int interval) - { - startTimer(interval); - } - - void DocumentBrowser::stop() { stopTimer(); } - std::vector DocumentBrowser::getDrives() const - { - return {m_distant_drive.get()}; - } - - void DocumentBrowser::networkSettingsChanged(NetworkSettings const& settings, const juce::Identifier& id) - { - if(id == Ids::session_port) - { - m_distant_drive->setSessionPort(settings.getSessionPort()); - } - else if(id == Ids::refresh_interval) - { - auto time = settings.getRefreshInterval(); - - if(time > 0) - { - start(time); - } - else - { - stop(); - } - } - } - - void DocumentBrowser::addListener(Listener& listener) + void DocumentBrowser::setDriveName(std::string const& name) { - m_listeners.add(listener); + m_distant_drive->setName(name); } - void DocumentBrowser::removeListener(Listener& listener) + DocumentBrowser::Drive* DocumentBrowser::getDrive() const { - m_listeners.remove(listener); + return m_distant_drive.get(); } void DocumentBrowser::timerCallback() { - process(); - } - - void DocumentBrowser::process() - { - m_distant_drive->refresh(); + m_distant_drive->refresh_internal(); } void DocumentBrowser::handleDeniedRequest() @@ -128,28 +77,11 @@ namespace kiwi } } - void DocumentBrowser::userLoggedIn(Api::AuthUser const& user) - { - m_distant_drive->setName(user.getName()); - } - - void DocumentBrowser::userLoggedOut(Api::AuthUser const&) - { - m_distant_drive->setName("logged out..."); - } - - void DocumentBrowser::authUserChanged(Api::AuthUser const& user) - { - m_distant_drive->setName(user.isLoggedIn() ? user.getName() : "logged out..."); - } - // ================================================================================ // // DOCUMENT BROWSER DRIVE // // ================================================================================ // - DocumentBrowser::Drive::Drive(std::string const& name, - uint16_t session_port) : - m_session_port(session_port), + DocumentBrowser::Drive::Drive(std::string const& name) : m_name(name), m_sort([](DocumentSession const& l_hs, DocumentSession const& r_hs) { @@ -169,16 +101,6 @@ namespace kiwi m_listeners.remove(listener); } - void DocumentBrowser::Drive::setSessionPort(uint16_t port) - { - m_session_port = port; - } - - uint16_t DocumentBrowser::Drive::getSessionPort() const - { - return m_session_port; - } - void DocumentBrowser::Drive::setName(std::string const& name) { m_name = name; @@ -268,11 +190,6 @@ namespace kiwi return m_documents; } - bool DocumentBrowser::Drive::operator==(Drive const& drive) const - { - return (getSessionPort() == drive.getSessionPort()) && (m_name == drive.getName()); - } - void DocumentBrowser::Drive::updateDocumentList(Api::Documents docs) { bool changed = false; @@ -352,6 +269,21 @@ namespace kiwi } } + void DocumentBrowser::Drive::refresh_internal() + { + KiwiApp::useApi().getDocuments([this](Api::Response res, Api::Documents docs) + { + if (res.result() == beast::http::status::ok + && !res.error) + { + KiwiApp::useInstance().useScheduler().schedule([this, docs]() + { + updateDocumentList(docs); + }); + } + }); + } + void DocumentBrowser::Drive::refresh() { KiwiApp::useApi().getDocuments([this](Api::Response res, Api::Documents docs) { diff --git a/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.h b/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.h index 95b9e4ab..534634fd 100644 --- a/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.h +++ b/Client/Source/KiwiApp_Network/KiwiApp_DocumentBrowser.h @@ -39,80 +39,38 @@ namespace kiwi // ================================================================================ // //! @brief Request Patcher document informations through a Kiwi API. - class DocumentBrowser - : public juce::Timer - , public NetworkSettings::Listener - , public ApiConnectStatusListener + class DocumentBrowser : public juce::Timer { public: // nested classes - struct Listener; class Drive; public: // methods //! @brief Constructor - DocumentBrowser(); + DocumentBrowser(std::string const& drive_name, int refresh_time); //! @brief Destructor ~DocumentBrowser(); - //! @brief start processing - void start(const int interval = 5000); - - //! @brief stop processing - void stop(); - - //! @brief Scan the LAN to find a service provider. - void process(); + //! @brief Sets the drive's name. + void setDriveName(std::string const& name); //! @brief juce::Timer callback. void timerCallback() override; //! @brief Returns a list of drives. - std::vector getDrives() const; - - //! @brief Add a listener. - void addListener(Listener& listener); - - //! @brief remove a listener. - void removeListener(Listener& listener); + Drive* getDrive() const; private: // methods //! @brief Handles request that denied by server. static void handleDeniedRequest(); - void networkSettingsChanged(NetworkSettings const&, const juce::Identifier& id) override; - - void userLoggedIn(Api::AuthUser const&) override; - void userLoggedOut(Api::AuthUser const&) override; - void authUserChanged(Api::AuthUser const&) override; - private: // variables - std::unique_ptr m_distant_drive; - tool::Listeners m_listeners = {}; - }; - - // ================================================================================ // - // DOCUMENT BROWSER LISTENER // - // ================================================================================ // - - //! @brief Listen to document explorer changes. - struct DocumentBrowser::Listener - { - //! @brief Destructor. - virtual ~Listener() = default; - - //! @brief Called when the document list changed. - virtual void driveAdded(DocumentBrowser::Drive& drive) = 0; - - //! @brief Called when the document list changed. - virtual void driveChanged(DocumentBrowser::Drive const& drive) = 0; - - //! @brief Called when the document list changed. - virtual void driveRemoved(DocumentBrowser::Drive const& drive) = 0; + std::unique_ptr m_distant_drive; + int m_refresh_time; }; // ================================================================================ // @@ -134,7 +92,7 @@ namespace kiwi public: // methods - Drive(std::string const& name, uint16_t session_port); + Drive(std::string const& name); ~Drive() = default; @@ -144,12 +102,6 @@ namespace kiwi //! @brief remove a listener. void removeListener(Listener& listener); - //! @brief Set the kiwi document session port. - void setSessionPort(uint16_t port); - - //! @brief Returns the kiwi document session port. - uint16_t getSessionPort() const; - //! @brief Set the name of this drive. void setName(std::string const& host); @@ -172,20 +124,20 @@ namespace kiwi //! @brief Returns the documents. DocumentSessions& getDocuments(); - //! @brief Returns true if the drive match the other drive - //! @details this operator only compares ip and port. - bool operator==(Drive const& drive) const; - //! @brief Refresh all the document list. void refresh(); + private: // methods + + //! @brief Refresh the document list without posting network erors. + void refresh_internal(); + private: // members //! @internal Update the document list (need to be called in the juce Message thread) void updateDocumentList(Api::Documents docs); - uint16_t m_session_port = 9090; - std::string m_name = "Drive"; + std::string m_name; DocumentSessions m_documents; tool::Listeners m_listeners; Comp m_sort; diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.h b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.h index 181a121a..a2ce396c 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.h @@ -63,7 +63,10 @@ namespace kiwi ~PatcherManager(); //! @brief Try to connect this patcher to a remote server. - bool connect(std::string const& host, uint16_t port, DocumentBrowser::Drive::DocumentSession& session); + bool connect(std::string const& host, uint16_t port, DocumentBrowser::Drive::DocumentSession& session); + + //! @brief Disconnects the patcher manager. + void disconnect(); //! @brief Pull changes from server if it is remote. void pull(); @@ -152,9 +155,6 @@ namespace kiwi //! @internal Reads data from file. bool readDocument(); - //! @internal If the patcher is remote, tries to disconnect it. - void disconnect(); - //! @internal flip::DocumentObserver::document_changed void document_changed(model::Patcher& patcher) override final; diff --git a/Client/Source/KiwiApp_Ressources/KiwiApp_BinaryData.cpp b/Client/Source/KiwiApp_Ressources/KiwiApp_BinaryData.cpp index e0f2bb6e..ca6aaed8 100644 --- a/Client/Source/KiwiApp_Ressources/KiwiApp_BinaryData.cpp +++ b/Client/Source/KiwiApp_Ressources/KiwiApp_BinaryData.cpp @@ -147685,13 +147685,15 @@ namespace kiwi 0x3c, 0x3f, 0x78, 0x6d, 0x6c, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x22, 0x31, 0x2e, 0x30, 0x22, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x55, 0x54, 0x46, 0x2d, 0x38, 0x22, 0x3f, 0x3e, 0x0d, 0x0a, 0x0d, 0x0a, 0x3c, 0x4e, 0x45, 0x54, 0x57, 0x4f, -0x52, 0x4b, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x20, 0x68, 0x6f, 0x73, 0x74, 0x3d, 0x22, -0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x22, 0x20, 0x61, 0x70, 0x69, 0x5f, 0x70, -0x6f, 0x72, 0x74, 0x3d, 0x22, 0x38, 0x30, 0x38, 0x30, 0x22, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69, -0x6f, 0x6e, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x3d, 0x22, 0x39, 0x30, 0x39, 0x30, 0x22, 0x20, 0x72, -0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x3d, -0x22, 0x30, 0x22, 0x20, 0x72, 0x65, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x6d, 0x65, 0x3d, -0x22, 0x31, 0x22, 0x2f, 0x3e, 0x0d, 0x0a +0x52, 0x4b, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x20, 0x72, 0x65, 0x6d, 0x65, 0x6d, 0x62, +0x65, 0x72, 0x5f, 0x6d, 0x65, 0x3d, 0x22, 0x31, 0x22, 0x3e, 0x0d, 0x0a, 0x20, 0x20, 0x3c, 0x73, +0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, 0x68, 0x6f, +0x73, 0x74, 0x3d, 0x22, 0x6b, 0x69, 0x77, 0x69, 0x2e, 0x6d, 0x73, 0x68, 0x70, 0x61, 0x72, 0x69, +0x73, 0x6e, 0x6f, 0x72, 0x64, 0x2e, 0x66, 0x72, 0x22, 0x20, 0x61, 0x70, 0x69, 0x5f, 0x70, 0x6f, +0x72, 0x74, 0x3d, 0x22, 0x38, 0x30, 0x22, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, +0x70, 0x6f, 0x72, 0x74, 0x3d, 0x22, 0x34, 0x34, 0x33, 0x22, 0x2f, 0x3e, 0x0d, 0x0a, 0x3c, 0x2f, +0x4e, 0x45, 0x54, 0x57, 0x4f, 0x52, 0x4b, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x3e, 0x0d, +0x0a }; const char* network_settings = (const char *) network_settings_array; diff --git a/Client/Source/KiwiApp_Ressources/KiwiApp_BinaryData.h b/Client/Source/KiwiApp_Ressources/KiwiApp_BinaryData.h index e82e9ad4..3a3abf2f 100644 --- a/Client/Source/KiwiApp_Ressources/KiwiApp_BinaryData.h +++ b/Client/Source/KiwiApp_Ressources/KiwiApp_BinaryData.h @@ -122,7 +122,7 @@ namespace kiwi namespace settings { extern char const* network_settings; - const int network_settings_size = 151; + const int network_settings_size = 177; } } diff --git a/Ressources/BinaryRes/Settings/network.settings b/Ressources/BinaryRes/Settings/network.settings index afcba1d7..8878d824 100644 --- a/Ressources/BinaryRes/Settings/network.settings +++ b/Ressources/BinaryRes/Settings/network.settings @@ -1,3 +1,5 @@ - + + + From a055e5e4cf0a97ed76c7c99803603603935c36c2 Mon Sep 17 00:00:00 2001 From: jmillot Date: Sun, 28 Jan 2018 18:19:30 +0100 Subject: [PATCH 129/148] Objects last review. --- .../KiwiApp_Objects/KiwiApp_SliderView.cpp | 10 +++++--- .../KiwiApp_Objects/KiwiApp_SliderView.h | 3 ++- .../KiwiEngine_AudioInterface.cpp | 8 +++++++ .../KiwiEngine_LineTilde.cpp | 11 +++++++-- .../KiwiEngine_Objects/KiwiEngine_Metro.cpp | 4 ++++ .../KiwiEngine_Operator.cpp | 23 ++++++++++++++----- .../KiwiEngine_OscTilde.cpp | 2 +- .../KiwiEngine_Objects/KiwiEngine_Pipe.cpp | 2 +- .../KiwiEngine_Objects/KiwiEngine_Print.cpp | 20 +++++++++++++++- .../KiwiEngine_SigTilde.cpp | 11 +++++++-- .../KiwiEngine_Objects/KiwiEngine_Slider.cpp | 23 +++++++++++++++++-- .../KiwiEngine_Objects/KiwiEngine_Slider.h | 7 +++++- .../KiwiModel_MeterTilde.cpp | 4 ++-- .../KiwiModel_Objects/KiwiModel_Operator.cpp | 12 +++++++++- .../KiwiModel_OperatorTilde.cpp | 12 +++++++++- .../KiwiModel_Objects/KiwiModel_Print.cpp | 9 ++++++-- .../KiwiModel_Objects/KiwiModel_Print.h | 2 +- .../KiwiModel_Objects/KiwiModel_Receive.cpp | 19 +++++++++++++-- .../KiwiModel_Objects/KiwiModel_Receive.h | 2 +- .../KiwiModel_Objects/KiwiModel_Select.cpp | 13 +++++++---- .../KiwiModel_Objects/KiwiModel_SigTilde.cpp | 10 ++++++++ .../KiwiModel_Objects/KiwiModel_Slider.cpp | 3 +++ .../KiwiModel_Objects/KiwiModel_Slider.h | 9 +++++++- 23 files changed, 184 insertions(+), 35 deletions(-) diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_SliderView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_SliderView.cpp index 77125229..4f3078cd 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_SliderView.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_SliderView.cpp @@ -27,7 +27,9 @@ #include #include -#include +#include + +#include namespace kiwi { @@ -37,7 +39,8 @@ namespace kiwi SliderView::SliderView(model::Object & object_model): ObjectView(object_model), - m_slider(juce::Slider::SliderStyle::LinearVertical, juce::Slider::TextEntryBoxPosition::NoTextBox) + m_slider(juce::Slider::SliderStyle::LinearVertical, juce::Slider::TextEntryBoxPosition::NoTextBox), + m_output_value(object_model.getSignal<>(model::Slider::Signal::OutputValue)) { m_slider.setColour(juce::Slider::ColourIds::backgroundColourId, findColour(ObjectView::ColourIds::Outline)); @@ -98,7 +101,8 @@ namespace kiwi void SliderView::sliderValueChanged(juce::Slider * slider) { - setParameter("value", tool::Parameter(tool::Parameter::Type::Float, {slider->getValue()})); + setParameter("value", tool::Parameter(tool::Parameter::Type::Float, {slider->getValue()})); + m_output_value(); } void SliderView::resized() diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_SliderView.h b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_SliderView.h index 931cbeb8..c1d65e1b 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_SliderView.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_SliderView.h @@ -69,7 +69,8 @@ namespace kiwi private: // members - juce::Slider m_slider; + juce::Slider m_slider; + flip::Signal<> & m_output_value; private: // delted methods diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_AudioInterface.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_AudioInterface.cpp index c1c83b30..c7a166eb 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_AudioInterface.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_AudioInterface.cpp @@ -85,6 +85,14 @@ namespace kiwi { namespace engine { { m_audio_controler.stopAudio(); } + else + { + warning("audio interface inlet 1 only understand start and stop"); + } + } + else + { + warning("audio interface inlet 1 only understand start and stop"); } } } diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_LineTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_LineTilde.cpp index 278ea9da..b3635978 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_LineTilde.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_LineTilde.cpp @@ -246,10 +246,17 @@ namespace kiwi{ namespace engine { } else if(index == 1) { - m_next_ramp_time_ms = args[0].getFloat(); - m_next_ramp_time_consumed = false; + if (args[0].isNumber()) + { + m_next_ramp_time_ms = args[0].getFloat(); + m_next_ramp_time_consumed = false; + } } } + else + { + warning("line~ inlet " + std::to_string(index + 1) + " parameter must be a number"); + } /* //! @todo else if(args[0].isString()) { diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Metro.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Metro.cpp index 85c23a91..91f4ee4f 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Metro.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Metro.cpp @@ -75,6 +75,10 @@ namespace kiwi { namespace engine { getScheduler().unschedule(m_task); } } + else + { + warning("metro inlet 1 only take numbers"); + } } else if(index == 1) { diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Operator.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Operator.cpp index 084a78ca..d62e7b9b 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Operator.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Operator.cpp @@ -47,21 +47,32 @@ namespace kiwi { namespace engine { { if(!args.empty()) { - if(args[0].isNumber()) + if(index == 0) { - if(index == 0) + if (args[0].isNumber()) { m_lhs = args[0].getFloat(); bang(); } - else if(index == 1) + else if(args[0].getString() == "bang") { - m_rhs = args[0].getFloat(); + bang(); + } + else + { + warning("operator inlet 1 parameter must be a number or bang"); } } - else if(index == 0 && args[0].getString() == "bang") + else if(index == 1) { - bang(); + if (args[0].isNumber()) + { + m_rhs = args[0].getFloat(); + } + else + { + warning("operator inlet 2 parameter must be a number"); + } } } } diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_OscTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_OscTilde.cpp index fea4a563..a75da5e0 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_OscTilde.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_OscTilde.cpp @@ -77,7 +77,7 @@ namespace kiwi { namespace engine { warning("osc~ inlet 1 doesn't understanc [" + args[0].getString() + "]"); } } - else if(index == 1 && args[0].isNumber()) + else if(index == 1) { if (args[0].isNumber()) { diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Pipe.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Pipe.cpp index 1abfef75..5bc2b9e7 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Pipe.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Pipe.cpp @@ -62,7 +62,7 @@ namespace kiwi { namespace engine { { schedule([this, args](){send(0, args);}, m_delay); } - else if(index == 1 && args[0].isNumber()) + else if(index == 1) { if (args[0].isNumber()) { diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Print.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Print.cpp index 7aa0cb97..b5183fa9 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Print.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Print.cpp @@ -46,7 +46,25 @@ namespace kiwi { namespace engine { { std::vector const& args = model.getArguments(); - m_name = !args.empty() ? args[0].getString() : "print"; + if (!args.empty()) + { + if (args[0].isFloat()) + { + m_name = std::to_string(args[0].getFloat()); + } + else if(args[0].isInt()) + { + m_name = std::to_string(args[0].getInt()); + } + else + { + m_name = args[0].getString(); + } + } + else + { + m_name = "print"; + } } void Print::receive(size_t, std::vector const& args) diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_SigTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_SigTilde.cpp index 8702e267..3c43c188 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_SigTilde.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_SigTilde.cpp @@ -51,9 +51,16 @@ namespace kiwi { namespace engine { void SigTilde::receive(size_t index, std::vector const& args) { - if (index == 0 && args[0].isNumber()) + if (index == 0) { - m_value = args[0].getFloat(); + if (args[0].isNumber()) + { + m_value = args[0].getFloat(); + } + else + { + warning("sig~ inlet 1 must receive a number"); + } } } diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Slider.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Slider.cpp index 516b7236..a4f207a3 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Slider.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Slider.cpp @@ -25,6 +25,8 @@ #include #include +#include + namespace kiwi { namespace engine { // ================================================================================ // @@ -43,7 +45,9 @@ namespace kiwi { namespace engine { Slider::Slider(model::Object const& object_model, Patcher& patcher): Object(object_model, patcher), - m_value(object_model.getParameter("value")[0].getFloat()) + m_value(object_model.getParameter("value")[0].getFloat()), + m_connection(object_model.getSignal<>(model::Slider::Signal::OutputValue) + .connect(std::bind(&Slider::outputValue, this))) { } @@ -57,18 +61,33 @@ namespace kiwi { namespace engine { if (name == "value") { m_value = parameter[0].getFloat(); - send(0, {m_value}); } } + void Slider::outputValue() + { + defer([this]() + { + send(0, {m_value}); + }); + } + void Slider::receive(size_t index, std::vector const& args) { if (index == 0 && !args.empty()) { if (args[0].isNumber()) { + send(0, {args[0].getFloat()}); setParameter("value", tool::Parameter(tool::Parameter::Type::Float, {args[0].getFloat()})); } + else if(args[0].isString() && args[0].getString() == "set") + { + if (args.size() >= 1 && args[1].isNumber()) + { + setParameter("value", tool::Parameter(tool::Parameter::Type::Float, {args[1].getFloat()})); + } + } else if (args[0].isString() && args[0].getString() == "bang") { send(0, {m_value}); diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Slider.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Slider.h index 2fa88050..548bec22 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Slider.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Slider.h @@ -52,10 +52,15 @@ namespace kiwi { namespace engine { static void declare(); static std::unique_ptr create(model::Object const& model, Patcher& patcher); + + private: // methods + + void outputValue(); private: // members - double m_value; + double m_value; + flip::SignalConnection m_connection; }; }} diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_MeterTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_MeterTilde.cpp index 30ff1dde..5baa9368 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_MeterTilde.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_MeterTilde.cpp @@ -78,11 +78,11 @@ namespace kiwi { namespace model { if (is_inlet && index == 0) { - description = "input monitored signal"; + description = "Input monitored signal"; } else if (!is_inlet && index == 0) { - description = "sends peak value each metering intervall"; + description = "Sends peak value each metering intervall"; } return description; diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Operator.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Operator.cpp index d3e4f5f1..b3b557c9 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Operator.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Operator.cpp @@ -39,9 +39,19 @@ namespace kiwi { namespace model { Operator::Operator(std::vector const& args): Object() { + if (args.size() > 1) + { + throw Error("operator too many arguments"); + } + + if (args.size() == 1 && !args[0].isNumber()) + { + throw Error("operator argument must be a number"); + } + pushInlet({PinType::IType::Control}); - if (args.empty() || !args[0].isNumber()) + if (args.empty()) { pushInlet({PinType::IType::Control}); } diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_OperatorTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_OperatorTilde.cpp index 776d411e..a8b5ddea 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_OperatorTilde.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_OperatorTilde.cpp @@ -39,9 +39,19 @@ namespace kiwi { namespace model { OperatorTilde::OperatorTilde(std::vector const& args): Object() { + if (args.size() > 1) + { + throw Error("operator~ too many arguments"); + } + + if (args.size() == 1 && args[0].isNumber()) + { + throw Error("operator~ argument must be a number"); + } + pushInlet({PinType::IType::Signal}); - if (args.empty() || !args[0].isNumber()) + if (args.empty()) { pushInlet({PinType::IType::Signal, PinType::IType::Control}); } diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Print.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Print.cpp index ebac4166..91f36838 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Print.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Print.cpp @@ -47,12 +47,17 @@ namespace kiwi std::unique_ptr Print::create(std::vector const& args) { - return std::make_unique(); + return std::make_unique(args); } - Print::Print(): + Print::Print(std::vector const& args): Object() { + if (args.size() > 1) + { + throw Error("print takes 1 or 0 arguments"); + } + pushInlet({PinType::IType::Control}); } diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Print.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Print.h index 465b9f14..5d28257c 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Print.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Print.h @@ -35,7 +35,7 @@ namespace kiwi { namespace model { Print(flip::Default& d) : model::Object(d) {} - Print(); + Print(std::vector const& args); std::string getIODescription(bool is_inlet, size_t index) const override; diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Receive.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Receive.cpp index f05c4478..fd86428d 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Receive.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Receive.cpp @@ -48,12 +48,27 @@ namespace kiwi { namespace model { std::unique_ptr Receive::create(std::vector const& args) { - return std::make_unique(); + return std::make_unique(args); } - Receive::Receive(): + Receive::Receive(std::vector const& args): Object() { + if (args.empty()) + { + throw Error("receive requires one argument"); + } + + if (args.size() > 1) + { + throw Error("receive requires only one argument"); + } + + if (args.size() == 1 && args[0].isString()) + { + throw Error("receive argument must be a symbol"); + } + pushOutlet(PinType::IType::Control); } diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Receive.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Receive.h index 81ddee00..b39eea23 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Receive.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Receive.h @@ -35,7 +35,7 @@ namespace kiwi { namespace model { Receive(flip::Default& d) : model::Object(d) {} - Receive(); + Receive(std::vector const& args); std::string getIODescription(bool is_inlet, size_t index) const override; diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Select.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Select.cpp index 7b29c6e0..40d87eb9 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Select.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Select.cpp @@ -46,6 +46,11 @@ namespace kiwi { namespace model { Select::Select(std::vector const& args) { + if (args.empty()) + { + throw Error("select requires at least one argument"); + } + pushInlet({PinType::IType::Control}); for(size_t i = 0; i < args.size(); ++i) @@ -65,22 +70,22 @@ namespace kiwi { namespace model { { if (index == 0) { - description = "value to be tested"; + description = "Value to be tested"; } else { - description = "sets value " + std::to_string(index) + " to be tested"; + description = "Sets value " + std::to_string(index) + " to be tested"; } } else { if (index == getArguments().size()) { - description = "ouptuts bang if input doesn't match"; + description = "Ouptuts bang if input doesn't match"; } else { - description = "outputs bang if input matches " + getArguments()[index].getString(); + description = "Outputs bang if input matches " + getArguments()[index].getString(); } } diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_SigTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_SigTilde.cpp index 3a5d4e53..d26da00f 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_SigTilde.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_SigTilde.cpp @@ -48,6 +48,16 @@ namespace kiwi { namespace model { SigTilde::SigTilde(std::vector const& args) { + if (args.size() > 1) + { + throw Error("sig~ too many arguments"); + } + + if (args.size() == 1 && !args[0].isNumber()) + { + throw Error("sig~ argument must be a number"); + } + if (args.empty() || !args[0].isNumber()) { pushInlet({PinType::IType::Control}); diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Slider.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Slider.cpp index 6180c81d..ee86b148 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Slider.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Slider.cpp @@ -69,6 +69,8 @@ namespace kiwi { namespace model { Slider::Slider(): Object() { + addSignal<>(Signal::OutputValue, *this); + setMinWidth(20.); setMinHeight(20.); setWidth(20); @@ -80,6 +82,7 @@ namespace kiwi { namespace model { Slider::Slider(flip::Default& d): Object(d) { + addSignal<>(Signal::OutputValue, *this); } std::string Slider::getIODescription(bool is_inlet, size_t index) const diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Slider.h b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Slider.h index 7ab40625..4c9e350b 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Slider.h +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Slider.h @@ -37,7 +37,14 @@ namespace kiwi { namespace model { // ================================================================================ // class Slider : public model::Object - { + { + public: // enum + + enum Signal : SignalKey + { + OutputValue + }; + public: // methods Slider(flip::Default& d); From 4c7c81eb4d8ec9a382351b29c257ff75a1914c0c Mon Sep 17 00:00:00 2001 From: jmillot Date: Mon, 29 Jan 2018 00:55:04 +0100 Subject: [PATCH 130/148] Bump data model version v2. --- .../KiwiModel_Converter.cpp | 20 ++++++++++++++++++- .../KiwiModel_Converter.h | 3 +++ Modules/KiwiModel/KiwiModel_Def.h | 2 +- 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/Modules/KiwiModel/KiwiModel_Converters/KiwiModel_Converter.cpp b/Modules/KiwiModel/KiwiModel_Converters/KiwiModel_Converter.cpp index 42de6529..72ae4bfe 100755 --- a/Modules/KiwiModel/KiwiModel_Converters/KiwiModel_Converter.cpp +++ b/Modules/KiwiModel/KiwiModel_Converters/KiwiModel_Converter.cpp @@ -30,6 +30,19 @@ namespace kiwi { namespace model { // CONVERTER // // ================================================================================ // + void Converter::convert_v1_v2(flip::BackEndIR & backend) + { + flip::BackEndIR::Type & patcher = backend.root; + + // removing patcher name. + patcher.members.remove_if([](std::pair const& member) + { + return member.first == "patcher_name"; + }); + + backend.version = "v2"; + } + bool Converter::process(flip::BackEndIR & backend) { bool success = false; @@ -40,7 +53,12 @@ namespace kiwi { namespace model { if (current_version.compare(backend.version) >= 0) { - if (backend.version.compare("v1") >= 0) + if (backend.version.compare("v1") == 0) + { + convert_v1_v2(backend); + } + + if (backend.version.compare("v2") == 0) { success = true; } diff --git a/Modules/KiwiModel/KiwiModel_Converters/KiwiModel_Converter.h b/Modules/KiwiModel/KiwiModel_Converters/KiwiModel_Converter.h index c41dede8..20fe00ff 100755 --- a/Modules/KiwiModel/KiwiModel_Converters/KiwiModel_Converter.h +++ b/Modules/KiwiModel/KiwiModel_Converters/KiwiModel_Converter.h @@ -41,6 +41,9 @@ namespace kiwi { namespace model { private: // methods + //! @brief Converts a v1 data model to a v2 data model. + static void convert_v1_v2(flip::BackEndIR & backend); + //! @brief Rollbacks depecrated revisions. static void process_rollback(flip::BackEndIR & backend); }; diff --git a/Modules/KiwiModel/KiwiModel_Def.h b/Modules/KiwiModel/KiwiModel_Def.h index 60292373..49915e86 100644 --- a/Modules/KiwiModel/KiwiModel_Def.h +++ b/Modules/KiwiModel/KiwiModel_Def.h @@ -21,4 +21,4 @@ #pragma once -#define KIWI_MODEL_VERSION_STRING "v1" +#define KIWI_MODEL_VERSION_STRING "v2" From 94b85ceb38cad2df38ced7ce484659015887b1b1 Mon Sep 17 00:00:00 2001 From: jmillot Date: Mon, 29 Jan 2018 01:13:22 +0100 Subject: [PATCH 131/148] Draft on master branch as well. --- .travis.yml | 4 ++-- appveyor.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4af73803..610a6d26 100755 --- a/.travis.yml +++ b/.travis.yml @@ -75,7 +75,7 @@ matrix: - Kiwi_linux.tar.gz - Kiwi_Server_linux.tar.gz skip_cleanup: true - draft: false + draft: true prerelease: false on: repo: Musicoll/Kiwi @@ -140,7 +140,7 @@ matrix: - Kiwi_macos.zip - Kiwi_Server_macos.zip skip_cleanup: true - draft: false + draft: true prerelease: false on: repo: Musicoll/Kiwi diff --git a/appveyor.yml b/appveyor.yml index de588193..77b977ff 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -58,7 +58,7 @@ deploy: auth_token: secure: ZtKK8yOVkgIf+6Vm0jQLCbjCjuTiln3w2k/xMHI/kgardyCVtZ6plKI5O8lR3NNY artifact: /.*\.zip/ - draft: false + draft: true prerelease: false on: appveyor_repo_tag: true From 351b64b2535e8f5b154814545f5e6d393b3c10d8 Mon Sep 17 00:00:00 2001 From: eliott PARIS Date: Mon, 29 Jan 2018 14:22:24 +0100 Subject: [PATCH 132/148] Improve Atom parser and add new Comma and Dollar special types --- Modules/KiwiTool/KiwiTool_Atom.cpp | 657 ++++++++++++++++++++ Modules/KiwiTool/KiwiTool_Atom.h | 964 +++++++++-------------------- Test/Tool/test_Atom.cpp | 432 ++++++++++++- 3 files changed, 1376 insertions(+), 677 deletions(-) create mode 100644 Modules/KiwiTool/KiwiTool_Atom.cpp diff --git a/Modules/KiwiTool/KiwiTool_Atom.cpp b/Modules/KiwiTool/KiwiTool_Atom.cpp new file mode 100644 index 00000000..8367ae01 --- /dev/null +++ b/Modules/KiwiTool/KiwiTool_Atom.cpp @@ -0,0 +1,657 @@ +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#include + +namespace kiwi { namespace tool { + + // ================================================================================ // + // ATOM // + // ================================================================================ // + + Atom::Atom() noexcept + : m_type(Type::Null) + , m_value() + { + ; + } + + Atom::Atom(const bool value) noexcept + : m_type(Type::Int) + , m_value(value ? int_t(1) : int_t(0)) + { + ; + } + + Atom::Atom(const int value) noexcept + : m_type(Type::Int) + , m_value(static_cast(value)) + { + ; + } + + Atom::Atom(const long value) noexcept + : m_type(Type::Int) + , m_value(static_cast(value)) + { + ; + } + + Atom::Atom(const long long value) noexcept + : m_type(Type::Int) + , m_value(static_cast(value)) + { + ; + } + + Atom::Atom(const float value) noexcept + : m_type(Type::Float) + , m_value(static_cast(value)) + { + ; + } + + Atom::Atom(const double value) noexcept + : m_type(Type::Float) + , m_value(static_cast(value)) + { + ; + } + + Atom::Atom(string_t const& sym) + : m_type(Type::String) + , m_value(sym) + { + ; + } + + Atom::Atom(string_t&& sym) + : m_type(Type::String) + , m_value(std::move(sym)) + { + ; + } + + Atom::Atom(char const* sym) + : m_type(Type::String) + , m_value(std::move(sym)) + { + ; + } + + Atom Atom::Comma() + { + Atom atom; + atom.m_type = Type::Comma; + return atom; + } + + Atom Atom::Dollar(int_t index) + { + assert((index > 0 && index <= 9)); + + Atom atom(index); + atom.m_type = Type::Dollar; + return (index > 0 && index <= 9) ? atom : Atom(); + } + + Atom::Atom(Atom const& other) + : m_type(other.m_type) + { + switch(m_type) + { + case Type::Int: + case Type::Dollar: + { + m_value = other.m_value.int_v; + break; + } + case Type::Float: + { + m_value = other.m_value.float_v; + break; + } + case Type::String: + { + assert(other.m_value.string_v != nullptr); + m_value = *other.m_value.string_v; + break; + } + case Type::Comma: + { + break; + } + + default: break; + } + } + + Atom::Atom(Atom&& other) + : m_type(std::move(other.m_type)) + , m_value(std::move(other.m_value)) + { + // leave the other as a Null value Atom + other.m_type = Type::Null; + other.m_value = {}; + } + + Atom::~Atom() + { + if(isString()) + { + std::allocator alloc; + alloc.destroy(m_value.string_v); + alloc.deallocate(m_value.string_v, 1); + } + } + + Atom& Atom::operator=(Atom const& other) + { + if(!other.isString()) + { + if(isString()) + { + std::allocator alloc; + alloc.destroy(m_value.string_v); + alloc.deallocate(m_value.string_v, 1); + } + + m_value = other.m_value; + } + else + { + if(isString()) + { + *m_value.string_v = *other.m_value.string_v; + } + else + { + m_value.string_v = create_string_pointer(*other.m_value.string_v); + } + } + + m_type = other.m_type; + + return *this; + } + + Atom& Atom::operator=(Atom&& other) noexcept + { + std::swap(m_type, other.m_type); + std::swap(m_value, other.m_value); + return *this; + } + // ================================================================================ // + // Type Getters // + // ================================================================================ // + + Atom::Type Atom::getType() const noexcept + { + return m_type; + } + + bool Atom::isNull() const noexcept + { + return (m_type == Type::Null); + } + + bool Atom::isInt() const noexcept + { + return m_type == Type::Int; + } + + bool Atom::isFloat() const noexcept + { + return m_type == Type::Float; + } + + bool Atom::isNumber() const noexcept + { + return (isInt() || isFloat()); + } + + bool Atom::isString() const noexcept + { + return m_type == Type::String; + } + + bool Atom::isBang() const + { + static const auto bang_str = "bang"; + return isString() && getString() == bang_str; + } + + bool Atom::isComma() const noexcept + { + return m_type == Type::Comma; + } + + bool Atom::isDollar() const noexcept + { + return m_type == Type::Dollar; + } + + // ================================================================================ // + // Value Getters // + // ================================================================================ // + + Atom::int_t Atom::getInt() const noexcept + { + if(isInt()) + { + return m_value.int_v; + } + else if(isFloat()) + { + return static_cast(m_value.float_v); + } + + return int_t(0); + } + + Atom::float_t Atom::getFloat() const noexcept + { + if(isFloat()) + { + return m_value.float_v; + } + else if(isInt()) + { + return static_cast(m_value.int_v); + } + + return float_t(0.0); + } + + Atom::string_t const& Atom::getString() const + { + if(isString()) + { + return *m_value.string_v; + } + + static const std::string empty_string; + return empty_string; + } + + //! @brief Retrieves the Dollar index value if the Atom is a dollar type. + //! @return The Dollar index if the Atom is a dollar, 0 otherwise. + //! @see getType(), isDollar(), isDollarTyped() + Atom::int_t Atom::getDollarIndex() const + { + return isDollar() ? m_value.int_v : 0; + } + + // ================================================================================ // + // VALUE // + // ================================================================================ // + + //! @internal Exception-safe object creation helper + Atom::string_t* Atom::create_string_pointer(string_t const& v) + { + std::allocator alloc; + auto deleter = [&alloc](string_t * object) { alloc.deallocate(object, 1); }; + std::unique_ptr object(alloc.allocate(1), deleter); + alloc.construct(object.get(), v); + return object.release(); + } + + Atom::string_t* Atom::create_string_pointer(string_t&& v) + { + std::allocator alloc; + auto deleter = [&alloc](string_t * object) { alloc.deallocate(object, 1); }; + std::unique_ptr object(alloc.allocate(1), deleter); + alloc.construct(object.get(), std::move(v)); + return object.release(); + } + + // ================================================================================ // + // ATOM HELPER // + // ================================================================================ // + + std::vector AtomHelper::parse(std::string const& text, int flags) + { + std::vector atoms; + const auto text_end = text.cend(); + auto text_it = text.begin(); + + enum class NumberState + { + NaN = -1, + MaybeNumber = 0, + GotMinus, + GotDigit, + GotDotWithoutDigit, + GotDotAfterDigit, + GotDigitAfterDot, + GotExpon, + GotPlusMinusAfterExpon, + GotDigitAfterExpon, + }; + + enum class DollarState + { + NotDollar = -1, + MaybeDollar = 0, + GotDollar, + DollarValid, // $1 => $9 + }; + + for(;;) + { + // skip witespaces + while((text_it != text_end) && (*text_it == ' ' || (*text_it <= 13 && *text_it >= 9))) + text_it++; + + if(text_it == text_end) + break; // end of parsing + + std::ostringstream text_buffer; + + NumberState numstate = NumberState::MaybeNumber; + DollarState dollar_state = ((flags & ParsingFlags::Dollar) + ? DollarState::MaybeDollar + : DollarState::NotDollar); + + bool is_quoted = false; + bool is_comma = false; + int dollar_index = 0; + + bool lastslash = false; + bool slash = false; + + while(text_it != text_end) + { + bool buffer_is_empty = (((long)text_buffer.tellp()) == 0); + char c = *text_it; + lastslash = slash; + slash = (c == '\\'); + + // skip witespaces characters + if(c == ' ' || (c <= 13 && c >= 9)) + { + // preserve whitespaces in quoted tags + if(!is_quoted) + { + break; + } + } + else if(c == '\"' && !lastslash) + { + // closing quote + if(is_quoted) + { + text_it++; + break; + } + + // opening quote + if(buffer_is_empty) + { + text_it++; + is_quoted = true; + continue; + } + } + else if(is_comma + || ((flags & ParsingFlags::Comma) && (c == ',' && !is_quoted))) + { + if(!buffer_is_empty) + { + break; + } + + is_comma = true; + } + else if(!is_quoted && numstate >= NumberState::MaybeNumber) + { + const bool digit = (c >= '0' && c <= '9'), + dot = (c == '.'), minus = (c == '-'), + plusminus = (minus || (c == '+')), + expon = (c == 'e' || c == 'E'); + + if (numstate == NumberState::MaybeNumber) + { + if (minus) numstate = NumberState::GotMinus; + else if (digit) numstate = NumberState::GotDigit; + else if (dot) numstate = NumberState::GotDotWithoutDigit; + else numstate = NumberState::NaN; + } + else if (numstate == NumberState::GotMinus) + { + if (digit) numstate = NumberState::GotDigit; + else if (dot) numstate = NumberState::GotDotWithoutDigit; + else numstate = NumberState::NaN; + } + else if (numstate == NumberState::GotDigit) + { + if (dot) numstate = NumberState::GotDotAfterDigit; + else if (expon) numstate = NumberState::GotDigit; + else if (!digit) numstate = NumberState::NaN; + } + else if (numstate == NumberState::GotDotWithoutDigit) + { + if (digit) numstate = NumberState::GotDigitAfterDot; + else numstate = NumberState::NaN; + } + else if (numstate == NumberState::GotDotAfterDigit) + { + if (digit) numstate = NumberState::GotDigitAfterDot; + else if (expon) numstate = NumberState::GotExpon; + else numstate = NumberState::NaN; + } + else if (numstate == NumberState::GotDigitAfterDot) + { + if (expon) numstate = NumberState::GotExpon; + else if (!digit) numstate = NumberState::NaN; + } + else if (numstate == NumberState::GotExpon) + { + if (plusminus) numstate = NumberState::GotPlusMinusAfterExpon; + else if (digit) numstate = NumberState::GotDigitAfterExpon; + else numstate = NumberState::NaN; + } + else if (numstate == NumberState::GotPlusMinusAfterExpon) + { + if (digit) numstate = NumberState::GotDigitAfterExpon; + else numstate = NumberState::NaN; + } + else if (numstate == NumberState::GotDigitAfterExpon) + { + if (!digit) numstate = NumberState::NaN; + } + } + + if(dollar_state >= DollarState::MaybeDollar + && numstate == NumberState::NaN && !is_quoted) + { + if(dollar_state == DollarState::MaybeDollar) + { + dollar_state = ((buffer_is_empty && (c == '$') && !is_quoted && !lastslash) + ? DollarState::GotDollar + : DollarState::NotDollar); + } + else if (dollar_state == DollarState::GotDollar) + { + dollar_state = ((c > '0' && c <= '9') + ? DollarState::DollarValid + : DollarState::NotDollar); + + dollar_index = (dollar_state == DollarState::DollarValid ? (c - '0') : 0); + } + else if (dollar_state == DollarState::DollarValid) + { + if((c == ' ') || (flags & ParsingFlags::Comma && c == ',')) + { + break; + } + else + { + dollar_state = DollarState::NotDollar; + } + } + } + + // strip slashes + if(slash) + { + if(!lastslash) + { + text_it++; + continue; + } + else + { + slash = false; + } + } + + text_buffer << c; + text_it++; + } + + const auto& word = text_buffer.str(); + + if(!word.empty()) + { + if(numstate == NumberState::GotDigit) + { + atoms.emplace_back(std::stol(word)); + } + else if(numstate == NumberState::GotDotAfterDigit + || numstate == NumberState::GotDigitAfterDot + || numstate == NumberState::GotDigitAfterExpon) + { + atoms.emplace_back(std::stod(word)); + } + else if(is_comma) + { + atoms.emplace_back(Atom::Comma()); + } + else if(dollar_state == DollarState::DollarValid) + { + atoms.emplace_back(Atom::Dollar(dollar_index)); + } + else + { + atoms.emplace_back(word); + } + } + } + + return atoms; + } + + std::string AtomHelper::toString(Atom const& atom, const bool add_quotes) + { + switch(atom.getType()) + { + case Atom::Type::Int: + { + return std::to_string(atom.getInt()); + } + case Atom::Type::Float: + { + return trimDecimal(std::to_string(atom.getFloat())); + } + case Atom::Type::String: + { + const auto& str = atom.getString(); + if(!str.empty()) + { + const bool need_quote = add_quotes && str.find_first_of(' ', 0) != std::string::npos; + + if(need_quote) + { + std::ostringstream output; + output << "\""; + + // add slashes + for(auto c : str) + { + if(c == '\\' || c == '"') + { + output << '\\'; + } + + output << c; + } + + output << "\""; + return output.str(); + } + + return str; + } + } + case Atom::Type::Comma: + { + return ","; + } + case Atom::Type::Dollar: + { + return "$" + std::to_string(atom.getDollarIndex()); + } + + default : break; + } + + return {}; + } + + std::string AtomHelper::toString(std::vector const& atoms, const bool add_quotes) + { + static const auto delimiter = ' '; + std::ostringstream output; + if(!atoms.empty()) + { + for(std::vector::size_type i = 0; i < atoms.size();) + { + output << toString(atoms[i], add_quotes); + if(++i != atoms.size() && !atoms[i].isComma()) + { + output << delimiter; + } + } + } + + return output.str(); + } + + std::string AtomHelper::trimDecimal(std::string const& text) + { + auto output = text; + auto pos = text.find('.'); + + if(pos != std::string::npos) + { + auto size = text.size(); + while(size > pos && text[size - 1] == '0') + { + output.pop_back(); + size--; + } + } + + return output; + } + +}} diff --git a/Modules/KiwiTool/KiwiTool_Atom.h b/Modules/KiwiTool/KiwiTool_Atom.h index 64b03c5f..291f7a26 100644 --- a/Modules/KiwiTool/KiwiTool_Atom.h +++ b/Modules/KiwiTool/KiwiTool_Atom.h @@ -1,657 +1,309 @@ -/* - ============================================================================== - - This file is part of the KIWI library. - - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. - - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. - - Permission is granted to use this software under the terms of the GPL v3 - (or any later version). Details can be found at: www.gnu.org/licenses - - KIWI is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - Contact : cicm.mshparisnord@gmail.com - - ============================================================================== - */ - -#pragma once - -#include -#include -#include -#include -#include -#include - -namespace kiwi { namespace tool { - - // ================================================================================ // - // ATOM // - // ================================================================================ // - - //! @brief The Atom can dynamically hold different types of value - //! @details The Atom can hold an integer, a float or a string. - class Atom - { - public: // methods - - // ================================================================================ // - // Types // - // ================================================================================ // - - //! @brief The type of a signed integer number in the Atom class. - using int_t = int64_t; - - //! @brief The type of a floating-point number in the Atom class. - using float_t = double; - - //! @brief The type of a string type in the Atom class. - using string_t = std::string; - - //! @brief Enum of Atom value types - //! @see getType(), isNull(), isInt(), isFloat(), isNumber(), isString() - enum class Type : uint8_t - { - Null = 0, - Int = 1, - Float = 2, - String = 3 - }; - - // ================================================================================ // - // CONSTRUCTORS // - // ================================================================================ // - - //! @brief Default constructor. - //! @details Constructs an Atom of type Null. - Atom() noexcept : - m_type(Type::Null), - m_value() - { - ; - } - - //! @brief Constructs an int_t Atom. - //! @details The integer value will be 1 or 0 depending on the bool value. - //! @param value The value. - Atom(const bool value) noexcept : - m_type(Type::Int), - m_value(value ? int_t(1) : int_t(0)) - { - ; - } - - //! @brief Constructs an int_t Atom. - //! @param value The value. - Atom(const int value) noexcept : - m_type(Type::Int), - m_value(static_cast(value)) - { - ; - } - - //! @brief Constructs an int_t Atom. - //! @param value The value. - Atom(const long value) noexcept : - m_type(Type::Int), - m_value(static_cast(value)) - { - ; - } - - //! @brief Constructs an int_t Atom. - //! @param value The value. - Atom(const long long value) noexcept : - m_type(Type::Int), - m_value(static_cast(value)) - { - ; - } - - //! @brief Constructs a float_t Atom. - //! @details infinty and NaN value both produce a Null Atom type. - //! @param value The value. - Atom(const float value) noexcept : - m_type(Type::Float), - m_value(static_cast(value)) - { - ; - } - - //! @brief Constructs a float_t Atom. - //! @details infinty and NaN value both produce a Null Atom type. - //! @param value The value. - Atom(const double value) noexcept : - m_type(Type::Float), - m_value(static_cast(value)) - { - ; - } - - //! @brief Constructs a string_t Atom. - //! @param sym The value. - Atom(string_t const& sym) : - m_type(Type::String), - m_value(sym) - { - ; - } - - //! @brief Constructs a string_t Atom. - //! @param sym The value. - Atom(string_t&& sym) : - m_type(Type::String), - m_value(std::move(sym)) - { - ; - } - - //! @brief Constructs a string_t Atom. - //! @param sym The value. - Atom(char const* sym) : - m_type(Type::String), - m_value(std::move(std::string(sym))) - { - ; - } - - //! @brief Copy constructor. - //! @details Constructs an Atom by copying the contents of an other Atom. - //! @param other The other Atom. - Atom(Atom const& other) : m_type(other.m_type) - { - switch(m_type) - { - case Type::Int: { m_value = other.m_value.int_v; break; } - case Type::Float: { m_value = other.m_value.float_v; break; } - case Type::String: - { - assert(other.m_value.string_v != nullptr); - m_value = *other.m_value.string_v; - } - - default: break; - } - } - - //! @brief Move constructor. - //! @details Constructs an Atom value by stealing the contents of an other Atom - //! using move semantics, leaving the other as a Null value Atom. - //! @param other The other Atom value. - Atom(Atom&& other) : - m_type(std::move(other.m_type)), - m_value(std::move(other.m_value)) - { - // leave the other as a Null value Atom - other.m_type = Type::Null; - other.m_value = {}; - } - - //! @brief Destructor. - inline ~Atom() - { - if(isString()) - { - std::allocator alloc; - alloc.destroy(m_value.string_v); - alloc.deallocate(m_value.string_v, 1); - } - } - - //! @brief Copy assigment operator. - //! @details Copies an Atom value. - //! @param other The Atom object to copy. - Atom& operator=(Atom const& other) - { - if(!other.isString()) - { - if(isString()) - { - std::allocator alloc; - alloc.destroy(m_value.string_v); - alloc.deallocate(m_value.string_v, 1); - } - - m_value = other.m_value; - } - else - { - if(isString()) - { - *m_value.string_v = *other.m_value.string_v; - } - else - { - m_value.string_v = create_string_pointer(*other.m_value.string_v); - } - } - - m_type = other.m_type; - - return *this; - } - - //! @brief Copy assigment operator. - //! @details Copies an Atom value with the "copy and swap" method. - //! @param other The Atom object to copy. - Atom& operator=(Atom&& other) noexcept - { - std::swap(m_type, other.m_type); - std::swap(m_value, other.m_value); - return *this; - } - // ================================================================================ // - // Type Getters // - // ================================================================================ // - - //! @brief Get the type of the Atom. - //! @return The Type of the atom as a Type. - //! @see isNull(), isInt(), isFloat(), isNumber(), isString() - inline Type getType() const noexcept { return m_type; } - - //! @brief Returns true if the Atom is Null. - //! @return true if the Atom is Null. - //! @see getType(), isInt(), isFloat(), isNumber(), isString() - inline bool isNull() const noexcept { return (m_type == Type::Null); } - - //! @brief Returns true if the Atom is an int_t. - //! @return true if the Atom is an int_t. - //! @see getType(), isNull(), isFloat(), isNumber(), isString() - inline bool isInt() const noexcept { return m_type == Type::Int; } - - //! @brief Returns true if the Atom is a float_t. - //! @return true if the Atom is an float_t. - //! @see getType(), isNull(), isInt(), isNumber(), isString() - inline bool isFloat() const noexcept { return m_type == Type::Float; } - - //! @brief Returns true if the Atom is a bool, an int_t, or a float_t. - //! @return true if the Atom is a bool, an int_t, or a float_t. - //! @see getType(), isNull(), isInt(), isFloat(), isString() - inline bool isNumber() const noexcept { return (isInt() || isFloat()); } - - //! @brief Returns true if the Atom is a string_t. - //! @return true if the Atom is a string_t. - //! @see getType(), isNull(), isInt(), isFloat(), isNumber() - inline bool isString() const noexcept { return m_type == Type::String; } - - // ================================================================================ // - // Value Getters // - // ================================================================================ // - - //! @brief Retrieves the Atom value as an int_t value. - //! @return The current integer atom value if it is a number otherwise 0. - //! @see getType(), isNumber(), isInt(), getFloat() - int_t getInt() const noexcept - { - if(isInt()) - { - return m_value.int_v; - } - else if(isFloat()) - { - return static_cast(m_value.float_v); - } - - return int_t(0); - } - - //! @brief Retrieves the Atom value as a float_t value. - //! @return The current floating-point atom value if it is a number otherwise 0.0. - //! @see getType(), isNumber(), isFloat(), getInt() - float_t getFloat() const noexcept - { - if(isFloat()) - { - return m_value.float_v; - } - else if(isInt()) - { - return static_cast(m_value.int_v); - } - - return float_t(0.0); - } - - //! @brief Retrieves the Atom value as a string_t value. - //! @return The current string atom value if it is a string otherwise an empty string. - //! @see getType(), isString(), getInt(), getFloat() - string_t getString() const - { - if(isString()) - { - return *m_value.string_v; - } - - return string_t(); - } - - private: // methods - - // ================================================================================ // - // VALUE // - // ================================================================================ // - - //! @internal Exception-safe object creation helper - static string_t* create_string_pointer(string_t const& v) - { - std::allocator alloc; - auto deleter = [&alloc](string_t * object) { alloc.deallocate(object, 1); }; - std::unique_ptr object(alloc.allocate(1), deleter); - alloc.construct(object.get(), v); - return object.release(); - } - - static string_t* create_string_pointer(string_t&& v) - { - std::allocator alloc; - auto deleter = [&alloc](string_t * object) { alloc.deallocate(object, 1); }; - std::unique_ptr object(alloc.allocate(1), deleter); - alloc.construct(object.get(), std::move(v)); - return object.release(); - } - - //! @internal The actual storage union for an Atom value. - union atom_value - { - //! @brief number (integer). - int_t int_v; - - //! @brief number (floating-point). - float_t float_v; - - //! @brief string. - string_t* string_v; - - //! @brief default constructor (for null values). - atom_value() = default; - - //! @brief constructor for numbers (integer). - atom_value(const int_t v) noexcept : int_v(v) {} - - //! @brief constructor for numbers (floating-point). - atom_value(const float_t v) noexcept : float_v(v) {} - - //! @brief constructor for strings - atom_value(string_t const& v) : string_v(create_string_pointer(v)) {} - - //! @brief constructor for strings - atom_value(string_t&& v) : string_v(create_string_pointer(std::move(v))) {} - }; - - private: // methods - - //! @internal Atom Type (Null by default) - Type m_type = Type::Null; - - //! @internal Atom value - atom_value m_value = {}; - }; - - // ================================================================================ // - // STRING HELPER // - // ================================================================================ // - - //! @brief An std::string helper class. - struct StringHelper - { - //! @brief unescape a string - static std::string unescape(std::string const& text) - { - bool state = false; - std::ostringstream ss; - for(const auto& iter : text) - { - if(state) - { - switch(iter) - { - case '"': ss << '\"'; break; - case '/': ss << '/'; break; - case 'b': ss << '\b'; break; - case 'f': ss << '\f'; break; - case 'n': ss << '\n'; break; - case 'r': ss << '\r'; break; - case 't': ss << '\t'; break; - case '\\': ss << '\\'; break; - default: ss << iter; break; - } - state = false; - } - else - { - switch(iter) - { - case '"': { return ss.str(); } - case '\\': { state = true; break; } - default: { ss << iter; break; } - } - } - } - return ss.str(); - } - }; - - // ================================================================================ // - // ATOM HELPER // - // ================================================================================ // - - //! @brief An Atom helper class. - struct AtomHelper - { - //! @brief Parse a string into a vector of atoms. - //! @details Parse a string into a vector of atoms. - //! @param text The string to parse. - //! @return The vector of atoms. - //! @remark For example, the string : "foo \"bar 42\" 1 2 3.14" will parsed into a vector of 5 atoms. - //! The atom types will be determined automatically as 2 #Atom::Type::TAG atoms, 2 #Atom::Type::LONG atoms, and 1 #Atom::Type::DOUBLE atom. - static std::vector parse(std::string const& text) - { - std::vector atoms; - const auto textlen = text.length(); - auto pos = text.find_first_not_of(' ', 0); - - while(pos < textlen) - { - std::string word; - word.reserve(20); - bool is_tag = false; - bool is_number = false; - bool is_float = false; - bool is_negative = false; - bool is_quoted = false; - - while(pos < textlen) - { - const char c = text[pos]; - - if(c == ' ') - { - if(!is_quoted) - { - // preserve white space in quoted tags, otherwise skip them - if(word.empty()) - { - pos++; - continue; - } - else - { - break; - } - } - } - else if(c == '\"') - { - // closing quote - if(is_quoted) - { - pos++; - break; - } - - // opening quote - if(word.empty()) - { - pos++; - - // ignore if it can not be closed - if(text.find_first_of('\"', pos) != std::string::npos) - is_quoted = is_tag = true; - - continue; - } - } - else if(!is_tag) - { - if(word.empty() && c == '-') - { - is_negative = true; - } - else if(!is_float && (word.empty() || is_number || is_negative) && c == '.') - { - is_float = true; - } - else if(isdigit(c) && (is_number || (word.empty() || is_negative || is_float))) - { - is_number = true; - } - else - { - is_tag = true; - is_number = is_negative = is_float = false; - } - } - - word += c; - pos++; - } - - if(!word.empty()) - { - if(is_number) - { - if(is_float) - { - atoms.emplace_back(std::stod(word.c_str())); - } - else - { - long value = 0; - try - { - value = std::stol(word.c_str()); - } - catch(std::out_of_range const& err) - { - // print error here - } - catch(std::invalid_argument const& err) - { - // print error here - } - - atoms.emplace_back(value); - } - } - else - { - atoms.emplace_back(StringHelper::unescape(word)); - } - } - } - - return atoms; - } - - static std::string trimDecimal(std::string& text) - { - std::string::size_type pos = text.find('.'); - - if(pos != std::string::npos) - { - std::string::size_type size = text.size(); - while(size > pos && text[size - 1] == '0') - { - text.pop_back(); - size--; - } - } - - return text; - } - - //! @brief Convert an Atom into a string. - static std::string toString(Atom const& atom) - { - std::string output; - if(atom.isInt()) - { - output += std::to_string(atom.getInt()); - } - else if(atom.isFloat()) - { - std::string str = std::to_string(atom.getFloat()); - output += trimDecimal(str); - } - else if(atom.isString()) - { - output += atom.getString(); - } - - return output; - } - - //! @brief Convert a vector of Atom into a string. - static std::string toString(std::vector const& atoms, const char delimiter = ' ') - { - std::string output; - if(!atoms.empty()) - { - for(std::vector::size_type i = 0; i < atoms.size();) - { - output += toString(atoms[i]); - if(++i != atoms.size()) - { - output += delimiter; - } - } - } - - return output; - } - - //! @brief Convert a vector of Atom into a string. - static std::string toJsonString(std::vector const& atoms) - { - std::string output; - if(!atoms.empty()) - { - if(atoms.size() == 1) - { - output += toString(atoms[0]); - } - else - { - output += '['; - for(std::vector::size_type i = 0; i < atoms.size();) - { - output += toString(atoms[i]); - if(++i != atoms.size()) - { - output += ", "; - } - } - output += ']'; - } - } - - return output; - } - }; - +/* + ============================================================================== + + This file is part of the KIWI library. + - Copyright (c) 2014-2016, Pierre Guillot & Eliott Paris. + - Copyright (c) 2016-2017, CICM, ANR MUSICOLL, Eliott Paris, Pierre Guillot, Jean Millot. + + Permission is granted to use this software under the terms of the GPL v3 + (or any later version). Details can be found at: www.gnu.org/licenses + + KIWI is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + Contact : cicm.mshparisnord@gmail.com + + ============================================================================== + */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace kiwi { namespace tool { + + // ================================================================================ // + // ATOM // + // ================================================================================ // + + //! @brief The Atom can dynamically hold different types of value + //! @details The Atom can hold an integer, a float or a string. + class Atom + { + public: // methods + + // ================================================================================ // + // Types // + // ================================================================================ // + + //! @brief The type of a signed integer number in the Atom class. + using int_t = int64_t; + + //! @brief The type of a floating-point number in the Atom class. + using float_t = double; + + //! @brief The type of a string type in the Atom class. + using string_t = std::string; + + //! @brief Enum of Atom value types + //! @see getType(), isNull(), isInt(), isFloat(), isNumber(), isString(), isComma(), isDollar() + enum class Type : uint8_t + { + // basic types: + Null = 0, + Int, + Float, + String, + + // special types: + Comma, + Dollar, + }; + + // ================================================================================ // + // CONSTRUCTORS // + // ================================================================================ // + + //! @brief Default constructor. + //! @details Constructs an Atom of type Null. + Atom() noexcept; + + //! @brief Constructs an int_t Atom. + //! @details The integer value will be 1 or 0 depending on the bool value. + //! @param value The value. + Atom(const bool value) noexcept; + + //! @brief Constructs an int_t Atom. + //! @param value The value. + Atom(const int value) noexcept; + + //! @brief Constructs an int_t Atom. + //! @param value The value. + Atom(const long value) noexcept; + + //! @brief Constructs an int_t Atom. + //! @param value The value. + Atom(const long long value) noexcept; + + //! @brief Constructs a float_t Atom. + //! @details infinty and NaN value both produce a Null Atom type. + //! @param value The value. + Atom(const float value) noexcept; + + //! @brief Constructs a float_t Atom. + //! @details infinty and NaN value both produce a Null Atom type. + //! @param value The value. + Atom(const double value) noexcept; + + //! @brief Constructs a string_t Atom. + //! @param sym The value. + Atom(string_t const& sym); + + //! @brief Constructs a string_t Atom. + //! @param sym The value. + Atom(string_t&& sym); + + //! @brief Constructs a string_t Atom. + //! @param sym The value. + Atom(char const* sym); + + //! @brief Constructs a Comma Atom. + static Atom Comma(); + + //! @brief Constructs a Dollar Atom. + //! @param index must be between 1 and 9 + //! @return A Dollar Atom or a Null Atom if out of range. + static Atom Dollar(int_t index); + + //! @brief Copy constructor. + //! @details Constructs an Atom by copying the contents of an other Atom. + //! @param other The other Atom. + Atom(Atom const& other); + + //! @brief Move constructor. + //! @details Constructs an Atom value by stealing the contents of an other Atom + //! using move semantics, leaving the other as a Null value Atom. + //! @param other The other Atom value. + Atom(Atom&& other); + + //! @brief Destructor. + ~Atom(); + + //! @brief Copy assigment operator. + //! @details Copies an Atom value. + //! @param other The Atom object to copy. + Atom& operator=(Atom const& other); + + //! @brief Copy assigment operator. + //! @details Copies an Atom value with the "copy and swap" method. + //! @param other The Atom object to copy. + Atom& operator=(Atom&& other) noexcept; + + // ================================================================================ // + // Type Getters // + // ================================================================================ // + + //! @brief Get the type of the Atom. + //! @return The Type of the atom as a Type. + //! @see isNull(), isInt(), isFloat(), isNumber(), isString() + Type getType() const noexcept; + + //! @brief Returns true if the Atom is Null. + //! @return true if the Atom is Null. + //! @see getType(), isInt(), isFloat(), isNumber(), isString() + bool isNull() const noexcept; + + //! @brief Returns true if the Atom is an int_t. + //! @return true if the Atom is an int_t. + //! @see getType(), isNull(), isFloat(), isNumber(), isString() + bool isInt() const noexcept; + + //! @brief Returns true if the Atom is a float_t. + //! @return true if the Atom is an float_t. + //! @see getType(), isNull(), isInt(), isNumber(), isString() + bool isFloat() const noexcept; + + //! @brief Returns true if the Atom is a bool, an int_t, or a float_t. + //! @return true if the Atom is a bool, an int_t, or a float_t. + //! @see getType(), isNull(), isInt(), isFloat(), isString() + bool isNumber() const noexcept; + + //! @brief Returns true if the Atom is a string_t. + //! @return true if the Atom is a string_t. + //! @see getType(), isNull(), isInt(), isFloat(), isNumber() + bool isString() const noexcept; + + //! @brief Returns true if the Atom is a string_t that contains the special "bang" keyword. + //! @return true if the Atom is a string_t that contains the special "bang" keyword. + //! @see getType(), isNull(), isInt(), isFloat(), isString() + bool isBang() const; + + //! @brief Returns true if the Atom is an comma_t. + //! @return true if the Atom is a comma_t. + //! @see getType(), isNull(), isInt(), isFloat(), isNumber(), isString() + bool isComma() const noexcept; + + //! @brief Returns true if the Atom is a dollar or a dollar typed. + //! @return true if the Atom is a dollar_t. + //! @see getType(), isNull(), isInt(), isFloat(), isNumber(), isString() + bool isDollar() const noexcept; + + // ================================================================================ // + // Value Getters // + // ================================================================================ // + + //! @brief Retrieves the Atom value as an int_t value. + //! @return The current integer atom value if it is a number otherwise 0. + //! @see getType(), isNumber(), isInt(), getFloat() + int_t getInt() const noexcept; + + //! @brief Retrieves the Atom value as a float_t value. + //! @return The current floating-point atom value if it is a number otherwise 0.0. + //! @see getType(), isNumber(), isFloat(), getInt() + float_t getFloat() const noexcept; + + //! @brief Retrieves the Atom value as a string_t value. + //! @return The current string atom value if it is a string otherwise an empty string. + //! @see getType(), isString(), getInt(), getFloat() + string_t const& getString() const; + + //! @brief Retrieves the Dollar index value if the Atom is a dollar type. + //! @return The Dollar index if the Atom is a dollar, 0 otherwise. + //! @see getType(), isDollar(), isDollarTyped() + int_t getDollarIndex() const; + + private: // methods + + // ================================================================================ // + // VALUE // + // ================================================================================ // + + //! @internal Exception-safe object creation helper + static string_t* create_string_pointer(string_t const& v); + + static string_t* create_string_pointer(string_t&& v); + + //! @internal The actual storage union for an Atom value. + union atom_value + { + //! @brief number (integer). + int_t int_v; + + //! @brief number (floating-point). + float_t float_v; + + //! @brief string. + string_t* string_v; + + //! @brief default constructor (for null values). + atom_value() = default; + + //! @brief constructor for numbers (integer). + atom_value(const int_t v) noexcept : int_v(v) {} + + //! @brief constructor for numbers (floating-point). + atom_value(const float_t v) noexcept : float_v(v) {} + + //! @brief constructor for strings + atom_value(string_t const& v) : string_v(create_string_pointer(v)) {} + + //! @brief constructor for strings + atom_value(string_t&& v) : string_v(create_string_pointer(std::move(v))) {} + }; + + private: // methods + + //! @internal Atom Type (Null by default) + Type m_type = Type::Null; + + //! @internal Atom value + atom_value m_value = {}; + }; + + // ================================================================================ // + // ATOM HELPER // + // ================================================================================ // + + //! @brief An Atom helper class. + struct AtomHelper + { + struct ParsingFlags { enum Flags { + Comma = 0x01, + Dollar = 0x02, + }; }; + + //! @brief Parse a string into a vector of atoms. + //! @param text The string to parse. + //! @param flags The flags as a set of #ParsingFlags. + //! @return The vector of atoms. + //! @details The parsing method can be altered by the #ParsingFlags \flags passed as parameter. + //! If the ParsingFlags::Comma flag is set, it will create a Comma atom type + //! for each ',' char of the string (except if the text is in double quotes) + //! If the ParsingFlags::Dollar flag is set, it will create a Dollar atom type + //! for each '$' char followed by a digit between 1 and 9. + //! @example The string : "foo \"bar 42\" 1 -2 3.14" will be parsed into a vector of 5 Atom. + //! The atom types will be determined automatically as : + //! 2 #Atom::Type::String, 2 #Atom::Type::Int, and 1 #Atom::Type::Float. + static std::vector parse(std::string const& text, int flags = 0); + + //! @brief Convert an Atom into a string. + static std::string toString(Atom const& atom, const bool add_quotes = true); + + //! @brief Convert a vector of Atom into a string. + //! @details This method will call the toString static method for each atom + //! of the vector and output a whitespace between each one + //! (except for the special Atom::Type::Comma that is stuck to the previous Atom). + static std::string toString(std::vector const& atoms, const bool add_quotes = true); + + static std::string trimDecimal(std::string const& text); + }; + }} diff --git a/Test/Tool/test_Atom.cpp b/Test/Tool/test_Atom.cpp index 36c1d30a..b2166881 100755 --- a/Test/Tool/test_Atom.cpp +++ b/Test/Tool/test_Atom.cpp @@ -27,10 +27,6 @@ using namespace kiwi::tool; -//! @brief kiwi::Atom unit test -//! @todo : -//! - Add more tests to kiwi::Atom::parse method - // ================================================================================ // // ATOM CONSTRUCTORS // // ================================================================================ // @@ -129,15 +125,15 @@ TEST_CASE("Atom Constructors", "[Atom]") } /* - SECTION("Unsigned Integral types are unsupported") - { - CHECK(Atom(1u).getType() == Atom::Type::Int); // unsigned (int) - CHECK(Atom(1ul).getType() == Atom::Type::Int); // unsigned long - CHECK(Atom(1lu).getType() == Atom::Type::Int); // unsigned long - CHECK(Atom(1ull).getType() == Atom::Type::Int); // unsigned long long - CHECK(Atom(1llu).getType() == Atom::Type::Int); // unsigned long long - } - */ + SECTION("Unsigned Integral types are unsupported") + { + CHECK(Atom(1u).getType() == Atom::Type::Int); // unsigned (int) + CHECK(Atom(1ul).getType() == Atom::Type::Int); // unsigned long + CHECK(Atom(1lu).getType() == Atom::Type::Int); // unsigned long + CHECK(Atom(1ull).getType() == Atom::Type::Int); // unsigned long long + CHECK(Atom(1llu).getType() == Atom::Type::Int); // unsigned long long + } + */ SECTION("Floating-Point types") { @@ -207,18 +203,32 @@ TEST_CASE("Atom Constructors", "[Atom]") SECTION("Copy constructor") { Atom a_null; - Atom a_int(42); - Atom a_float(3.14); - Atom a_string("string"); - Atom a_null_copy = a_null; - CHECK(a_null_copy.getType() == Atom::Type::Null); + CHECK(a_null_copy.isNull()); + + Atom a_int(42); Atom a_int_copy = a_int; - CHECK(a_int_copy.getType() == Atom::Type::Int); + CHECK(a_int_copy.isInt()); + CHECK(a_int_copy.getInt() == a_int.getInt()); + + Atom a_float(3.14); Atom a_float_copy = a_float; - CHECK(a_float_copy.getType() == Atom::Type::Float); + CHECK(a_float_copy.isFloat()); + CHECK(a_float_copy.getFloat() == a_float.getFloat()); + + Atom a_string("string"); Atom a_string_copy = a_string; - CHECK(a_string_copy.getType()== Atom::Type::String); + CHECK(a_string_copy.isString()); + CHECK(a_string_copy.getString() == a_string.getString()); + + Atom a_comma = Atom::Comma(); + Atom a_comma_copy = a_comma; + CHECK(a_comma_copy.getType()== Atom::Type::Comma); + + Atom a_dollar = Atom::Dollar(1); + Atom a_dollar_copy = a_dollar; + CHECK(a_dollar_copy.isDollar()); + CHECK(a_dollar_copy.getDollarIndex() == a_dollar.getDollarIndex()); } SECTION("Copy assigment operator") @@ -281,6 +291,14 @@ TEST_CASE("Atom Constructors", "[Atom]") CHECK(moved.isString() == true); CHECK(moved.getString() == "string"); } + + SECTION("std::string move ctor") + { + std::string str_to_move("string"); + Atom moved(std::move(str_to_move)); + CHECK(moved.isString() == true); + CHECK(moved.getString() == "string"); + } } } @@ -333,6 +351,9 @@ TEST_CASE("Check Types", "[Atom]") CHECK(atom.isInt() == false); CHECK(atom.isFloat() == false); CHECK(atom.isString() == false); + CHECK(atom.isBang() == false); + CHECK(atom.isComma() == false); + CHECK(atom.isDollar() == false); } SECTION("Check Types (Int)") @@ -344,6 +365,9 @@ TEST_CASE("Check Types", "[Atom]") CHECK(atom.isInt() == true); CHECK(atom.isFloat() == false); CHECK(atom.isString() == false); + CHECK(atom.isBang() == false); + CHECK(atom.isComma() == false); + CHECK(atom.isDollar() == false); } SECTION("Check Types (Float)") @@ -355,6 +379,9 @@ TEST_CASE("Check Types", "[Atom]") CHECK(atom.isInt() == false); CHECK(atom.isFloat() == true); CHECK(atom.isString() == false); + CHECK(atom.isBang() == false); + CHECK(atom.isComma() == false); + CHECK(atom.isDollar() == false); } SECTION("Check Types (String)") @@ -366,6 +393,51 @@ TEST_CASE("Check Types", "[Atom]") CHECK(atom.isInt() == false); CHECK(atom.isFloat() == false); CHECK(atom.isString() == true); + CHECK(atom.isBang() == false); + CHECK(atom.isComma() == false); + CHECK(atom.isDollar() == false); + } + + SECTION("Check Types (String) - bang") + { + Atom atom("bang"); + CHECK(atom.getType() == Atom::Type::String); + CHECK(atom.isNull() == false); + CHECK(atom.isNumber() == false); + CHECK(atom.isInt() == false); + CHECK(atom.isFloat() == false); + CHECK(atom.isString() == true); + CHECK(atom.isBang() == true); + CHECK(atom.isComma() == false); + CHECK(atom.isDollar() == false); + } + + SECTION("Check Types (Comma)") + { + Atom atom = Atom::Comma(); + CHECK(atom.getType() == Atom::Type::Comma); + CHECK(atom.isNull() == false); + CHECK(atom.isNumber() == false); + CHECK(atom.isInt() == false); + CHECK(atom.isFloat() == false); + CHECK(atom.isString() == false); + CHECK(atom.isBang() == false); + CHECK(atom.isComma() == true); + CHECK(atom.isDollar() == false); + } + + SECTION("Check Types (Dollar)") + { + Atom atom = Atom::Dollar(1); + CHECK(atom.getType() == Atom::Type::Dollar); + CHECK(atom.isNull() == false); + CHECK(atom.isNumber() == false); + CHECK(atom.isInt() == false); + CHECK(atom.isFloat() == false); + CHECK(atom.isString() == false); + CHECK(atom.isBang() == false); + CHECK(atom.isComma() == false); + CHECK(atom.isDollar() == true); } } @@ -409,4 +481,322 @@ TEST_CASE("Value getters", "[Atom]") } } +// ------- +// Parser +// ------- +TEST_CASE("Atom Parse", "[Atom]") +{ + SECTION("basic atom parsing") + { + const auto atoms = AtomHelper::parse("foo \"bar 42\" 1 -2 3.14 -3.14"); + REQUIRE(atoms.size() == 6); + + CHECK(atoms[0].getString() == "foo"); + CHECK(atoms[1].getString() == "bar 42"); + + CHECK((atoms[2].isInt() && atoms[3].isInt())); + + CHECK(atoms[4].isFloat()); + CHECK(atoms[4].getFloat() == 3.14); + + CHECK(atoms[5].isFloat()); + CHECK(atoms[5].getFloat() == -3.14); + } + + SECTION("parse integer beginning with multiple zeros") + { + const auto atoms = AtomHelper::parse("000101"); + REQUIRE(atoms.size() == 1); + CHECK(atoms[0].isInt()); + CHECK(atoms[0].getInt() == 101); + } + + SECTION("parse float beginning with multiple zeros") + { + const auto atoms = AtomHelper::parse("000.101"); + REQUIRE(atoms.size() == 1); + CHECK(atoms[0].isFloat()); + CHECK(atoms[0].getFloat() == 0.101); + } + + SECTION("simple dot is a string") + { + const auto atoms = AtomHelper::parse("."); + REQUIRE(atoms.size() == 1); + CHECK(atoms[0].isString()); + } + + SECTION("dot following by digits is a Float") + { + const auto atoms = AtomHelper::parse(".001"); + REQUIRE(atoms.size() == 1); + CHECK(atoms[0].isFloat()); + } + + SECTION("float values are trimmed") + { + const auto atoms = AtomHelper::parse(".001000"); + REQUIRE(atoms.size() == 1); + CHECK(atoms[0].isFloat()); + CHECK(AtomHelper::toString(atoms[0]) == "0.001"); + } + + SECTION("negative sign following by a dot and digits is a Float") + { + const auto atoms = AtomHelper::parse("-.001"); + REQUIRE(atoms.size() == 1); + CHECK(atoms[0].isFloat()); + CHECK(atoms[0].getFloat() == -.001); + } + + SECTION("exponent is a Float") + { + const auto atoms = AtomHelper::parse("6.02e23"); + REQUIRE(atoms.size() == 1); + CHECK(atoms[0].isFloat()); + CHECK(atoms[0].getFloat() == 6.02e23); + } + + SECTION("digits with more than one dot is a String") + { + const auto atoms = AtomHelper::parse("0.001."); + REQUIRE(atoms.size() == 1); + CHECK(atoms[0].isString()); + } + + SECTION("skip whitespaces") + { + const auto atoms = AtomHelper::parse(" toto 44"); + CHECK(atoms.size() == 2); + CHECK(atoms[0].isString()); + CHECK(atoms[0].getString() == "toto"); + CHECK(atoms[1].isInt()); + CHECK(atoms[1].getInt() == 44); + } + + SECTION("skip special whitespace characters") + { + const auto text = "\f\n\r\t\v \f \n \r \t \v "; + const auto atoms = AtomHelper::parse(text); + REQUIRE(atoms.size() == 0); + } + + SECTION("preserve special whitespace characters in double-quoted text sequence") + { + const auto text = "\"\f\n\r\t\v \f \n \r \t \v \""; + const auto atoms = AtomHelper::parse(text); + REQUIRE(atoms.size() == 1); + CHECK(atoms[0].isString()); + CHECK(AtomHelper::toString(atoms) == text); + CHECK(AtomHelper::toString(atoms[0]) == text); + CHECK(atoms[0].getString() == "\f\n\r\t\v \f \n \r \t \v "); + } + + SECTION("strip slashes") + { + const auto text = R"(\0\a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z)"; + const auto text_result = "0abcdefghijklmnopqrstuvwxyz"; + const auto atoms = AtomHelper::parse(text); + REQUIRE(atoms.size() == 1); + CHECK(atoms[0].isString()); + CHECK(AtomHelper::toString(atoms) == text_result); + CHECK(AtomHelper::toString(atoms[0]) == text_result); + CHECK(atoms[0].getString() == text_result); + } + + SECTION("strip slashes double slash") + { + const auto text = R"(\\a\\b\\c\\d)"; + const auto normal_text = "\\\\a\\\\b\\\\c\\\\d"; + REQUIRE(text == normal_text); + + const auto atoms = AtomHelper::parse(text); + REQUIRE(atoms.size() == 1); + CHECK(atoms[0].isString()); + + /* + CHECK(AtomHelper::toString(atoms) == text_result); + CHECK(AtomHelper::toString(atoms[0]) == text_result); + CHECK(atoms[0].getString() == text_result); + */ + } + + SECTION("foo \"bar 42\" 1 -2 3.14") + { + const auto atoms = AtomHelper::parse("foo \"bar 42\" 1 -2 3.14"); + REQUIRE(atoms.size() == 5); + CHECK(atoms[0].getString() == "foo"); + CHECK(atoms[1].getString() == "bar 42"); + CHECK((atoms[2].isInt() && atoms[3].isInt())); + CHECK(atoms[4].isFloat()); + } + + SECTION("test escaping") + { + const auto original_text = R"(foo "bar 42" 1 -2 3.14)"; + const auto atoms = AtomHelper::parse(original_text); + const auto text = AtomHelper::toString(atoms); + CHECK(text == original_text); + } +} + +TEST_CASE("Atom Parse Quoted", "[Atom]") +{ + SECTION("basic") + { + const auto atoms = AtomHelper::parse("\"0 10\""); + REQUIRE(atoms.size() == 1); + CHECK(atoms[0].isString()); + CHECK(atoms[0].getString() == "0 10"); + } + + SECTION("with comma") + { + const auto atoms = AtomHelper::parse(R"("0, 10")"); + REQUIRE(atoms.size() == 1); + CHECK(atoms[0].isString()); + CHECK(atoms[0].getString() == "0, 10"); + } + + SECTION("with escaped quote") + { + const auto typed_text = R"("name: \"toto\"")"; + const auto formated_text = R"("name: \"toto\"")"; + const auto display_text = R"(name: "toto")"; + + const auto atoms = AtomHelper::parse(typed_text); + REQUIRE(atoms.size() == 1); + REQUIRE(atoms[0].isString()); + + CHECK(atoms[0].getString() == display_text); + CHECK(AtomHelper::toString(atoms[0]) == formated_text); + CHECK(AtomHelper::toString(atoms[0], false) == display_text); + } +} + +TEST_CASE("Atom Parse Comma", "[Atom]") +{ + SECTION("parse \"0, 10\" without comma option") + { + const auto atoms = AtomHelper::parse("0, 10"); + REQUIRE(atoms.size() == 2); + CHECK(atoms[0].isString()); + CHECK(atoms[0].getString() == "0,"); + CHECK(atoms[1].isInt()); + } + + SECTION("parse \"0, 10\" without flag then toString") + { + const auto typed_text = R"(0, 10)"; + const auto text_to_display = R"(0, 10)"; + const auto atoms = AtomHelper::parse(typed_text); + REQUIRE(atoms.size() == 2); + CHECK(atoms[0].getString() == "0,"); + CHECK(AtomHelper::toString(atoms[0]) == "0,"); + const auto formated_text = AtomHelper::toString(atoms); + CHECK(text_to_display == formated_text); + } + + SECTION("parse with comma flag") + { + const auto atoms = AtomHelper::parse("0, 10", AtomHelper::ParsingFlags::Comma); + REQUIRE(atoms.size() == 3); + CHECK(atoms[0].isInt()); + CHECK(atoms[1].isComma()); + CHECK(atoms[2].isInt()); + } + + SECTION("parse \"0, 10\" with comma flag then toString") + { + const auto original_text = "0, 10"; + const auto atoms = AtomHelper::parse(original_text, AtomHelper::ParsingFlags::Comma); + REQUIRE(atoms.size() == 3); + const auto text = AtomHelper::toString(atoms); + CHECK(text == original_text); + } + + SECTION("parse comma without space after it") + { + const auto original_text = "0,10"; + const auto atoms = AtomHelper::parse(original_text, AtomHelper::ParsingFlags::Comma); + REQUIRE(atoms.size() == 3); + CHECK(atoms[0].isInt()); + CHECK(atoms[1].isComma()); + CHECK(atoms[2].isInt()); + const auto text = AtomHelper::toString(atoms); + CHECK(text == "0, 10"); + } + + SECTION("parse several commas") + { + const auto original_text = ",,,"; + const auto atoms = AtomHelper::parse(original_text, AtomHelper::ParsingFlags::Comma); + REQUIRE(atoms.size() == 3); + CHECK(atoms[0].isComma()); + CHECK(atoms[1].isComma()); + CHECK(atoms[2].isComma()); + const auto text = AtomHelper::toString(atoms); + CHECK(text == ",,,"); + } +} + +TEST_CASE("Atom Parse Dollar", "[Atom]") +{ + const int flags = AtomHelper::ParsingFlags::Dollar; + + SECTION("parse without dollar flags") + { + const auto atoms = AtomHelper::parse("$1 $2 $3 $4 $5 $6 $7 $8 $9"); + REQUIRE(atoms.size() == 9); + for (auto const& atom : atoms) + { + CHECK(atom.isString()); + } + } + + SECTION("invalid dollar atoms") + { + const auto atoms = AtomHelper::parse("$0 a$1 $10 $-1 $ $$", AtomHelper::ParsingFlags::Dollar); + REQUIRE(atoms.size() == 6); + for (auto const& atom : atoms) + { + CHECK(atom.isString()); + CHECK(atom.getDollarIndex() == 0); + } + } + + SECTION("valid dollar atoms") + { + const auto atoms = AtomHelper::parse("$1 $2 $3 $4 $5 $6 $7 $8 $9", AtomHelper::ParsingFlags::Dollar); + REQUIRE(atoms.size() == 9); + for (auto const& atom : atoms) + { + REQUIRE(atom.isDollar()); + + static auto count = 0; + CHECK(++count == atom.getDollarIndex()); + } + } + + SECTION("dollar followed by comma") + { + const auto atoms = AtomHelper::parse("$1, $2", + AtomHelper::ParsingFlags::Dollar + | AtomHelper::ParsingFlags::Comma); + REQUIRE(atoms.size() == 3); + CHECK(atoms[0].isDollar()); + CHECK(atoms[1].isComma()); + CHECK(atoms[2].isDollar()); + } + + SECTION("dollar followed by comma without Comma flag") + { + const auto atoms = AtomHelper::parse("$1, $2", + AtomHelper::ParsingFlags::Dollar); + REQUIRE(atoms.size() == 2); + CHECK(atoms[0].isString()); + CHECK(atoms[0].getString() == "$1,"); + CHECK(atoms[1].isDollar()); + } +} From 8edc39b344821ac3522bbd206a318a9c5c3db518 Mon Sep 17 00:00:00 2001 From: eliott PARIS Date: Mon, 29 Jan 2018 14:32:39 +0100 Subject: [PATCH 133/148] [message] - Add Comma and Dollar syntax support --- .../KiwiApp_Objects/KiwiApp_MessageView.cpp | 23 ++-- .../KiwiEngine_Objects/KiwiEngine_Message.cpp | 105 ++++++++++++++++-- .../KiwiEngine_Objects/KiwiEngine_Message.h | 22 +++- 3 files changed, 132 insertions(+), 18 deletions(-) diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_MessageView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_MessageView.cpp index ce5ab011..66f757d6 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_MessageView.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_MessageView.cpp @@ -128,16 +128,23 @@ namespace kiwi { void MessageView::textChanged() { - juce::Label & label = getLabel(); - - const int text_width = label.getFont().getStringWidth(label.getText()); - - model::Object & model = getModel(); - - model.setWidth(text_width + 16); + juce::Label& label = getLabel(); + + // Parse text and convert it back to string to display the formated version. + const auto atoms = tool::AtomHelper::parse(label.getText().toStdString(), + tool::AtomHelper::ParsingFlags::Comma + | tool::AtomHelper::ParsingFlags::Dollar); + + auto formatted_text = tool::AtomHelper::toString(atoms); + const int text_width = label.getFont().getStringWidth(formatted_text); + model::Object & model = getModel(); + model.setWidth(text_width + 16); + + // set the attribute and label text with formated text + getLabel().setText(formatted_text, juce::NotificationType::dontSendNotification); setAttribute("text", tool::Parameter(tool::Parameter::Type::String, - {label.getText().toStdString()})); + {std::move(formatted_text)})); } juce::TextEditor* MessageView::createdTextEditor() diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message.cpp index 5e1c9158..5462025a 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message.cpp @@ -40,12 +40,12 @@ namespace kiwi { namespace engine { return std::make_unique(model, patcher); } - Message::Message(model::Object const& object_model, Patcher& patcher): - Object(object_model, patcher), - m_text(object_model.getAttribute("text")[0].getString()), - m_connection(object_model.getSignal<>(model::Message::Signal::outputMessage) - .connect(std::bind(&Message::outputMessage, this))) + Message::Message(model::Object const& object_model, Patcher& patcher) + : Object(object_model, patcher) + , m_connection(object_model.getSignal<>(model::Message::Signal::outputMessage) + .connect(std::bind(&Message::outputMessage, this))) { + attributeChanged("text", object_model.getAttribute("text")); } @@ -57,7 +57,7 @@ namespace kiwi { namespace engine { { defer([this]() { - send(0, tool::AtomHelper::parse(m_text)); + sendMessages(); }); } @@ -65,7 +65,13 @@ namespace kiwi { namespace engine { { if (name == "text") { - m_text = parameter[0].getString(); + tool::Atom null; + for(auto& input_args : m_input_args) + { + input_args = null; + } + + prepareMessagesForText(parameter[0].getString()); } } @@ -73,7 +79,90 @@ namespace kiwi { namespace engine { { if (index == 0 && !args.empty()) { - send(0, tool::AtomHelper::parse(m_text));; + if(!args[0].isBang()) + { + for(size_t i = 0; i <= 9; i++) + { + if(i < args.size()) + { + m_input_args[i] = args[i]; + } + } + } + + sendMessages(); + } + } + + void Message::prepareMessagesForText(std::string const& text) + { + static const int flags = (0 + | tool::AtomHelper::ParsingFlags::Comma + | tool::AtomHelper::ParsingFlags::Dollar); + + auto atoms = tool::AtomHelper::parse(text, flags); + + m_messages.clear(); + if(!atoms.empty()) + { + std::vector atom_sequence; + bool dollar_flag = false; + + for(auto&& atom : atoms) + { + if(atom.isComma()) + { + if(!atom_sequence.empty()) + { + m_messages.emplace_back(std::move(atom_sequence), + dollar_flag); + atom_sequence.clear(); + dollar_flag = false; + } + } + else + { + if(atom.isDollar()) + { + dollar_flag = true; + } + + atom_sequence.emplace_back(std::move(atom)); + } + } + + if(!atom_sequence.empty()) + { + m_messages.emplace_back(std::move(atom_sequence), + dollar_flag); + } + } + } + + void Message::sendMessages() + { + for(auto const& message : m_messages) + { + if(message.has_dollar) + { + std::vector atoms = message.atoms; + + for(auto& atom : atoms) + { + if(atom.isDollar()) + { + const size_t index = atom.getDollarIndex() - 1; + auto& atom_arg = m_input_args[index]; + atom = !atom_arg.isNull() ? atom_arg : 0; + } + } + + send(0, atoms); + } + else + { + send(0, message.atoms); + } } } diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message.h b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message.h index 41da4fdf..380ac6d4 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message.h +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Message.h @@ -23,6 +23,8 @@ #include +#include + namespace kiwi { namespace engine { // ================================================================================ // @@ -48,10 +50,26 @@ namespace kiwi { namespace engine { static std::unique_ptr create(model::Object const& model, Patcher& patcher); private: // members + + void sendMessages(); + void prepareMessagesForText(std::string const& text); - std::string m_text; - flip::SignalConnection m_connection; + flip::SignalConnection m_connection; + std::array m_input_args {}; + + struct Sequence + { + Sequence(std::vector&& _atoms, bool _has_dollar) + : atoms(_atoms), has_dollar(_has_dollar) + {} + + ~Sequence() = default; + + const std::vector atoms {}; + const bool has_dollar = false; + }; + std::vector m_messages {}; }; }} From 91259b55ea0e67f7176a6a33163e6707a3e4f2da Mon Sep 17 00:00:00 2001 From: eliott PARIS Date: Mon, 29 Jan 2018 14:55:59 +0100 Subject: [PATCH 134/148] Update several objects' code --- .../KiwiApp_Objects/KiwiApp_ObjectView.cpp | 2 - .../KiwiEngine_Objects/KiwiEngine_Delay.cpp | 2 +- .../KiwiEngine_Objects/KiwiEngine_Hub.cpp | 6 ++- .../KiwiEngine_Loadmess.cpp | 2 +- .../KiwiEngine_Objects/KiwiEngine_Number.cpp | 2 +- .../KiwiEngine_Operator.cpp | 2 +- .../KiwiEngine_Objects/KiwiEngine_Pack.cpp | 10 ++-- .../KiwiEngine_Objects/KiwiEngine_Print.cpp | 3 +- .../KiwiEngine_Objects/KiwiEngine_Random.cpp | 2 +- .../KiwiEngine_Objects/KiwiEngine_Scale.cpp | 2 +- .../KiwiEngine_Objects/KiwiEngine_Slider.cpp | 2 +- .../KiwiEngine_SnapshotTilde.cpp | 2 +- .../KiwiEngine_Objects/KiwiEngine_Toggle.cpp | 2 +- .../KiwiEngine_Objects/KiwiEngine_Trigger.cpp | 50 ------------------- .../KiwiEngine_Objects/KiwiEngine_Unpack.cpp | 9 ++-- .../KiwiModel_Objects/KiwiModel_Pack.cpp | 36 ++++--------- .../KiwiModel_Objects/KiwiModel_Unpack.cpp | 32 +++--------- 17 files changed, 40 insertions(+), 126 deletions(-) diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectView.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectView.cpp index 7bb3b490..306a26dd 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectView.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_Objects/KiwiApp_ObjectView.cpp @@ -102,8 +102,6 @@ namespace kiwi void ObjectView::drawOutline(juce::Graphics & g) { - juce::Rectangle outline = getOutline(); - g.drawRect(getOutline(), m_border_size); } diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Delay.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Delay.cpp index 90dbed2a..5796680c 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Delay.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Delay.cpp @@ -69,7 +69,7 @@ namespace kiwi { if (index == 0) { - if(args[0].isString() && args[0].getString() == "bang") + if(args[0].isBang()) { getScheduler().schedule(m_task, m_delay); } diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Hub.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Hub.cpp index b3831aac..2f987b86 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Hub.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Hub.cpp @@ -54,7 +54,7 @@ namespace kiwi { namespace engine { { if (name == "message") { - send(0,{tool::AtomHelper::parse(parameter[0].getString())}); + send(0, tool::AtomHelper::parse(parameter[0].getString())); } } @@ -62,7 +62,9 @@ namespace kiwi { namespace engine { { if (index == 0 && !args.empty()) { - setAttribute("message", tool::Parameter(tool::Parameter::Type::String, {tool::AtomHelper::toString(args)})); + setAttribute("message", + tool::Parameter(tool::Parameter::Type::String, + {tool::AtomHelper::toString(args)})); } } diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Loadmess.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Loadmess.cpp index ddd1db89..d9fcb478 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Loadmess.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Loadmess.cpp @@ -46,7 +46,7 @@ namespace kiwi { namespace engine { void Loadmess::receive(size_t index, std::vector const& args) { - if (!args.empty() && args[0].isString() && args[0].getString() == "bang") + if (!args.empty() && args[0].isBang()) { send(0ul, m_args); } diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Number.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Number.cpp index e23738f0..2e1eb28a 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Number.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Number.cpp @@ -76,7 +76,7 @@ namespace kiwi { namespace engine { } else if (args[0].isString()) { - if (args[0].getString() == "bang") + if (args[0].isBang()) { outputValue(); } diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Operator.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Operator.cpp index d62e7b9b..f42d8a35 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Operator.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Operator.cpp @@ -54,7 +54,7 @@ namespace kiwi { namespace engine { m_lhs = args[0].getFloat(); bang(); } - else if(args[0].getString() == "bang") + else if(args[0].isBang()) { bang(); } diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Pack.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Pack.cpp index 34851de6..c33f333e 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Pack.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Pack.cpp @@ -51,7 +51,8 @@ namespace kiwi { namespace engine { void Pack::receive(size_t index, std::vector const& args) { - if (args[0].getString() != "bang") + const bool is_bang = args[0].isBang(); + if (!is_bang) { switch (m_list[index].getType()) { @@ -70,14 +71,11 @@ namespace kiwi { namespace engine { m_list[index] = args[0].getString(); break; } - case tool::Atom::Type::Null: - { - break; - } + default: break; } } - if (index == 0 && args[0].isString() && args[0].getString() == "bang") + if (index == 0 && is_bang) { output_list(); } diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Print.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Print.cpp index b5183fa9..2475076b 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Print.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Print.cpp @@ -71,7 +71,8 @@ namespace kiwi { namespace engine { { if(!args.empty()) { - post(m_name + " \xe2\x80\xa2 " + tool::AtomHelper::toString(args)); + // do not include quotes in printed atoms + post(m_name + " \xe2\x80\xa2 " + tool::AtomHelper::toString(args, false)); } } diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Random.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Random.cpp index 00be1729..4e143b0f 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Random.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Random.cpp @@ -65,7 +65,7 @@ namespace kiwi { namespace engine { { if (index == 0) { - if (args[0].isString() && args[0].getString() == "bang") + if (args[0].isBang()) { send(0, {m_random_distribution(m_random_generator)}); } diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Scale.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Scale.cpp index bfb00a55..4a5aab88 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Scale.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Scale.cpp @@ -73,7 +73,7 @@ namespace kiwi { namespace engine { m_value = args[0].getFloat(); send(0, {scaleValue()}); } - else if (args[0].isString() && args[0].getString() == "bang") + else if (args[0].isBang()) { send(0, {scaleValue()}); } diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Slider.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Slider.cpp index a4f207a3..d2839a22 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Slider.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Slider.cpp @@ -88,7 +88,7 @@ namespace kiwi { namespace engine { setParameter("value", tool::Parameter(tool::Parameter::Type::Float, {args[1].getFloat()})); } } - else if (args[0].isString() && args[0].getString() == "bang") + else if (args[0].isBang()) { send(0, {m_value}); } diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_SnapshotTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_SnapshotTilde.cpp index 774f4f9f..d380e68e 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_SnapshotTilde.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_SnapshotTilde.cpp @@ -48,7 +48,7 @@ namespace kiwi { namespace engine { { if (index == 0 && !args.empty()) { - if(args[0].getString() == "bang") + if(args[0].isBang()) { send(0, {m_value.load()}); } diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Toggle.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Toggle.cpp index 1087ce96..cfc3cc0e 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Toggle.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Toggle.cpp @@ -76,7 +76,7 @@ namespace kiwi { namespace engine { { if(args[0].isString()) { - if (args[0].getString() == "bang") + if (args[0].isBang()) { send(0, {!m_is_on}); setParameter("value", tool::Parameter(tool::Parameter::Type::Int, {!m_is_on})); diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Trigger.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Trigger.cpp index 89e37ca6..e5201a80 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Trigger.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Trigger.cpp @@ -103,56 +103,6 @@ namespace kiwi { namespace engine { } return triggers; - - /* - trigger_fn_t test = trigger_fn_factory(atom); - - triggers.emplace_back([atom](std::vector const& args) { - - if(atom.isNumber()) - { - const auto value = atom.isInt() ? atom.getInt() : atom.getFloat(); - return std::vector{{value}}; - } - - const auto str = atom.getString(); - - if(str.empty()) - { - return std::vector(); - } - - if(str == "b" || str == "bang") - { - return std::vector{{"bang"}}; - } - - if(str == "i" || str == "int") - { - return std::vector{{args[0].getInt()}}; - } - - if(str == "f" || str == "float") - { - return std::vector{{args[0].getFloat()}}; - } - - if(str == "s" || str == "symbol") - { - return args; - } - - if(str == "l" || str == "list") - { - return args; - } - - return std::vector{{str}}; - - }); - - } - */ } void Trigger::receive(size_t, std::vector const& args) diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Unpack.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Unpack.cpp index a2ea8e1a..48238811 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Unpack.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_Unpack.cpp @@ -54,7 +54,7 @@ namespace kiwi { namespace engine { void Unpack::receive(size_t index, std::vector const& args) { - if (args[0].getString() == "bang") + if (args[0].isBang()) { output_list(); } @@ -62,7 +62,7 @@ namespace kiwi { namespace engine { { for (int i = std::max(m_list.size() - 1, args.size() - 1); i >= 0; --i) { - if (args[i].getString() != "bang") + if (!args[i].isBang()) { switch (m_list[i].getType()) { @@ -87,10 +87,7 @@ namespace kiwi { namespace engine { } break; } - case tool::Atom::Type::Null: - { - break; - } + default: break; } } else if (i > 0) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Pack.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Pack.cpp index 385bc163..ee10b9fa 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Pack.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Pack.cpp @@ -62,35 +62,19 @@ namespace kiwi { namespace model { } else if (is_inlet) { - std::vector const& args = getArguments(); + auto const& args = getArguments(); - std::string type = ""; - - switch (args[index].getType()) - { - case tool::Atom::Type::Float: - { - type = "float"; - break; - } - case tool::Atom::Type::Int: - { - type = "int"; - break; - } - case tool::Atom::Type::String: + const std::string type_str = [atom = args[index]]() { + switch(atom.getType()) { - type = "symbol"; - break; + case tool::Atom::Type::Int: return "int"; + case tool::Atom::Type::Float: return "float"; + case tool::Atom::Type::String: return "symbol"; + default: return "null"; } - case tool::Atom::Type::Null: - { - type = "void"; - break; - } - } - - return type + "to be element" + std::to_string(index + 1) + " int list"; + }(); + + return type_str + " atom " + std::to_string(index + 1) + " in list"; } return {}; diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Unpack.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Unpack.cpp index 5c89789a..e82cebe0 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Unpack.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Unpack.cpp @@ -64,33 +64,17 @@ namespace kiwi { namespace model { { std::vector const& args = getArguments(); - std::string type = ""; - - switch (args[index].getType()) - { - case tool::Atom::Type::Float: - { - type = "float"; - break; - } - case tool::Atom::Type::Int: - { - type = "int"; - break; - } - case tool::Atom::Type::String: - { - type = "symbol"; - break; - } - case tool::Atom::Type::Null: + const std::string type_str = [atom = args[index]]() { + switch(atom.getType()) { - type = "void"; - break; + case tool::Atom::Type::Int: return "int"; + case tool::Atom::Type::Float: return "float"; + case tool::Atom::Type::String: return "symbol"; + default: return "null"; } - } + }(); - return "element " + std::to_string(index + 1) + " in list of type " + type; + return "element " + std::to_string(index + 1) + " in list (" + type_str + ")"; } From beed94591e502e6cb7e9122eaa8c4755ca8be621 Mon Sep 17 00:00:00 2001 From: jean-millot Date: Mon, 29 Jan 2018 17:45:37 +0100 Subject: [PATCH 135/148] Fixup object receive and operators. --- Modules/KiwiModel/KiwiModel_Objects/KiwiModel_OperatorTilde.cpp | 2 +- Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Receive.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_OperatorTilde.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_OperatorTilde.cpp index a8b5ddea..602f7dc2 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_OperatorTilde.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_OperatorTilde.cpp @@ -44,7 +44,7 @@ namespace kiwi { namespace model { throw Error("operator~ too many arguments"); } - if (args.size() == 1 && args[0].isNumber()) + if (args.size() == 1 && !args[0].isNumber()) { throw Error("operator~ argument must be a number"); } diff --git a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Receive.cpp b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Receive.cpp index fd86428d..bf28c141 100755 --- a/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Receive.cpp +++ b/Modules/KiwiModel/KiwiModel_Objects/KiwiModel_Receive.cpp @@ -64,7 +64,7 @@ namespace kiwi { namespace model { throw Error("receive requires only one argument"); } - if (args.size() == 1 && args[0].isString()) + if (args.size() == 1 && !args[0].isString()) { throw Error("receive argument must be a symbol"); } From 164c889d7d2ea74355498f74abafc0aed091d8ec Mon Sep 17 00:00:00 2001 From: jean-millot Date: Mon, 29 Jan 2018 17:55:15 +0100 Subject: [PATCH 136/148] Opening document uploaded by someone else. --- .../KiwiApp_Patcher/KiwiApp_PatcherManager.cpp | 11 +++++++---- Modules/KiwiModel/KiwiModel_Patcher.cpp | 12 ++++++++++++ Modules/KiwiModel/KiwiModel_Patcher.h | 5 ++++- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.cpp index f389270b..33997d92 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.cpp @@ -617,11 +617,14 @@ namespace kiwi void PatcherManager::updateTitleBars() { - flip::Collection & views = getPatcher().useSelfUser().getViews(); - - for(auto & view : views) + if (getPatcher().hasSelfUser()) { - updateTitleBar(view); + flip::Collection & views = getPatcher().useSelfUser().getViews(); + + for(auto & view : views) + { + updateTitleBar(view); + } } } diff --git a/Modules/KiwiModel/KiwiModel_Patcher.cpp b/Modules/KiwiModel/KiwiModel_Patcher.cpp index 017e6b8d..a79ac74b 100755 --- a/Modules/KiwiModel/KiwiModel_Patcher.cpp +++ b/Modules/KiwiModel/KiwiModel_Patcher.cpp @@ -264,6 +264,18 @@ namespace kiwi Patcher::Users& Patcher::getUsers() noexcept { return m_users; + } + + bool Patcher::hasSelfUser() const + { + auto it = std::find_if(m_users.begin(), m_users.end(), + [self_id = document().user()](User const& user) + { + return (user.getId() == self_id); + + }); + + return it != m_users.end(); } Patcher::User& Patcher::useSelfUser() diff --git a/Modules/KiwiModel/KiwiModel_Patcher.h b/Modules/KiwiModel/KiwiModel_Patcher.h index f7ef3ded..c595eaeb 100755 --- a/Modules/KiwiModel/KiwiModel_Patcher.h +++ b/Modules/KiwiModel/KiwiModel_Patcher.h @@ -109,7 +109,10 @@ namespace kiwi Users const& getUsers() const noexcept; //! @brief Gets the users. - Users& getUsers() noexcept; + Users& getUsers() noexcept; + + //! @brief Returns true if current user is already in added to the document. + bool hasSelfUser() const; //! @brief Returns the current User. //! @details The function will look for a User that match From 9014b6558dae25817055912d4c5e15703bd67a6d Mon Sep 17 00:00:00 2001 From: jean-millot Date: Mon, 29 Jan 2018 18:18:58 +0100 Subject: [PATCH 137/148] Display own user name when opening patcher. --- .../KiwiApp_PatcherComponent.cpp | 57 +++++++++++-------- .../KiwiApp_PatcherComponent.h | 5 +- 2 files changed, 38 insertions(+), 24 deletions(-) diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherComponent.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherComponent.cpp index 5208e4a0..b743e1d4 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherComponent.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherComponent.cpp @@ -166,6 +166,7 @@ namespace kiwi binary_data::images::users_png_size)) , m_flash_alpha(0.f) { + updateUsers(); m_patcher_manager.addListener(*this); } @@ -174,36 +175,46 @@ namespace kiwi m_patcher_manager.removeListener(*this); } - void PatcherToolbar::UsersItemComponent::connectedUserChanged(PatcherManager& manager) + void PatcherToolbar::UsersItemComponent::updateUsers() { - if(&manager == &m_patcher_manager) + m_user_nb = m_patcher_manager.getNumberOfUsers(); + + startFlashing(); + + auto success = [this](Api::Users users) { - m_user_nb = manager.getNumberOfUsers(); - - startFlashing(); - - auto success = [this](Api::Users users) + KiwiApp::useInstance().useScheduler().schedule([this, users]() { - KiwiApp::useInstance().useScheduler().schedule([this, users]() + m_users.clear(); + + for(Api::User const& user : users) { - m_users.clear(); + m_users.push_back(user.getName()); - for(Api::User const& user : users) - { - m_users.push_back(user.getName()); - } - }); - }; - - auto fail = [this](Api::Error error) + } + + }); + }; + + auto fail = [this](Api::Error error) + { + KiwiApp::useInstance().useScheduler().schedule([this, error]() { - KiwiApp::useInstance().useScheduler().schedule([this, error]() - { - m_users.clear(); - }); - }; + m_users.clear(); + + }); + }; + + KiwiApp::useApi().getUsers(m_patcher_manager.getConnectedUsers(), success, fail); + } + + void PatcherToolbar::UsersItemComponent::connectedUserChanged(PatcherManager& manager) + { + if(&manager == &m_patcher_manager) + { + updateUsers(); - KiwiApp::useApi().getUsers(m_patcher_manager.getConnectedUsers(), success, fail); + startFlashing(); } } diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherComponent.h b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherComponent.h index c2bc7f83..bdf5e11d 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherComponent.h +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherComponent.h @@ -100,7 +100,10 @@ namespace kiwi ~UsersItemComponent(); //! @brief Called when one or more users are connecting or disconnecting to the Patcher Document. - void connectedUserChanged(PatcherManager& manager) override; + void connectedUserChanged(PatcherManager& manager) override; + + //! @brief Call to update the number of users displayed and user names. + void updateUsers(); //! @brief Provides prefered size for this item. bool getToolbarItemSizes(int toolbarDepth, bool isVertical, From 43c2446abd65cbddb0546b72c6b04139cde76df8 Mon Sep 17 00:00:00 2001 From: jean-millot Date: Mon, 29 Jan 2018 18:30:12 +0100 Subject: [PATCH 138/148] Audio setings resizables for windows. --- Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp b/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp index d241af5e..ece653bb 100644 --- a/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp +++ b/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp @@ -465,13 +465,13 @@ namespace kiwi auto device_selector = std::make_unique(manager, 1, 20, 1, 20, - false, false, false, true); + false, false, false, false); device_selector->setSize(300, 300); return std::make_unique("Audio Settings", std::move(device_selector), - false, false, "audio_settings_window"); + true, false, "audio_settings_window"); }); } From bd32277cbdb8f0e511b825a31577239c0e741f77 Mon Sep 17 00:00:00 2001 From: jean-millot Date: Mon, 29 Jan 2018 18:54:47 +0100 Subject: [PATCH 139/148] Stackoverflow. --- Modules/KiwiEngine/KiwiEngine_Object.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Modules/KiwiEngine/KiwiEngine_Object.cpp b/Modules/KiwiEngine/KiwiEngine_Object.cpp index 74da9d62..b0ad9799 100644 --- a/Modules/KiwiEngine/KiwiEngine_Object.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Object.cpp @@ -261,7 +261,7 @@ namespace kiwi return m_patcher.getBeacon(name); } -#define KIWI_ENGINE_STACKOVERFLOW_MAX 256 +#define KIWI_ENGINE_STACKOVERFLOW_MAX 128 void Object::send(const size_t index, std::vector const& args) { @@ -286,6 +286,7 @@ namespace kiwi else { m_patcher.endStackOverflow(); + error("message loop detected"); } --(receiver.m_stack_count); } From 863ef917d68e7433105583184f410253775a9203 Mon Sep 17 00:00:00 2001 From: jean-millot Date: Mon, 29 Jan 2018 20:04:27 +0100 Subject: [PATCH 140/148] Logger on flip server. --- Modules/KiwiServer/KiwiServer_Server.cpp | 84 ++++++++++++++++++------ Modules/KiwiServer/KiwiServer_Server.h | 27 +++++++- 2 files changed, 90 insertions(+), 21 deletions(-) diff --git a/Modules/KiwiServer/KiwiServer_Server.cpp b/Modules/KiwiServer/KiwiServer_Server.cpp index 434f87ef..4f1006d4 100644 --- a/Modules/KiwiServer/KiwiServer_Server.cpp +++ b/Modules/KiwiServer/KiwiServer_Server.cpp @@ -62,7 +62,11 @@ namespace kiwi m_kiwi_version(kiwi_version), m_sessions(), m_socket(*this, port), - m_ports() + m_ports(), + m_logger(m_backend_directory.getChildFile("log.txt"), + "server port: " + std::to_string(port) + + " server model version: " + KIWI_MODEL_VERSION_STRING + + " server kiwi version: " + m_kiwi_version) { if (m_backend_directory.exists() && !m_backend_directory.isDirectory()) { @@ -144,19 +148,20 @@ namespace kiwi { juce::File session_file = getSessionFile(port.session()); - DBG("[server] - creating new session for session_id : " << hexadecimal_convert(session_id)); + m_logger.log("[server] - creating new session for session_id : " + hexadecimal_convert(session_id)); auto session = m_sessions .insert(std::make_pair(session_id, - Session(session_id, session_file, m_open_token, m_kiwi_version))); + Session(session_id, session_file, m_open_token, m_kiwi_version, m_logger))); if (session_file.exists()) { - DBG("[server] - loading session file for session_id : " << hexadecimal_convert(session_id)); + m_logger.log("[server] - loading session file for session_id : " + hexadecimal_convert(session_id)); if (!(*session.first).second.load()) { - DBG("[server] - opening document document session : " << hexadecimal_convert(session_id) << " failed"); + m_logger.log("[server] - opening document document session : " + + hexadecimal_convert(session_id) + " failed"); m_sessions.erase(session_id); @@ -232,6 +237,30 @@ namespace kiwi flip_FATAL; } + // ================================================================================ // + // SERVER LOGGER // + // ================================================================================ // + + Server::Logger::Logger(juce::File const& file, juce::String const& welcome): + m_limit(10 * 1000 * 1000), // 10 Mo + m_jlogger(file, welcome, m_limit) + { + } + + Server::Logger::~Logger() + { + } + + void Server::Logger::log(juce::String const& message) + { + if (m_jlogger.getLogFile().getSize() > m_limit) + { + juce::FileLogger::trimFileSize(m_jlogger.getLogFile(), m_limit); + } + + m_jlogger.logMessage(message); + } + // ================================================================================ // // SERVER SESSION // // ================================================================================ // @@ -244,6 +273,7 @@ namespace kiwi , m_backend_file(std::move(other.m_backend_file)) , m_token(other.m_token) , m_kiwi_version(other.m_kiwi_version) + , m_logger(other.m_logger) { ; } @@ -251,7 +281,8 @@ namespace kiwi Server::Session::Session(uint64_t identifier, juce::File const& backend_file, std::string const& token, - std::string const& kiwi_version) + std::string const& kiwi_version, + Server::Logger & logger) : m_identifier(identifier) , m_validator(new model::PatcherValidator()) , m_document(new flip::DocumentServer(model::DataModel::use(), *m_validator, m_identifier)) @@ -259,6 +290,7 @@ namespace kiwi , m_backend_file(backend_file) , m_token(token) , m_kiwi_version(kiwi_version) + , m_logger(logger) { model::Patcher& patcher = m_document->root(); @@ -285,13 +317,22 @@ namespace kiwi return m_identifier; } - void Server::Session::save() const - { + bool Server::Session::save() const + { flip::BackEndIR backend(m_document->write()); flip::DataConsumerFile consumer(m_backend_file.getFullPathName().toStdString().c_str()); - backend.write(consumer); + try + { + backend.write(consumer); + } + catch(...) + { + return false; + } + + return true; } bool Server::Session::load() @@ -339,10 +380,8 @@ namespace kiwi void Server::Session::bind(flip::PortBase & port) { - DBG("[server] - User: " - << std::to_string(port.user()) - << " connecting to session : " - << hexadecimal_convert(m_identifier)); + m_logger.log("[server] - User: " + std::to_string(port.user()) + + " connecting to session : " + hexadecimal_convert(m_identifier)); if (authenticateUser(port.user(), port.metadata())) { @@ -387,14 +426,18 @@ namespace kiwi } else { + m_logger.log("[server] - User: " + std::to_string(port.user()) + + " failed to authenticate : " + + "metadata : " + port.metadata()); + throw std::runtime_error("authentication failed"); } } void Server::Session::unbind(flip::PortBase & port) { - DBG("[server] - User " << std::to_string(port.user()) - << " disconnecting from session: " << hexadecimal_convert(m_identifier)); + m_logger.log("[server] - User " + std::to_string(port.user()) + + " disconnecting from session" + hexadecimal_convert(m_identifier)); std::set ports = m_document->ports(); @@ -417,11 +460,14 @@ namespace kiwi m_backend_file.create(); } - DBG("[server] - Saving session : " << hexadecimal_convert(m_identifier) - << " in file : " - << m_backend_file.getFileName()); + m_logger.log("[server] - Saving session : " + hexadecimal_convert(m_identifier) + + " in file : " + m_backend_file.getFileName()); - save(); + if (!save()) + { + m_logger.log("[server] - saving session to " + + m_backend_file.getFileName() + " failed"); + } } } } diff --git a/Modules/KiwiServer/KiwiServer_Server.h b/Modules/KiwiServer/KiwiServer_Server.h index d04dfd30..e1dab500 100644 --- a/Modules/KiwiServer/KiwiServer_Server.h +++ b/Modules/KiwiServer/KiwiServer_Server.h @@ -53,6 +53,25 @@ namespace kiwi class Session; + class Logger final + { + public: // methods + + //! @brief Constructor + Logger(juce::File const& file, juce::String const& welcome_message); + + //! @brief Destructor. + ~Logger(); + + //! @brief Logs a message + void log(juce::String const& message); + + private: // members + + uint64_t m_limit; + juce::FileLogger m_jlogger; + }; + public: // methods //! @brief Constructor. @@ -119,6 +138,7 @@ namespace kiwi std::map m_sessions; flip::PortTransportServerTcp m_socket; std::set m_ports; + Logger m_logger; static const char* kiwi_file_extension; @@ -149,7 +169,8 @@ namespace kiwi Session(uint64_t identifier, juce::File const& backend_file, std::string const& token, - std::string const& kiwi_version); + std::string const& kiwi_version, + Server::Logger & logger); //! @brief Destructor. //! @details Unbinds all documents and ports. @@ -159,7 +180,8 @@ namespace kiwi uint64_t getId() const; //! @brief Saves the document into designated backend file. - void save() const; + //! @details Returns true if saving succeeded. + bool save() const; //! @brief Loads the document from designated backend file. bool load(); @@ -191,6 +213,7 @@ namespace kiwi juce::File m_backend_file; std::string m_token; std::string m_kiwi_version; + Logger & m_logger; private: // deleted methods From 905e232e99a1c80a6521d5d339b341bdea0fd2ab Mon Sep 17 00:00:00 2001 From: jmillot Date: Tue, 30 Jan 2018 20:30:18 +0100 Subject: [PATCH 141/148] Improve server logger. --- Modules/KiwiServer/KiwiServer_Server.cpp | 28 +++++++++++++++--------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/Modules/KiwiServer/KiwiServer_Server.cpp b/Modules/KiwiServer/KiwiServer_Server.cpp index 4f1006d4..7919ca0a 100644 --- a/Modules/KiwiServer/KiwiServer_Server.cpp +++ b/Modules/KiwiServer/KiwiServer_Server.cpp @@ -148,7 +148,7 @@ namespace kiwi { juce::File session_file = getSessionFile(port.session()); - m_logger.log("[server] - creating new session for session_id : " + hexadecimal_convert(session_id)); + m_logger.log("creating new session for session_id : " + hexadecimal_convert(session_id)); auto session = m_sessions .insert(std::make_pair(session_id, @@ -156,11 +156,11 @@ namespace kiwi if (session_file.exists()) { - m_logger.log("[server] - loading session file for session_id : " + hexadecimal_convert(session_id)); + m_logger.log("loading session file for session_id : " + hexadecimal_convert(session_id)); if (!(*session.first).second.load()) { - m_logger.log("[server] - opening document document session : " + m_logger.log("opening document document session : " + hexadecimal_convert(session_id) + " failed"); m_sessions.erase(session_id); @@ -258,7 +258,15 @@ namespace kiwi juce::FileLogger::trimFileSize(m_jlogger.getLogFile(), m_limit); } - m_jlogger.logMessage(message); + std::string timestamp(juce::Time::getCurrentTime().toISO8601(true).toStdString()); + + std::string log = "[server] - "; + + log.append(timestamp); + log.append(" "); + log.append(message.toStdString()); + + m_jlogger.logMessage(log); } // ================================================================================ // @@ -380,7 +388,7 @@ namespace kiwi void Server::Session::bind(flip::PortBase & port) { - m_logger.log("[server] - User: " + std::to_string(port.user()) + m_logger.log("User: " + std::to_string(port.user()) + " connecting to session : " + hexadecimal_convert(m_identifier)); if (authenticateUser(port.user(), port.metadata())) @@ -426,7 +434,7 @@ namespace kiwi } else { - m_logger.log("[server] - User: " + std::to_string(port.user()) + m_logger.log("User: " + std::to_string(port.user()) + " failed to authenticate : " + "metadata : " + port.metadata()); @@ -436,7 +444,7 @@ namespace kiwi void Server::Session::unbind(flip::PortBase & port) { - m_logger.log("[server] - User " + std::to_string(port.user()) + m_logger.log("User " + std::to_string(port.user()) + " disconnecting from session" + hexadecimal_convert(m_identifier)); std::set ports = m_document->ports(); @@ -460,13 +468,13 @@ namespace kiwi m_backend_file.create(); } - m_logger.log("[server] - Saving session : " + hexadecimal_convert(m_identifier) + m_logger.log("saving session : " + hexadecimal_convert(m_identifier) + " in file : " + m_backend_file.getFileName()); if (!save()) { - m_logger.log("[server] - saving session to " - + m_backend_file.getFileName() + " failed"); + m_logger.log("saving session to " + + m_backend_file.getFileName() + " failed"); } } } From 9937f95da277ed3678db246dad86ae6d3d88f014 Mon Sep 17 00:00:00 2001 From: jean-millot Date: Mon, 29 Jan 2018 20:12:12 +0100 Subject: [PATCH 142/148] Bump kiwi version. --- Client/Source/KiwiApp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Client/Source/KiwiApp.h b/Client/Source/KiwiApp.h index db6c281b..d4464c89 100644 --- a/Client/Source/KiwiApp.h +++ b/Client/Source/KiwiApp.h @@ -34,7 +34,7 @@ namespace ProjectInfo { const char* const projectName = "Kiwi"; - const char* const versionString = "v0.1.0"; + const char* const versionString = "v1.0.0-beta.draft.1"; const int versionNumber = 0x010; } From f13d8a933df5fd4a8d56442eadea7518f1df3f5c Mon Sep 17 00:00:00 2001 From: jmillot Date: Tue, 30 Jan 2018 18:42:39 +0100 Subject: [PATCH 143/148] Bug hexadecimal converter server. (fix download). --- Modules/KiwiServer/KiwiServer_Server.cpp | 4 +++- Test/Server/test_Server.cpp | 7 +++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/Modules/KiwiServer/KiwiServer_Server.cpp b/Modules/KiwiServer/KiwiServer_Server.cpp index 7919ca0a..54d0e0e3 100644 --- a/Modules/KiwiServer/KiwiServer_Server.cpp +++ b/Modules/KiwiServer/KiwiServer_Server.cpp @@ -33,6 +33,8 @@ #include #include +#include + namespace kiwi { namespace server @@ -46,7 +48,7 @@ namespace kiwi std::string hexadecimal_convert(uint64_t hexa_decimal) { std::stringstream converter; - converter << std::hex << hexa_decimal; + converter << std::setfill('0') << std::setw(16) << std::hex << hexa_decimal; return converter.str(); } diff --git a/Test/Server/test_Server.cpp b/Test/Server/test_Server.cpp index 1fd5e8aa..c92fbbbf 100755 --- a/Test/Server/test_Server.cpp +++ b/Test/Server/test_Server.cpp @@ -260,5 +260,12 @@ TEST_CASE("Server - Server", "[Server, Server]") { backend.deleteRecursively(); } + + SECTION("Hexadecimal convert") + { + std::string hex = server::hexadecimal_convert(139928974906665000); + + CHECK(hex == "01f120a94b18a828"); + } } } From 72f49dcad8d3a9be1e3ac37e034dc30209a351bb Mon Sep 17 00:00:00 2001 From: jean-millot Date: Tue, 30 Jan 2018 20:06:46 +0000 Subject: [PATCH 144/148] Directly open file in windows. --- Client/Source/KiwiApp.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Client/Source/KiwiApp.cpp b/Client/Source/KiwiApp.cpp index f8588269..bc72ebbf 100644 --- a/Client/Source/KiwiApp.cpp +++ b/Client/Source/KiwiApp.cpp @@ -121,6 +121,10 @@ namespace kiwi m_command_manager->registerAllCommandsForTarget(this); checkLatestRelease(); + + #if JUCE_WINDOWS + m_instance->openFile(juce::File(commandLine.unquoted())); + #endif #if JUCE_MAC juce::PopupMenu macMainMenuPopup; From bfbf6ce2bd0247c45876c83119cca839051e4215 Mon Sep 17 00:00:00 2001 From: jmillot Date: Tue, 30 Jan 2018 22:08:53 +0100 Subject: [PATCH 145/148] Hide beacon dispatcher by default. --- Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp b/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp index ece653bb..9eb4cb9a 100644 --- a/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp +++ b/Client/Source/KiwiApp_Application/KiwiApp_Instance.cpp @@ -55,7 +55,7 @@ namespace kiwi m_windows.resize(std::size_t(WindowId::count)); //showAppSettingsWindow(); - showBeaconDispatcherWindow(); + //showBeaconDispatcherWindow(); showDocumentBrowserWindow(); showConsoleWindow(); } From ef92649523cf6e3082ca286a1a0976c1225542aa Mon Sep 17 00:00:00 2001 From: eliott PARIS Date: Wed, 31 Jan 2018 09:16:20 +0100 Subject: [PATCH 146/148] [osc~] - fix performing by phase method --- .../KiwiEngine/KiwiEngine_Objects/KiwiEngine_OscTilde.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_OscTilde.cpp b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_OscTilde.cpp index a75da5e0..4297626f 100644 --- a/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_OscTilde.cpp +++ b/Modules/KiwiEngine/KiwiEngine_Objects/KiwiEngine_OscTilde.cpp @@ -149,15 +149,11 @@ namespace kiwi { namespace engine { dsp::sample_t* output_sig = output[0ul].data(); size_t sample_index = output[0ul].size(); dsp::sample_t const* phase = input[1ul].data(); - dsp::sample_t const time_inc = m_freq/m_sr; while(sample_index--) { - *output_sig++ = std::cos(2.f * dsp::pi * (m_time + fmodf(*phase++, 1.f))); - m_time += time_inc; + *output_sig++ = std::cos(2.f * dsp::pi * fmodf(*phase++, 1.f)); } - - m_time = fmodf(m_time, 1.f); } void OscTilde::performPhaseAndFreq(dsp::Buffer const& input, dsp::Buffer& output) noexcept From 41e6beac9a1d92feac6439069e0e86da47d9fc01 Mon Sep 17 00:00:00 2001 From: jmillot Date: Wed, 31 Jan 2018 13:31:12 +0100 Subject: [PATCH 147/148] Suggest file name whensaving. Fix linux extension bug. --- Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.cpp b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.cpp index 33997d92..b3d73258 100644 --- a/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.cpp +++ b/Client/Source/KiwiApp_Patcher/KiwiApp_PatcherManager.cpp @@ -370,7 +370,9 @@ namespace kiwi { auto directory = juce::File::getSpecialLocation(juce::File::userHomeDirectory); - juce::FileChooser saveFileChooser("Save file", directory, "*.kiwi"); + juce::File suggest_file = directory.getChildFile(juce::String(m_name)).withFileExtension("kiwi"); + + juce::FileChooser saveFileChooser("Save file", suggest_file, "*.kiwi"); if ((saved = saveFileChooser.browseForFileToSave(true))) { From d7c1516473b9fff76f47800c990ce60c74f77636 Mon Sep 17 00:00:00 2001 From: jmillot Date: Wed, 31 Jan 2018 14:27:40 +0100 Subject: [PATCH 148/148] Bump Kiwi version. --- Client/Source/KiwiApp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Client/Source/KiwiApp.h b/Client/Source/KiwiApp.h index d4464c89..f8a4c621 100644 --- a/Client/Source/KiwiApp.h +++ b/Client/Source/KiwiApp.h @@ -34,7 +34,7 @@ namespace ProjectInfo { const char* const projectName = "Kiwi"; - const char* const versionString = "v1.0.0-beta.draft.1"; + const char* const versionString = "v1.0.0-beta"; const int versionNumber = 0x010; }