/* * Carla OSC utils * Copyright (C) 2012-2014 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ #ifndef CARLA_OSC_UTILS_HPP_INCLUDED #define CARLA_OSC_UTILS_HPP_INCLUDED #include "CarlaUtils.hpp" #include #define try_lo_send(...) \ try { \ lo_send(__VA_ARGS__); \ } CARLA_SAFE_EXCEPTION("lo_send"); // ----------------------------------------------------------------------- struct CarlaOscData { const char* path; lo_address source; lo_address target; CarlaOscData() noexcept : path(nullptr), source(nullptr), target(nullptr) {} ~CarlaOscData() noexcept { clear(); } void clear() noexcept { if (path != nullptr) { delete[] path; path = nullptr; } if (source != nullptr) { try { lo_address_free(source); } CARLA_SAFE_EXCEPTION("lo_address_free source"); source = nullptr; } if (target != nullptr) { try { lo_address_free(target); } CARLA_SAFE_EXCEPTION("lo_address_free target"); target = nullptr; } } void setNewURL(const char* const url) { if (path != nullptr) { delete[] path; path = nullptr; } if (target != nullptr) { try { lo_address_free(target); } CARLA_SAFE_EXCEPTION("lo_address_free target"); target = nullptr; } char* const host = lo_url_get_hostname(url); char* const port = lo_url_get_port(url); path = carla_strdup_free(lo_url_get_path(url)); target = lo_address_new_with_proto(LO_UDP, host, port); std::free(host); std::free(port); } CARLA_PREVENT_HEAP_ALLOCATION CARLA_DECLARE_NON_COPY_STRUCT(CarlaOscData) }; // ----------------------------------------------------------------------- static inline void osc_send_configure(const CarlaOscData& oscData, const char* const key, const char* const value) noexcept { CARLA_SAFE_ASSERT_RETURN(oscData.path != nullptr && oscData.path[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(oscData.target != nullptr,); CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(value != nullptr,); carla_debug("osc_send_configure(path:\"%s\", \"%s\", \"%s\")", oscData.path, key, value); char targetPath[std::strlen(oscData.path)+11]; std::strcpy(targetPath, oscData.path); std::strcat(targetPath, "/configure"); try_lo_send(oscData.target, targetPath, "ss", key, value); } static inline void osc_send_control(const CarlaOscData& oscData, const int32_t index, const float value) noexcept { CARLA_SAFE_ASSERT_RETURN(oscData.path != nullptr && oscData.path[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(oscData.target != nullptr,); CARLA_SAFE_ASSERT_RETURN(index != -1,); // -1 == PARAMETER_NULL carla_debug("osc_send_control(path:\"%s\", %i, %f)", oscData.path, index, value); char targetPath[std::strlen(oscData.path)+9]; std::strcpy(targetPath, oscData.path); std::strcat(targetPath, "/control"); try_lo_send(oscData.target, targetPath, "if", index, value); } static inline void osc_send_program(const CarlaOscData& oscData, const uint32_t index) noexcept { CARLA_SAFE_ASSERT_RETURN(oscData.path != nullptr && oscData.path[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(oscData.target != nullptr,); carla_debug("osc_send_program(path:\"%s\", %u)", oscData.path, index); char targetPath[std::strlen(oscData.path)+9]; std::strcpy(targetPath, oscData.path); std::strcat(targetPath, "/program"); try_lo_send(oscData.target, targetPath, "i", static_cast(index)); } static inline void osc_send_program(const CarlaOscData& oscData, const uint32_t bank, const uint32_t program) noexcept { CARLA_SAFE_ASSERT_RETURN(oscData.path != nullptr && oscData.path[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(oscData.target != nullptr,); carla_debug("osc_send_program(path:\"%s\", %u, %u)", oscData.path, bank, program); char targetPath[std::strlen(oscData.path)+9]; std::strcpy(targetPath, oscData.path); std::strcat(targetPath, "/program"); try_lo_send(oscData.target, targetPath, "ii", static_cast(bank), static_cast(program)); } static inline void osc_send_midi_program(const CarlaOscData& oscData, const uint32_t index) noexcept { CARLA_SAFE_ASSERT_RETURN(oscData.path != nullptr && oscData.path[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(oscData.target != nullptr,); carla_debug("osc_send_midi_program(path:\"%s\", %u)", oscData.path, index); char targetPath[std::strlen(oscData.path)+14]; std::strcpy(targetPath, oscData.path); std::strcat(targetPath, "/midi-program"); try_lo_send(oscData.target, targetPath, "i", static_cast(index)); } static inline void osc_send_midi_program(const CarlaOscData& oscData, const uint32_t bank, const uint32_t program) noexcept { CARLA_SAFE_ASSERT_RETURN(oscData.path != nullptr && oscData.path[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(oscData.target != nullptr,); carla_debug("osc_send_midi_program(path:\"%s\", %u, %u)", oscData.path, bank, program); char targetPath[std::strlen(oscData.path)+14]; std::strcpy(targetPath, oscData.path); std::strcat(targetPath, "/midi-program"); try_lo_send(oscData.target, targetPath, "ii", static_cast(bank), static_cast(program)); } static inline void osc_send_midi(const CarlaOscData& oscData, const uint8_t buf[4]) noexcept { CARLA_SAFE_ASSERT_RETURN(oscData.path != nullptr && oscData.path[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(oscData.target != nullptr,); CARLA_SAFE_ASSERT_RETURN(buf[0] == 0,); CARLA_SAFE_ASSERT_RETURN(buf[1] != 0,); carla_debug("osc_send_midi(path:\"%s\", port:%u, {0x%X, %03u, %03u})", oscData.path, buf[0], buf[1], buf[2], buf[3]); char targetPath[std::strlen(oscData.path)+6]; std::strcpy(targetPath, oscData.path); std::strcat(targetPath, "/midi"); try_lo_send(oscData.target, targetPath, "m", buf); } static inline void osc_send_sample_rate(const CarlaOscData& oscData, const float sampleRate) noexcept { CARLA_SAFE_ASSERT_RETURN(oscData.path != nullptr && oscData.path[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(oscData.target != nullptr,); CARLA_SAFE_ASSERT_RETURN(sampleRate > 0.0f,); carla_debug("osc_send_sample_rate(path:\"%s\", %f)", oscData.path, sampleRate); char targetPath[std::strlen(oscData.path)+13]; std::strcpy(targetPath, oscData.path); std::strcat(targetPath, "/sample-rate"); try_lo_send(oscData.target, targetPath, "f", sampleRate); } static inline void osc_send_update(const CarlaOscData& oscData, const char* const url) noexcept { CARLA_SAFE_ASSERT_RETURN(oscData.path != nullptr && oscData.path[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(oscData.target != nullptr,); CARLA_SAFE_ASSERT_RETURN(url != nullptr && url[0] != '\0',); carla_debug("osc_send_update(path:\"%s\", \"%s\")", oscData.path, url); char targetPath[std::strlen(oscData.path)+8]; std::strcpy(targetPath, oscData.path); std::strcat(targetPath, "/update"); try_lo_send(oscData.target, targetPath, "s", url); } static inline void osc_send_update_url(const CarlaOscData& oscData, const char* const url) noexcept { CARLA_SAFE_ASSERT_RETURN(oscData.path != nullptr && oscData.path[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(oscData.target != nullptr,);; CARLA_SAFE_ASSERT_RETURN(url != nullptr && url[0] != '\0',); carla_debug("osc_send_update_url(path:\"%s\", \"%s\")", oscData.path, url); char targetPath[std::strlen(oscData.path)+12]; std::strcpy(targetPath, oscData.path); std::strcat(targetPath, "/update_url"); try_lo_send(oscData.target, targetPath, "s", url); } static inline void osc_send_show(const CarlaOscData& oscData) noexcept { CARLA_SAFE_ASSERT_RETURN(oscData.path != nullptr && oscData.path[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(oscData.target != nullptr,); carla_debug("osc_send_show(path:\"%s\")", oscData.path); char targetPath[std::strlen(oscData.path)+6]; std::strcpy(targetPath, oscData.path); std::strcat(targetPath, "/show"); try_lo_send(oscData.target, targetPath, ""); } static inline void osc_send_hide(const CarlaOscData& oscData) noexcept { CARLA_SAFE_ASSERT_RETURN(oscData.path != nullptr && oscData.path[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(oscData.target != nullptr,); carla_debug("osc_send_hide(path:\"%s\")", oscData.path); char targetPath[std::strlen(oscData.path)+6]; std::strcpy(targetPath, oscData.path); std::strcat(targetPath, "/hide"); try_lo_send(oscData.target, targetPath, ""); } static inline void osc_send_quit(const CarlaOscData& oscData) noexcept { CARLA_SAFE_ASSERT_RETURN(oscData.path != nullptr && oscData.path[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(oscData.target != nullptr,); carla_debug("osc_send_quit(path:\"%s\")", oscData.path); char targetPath[std::strlen(oscData.path)+6]; std::strcpy(targetPath, oscData.path); std::strcat(targetPath, "/quit"); try_lo_send(oscData.target, targetPath, ""); } static inline void osc_send_exiting(const CarlaOscData& oscData) noexcept { CARLA_SAFE_ASSERT_RETURN(oscData.path != nullptr && oscData.path[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(oscData.target != nullptr,); carla_debug("osc_send_exiting(path:\"%s\")", oscData.path); char targetPath[std::strlen(oscData.path)+9]; std::strcpy(targetPath, oscData.path); std::strcat(targetPath, "/exiting"); try_lo_send(oscData.target, targetPath, ""); } // ----------------------------------------------------------------------- static inline void osc_send_bridge_ready(const CarlaOscData& oscData, const char* const url) noexcept { CARLA_SAFE_ASSERT_RETURN(oscData.path != nullptr && oscData.path[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(oscData.target != nullptr,); CARLA_SAFE_ASSERT_RETURN(url != nullptr && url[0] != '\0',); carla_debug("osc_send_bridge_ready(path:\"%s\", \"%s\")", oscData.path, url); char targetPath[std::strlen(oscData.path)+18]; std::strcpy(targetPath, oscData.path); std::strcat(targetPath, "/bridge_ready"); try_lo_send(oscData.target, targetPath, "s", url); } static inline void osc_send_bridge_error(const CarlaOscData& oscData, const char* const error) noexcept { CARLA_SAFE_ASSERT_RETURN(oscData.path != nullptr && oscData.path[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(oscData.target != nullptr,); CARLA_SAFE_ASSERT_RETURN(error != nullptr && error[0] != '\0',); carla_debug("osc_send_bridge_error(path:\"%s\", \"%s\")", oscData.path, error); char targetPath[std::strlen(oscData.path)+14]; std::strcpy(targetPath, oscData.path); std::strcat(targetPath, "/bridge_error"); try_lo_send(oscData.target, targetPath, "s", error); } // ----------------------------------------------------------------------- static inline void osc_send_lv2_atom_transfer(const CarlaOscData& oscData, const uint32_t portIndex, const char* const atomBuf) noexcept { CARLA_SAFE_ASSERT_RETURN(oscData.path != nullptr && oscData.path[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(oscData.target != nullptr,); CARLA_SAFE_ASSERT_RETURN(atomBuf != nullptr && atomBuf[0] != '\0',); carla_debug("osc_send_lv2_atom_transfer(path:\"%s\", %u, )", oscData.path, portIndex, atomBuf); char targetPath[std::strlen(oscData.path)+19]; std::strcpy(targetPath, oscData.path); std::strcat(targetPath, "/lv2_atom_transfer"); try_lo_send(oscData.target, targetPath, "is", static_cast(portIndex), atomBuf); } static inline void osc_send_lv2_urid_map(const CarlaOscData& oscData, const uint32_t urid, const char* const uri) noexcept { CARLA_SAFE_ASSERT_RETURN(oscData.path != nullptr && oscData.path[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(oscData.target != nullptr,); //CARLA_SAFE_ASSERT_RETURN(urid != 0,); CARLA_SAFE_ASSERT_RETURN(uri != nullptr && uri[0] != '\0',); carla_debug("osc_send_lv2_urid_map(path:\"%s\", %u, \"%s\")", oscData.path, urid, uri); char targetPath[std::strlen(oscData.path)+14]; std::strcpy(targetPath, oscData.path); std::strcat(targetPath, "/lv2_urid_map"); try_lo_send(oscData.target, targetPath, "is", static_cast(urid), uri); } // ----------------------------------------------------------------------- #endif // CARLA_OSC_UTILS_HPP_INCLUDED