Jack2 1.9.7

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     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