Ejemplo n.º 1
0
inline void JackClient::Error()
{
    jack_error("JackClient::Execute error name = %s", GetClientControl()->fName);
    // Hum... not sure about this, the following "close" code is called in the RT thread...
    int result;
    fThread.DropSelfRealTime();
    GetClientControl()->fActive = false;
    fChannel->ClientDeactivate(GetClientControl()->fRefNum, &result);
    ShutDown(jack_status_t(JackFailure | JackServerError), JACK_SERVER_FAILURE);
    fThread.Terminate();
}
END_NAMESPACE_DISTRHO

// -----------------------------------------------------------------------

int main()
{
    USE_NAMESPACE_DISTRHO;

    jack_status_t  status = jack_status_t(0x0);
    jack_client_t* client = jack_client_open(DISTRHO_PLUGIN_NAME, JackNoStartServer, &status);

    if (client == nullptr)
    {
        d_string errorString;

        if (status & JackFailure)
            errorString += "Overall operation failed;\n";
        if (status & JackInvalidOption)
            errorString += "The operation contained an invalid or unsupported option;\n";
        if (status & JackNameNotUnique)
            errorString += "The desired client name was not unique;\n";
        if (status & JackServerStarted)
            errorString += "The JACK server was started as a result of this operation;\n";
        if (status & JackServerFailed)
            errorString += "Unable to connect to the JACK server;\n";
        if (status & JackServerError)
            errorString += "Communication error with the JACK server;\n";
        if (status & JackNoSuchClient)
            errorString += "Requested client does not exist;\n";
        if (status & JackLoadFailure)
            errorString += "Unable to load internal client;\n";
        if (status & JackInitFailure)
            errorString += "Unable to initialize client;\n";
        if (status & JackShmFailure)
            errorString += "Unable to access shared memory;\n";
        if (status & JackVersionError)
            errorString += "Client's protocol version does not match;\n";
        if (status & JackBackendError)
            errorString += "Backend Error;\n";
        if (status & JackClientZombie)
            errorString += "Client is being shutdown against its will;\n";

        if (errorString.isNotEmpty())
        {
            errorString[errorString.length()-2] = '.';
            d_stderr("Failed to create jack client, reason was:\n%s", errorString.buffer());
        }
        else
            d_stderr("Failed to create jack client, cannot continue!");

        return 1;
    }

    USE_NAMESPACE_DISTRHO;

    d_lastBufferSize = jack_get_buffer_size(client);
    d_lastSampleRate = jack_get_sample_rate(client);
    d_lastUiSampleRate = d_lastSampleRate;

    PluginJack p(client);
    p.exec();

    return 0;
}
Ejemplo n.º 3
0
int JackClient::ClientNotify(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2)
{
    int res = 0;

    jack_log("JackClient::ClientNotify ref = %ld name = %s notify = %ld", refnum, name, notify);

    // Done all time: redirected on subclass implementation JackLibClient and JackInternalClient
    switch (notify) {

        case kAddClient:
            res = ClientNotifyImp(refnum, name, notify, sync, message, value1, value2);
            break;

        case kRemoveClient:
            res = ClientNotifyImp(refnum, name, notify, sync, message, value1, value2);
            break;

        case kActivateClient:
            jack_log("JackClient::kActivateClient name = %s ref = %ld ", name, refnum);
            InitAux();
            break;
    }

    /*
    The current semantic is that notifications can only be received when the client has been activated,
    although is this implementation, one could imagine calling notifications as soon as the client has be opened.
    */
    if (IsActive()) {

        switch (notify) {

            case kAddClient:
                jack_log("JackClient::kAddClient fName = %s name = %s", GetClientControl()->fName, name);
                if (fClientRegistration && strcmp(GetClientControl()->fName, name) != 0) {      // Don't call the callback for the registering client itself
                    fClientRegistration(name, 1, fClientRegistrationArg);
                }
                break;

            case kRemoveClient:
                jack_log("JackClient::kRemoveClient fName = %s name = %s", GetClientControl()->fName, name);
                if (fClientRegistration && strcmp(GetClientControl()->fName, name) != 0) { // Don't call the callback for the registering client itself
                    fClientRegistration(name, 0, fClientRegistrationArg);
                }
                break;

            case kBufferSizeCallback:
                jack_log("JackClient::kBufferSizeCallback buffer_size = %ld", value1);
                if (fBufferSize) {
                    res = fBufferSize(value1, fBufferSizeArg);
                }
                break;

            case kSampleRateCallback:
                jack_log("JackClient::kSampleRateCallback sample_rate = %ld", value1);
                if (fSampleRate) {
                    res = fSampleRate(value1, fSampleRateArg);
                }
                break;

            case kGraphOrderCallback:
                jack_log("JackClient::kGraphOrderCallback");
                if (fGraphOrder) {
                    res = fGraphOrder(fGraphOrderArg);
                }
                break;

            case kStartFreewheelCallback:
                jack_log("JackClient::kStartFreewheel");
                SetupDriverSync(true);
                // Drop RT only when the RT thread is actually running
                if (fThread.GetStatus() == JackThread::kRunning) {
                    fThread.DropRealTime();     
                }
                if (fFreewheel) {
                    fFreewheel(1, fFreewheelArg);
                }
                break;

            case kStopFreewheelCallback:
                jack_log("JackClient::kStopFreewheel");
                SetupDriverSync(false);
                if (fFreewheel) {
                    fFreewheel(0, fFreewheelArg);
                }
                // Acquire RT only when the RT thread is actually running
                if (GetEngineControl()->fRealTime && fThread.GetStatus() == JackThread::kRunning) {
                    if (fThread.AcquireRealTime(GetEngineControl()->fClientPriority) < 0) {
                        jack_error("JackClient::AcquireRealTime error");
                    }
                }
                break;

            case kPortRegistrationOnCallback:
                jack_log("JackClient::kPortRegistrationOn port_index = %ld", value1);
                if (fPortRegistration) {
                    fPortRegistration(value1, 1, fPortRegistrationArg);
                }
                break;

            case kPortRegistrationOffCallback:
                jack_log("JackClient::kPortRegistrationOff port_index = %ld ", value1);
                if (fPortRegistration) {
                    fPortRegistration(value1, 0, fPortRegistrationArg);
                }
                break;

            case kPortConnectCallback:
                jack_log("JackClient::kPortConnectCallback src = %ld dst = %ld", value1, value2);
                if (fPortConnect) {
                    fPortConnect(value1, value2, 1, fPortConnectArg);
                }
                break;

            case kPortDisconnectCallback:
                jack_log("JackClient::kPortDisconnectCallback src = %ld dst = %ld", value1, value2);
                if (fPortConnect) {
                    fPortConnect(value1, value2, 0, fPortConnectArg);
                }
                break;

             case kPortRenameCallback:
                jack_log("JackClient::kPortRenameCallback port = %ld", value1);
                if (fPortRename) {
                    fPortRename(value1, message, GetGraphManager()->GetPort(value1)->GetName(), fPortRenameArg);
                }
                break;

            case kXRunCallback:
                jack_log("JackClient::kXRunCallback");
                if (fXrun) {
                    res = fXrun(fXrunArg);
                }
                break;

            case kShutDownCallback:
                jack_log("JackClient::kShutDownCallback");
                ShutDown(jack_status_t(value1), message);
                break;

            case kSessionCallback:
                jack_log("JackClient::kSessionCallback");
                if (fSession) {
                    jack_session_event_t* event = (jack_session_event_t*)malloc( sizeof(jack_session_event_t));
                    char uuid_buf[JACK_UUID_SIZE];
                    event->type = (jack_session_event_type_t)value1;
                    event->session_dir = strdup(message);
                    event->command_line = NULL;
                    event->flags = (jack_session_flags_t)0;
                    snprintf(uuid_buf, sizeof(uuid_buf), "%d", GetClientControl()->fSessionID);
                    event->client_uuid = strdup(uuid_buf);
                    fSessionReply = kPendingSessionReply;
                    // Session callback may change fSessionReply by directly using jack_session_reply
                    fSession(event, fSessionArg);
                    res = fSessionReply;
                }
                break;

            case kLatencyCallback:
                res = HandleLatencyCallback(value1);
                break;
        }
    }

    return res;
}
Ejemplo n.º 4
0
bool AudioDevJack::init(const QString &device, const AkAudioCaps &caps)
{
    if (!this->m_caps.contains(device)
        || caps.channels() < 1
        || caps.channels() > 2
        || caps.rate() != int(jack_get_sample_rate(this->m_client))
        || caps.format() != AkAudioCaps::SampleFormat_flt)
        return false;

    this->m_appPorts.clear();
    this->m_curChannels = 0;
    this->m_curSampleRate = 0;
    this->m_buffer.clear();

    QString portName = device == ":jackinput:"?
                           "input": "output";
    JackPortFlags portFlags = device == ":jackinput:"?
                                  JackPortIsInput: JackPortIsOutput;

    // Create ports for sending/receiving data
    for (int channel = 0; channel < caps.channels(); channel++) {
        auto port = jack_port_register(this->m_client,
                                       QString("%1_%2")
                                           .arg(portName)
                                           .arg(channel + 1).toStdString().c_str(),
                                       JACK_DEFAULT_AUDIO_TYPE,
                                       portFlags,
                                       0);

        if (port)
            this->m_appPorts << port;
    }

    if (this->m_appPorts.size() < caps.channels()) {
        this->m_error = "AudioDevJack::init: No more JACK ports available";
        Q_EMIT this->errorChanged(this->m_error);
        this->uninit();

        return false;
    }

    auto bufferSize = jack_get_buffer_size(this->m_client);

    // Activate JACK client

    if (auto error = jack_status_t(jack_activate(this->m_client))) {
        this->m_error = jackErrorCodes->value(error);
        Q_EMIT this->errorChanged(this->m_error);
        this->uninit();

        return false;
    }

    if (caps.channels() == 1) {
        if (device == ":jackinput:") {
            for (auto port: this->m_devicePorts[device])
                jack_connect(this->m_client,
                             port.toStdString().c_str(),
                             jack_port_name(this->m_appPorts.first()));
        } else {
            for (auto port: this->m_devicePorts[device])
                jack_connect(this->m_client,
                             jack_port_name(this->m_appPorts.first()),
                             port.toStdString().c_str());
        }
    } else {
        auto ports = this->m_devicePorts[device];

        if (device == ":jackinput:") {
            for (int i = 0; i < this->m_appPorts.size(); i++)
                jack_connect(this->m_client,
                             ports[i].toStdString().c_str(),
                             jack_port_name(this->m_appPorts[i]));
        } else {
            for (int i = 0; i < this->m_appPorts.size(); i++)
                jack_connect(this->m_client,
                             jack_port_name(this->m_appPorts[i]),
                             ports[i].toStdString().c_str());
        }
    }

    this->m_curDevice = device;
    this->m_curChannels = caps.channels();
    this->m_curSampleRate = caps.rate();
    this->m_maxBufferSize = int(2
                                * sizeof(jack_default_audio_sample_t)
                                * uint(caps.channels())
                                * bufferSize);
    this->m_isInput = device == ":jackinput:";

    return true;
}