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