jack2 codebase
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.

299 lines
6.8KB

  1. /*
  2. Copyright (C) 2001-2003 Paul Davis
  3. Copyright (C) 2004-2008 Grame
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU Lesser General Public License as published by
  6. the Free Software Foundation; either version 2.1 of the License, or
  7. (at your option) any later version.
  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 Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  15. */
  16. #include "JackPort.h"
  17. #include "JackError.h"
  18. #include "JackPortType.h"
  19. #include <stdio.h>
  20. #include <assert.h>
  21. namespace Jack
  22. {
  23. JackPort::JackPort()
  24. {
  25. Release();
  26. }
  27. bool JackPort::Allocate(int refnum, const char* port_name, const char* port_type, JackPortFlags flags)
  28. {
  29. jack_port_type_id_t id = GetPortTypeId(port_type);
  30. if (id == PORT_TYPES_MAX)
  31. return false;
  32. fTypeId = id;
  33. fFlags = flags;
  34. fRefNum = refnum;
  35. strcpy(fName, port_name);
  36. fInUse = true;
  37. fLatency = 0;
  38. fTotalLatency = 0;
  39. fPlaybackLatency.min = fPlaybackLatency.max = 0;
  40. fCaptureLatency.min = fCaptureLatency.max = 0;
  41. fTied = NO_PORT;
  42. // DB: At this point we do not know current buffer size in frames,
  43. // but every time buffer will be returned to any user,
  44. // it will be called with either ClearBuffer or MixBuffers
  45. // with correct current buffer size.
  46. // So it is safe to init with 0 here.
  47. ClearBuffer(0);
  48. return true;
  49. }
  50. void JackPort::Release()
  51. {
  52. fTypeId = 0;
  53. fFlags = JackPortIsInput;
  54. fRefNum = -1;
  55. fInUse = false;
  56. fLatency = 0;
  57. fTotalLatency = 0;
  58. fMonitorRequests = 0;
  59. fTied = NO_PORT;
  60. fAlias1[0] = '\0';
  61. fAlias2[0] = '\0';
  62. }
  63. int JackPort::GetRefNum() const
  64. {
  65. return fRefNum;
  66. }
  67. jack_nframes_t JackPort::GetLatency() const
  68. {
  69. return fLatency;
  70. }
  71. jack_nframes_t JackPort::GetTotalLatency() const
  72. {
  73. return fTotalLatency;
  74. }
  75. void JackPort::SetLatency(jack_nframes_t nframes)
  76. {
  77. fLatency = nframes;
  78. /* setup the new latency values here,
  79. * so we dont need to change the backend codes.
  80. */
  81. if (fFlags & JackPortIsOutput) {
  82. fCaptureLatency.min = nframes;
  83. fCaptureLatency.max = nframes;
  84. }
  85. if (fFlags & JackPortIsInput) {
  86. fPlaybackLatency.min = nframes;
  87. fPlaybackLatency.max = nframes;
  88. }
  89. }
  90. void JackPort::SetLatencyRange(jack_latency_callback_mode_t mode, jack_latency_range_t* range)
  91. {
  92. if (mode == JackCaptureLatency) {
  93. fCaptureLatency = *range;
  94. /* hack to set port->shared->latency up for
  95. * backend ports
  96. */
  97. if ((fFlags & JackPortIsOutput) && (fFlags & JackPortIsPhysical))
  98. fLatency = (range->min + range->max) / 2;
  99. } else {
  100. fPlaybackLatency = *range;
  101. /* hack to set port->shared->latency up for
  102. * backend ports
  103. */
  104. if ((fFlags & JackPortIsInput) && (fFlags & JackPortIsPhysical))
  105. fLatency = (range->min + range->max) / 2;
  106. }
  107. }
  108. void JackPort::GetLatencyRange(jack_latency_callback_mode_t mode, jack_latency_range_t* range) const
  109. {
  110. if (mode == JackCaptureLatency) {
  111. *range = fCaptureLatency;
  112. } else {
  113. *range = fPlaybackLatency;
  114. }
  115. }
  116. int JackPort::Tie(jack_port_id_t port_index)
  117. {
  118. fTied = port_index;
  119. return 0;
  120. }
  121. int JackPort::UnTie()
  122. {
  123. fTied = NO_PORT;
  124. return 0;
  125. }
  126. int JackPort::RequestMonitor(bool onoff)
  127. {
  128. /**
  129. jackd.h
  130. * If @ref JackPortCanMonitor is set for this @a port, turn input
  131. * monitoring on or off. Otherwise, do nothing.
  132. if (!(fFlags & JackPortCanMonitor))
  133. return -1;
  134. */
  135. if (onoff) {
  136. fMonitorRequests++;
  137. } else if (fMonitorRequests) {
  138. fMonitorRequests--;
  139. }
  140. return 0;
  141. }
  142. int JackPort::EnsureMonitor(bool onoff)
  143. {
  144. /**
  145. jackd.h
  146. * If @ref JackPortCanMonitor is set for this @a port, turn input
  147. * monitoring on or off. Otherwise, do nothing.
  148. if (!(fFlags & JackPortCanMonitor))
  149. return -1;
  150. */
  151. if (onoff) {
  152. if (fMonitorRequests == 0) {
  153. fMonitorRequests++;
  154. }
  155. } else {
  156. if (fMonitorRequests > 0) {
  157. fMonitorRequests = 0;
  158. }
  159. }
  160. return 0;
  161. }
  162. const char* JackPort::GetName() const
  163. {
  164. return fName;
  165. }
  166. const char* JackPort::GetShortName() const
  167. {
  168. /* we know there is always a colon, because we put
  169. it there ...
  170. */
  171. return strchr(fName, ':') + 1;
  172. }
  173. int JackPort::GetFlags() const
  174. {
  175. return fFlags;
  176. }
  177. const char* JackPort::GetType() const
  178. {
  179. const JackPortType* type = GetPortType(fTypeId);
  180. return type->fName;
  181. }
  182. void JackPort::SetName(const char* new_name)
  183. {
  184. char* colon = strchr(fName, ':');
  185. int len = sizeof(fName) - ((int) (colon - fName)) - 2;
  186. snprintf(colon + 1, len, "%s", new_name);
  187. }
  188. bool JackPort::NameEquals(const char* target)
  189. {
  190. char buf[JACK_PORT_NAME_SIZE + 1];
  191. /* this nasty, nasty kludge is here because between 0.109.0 and 0.109.1,
  192. the ALSA audio backend had the name "ALSA", whereas as before and
  193. after it, it was called "alsa_pcm". this stops breakage for
  194. any setups that have saved "alsa_pcm" or "ALSA" in their connection
  195. state.
  196. */
  197. if (strncmp(target, "ALSA:capture", 12) == 0 || strncmp(target, "ALSA:playback", 13) == 0) {
  198. snprintf(buf, sizeof(buf), "alsa_pcm%s", target + 4);
  199. target = buf;
  200. }
  201. return (strcmp(fName, target) == 0
  202. || strcmp(fAlias1, target) == 0
  203. || strcmp(fAlias2, target) == 0);
  204. }
  205. int JackPort::GetAliases(char* const aliases[2])
  206. {
  207. int cnt = 0;
  208. if (fAlias1[0] != '\0') {
  209. snprintf(aliases[0], JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE, "%s", fAlias1);
  210. cnt++;
  211. }
  212. if (fAlias2[0] != '\0') {
  213. snprintf(aliases[1], JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE, "%s", fAlias2);
  214. cnt++;
  215. }
  216. return cnt;
  217. }
  218. int JackPort::SetAlias(const char* alias)
  219. {
  220. if (fAlias1[0] == '\0') {
  221. snprintf(fAlias1, sizeof(fAlias1), "%s", alias);
  222. } else if (fAlias2[0] == '\0') {
  223. snprintf(fAlias2, sizeof(fAlias2), "%s", alias);
  224. } else {
  225. return -1;
  226. }
  227. return 0;
  228. }
  229. int JackPort::UnsetAlias(const char* alias)
  230. {
  231. if (strcmp(fAlias1, alias) == 0) {
  232. fAlias1[0] = '\0';
  233. } else if (strcmp(fAlias2, alias) == 0) {
  234. fAlias2[0] = '\0';
  235. } else {
  236. return -1;
  237. }
  238. return 0;
  239. }
  240. void JackPort::ClearBuffer(jack_nframes_t frames)
  241. {
  242. const JackPortType* type = GetPortType(fTypeId);
  243. (type->init)(GetBuffer(), frames * sizeof(float), frames);
  244. }
  245. void JackPort::MixBuffers(void** src_buffers, int src_count, jack_nframes_t buffer_size)
  246. {
  247. const JackPortType* type = GetPortType(fTypeId);
  248. (type->mixdown)(GetBuffer(), src_buffers, src_count, buffer_size);
  249. }
  250. } // end of namespace