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.

145 lines
3.9KB

  1. #include "subtree-serialize.h"
  2. #include "ports.h"
  3. #include "rtosc.h"
  4. #include <cstring>
  5. #include <cassert>
  6. using namespace rtosc;
  7. /*
  8. * Append another message onto a bundle if the space permits it.
  9. * If insufficient space is available, then zero is returned and the buffer is
  10. * untouched.
  11. *
  12. * If this is useful it may be generalized to rtosc_bundle_append()
  13. */
  14. static size_t append_bundle(char *dst, const char *src,
  15. size_t max_len, size_t dst_len, size_t src_len)
  16. {
  17. assert(rtosc_message_length(src,src_len) == src_len);
  18. //Handle Edge case alignment
  19. //if(rtosc_bundle_elements(dst, dst_len) == 0)
  20. // dst_len -= 4;
  21. if(max_len < dst_len + src_len + 4 || dst_len == 0 || src_len == 0)
  22. return 0;
  23. *(int32_t*)(dst+dst_len) = (int32_t)src_len;
  24. memcpy(dst+dst_len+4, src, src_len);
  25. return dst_len + src_len + 4;
  26. }
  27. //This object captures the output of any given port by calling it through a no
  28. //argument message
  29. //Assuming that the loc field is set correctly the message stored here will be
  30. //able to be replayed to get an object to a previous state
  31. class VarCapture : public RtData
  32. {
  33. public:
  34. char buf[128];
  35. char location[128];
  36. char msg[128];
  37. const char *dummy;
  38. bool success;
  39. VarCapture(void)
  40. :dummy("/ser\0\0\0\0,\0\0\0")
  41. {
  42. memset(buf, 0, sizeof(buf));
  43. memset(location, 0, sizeof(buf));
  44. this->loc = location;
  45. success = false;
  46. }
  47. const char *capture(const Ports *p, const char *path, void *obj_)
  48. {
  49. this->loc = location;
  50. assert(this->loc == location);
  51. this->obj = obj_;
  52. location[0] = '/';
  53. strcpy(location+1, path);
  54. success = false;
  55. size_t len = rtosc_message(msg, 128, path, "");
  56. (void) len;
  57. assert(len);
  58. assert(!strchr(path, ':'));
  59. p->dispatch(msg, *this);
  60. return success ? buf : NULL;
  61. }
  62. virtual void reply(const char *path, const char *args, ...)
  63. {
  64. assert(!success);
  65. assert(*path);
  66. va_list va;
  67. va_start(va, args);
  68. size_t len = rtosc_vmessage(buf, 128, path, args, va);
  69. (void) len;
  70. assert(len != 0);
  71. success = true;
  72. va_end(va);
  73. }
  74. virtual void broadcast(const char *msg)
  75. {
  76. (void) msg;
  77. }
  78. };
  79. struct subtree_args_t
  80. {
  81. VarCapture v, vv;
  82. size_t len;
  83. char *buffer;
  84. size_t buffer_size;
  85. void *object;
  86. rtosc::Ports *ports;
  87. };
  88. size_t subtree_serialize(char *buffer, size_t buffer_size,
  89. void *object, rtosc::Ports *ports)
  90. {
  91. (void) object;
  92. assert(buffer);
  93. assert(ports);
  94. subtree_args_t args;
  95. args.v.obj = object;
  96. args.len = rtosc_bundle(buffer, buffer_size, 0xdeadbeef0a0b0c0dULL, 0);
  97. args.buffer = buffer;
  98. args.buffer_size = buffer_size;
  99. args.object = object;
  100. args.ports = ports;
  101. //TODO FIXME this is not currently RT safe at the moment
  102. walk_ports(ports, args.v.loc, 128, &args, [](const Port *p, const char *, void *dat) {
  103. if(p->meta().find("internal") != p->meta().end())
  104. return;
  105. subtree_args_t *args = (subtree_args_t*) dat;
  106. const char *buf = args->vv.capture(args->ports, args->v.loc+1, args->object);
  107. if(buf)
  108. args->len = append_bundle(args->buffer, buf, args->buffer_size, args->len,
  109. rtosc_message_length(buf, 128));
  110. });
  111. return args.len;
  112. }
  113. void subtree_deserialize(char *buffer, size_t buffer_size,
  114. void *object, rtosc::Ports *ports, RtData &d)
  115. {
  116. d.obj = object;
  117. //simply replay all objects seen here
  118. for(unsigned i=0; i<rtosc_bundle_elements(buffer, buffer_size); ++i) {
  119. const char *msg = rtosc_bundle_fetch(buffer, i);
  120. ports->dispatch(msg+1, d);
  121. }
  122. }