Jack2 1.9.7
|
00001 /* 00002 Copyright (C) 2001-2003 Paul Davis 00003 Copyright (C) 2004-2008 Grame 00004 00005 This program is free software; you can redistribute it and/or modify 00006 it under the terms of the GNU Lesser General Public License as published by 00007 the Free Software Foundation; either version 2.1 of the License, or 00008 (at your option) any later version. 00009 00010 This program is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 GNU Lesser General Public License for more details. 00014 00015 You should have received a copy of the GNU Lesser General Public License 00016 along with this program; if not, write to the Free Software 00017 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00018 00019 */ 00020 00021 #include "JackPort.h" 00022 #include "JackError.h" 00023 #include "JackPortType.h" 00024 #include <stdio.h> 00025 #include <assert.h> 00026 00027 namespace Jack 00028 { 00029 00030 JackPort::JackPort() 00031 { 00032 Release(); 00033 } 00034 00035 bool JackPort::Allocate(int refnum, const char* port_name, const char* port_type, JackPortFlags flags) 00036 { 00037 jack_port_type_id_t id = GetPortTypeId(port_type); 00038 if (id == PORT_TYPES_MAX) 00039 return false; 00040 fTypeId = id; 00041 fFlags = flags; 00042 fRefNum = refnum; 00043 strcpy(fName, port_name); 00044 fInUse = true; 00045 fLatency = 0; 00046 fTotalLatency = 0; 00047 fPlaybackLatency.min = fPlaybackLatency.max = 0; 00048 fCaptureLatency.min = fCaptureLatency.max = 0; 00049 fTied = NO_PORT; 00050 // DB: At this point we do not know current buffer size in frames, 00051 // but every time buffer will be returned to any user, 00052 // it will be called with either ClearBuffer or MixBuffers 00053 // with correct current buffer size. 00054 // So it is safe to init with 0 here. 00055 ClearBuffer(0); 00056 return true; 00057 } 00058 00059 void JackPort::Release() 00060 { 00061 fTypeId = 0; 00062 fFlags = JackPortIsInput; 00063 fRefNum = -1; 00064 fInUse = false; 00065 fLatency = 0; 00066 fTotalLatency = 0; 00067 fMonitorRequests = 0; 00068 fTied = NO_PORT; 00069 fAlias1[0] = '\0'; 00070 fAlias2[0] = '\0'; 00071 } 00072 00073 int JackPort::GetRefNum() const 00074 { 00075 return fRefNum; 00076 } 00077 00078 jack_nframes_t JackPort::GetLatency() const 00079 { 00080 return fLatency; 00081 } 00082 00083 jack_nframes_t JackPort::GetTotalLatency() const 00084 { 00085 return fTotalLatency; 00086 } 00087 00088 void JackPort::SetLatency(jack_nframes_t nframes) 00089 { 00090 fLatency = nframes; 00091 00092 /* setup the new latency values here, 00093 * so we dont need to change the backend codes. 00094 */ 00095 if (fFlags & JackPortIsOutput) { 00096 fCaptureLatency.min = nframes; 00097 fCaptureLatency.max = nframes; 00098 } 00099 if (fFlags & JackPortIsInput) { 00100 fPlaybackLatency.min = nframes; 00101 fPlaybackLatency.max = nframes; 00102 } 00103 } 00104 00105 void JackPort::SetLatencyRange(jack_latency_callback_mode_t mode, jack_latency_range_t* range) 00106 { 00107 if (mode == JackCaptureLatency) { 00108 fCaptureLatency = *range; 00109 00110 /* hack to set port->shared->latency up for 00111 * backend ports 00112 */ 00113 if ((fFlags & JackPortIsOutput) && (fFlags & JackPortIsPhysical)) 00114 fLatency = (range->min + range->max) / 2; 00115 } else { 00116 fPlaybackLatency = *range; 00117 00118 /* hack to set port->shared->latency up for 00119 * backend ports 00120 */ 00121 if ((fFlags & JackPortIsInput) && (fFlags & JackPortIsPhysical)) 00122 fLatency = (range->min + range->max) / 2; 00123 } 00124 } 00125 00126 void JackPort::GetLatencyRange(jack_latency_callback_mode_t mode, jack_latency_range_t* range) const 00127 { 00128 if (mode == JackCaptureLatency) { 00129 *range = fCaptureLatency; 00130 } else { 00131 *range = fPlaybackLatency; 00132 } 00133 } 00134 00135 int JackPort::Tie(jack_port_id_t port_index) 00136 { 00137 fTied = port_index; 00138 return 0; 00139 } 00140 00141 int JackPort::UnTie() 00142 { 00143 fTied = NO_PORT; 00144 return 0; 00145 } 00146 00147 int JackPort::RequestMonitor(bool onoff) 00148 { 00158 if (onoff) { 00159 fMonitorRequests++; 00160 } else if (fMonitorRequests) { 00161 fMonitorRequests--; 00162 } 00163 00164 return 0; 00165 } 00166 00167 int JackPort::EnsureMonitor(bool onoff) 00168 { 00178 if (onoff) { 00179 if (fMonitorRequests == 0) { 00180 fMonitorRequests++; 00181 } 00182 } else { 00183 if (fMonitorRequests > 0) { 00184 fMonitorRequests = 0; 00185 } 00186 } 00187 00188 return 0; 00189 } 00190 00191 const char* JackPort::GetName() const 00192 { 00193 return fName; 00194 } 00195 00196 const char* JackPort::GetShortName() const 00197 { 00198 /* we know there is always a colon, because we put 00199 it there ... 00200 */ 00201 return strchr(fName, ':') + 1; 00202 } 00203 00204 int JackPort::GetFlags() const 00205 { 00206 return fFlags; 00207 } 00208 00209 const char* JackPort::GetType() const 00210 { 00211 const JackPortType* type = GetPortType(fTypeId); 00212 return type->fName; 00213 } 00214 00215 void JackPort::SetName(const char* new_name) 00216 { 00217 char* colon = strchr(fName, ':'); 00218 int len = sizeof(fName) - ((int) (colon - fName)) - 2; 00219 snprintf(colon + 1, len, "%s", new_name); 00220 } 00221 00222 bool JackPort::NameEquals(const char* target) 00223 { 00224 char buf[JACK_PORT_NAME_SIZE + 1]; 00225 00226 /* this nasty, nasty kludge is here because between 0.109.0 and 0.109.1, 00227 the ALSA audio backend had the name "ALSA", whereas as before and 00228 after it, it was called "alsa_pcm". this stops breakage for 00229 any setups that have saved "alsa_pcm" or "ALSA" in their connection 00230 state. 00231 */ 00232 00233 if (strncmp(target, "ALSA:capture", 12) == 0 || strncmp(target, "ALSA:playback", 13) == 0) { 00234 snprintf(buf, sizeof(buf), "alsa_pcm%s", target + 4); 00235 target = buf; 00236 } 00237 00238 return (strcmp(fName, target) == 0 00239 || strcmp(fAlias1, target) == 0 00240 || strcmp(fAlias2, target) == 0); 00241 } 00242 00243 int JackPort::GetAliases(char* const aliases[2]) 00244 { 00245 int cnt = 0; 00246 00247 if (fAlias1[0] != '\0') { 00248 snprintf(aliases[0], JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE, "%s", fAlias1); 00249 cnt++; 00250 } 00251 00252 if (fAlias2[0] != '\0') { 00253 snprintf(aliases[1], JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE, "%s", fAlias2); 00254 cnt++; 00255 } 00256 00257 return cnt; 00258 } 00259 00260 int JackPort::SetAlias(const char* alias) 00261 { 00262 if (fAlias1[0] == '\0') { 00263 snprintf(fAlias1, sizeof(fAlias1), "%s", alias); 00264 } else if (fAlias2[0] == '\0') { 00265 snprintf(fAlias2, sizeof(fAlias2), "%s", alias); 00266 } else { 00267 return -1; 00268 } 00269 00270 return 0; 00271 } 00272 00273 int JackPort::UnsetAlias(const char* alias) 00274 { 00275 if (strcmp(fAlias1, alias) == 0) { 00276 fAlias1[0] = '\0'; 00277 } else if (strcmp(fAlias2, alias) == 0) { 00278 fAlias2[0] = '\0'; 00279 } else { 00280 return -1; 00281 } 00282 00283 return 0; 00284 } 00285 00286 void JackPort::ClearBuffer(jack_nframes_t frames) 00287 { 00288 const JackPortType* type = GetPortType(fTypeId); 00289 (type->init)(GetBuffer(), frames * sizeof(jack_default_audio_sample_t), frames); 00290 } 00291 00292 void JackPort::MixBuffers(void** src_buffers, int src_count, jack_nframes_t buffer_size) 00293 { 00294 const JackPortType* type = GetPortType(fTypeId); 00295 (type->mixdown)(GetBuffer(), src_buffers, src_count, buffer_size); 00296 } 00297 00298 } // end of namespace