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