Jack2  1.9.10
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     }
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