Jack2
1.9.8
|
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 assert(id >= 0 && id <= PORT_TYPES_MAX); 00039 if (id == PORT_TYPES_MAX) 00040 return false; 00041 fTypeId = id; 00042 fFlags = flags; 00043 fRefNum = refnum; 00044 strcpy(fName, port_name); 00045 fInUse = true; 00046 fLatency = 0; 00047 fTotalLatency = 0; 00048 fMonitorRequests = 0; 00049 fPlaybackLatency.min = fPlaybackLatency.max = 0; 00050 fCaptureLatency.min = fCaptureLatency.max = 0; 00051 fTied = NO_PORT; 00052 // DB: At this point we do not know current buffer size in frames, 00053 // but every time buffer will be returned to any user, 00054 // it will be called with either ClearBuffer or MixBuffers 00055 // with correct current buffer size. 00056 // So it is safe to init with 0 here. 00057 ClearBuffer(0); 00058 return true; 00059 } 00060 00061 void JackPort::Release() 00062 { 00063 fTypeId = 0; 00064 fFlags = JackPortIsInput; 00065 fRefNum = -1; 00066 fInUse = false; 00067 fLatency = 0; 00068 fTotalLatency = 0; 00069 fMonitorRequests = 0; 00070 fPlaybackLatency.min = fPlaybackLatency.max = 0; 00071 fCaptureLatency.min = fCaptureLatency.max = 0; 00072 fTied = NO_PORT; 00073 fAlias1[0] = '\0'; 00074 fAlias2[0] = '\0'; 00075 } 00076 00077 int JackPort::GetRefNum() const 00078 { 00079 return fRefNum; 00080 } 00081 00082 jack_nframes_t JackPort::GetLatency() const 00083 { 00084 return fLatency; 00085 } 00086 00087 jack_nframes_t JackPort::GetTotalLatency() const 00088 { 00089 return fTotalLatency; 00090 } 00091 00092 void JackPort::SetLatency(jack_nframes_t nframes) 00093 { 00094 fLatency = nframes; 00095 00096 /* setup the new latency values here, 00097 * so we dont need to change the backend codes. 00098 */ 00099 if (fFlags & JackPortIsOutput) { 00100 fCaptureLatency.min = nframes; 00101 fCaptureLatency.max = nframes; 00102 } 00103 if (fFlags & JackPortIsInput) { 00104 fPlaybackLatency.min = nframes; 00105 fPlaybackLatency.max = nframes; 00106 } 00107 } 00108 00109 void JackPort::SetLatencyRange(jack_latency_callback_mode_t mode, jack_latency_range_t* range) 00110 { 00111 if (mode == JackCaptureLatency) { 00112 fCaptureLatency = *range; 00113 00114 /* hack to set latency up for 00115 * backend ports 00116 */ 00117 if ((fFlags & JackPortIsOutput) && (fFlags & JackPortIsPhysical)) 00118 fLatency = (range->min + range->max) / 2; 00119 } else { 00120 fPlaybackLatency = *range; 00121 00122 /* hack to set latency up for 00123 * backend ports 00124 */ 00125 if ((fFlags & JackPortIsInput) && (fFlags & JackPortIsPhysical)) 00126 fLatency = (range->min + range->max) / 2; 00127 } 00128 } 00129 00130 void JackPort::GetLatencyRange(jack_latency_callback_mode_t mode, jack_latency_range_t* range) const 00131 { 00132 if (mode == JackCaptureLatency) { 00133 *range = fCaptureLatency; 00134 } else { 00135 *range = fPlaybackLatency; 00136 } 00137 } 00138 00139 int JackPort::Tie(jack_port_id_t port_index) 00140 { 00141 fTied = port_index; 00142 return 0; 00143 } 00144 00145 int JackPort::UnTie() 00146 { 00147 fTied = NO_PORT; 00148 return 0; 00149 } 00150 00151 int JackPort::RequestMonitor(bool onoff) 00152 { 00162 if (onoff) { 00163 fMonitorRequests++; 00164 } else if (fMonitorRequests) { 00165 fMonitorRequests--; 00166 } 00167 00168 return 0; 00169 } 00170 00171 int JackPort::EnsureMonitor(bool onoff) 00172 { 00182 if (onoff) { 00183 if (fMonitorRequests == 0) { 00184 fMonitorRequests++; 00185 } 00186 } else { 00187 if (fMonitorRequests > 0) { 00188 fMonitorRequests = 0; 00189 } 00190 } 00191 00192 return 0; 00193 } 00194 00195 const char* JackPort::GetName() const 00196 { 00197 return fName; 00198 } 00199 00200 const char* JackPort::GetShortName() const 00201 { 00202 /* we know there is always a colon, because we put 00203 it there ... 00204 */ 00205 return strchr(fName, ':') + 1; 00206 } 00207 00208 int JackPort::GetFlags() const 00209 { 00210 return fFlags; 00211 } 00212 00213 const char* JackPort::GetType() const 00214 { 00215 const JackPortType* type = GetPortType(fTypeId); 00216 return type->fName; 00217 } 00218 00219 void JackPort::SetName(const char* new_name) 00220 { 00221 char* colon = strchr(fName, ':'); 00222 int len = sizeof(fName) - ((int) (colon - fName)) - 2; 00223 snprintf(colon + 1, len, "%s", new_name); 00224 } 00225 00226 bool JackPort::NameEquals(const char* target) 00227 { 00228 char buf[REAL_JACK_PORT_NAME_SIZE]; 00229 00230 /* this nasty, nasty kludge is here because between 0.109.0 and 0.109.1, 00231 the ALSA audio backend had the name "ALSA", whereas as before and 00232 after it, it was called "alsa_pcm". this stops breakage for 00233 any setups that have saved "alsa_pcm" or "ALSA" in their connection 00234 state. 00235 */ 00236 00237 if (strncmp(target, "ALSA:capture", 12) == 0 || strncmp(target, "ALSA:playback", 13) == 0) { 00238 snprintf(buf, sizeof(buf), "alsa_pcm%s", target + 4); 00239 target = buf; 00240 } 00241 00242 return (strcmp(fName, target) == 0 00243 || strcmp(fAlias1, target) == 0 00244 || strcmp(fAlias2, target) == 0); 00245 } 00246 00247 int JackPort::GetAliases(char* const aliases[2]) 00248 { 00249 int cnt = 0; 00250 00251 if (fAlias1[0] != '\0') { 00252 snprintf(aliases[0], REAL_JACK_PORT_NAME_SIZE, "%s", fAlias1); 00253 cnt++; 00254 } 00255 00256 if (fAlias2[0] != '\0') { 00257 snprintf(aliases[1], REAL_JACK_PORT_NAME_SIZE, "%s", fAlias2); 00258 cnt++; 00259 } 00260 00261 return cnt; 00262 } 00263 00264 int JackPort::SetAlias(const char* alias) 00265 { 00266 if (fAlias1[0] == '\0') { 00267 snprintf(fAlias1, sizeof(fAlias1), "%s", alias); 00268 } else if (fAlias2[0] == '\0') { 00269 snprintf(fAlias2, sizeof(fAlias2), "%s", alias); 00270 } else { 00271 return -1; 00272 } 00273 00274 return 0; 00275 } 00276 00277 int JackPort::UnsetAlias(const char* alias) 00278 { 00279 if (strcmp(fAlias1, alias) == 0) { 00280 fAlias1[0] = '\0'; 00281 } else if (strcmp(fAlias2, alias) == 0) { 00282 fAlias2[0] = '\0'; 00283 } else { 00284 return -1; 00285 } 00286 00287 return 0; 00288 } 00289 00290 void JackPort::ClearBuffer(jack_nframes_t frames) 00291 { 00292 const JackPortType* type = GetPortType(fTypeId); 00293 (type->init)(GetBuffer(), frames * sizeof(jack_default_audio_sample_t), frames); 00294 } 00295 00296 void JackPort::MixBuffers(void** src_buffers, int src_count, jack_nframes_t buffer_size) 00297 { 00298 const JackPortType* type = GetPortType(fTypeId); 00299 (type->mixdown)(GetBuffer(), src_buffers, src_count, buffer_size); 00300 } 00301 00302 } // end of namespace