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.

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