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.

303 lines
7.0KB

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