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