Merge branch 'master' into develop
[jack2.git] / common / JackPort.cpp
blobad2e75288ff155bb64cef868d0136404c8c133bc
1 /*
2 Copyright (C) 2001-2003 Paul Davis
3 Copyright (C) 2004-2008 Grame
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.
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.
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.
21 #include "JackPort.h"
22 #include "JackError.h"
23 #include "JackPortType.h"
24 #include <stdio.h>
25 #include <assert.h>
27 namespace Jack
30 JackPort::JackPort()
32 Release();
35 bool JackPort::Allocate(int refnum, const char* port_name, const char* port_type, JackPortFlags flags)
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;
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;
64 void JackPort::Release()
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';
80 int JackPort::GetRefNum() const
82 return fRefNum;
85 jack_nframes_t JackPort::GetLatency() const
87 return fLatency;
90 jack_nframes_t JackPort::GetTotalLatency() const
92 return fTotalLatency;
95 void JackPort::SetLatency(jack_nframes_t nframes)
97 fLatency = nframes;
99 /* setup the new latency values here,
100 * so we don't need to change the backend codes.
102 if (fFlags & JackPortIsOutput) {
103 fCaptureLatency.min = nframes;
104 fCaptureLatency.max = nframes;
106 if (fFlags & JackPortIsInput) {
107 fPlaybackLatency.min = nframes;
108 fPlaybackLatency.max = nframes;
112 void JackPort::SetLatencyRange(jack_latency_callback_mode_t mode, jack_latency_range_t* range)
114 if (mode == JackCaptureLatency) {
115 fCaptureLatency = *range;
117 /* hack to set latency up for
118 * backend ports
120 if ((fFlags & JackPortIsOutput) && (fFlags & JackPortIsPhysical)) {
121 fLatency = (range->min + range->max) / 2;
123 } else {
124 fPlaybackLatency = *range;
126 /* hack to set latency up for
127 * backend ports
129 if ((fFlags & JackPortIsInput) && (fFlags & JackPortIsPhysical)) {
130 fLatency = (range->min + range->max) / 2;
135 void JackPort::GetLatencyRange(jack_latency_callback_mode_t mode, jack_latency_range_t* range) const
137 if (mode == JackCaptureLatency) {
138 *range = fCaptureLatency;
139 } else {
140 *range = fPlaybackLatency;
144 int JackPort::Tie(jack_port_id_t port_index)
146 fTied = port_index;
147 return 0;
150 int JackPort::UnTie()
152 fTied = NO_PORT;
153 return 0;
156 int JackPort::RequestMonitor(bool onoff)
159 jackd.h
160 * If @ref JackPortCanMonitor is set for this @a port, turn input
161 * monitoring on or off. Otherwise, do nothing.
163 if (!(fFlags & JackPortCanMonitor))
164 return -1;
167 if (onoff) {
168 fMonitorRequests++;
169 } else if (fMonitorRequests) {
170 fMonitorRequests--;
173 return 0;
176 int JackPort::EnsureMonitor(bool onoff)
179 jackd.h
180 * If @ref JackPortCanMonitor is set for this @a port, turn input
181 * monitoring on or off. Otherwise, do nothing.
183 if (!(fFlags & JackPortCanMonitor))
184 return -1;
187 if (onoff) {
188 if (fMonitorRequests == 0) {
189 fMonitorRequests++;
191 } else {
192 if (fMonitorRequests > 0) {
193 fMonitorRequests = 0;
197 return 0;
200 const char* JackPort::GetName() const
202 return fName;
205 const char* JackPort::GetShortName() const
207 /* we know there is always a colon, because we put
208 it there ...
210 return strchr(fName, ':') + 1;
213 int JackPort::GetFlags() const
215 return fFlags;
218 const char* JackPort::GetType() const
220 const JackPortType* type = GetPortType(fTypeId);
221 return type->fName;
224 void JackPort::SetName(const char* new_name)
226 char* colon = strchr(fName, ':');
227 int len = sizeof(fName) - ((int) (colon - fName)) - 2;
228 snprintf(colon + 1, len, "%s", new_name);
231 bool JackPort::NameEquals(const char* target)
233 char buf[REAL_JACK_PORT_NAME_SIZE+1];
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.
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;
247 return (strcmp(fName, target) == 0
248 || strcmp(fAlias1, target) == 0
249 || strcmp(fAlias2, target) == 0);
252 int JackPort::GetAliases(char* const aliases[2])
254 int cnt = 0;
256 if (fAlias1[0] != '\0') {
257 strncpy(aliases[0], fAlias1, REAL_JACK_PORT_NAME_SIZE);
258 cnt++;
261 if (fAlias2[0] != '\0') {
262 strncpy(aliases[1], fAlias2, REAL_JACK_PORT_NAME_SIZE);
263 cnt++;
266 return cnt;
269 int JackPort::SetAlias(const char* alias)
271 if (fAlias1[0] == '\0') {
272 strncpy(fAlias1, alias, sizeof(fAlias1));
273 } else if (fAlias2[0] == '\0') {
274 strncpy(fAlias2, alias, sizeof(fAlias2));
275 } else {
276 return -1;
279 return 0;
282 int JackPort::UnsetAlias(const char* alias)
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;
292 return 0;
295 void JackPort::ClearBuffer(jack_nframes_t frames)
297 const JackPortType* type = GetPortType(fTypeId);
298 (type->init)(GetBuffer(), frames * sizeof(jack_default_audio_sample_t), frames);
301 void JackPort::MixBuffers(void** src_buffers, int src_count, jack_nframes_t buffer_size)
303 const JackPortType* type = GetPortType(fTypeId);
304 (type->mixdown)(GetBuffer(), src_buffers, src_count, buffer_size);
307 } // end of namespace