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