|  | /*
Copyright (C) 2001-2003 Paul Davis
Copyright (C) 2004-2008 Grame
This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "JackPort.h"
#include "JackError.h"
#include "JackPortType.h"
#include <stdio.h>
#include <assert.h>
namespace Jack
{
JackPort::JackPort()
        : fFlags(JackPortIsInput), fRefNum( -1), fLatency(0), fTotalLatency(0), fMonitorRequests(0), fInUse(false), fTied(NO_PORT)
{}
JackPort::~JackPort()
{}
bool JackPort::Allocate(int refnum, const char* port_name, const char* port_type, JackPortFlags flags)
{
    int id = GetPortTypeId(port_type);
    if (id < 0)
        return false;
    fTypeId = id;
    fFlags = flags;
    fRefNum = refnum;
    strcpy(fName, port_name);
    fInUse = true;
    fLatency = 0;
    fTotalLatency = 0;
    fTied = NO_PORT;
    // DB: At this point we do not know current buffer size in frames,
    // but every time buffer will be returned to any user,
    // it will be called with either ClearBuffer or MixBuffers
    // with correct current buffer size.
    // So it is safe to init with 0 here.
    ClearBuffer(0);
    return true;
}
void JackPort::Release()
{
    fTypeId = 0;
    fFlags = JackPortIsInput;
    fRefNum = -1;
    fInUse = false;
    fLatency = 0;
    fTotalLatency = 0;
    fTied = NO_PORT;
    fAlias1[0] = '\0';
    fAlias2[0] = '\0';
}
bool JackPort::IsUsed() const
{
    return fInUse;
}
float* JackPort::GetBuffer()
{
    return fBuffer;
}
int JackPort::GetRefNum() const
{
    return fRefNum;
}
jack_nframes_t JackPort::GetLatency() const
{
    return fLatency;
}
jack_nframes_t JackPort::GetTotalLatency() const
{
    return fTotalLatency;
}
void JackPort::SetLatency(jack_nframes_t nframes)
{
    fLatency = nframes;
}
int JackPort::Tie(jack_port_id_t port_index)
{
    fTied = port_index;
    return 0;
}
int JackPort::UnTie()
{
    fTied = NO_PORT;
    return 0;
}
int JackPort::RequestMonitor(bool onoff)
{
    /**
    jackd.h 
     * If @ref JackPortCanMonitor is set for this @a port, turn input
     * monitoring on or off. Otherwise, do nothing.
     
     if (!(fFlags & JackPortCanMonitor))
    	return -1;
     */
    if (onoff) {
        fMonitorRequests++;
    } else if (fMonitorRequests) {
        fMonitorRequests--;
    }
    return 0;
}
int JackPort::EnsureMonitor(bool onoff)
{
    /**
    jackd.h 
        * If @ref JackPortCanMonitor is set for this @a port, turn input
        * monitoring on or off. Otherwise, do nothing.
     
     if (!(fFlags & JackPortCanMonitor))
    	return -1;
     */
    if (onoff) {
        if (fMonitorRequests == 0) {
            fMonitorRequests++;
        }
    } else {
        if (fMonitorRequests > 0) {
            fMonitorRequests = 0;
        }
    }
    return 0;
}
bool JackPort::MonitoringInput()
{
    return (fMonitorRequests > 0);
}
const char* JackPort::GetName() const
{
    return fName;
}
const char* JackPort::GetShortName() const
{
    /* we know there is always a colon, because we put
       it there ...
    */
    return strchr(fName, ':') + 1;
}
int JackPort::GetFlags() const
{
    return fFlags;
}
const char* JackPort::GetType() const
{
    const JackPortType* type = GetPortType(fTypeId);
    return type->name;
}
int JackPort::SetName(const char* new_name)
{
    char* colon = strchr(fName, ':');
    int len = sizeof(fName) - ((int) (colon - fName)) - 2;
    snprintf(colon + 1, len, "%s", new_name);
    return 0;
}
bool JackPort::NameEquals(const char* target)
{
    char buf[JACK_PORT_NAME_SIZE + 1];
    /* this nasty, nasty kludge is here because between 0.109.0 and 0.109.1,
       the ALSA audio backend had the name "ALSA", whereas as before and
       after it, it was called "alsa_pcm". this stops breakage for
       any setups that have saved "alsa_pcm" or "ALSA" in their connection
       state.
    */
    if (strncmp(target, "ALSA:capture", 12) == 0 || strncmp(target, "ALSA:playback", 13) == 0) {
        snprintf(buf, sizeof(buf), "alsa_pcm%s", target + 4);
        target = buf;
    }
    return (strcmp(fName, target) == 0
            || strcmp(fAlias1, target) == 0
            || strcmp(fAlias2, target) == 0);
}
int JackPort::GetAliases(char* const aliases[2])
{
    int cnt = 0;
    if (fAlias1[0] != '\0') {
        snprintf(aliases[0], JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE, "%s", fAlias1);
        cnt++;
    }
    if (fAlias2[0] != '\0') {
        snprintf(aliases[1], JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE, "%s", fAlias2);
        cnt++;
    }
    return cnt;
}
int JackPort::SetAlias(const char* alias)
{
    if (fAlias1[0] == '\0') {
        snprintf(fAlias1, sizeof(fAlias1), "%s", alias);
    } else if (fAlias2[0] == '\0') {
        snprintf(fAlias2, sizeof(fAlias2), "%s", alias);
    } else {
        return -1;
    }
    return 0;
}
int JackPort::UnsetAlias(const char* alias)
{
    if (strcmp(fAlias1, alias) == 0) {
        fAlias1[0] = '\0';
    } else if (strcmp(fAlias2, alias) == 0) {
        fAlias2[0] = '\0';
    } else {
        return -1;
    }
    return 0;
}
void JackPort::ClearBuffer(jack_nframes_t frames)
{
    const JackPortType* type = GetPortType(fTypeId);
    (type->init)(fBuffer, BUFFER_SIZE_MAX * sizeof(float), frames);
}
void JackPort::MixBuffers(void** src_buffers, int src_count, jack_nframes_t buffer_size)
{
    const JackPortType* type = GetPortType(fTypeId);
    (type->mixdown)(fBuffer, src_buffers, src_count, buffer_size);
}
} // end of namespace
 |