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.

204 lines
6.8KB

  1. /*
  2. * Carla JACK API for external applications
  3. * Copyright (C) 2016-2017 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation; either version 2 of
  8. * the License, or any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * For a full copy of the GNU General Public License see the doc/GPL.txt file.
  16. */
  17. #include "libjack.hpp"
  18. #include "CarlaStringList.hpp"
  19. CARLA_BACKEND_USE_NAMESPACE
  20. // --------------------------------------------------------------------------------------------------------------------
  21. const char* allocate_port_name(const char* const prefix, const uint32_t num)
  22. {
  23. static CarlaStringList portList;
  24. char portName[STR_MAX];
  25. carla_zeroChars(portName, STR_MAX);
  26. std::snprintf(portName, STR_MAX-1, "%s%u", prefix, num+1);
  27. if (const char* const storedPortName = portList.containsAndReturnString(portName))
  28. return storedPortName;
  29. CARLA_SAFE_ASSERT_RETURN(portList.append(portName), nullptr);
  30. return portList.getLast();
  31. }
  32. CARLA_EXPORT
  33. const char** jack_get_ports(jack_client_t* client, const char* a, const char* b, unsigned long flags)
  34. {
  35. carla_stdout("%s(%p, %s, %s, 0x%lx) WIP", __FUNCTION__, client, a, b, flags);
  36. JackClientState* const jclient = (JackClientState*)client;
  37. CARLA_SAFE_ASSERT_RETURN(jclient != nullptr, nullptr);
  38. const JackServerState& jserver(jclient->server);
  39. const uint32_t numIns = jserver.numAudioIns + jserver.numMidiIns;
  40. const uint32_t numOuts = jserver.numAudioOuts + jserver.numMidiOuts;
  41. if (flags == 0 || (flags & (JackPortIsInput|JackPortIsOutput)) == (JackPortIsInput|JackPortIsOutput))
  42. {
  43. if (const char** const ret = (const char**)calloc(numIns+numOuts, sizeof(const char*)))
  44. {
  45. uint32_t i=0;
  46. for (uint32_t j=0; j<jserver.numAudioIns; ++i, ++j)
  47. ret[i] = allocate_port_name("system:capture_", j);
  48. for (uint32_t j=0; j<jserver.numAudioOuts; ++i, ++j)
  49. ret[i] = allocate_port_name("system:playback_", j);
  50. for (uint32_t j=0; j<jserver.numMidiIns; ++i, ++j)
  51. ret[i] = allocate_port_name("system:midi_capture_", j);
  52. for (uint32_t j=0; j<jserver.numMidiOuts; ++i, ++j)
  53. ret[i] = allocate_port_name("system:midi_playback_", j);
  54. return ret;
  55. }
  56. }
  57. if (flags & JackPortIsInput)
  58. {
  59. if (const char** const ret = (const char**)calloc(numIns, sizeof(const char*)))
  60. {
  61. uint32_t i=0;
  62. for (uint32_t j=0; j<jserver.numAudioOuts; ++i, ++j)
  63. ret[i] = allocate_port_name("system:playback_", j);
  64. for (uint32_t j=0; j<jserver.numMidiOuts; ++i, ++j)
  65. ret[i] = allocate_port_name("system:midi_playback_", j);
  66. return ret;
  67. }
  68. }
  69. if (flags & JackPortIsOutput)
  70. {
  71. if (const char** const ret = (const char**)calloc(numOuts, sizeof(const char*)))
  72. {
  73. uint32_t i=0;
  74. for (uint32_t j=0; j<jserver.numAudioIns; ++i, ++j)
  75. ret[i] = allocate_port_name("system:capture_", j);
  76. for (uint32_t j=0; j<jserver.numMidiIns; ++i, ++j)
  77. ret[i] = allocate_port_name("system:midi_capture_", j);
  78. return ret;
  79. }
  80. }
  81. return nullptr;
  82. }
  83. CARLA_EXPORT
  84. jack_port_t* jack_port_by_name(jack_client_t* client, const char* name)
  85. {
  86. carla_stdout("%s(%p, %s) WIP", __FUNCTION__, client, name);
  87. JackClientState* const jclient = (JackClientState*)client;
  88. CARLA_SAFE_ASSERT_RETURN(jclient != nullptr, 0);
  89. const JackServerState& jserver(jclient->server);
  90. const int commonFlags = JackPortIsPhysical|JackPortIsTerminal;
  91. static JackPortState retPort(
  92. /* name */ nullptr,
  93. /* fullname */ nullptr,
  94. /* index */ 0,
  95. /* flags */ 0x0,
  96. /* isMidi */ false,
  97. /* isSystem */ true,
  98. /* isConnected */ false
  99. );
  100. if (std::strncmp(name, "system:", 7) == 0)
  101. {
  102. std::free(retPort.fullname);
  103. retPort.fullname = strdup(name);
  104. name += 7;
  105. std::free(retPort.name);
  106. retPort.name = strdup(name);
  107. /**/ if (std::strncmp(name, "capture_", 8) == 0)
  108. {
  109. name += 8;
  110. const int index = std::atoi(name)-1;
  111. CARLA_SAFE_ASSERT_RETURN(index >= 0 && index < jserver.numAudioIns, nullptr);
  112. retPort.index = index;
  113. retPort.flags = commonFlags|JackPortIsOutput;
  114. retPort.isMidi = false;
  115. retPort.isConnected = jserver.numAudioIns > index;
  116. }
  117. else if (std::strncmp(name, "playback_", 9) == 0)
  118. {
  119. name += 9;
  120. const int index = std::atoi(name)-1;
  121. CARLA_SAFE_ASSERT_RETURN(index >= 0 && index < jserver.numAudioOuts, nullptr);
  122. retPort.index = (jserver.numAudioIns) + index;
  123. retPort.flags = commonFlags|JackPortIsInput;
  124. retPort.isMidi = false;
  125. retPort.isConnected = jserver.numAudioOuts > index;
  126. }
  127. else if (std::strncmp(name, "midi_capture_", 13) == 0)
  128. {
  129. name += 13;
  130. const int index = std::atoi(name)-1;
  131. CARLA_SAFE_ASSERT_RETURN(index >= 0 && index < jserver.numAudioIns, nullptr);
  132. retPort.index = index;
  133. retPort.flags = commonFlags|JackPortIsOutput;
  134. retPort.isMidi = true;
  135. retPort.isConnected = jserver.numMidiIns > index;
  136. }
  137. else if (std::strncmp(name, "midi_playback_", 14) == 0)
  138. {
  139. name += 14;
  140. const int index = std::atoi(name)-1;
  141. CARLA_SAFE_ASSERT_RETURN(index >= 0 && index < jserver.numAudioOuts, nullptr);
  142. retPort.index = (jserver.numAudioIns) + index;
  143. retPort.flags = commonFlags|JackPortIsInput;
  144. retPort.isMidi = true;
  145. retPort.isConnected = jserver.numMidiOuts > index;
  146. }
  147. else
  148. {
  149. carla_stderr2("jack_port_by_name: invalid port short name '%s'", name);
  150. return nullptr;
  151. }
  152. return (jack_port_t*)&retPort;
  153. }
  154. carla_stderr2("jack_port_by_name: invalid port name '%s'", name);
  155. return nullptr;
  156. }
  157. CARLA_EXPORT
  158. jack_port_t* jack_port_by_id(jack_client_t* client, jack_port_id_t port_id)
  159. {
  160. carla_stderr2("%s(%p, %u)", __FUNCTION__, client, port_id);
  161. return nullptr;
  162. }
  163. // --------------------------------------------------------------------------------------------------------------------