Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

111 lines
3.0KB

  1. /* Copyright 2016, Ableton AG, Berlin. All rights reserved.
  2. *
  3. * This program is free software: you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation, either version 2 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. *
  16. * If you would like to incorporate Link into a proprietary software application,
  17. * please contact <link-devs@ableton.com>.
  18. */
  19. #pragma once
  20. #include <ableton/platforms/asio/AsioWrapper.hpp>
  21. #include <ableton/util/SafeAsyncHandler.hpp>
  22. #include <array>
  23. #include <cassert>
  24. namespace ableton
  25. {
  26. namespace platforms
  27. {
  28. namespace asio
  29. {
  30. template <std::size_t MaxPacketSize>
  31. struct Socket
  32. {
  33. Socket(::asio::io_service& io)
  34. : mpImpl(std::make_shared<Impl>(io))
  35. {
  36. }
  37. Socket(const Socket&) = delete;
  38. Socket& operator=(const Socket&) = delete;
  39. Socket(Socket&& rhs)
  40. : mpImpl(std::move(rhs.mpImpl))
  41. {
  42. }
  43. std::size_t send(const uint8_t* const pData,
  44. const size_t numBytes,
  45. const ::asio::ip::udp::endpoint& to)
  46. {
  47. assert(numBytes < MaxPacketSize);
  48. return mpImpl->mSocket.send_to(::asio::buffer(pData, numBytes), to);
  49. }
  50. template <typename Handler>
  51. void receive(Handler handler)
  52. {
  53. mpImpl->mHandler = std::move(handler);
  54. mpImpl->mSocket.async_receive_from(
  55. ::asio::buffer(mpImpl->mReceiveBuffer, MaxPacketSize), mpImpl->mSenderEndpoint,
  56. util::makeAsyncSafe(mpImpl));
  57. }
  58. ::asio::ip::udp::endpoint endpoint() const
  59. {
  60. return mpImpl->mSocket.local_endpoint();
  61. }
  62. struct Impl
  63. {
  64. Impl(::asio::io_service& io)
  65. : mSocket(io, ::asio::ip::udp::v4())
  66. {
  67. }
  68. ~Impl()
  69. {
  70. // Ignore error codes in shutdown and close as the socket may
  71. // have already been forcibly closed
  72. ::asio::error_code ec;
  73. mSocket.shutdown(::asio::ip::udp::socket::shutdown_both, ec);
  74. mSocket.close(ec);
  75. }
  76. void operator()(const ::asio::error_code& error, const std::size_t numBytes)
  77. {
  78. if (!error && numBytes > 0 && numBytes <= MaxPacketSize)
  79. {
  80. const auto bufBegin = begin(mReceiveBuffer);
  81. mHandler(mSenderEndpoint, bufBegin, bufBegin + static_cast<ptrdiff_t>(numBytes));
  82. }
  83. }
  84. ::asio::ip::udp::socket mSocket;
  85. ::asio::ip::udp::endpoint mSenderEndpoint;
  86. using Buffer = std::array<uint8_t, MaxPacketSize>;
  87. Buffer mReceiveBuffer;
  88. using ByteIt = typename Buffer::const_iterator;
  89. std::function<void(const ::asio::ip::udp::endpoint&, ByteIt, ByteIt)> mHandler;
  90. };
  91. std::shared_ptr<Impl> mpImpl;
  92. };
  93. } // namespace asio
  94. } // namespace platforms
  95. } // namespace ableton