Jack2  1.9.8
JackPort.cpp
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