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.

213 lines
7.2KB

  1. /*
  2. * Carla JACK API for external applications
  3. * Copyright (C) 2016-2019 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. static const char* allocate_port_name(const char* const prefix, const uint 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. // --------------------------------------------------------------------------------------------------------------------
  33. CARLA_EXPORT
  34. const char** jack_get_ports(jack_client_t* client, const char* a, const char* b, unsigned long flags)
  35. {
  36. carla_stdout("%s(%p, %s, %s, 0x%lx) WIP", __FUNCTION__, client, a, b, flags);
  37. JackClientState* const jclient = (JackClientState*)client;
  38. CARLA_SAFE_ASSERT_RETURN(jclient != nullptr, nullptr);
  39. const JackServerState& jserver(jclient->server);
  40. const uint numIns = static_cast<uint>(jserver.numAudioIns + jserver.numMidiIns);
  41. const uint numOuts = static_cast<uint>(jserver.numAudioOuts + jserver.numMidiOuts);
  42. if (flags == 0 || (flags & (JackPortIsInput|JackPortIsOutput)) == (JackPortIsInput|JackPortIsOutput))
  43. {
  44. if (const char** const ret = (const char**)calloc(numIns+numOuts, sizeof(const char*)))
  45. {
  46. uint i=0;
  47. for (uint j=0; j<jserver.numAudioIns; ++i, ++j)
  48. ret[i] = allocate_port_name("system:capture_", j);
  49. for (uint j=0; j<jserver.numAudioOuts; ++i, ++j)
  50. ret[i] = allocate_port_name("system:playback_", j);
  51. for (uint j=0; j<jserver.numMidiIns; ++i, ++j)
  52. ret[i] = allocate_port_name("system:midi_capture_", j);
  53. for (uint j=0; j<jserver.numMidiOuts; ++i, ++j)
  54. ret[i] = allocate_port_name("system:midi_playback_", j);
  55. return ret;
  56. }
  57. }
  58. if (flags & JackPortIsInput)
  59. {
  60. if (const char** const ret = (const char**)calloc(numIns, sizeof(const char*)))
  61. {
  62. uint i=0;
  63. for (uint j=0; j<jserver.numAudioOuts; ++i, ++j)
  64. ret[i] = allocate_port_name("system:playback_", j);
  65. for (uint j=0; j<jserver.numMidiOuts; ++i, ++j)
  66. ret[i] = allocate_port_name("system:midi_playback_", j);
  67. return ret;
  68. }
  69. }
  70. if (flags & JackPortIsOutput)
  71. {
  72. if (const char** const ret = (const char**)calloc(numOuts, sizeof(const char*)))
  73. {
  74. uint i=0;
  75. for (uint j=0; j<jserver.numAudioIns; ++i, ++j)
  76. ret[i] = allocate_port_name("system:capture_", j);
  77. for (uint j=0; j<jserver.numMidiIns; ++i, ++j)
  78. ret[i] = allocate_port_name("system:midi_capture_", j);
  79. return ret;
  80. }
  81. }
  82. return nullptr;
  83. }
  84. CARLA_EXPORT
  85. jack_port_t* jack_port_by_name(jack_client_t* client, const char* name)
  86. {
  87. carla_debug("%s(%p, %s)", __FUNCTION__, client, name);
  88. JackClientState* const jclient = (JackClientState*)client;
  89. CARLA_SAFE_ASSERT_RETURN(jclient != nullptr, nullptr);
  90. if (std::strncmp(name, "system:", 7) == 0)
  91. {
  92. static JackPortState retPort(
  93. /* name */ nullptr,
  94. /* fullname */ nullptr,
  95. /* index */ 0,
  96. /* flags */ 0x0,
  97. /* isMidi */ false,
  98. /* isSystem */ true,
  99. /* isConnected */ false
  100. );
  101. static CarlaString rname, rfullname;
  102. const JackServerState& jserver(jclient->server);
  103. const int commonFlags = JackPortIsPhysical|JackPortIsTerminal;
  104. rfullname = name;
  105. name += 7;
  106. rname = name;
  107. retPort.name = rname.buffer();
  108. retPort.fullname = rfullname.buffer();
  109. /**/ if (std::strncmp(name, "capture_", 8) == 0)
  110. {
  111. name += 8;
  112. const int index = std::atoi(name)-1;
  113. CARLA_SAFE_ASSERT_RETURN(index >= 0 && index < jserver.numAudioIns, nullptr);
  114. retPort.index = static_cast<uint>(index);
  115. retPort.flags = commonFlags|JackPortIsOutput;
  116. retPort.isMidi = false;
  117. retPort.isConnected = jserver.numAudioIns > index;
  118. }
  119. else if (std::strncmp(name, "playback_", 9) == 0)
  120. {
  121. name += 9;
  122. const int index = std::atoi(name)-1;
  123. CARLA_SAFE_ASSERT_RETURN(index >= 0 && index < jserver.numAudioOuts, nullptr);
  124. retPort.index = static_cast<uint>(jserver.numAudioIns + index);
  125. retPort.flags = commonFlags|JackPortIsInput;
  126. retPort.isMidi = false;
  127. retPort.isConnected = jserver.numAudioOuts > index;
  128. }
  129. else if (std::strncmp(name, "midi_capture_", 13) == 0)
  130. {
  131. name += 13;
  132. const int index = std::atoi(name)-1;
  133. CARLA_SAFE_ASSERT_RETURN(index >= 0 && index < jserver.numMidiIns, nullptr);
  134. retPort.index = static_cast<uint>(index);
  135. retPort.flags = commonFlags|JackPortIsOutput;
  136. retPort.isMidi = true;
  137. retPort.isConnected = jserver.numMidiIns > index;
  138. }
  139. else if (std::strncmp(name, "midi_playback_", 14) == 0)
  140. {
  141. name += 14;
  142. const int index = std::atoi(name)-1;
  143. CARLA_SAFE_ASSERT_RETURN(index >= 0 && index < jserver.numMidiOuts, nullptr);
  144. retPort.index = static_cast<uint>(jserver.numMidiIns + index);
  145. retPort.flags = commonFlags|JackPortIsInput;
  146. retPort.isMidi = true;
  147. retPort.isConnected = jserver.numMidiOuts > index;
  148. }
  149. else
  150. {
  151. carla_stderr2("jack_port_by_name: invalid port short name '%s'", name);
  152. return nullptr;
  153. }
  154. return (jack_port_t*)&retPort;
  155. }
  156. else
  157. {
  158. if (JackPortState* const port = jclient->portNameMapping[name])
  159. return (jack_port_t*)port;
  160. }
  161. carla_stderr2("jack_port_by_name: invalid port name '%s'", name);
  162. return nullptr;
  163. }
  164. CARLA_EXPORT
  165. jack_port_t* jack_port_by_id(jack_client_t* client, jack_port_id_t port_id)
  166. {
  167. carla_stderr2("%s(%p, %u)", __FUNCTION__, client, port_id);
  168. return nullptr;
  169. }
  170. // --------------------------------------------------------------------------------------------------------------------