Exemple #1
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;
}
Exemple #2
0
int JackLibClient::Open(const char* server_name, const char* name, int uuid, jack_options_t options, jack_status_t* status)
{
    int shared_engine, shared_client, shared_graph, result;
    bool res;
    jack_log("JackLibClient::Open name = %s", name);
    
    if (strlen(name) >= JACK_CLIENT_NAME_SIZE) {
        jack_error("\"%s\" is too long to be used as a JACK client name.\n"
                   "Please use %lu characters or less",
                   name,
                   JACK_CLIENT_NAME_SIZE - 1);
        return -1; 
    }
    
    strncpy(fServerName, server_name, sizeof(fServerName));

    // Open server/client channel
    char name_res[JACK_CLIENT_NAME_SIZE+1];
    if (fChannel->Open(server_name, name, uuid, name_res, this, options, status) < 0) {
        jack_error("Cannot connect to the server");
        goto error;
    }

    // Start receiving notifications
    if (fChannel->Start() < 0) {
        jack_error("Cannot start channel");
        goto error;
    }

    // Require new client
    fChannel->ClientOpen(name_res, JackTools::GetPID(), uuid, &shared_engine, &shared_client, &shared_graph, &result);
    if (result < 0) {
        jack_error("Cannot open %s client", name_res);
        goto error;
    }

    try {
        // Map shared memory segments
        JackLibGlobals::fGlobals->fEngineControl.SetShmIndex(shared_engine, fServerName);
        JackLibGlobals::fGlobals->fGraphManager.SetShmIndex(shared_graph, fServerName);
        fClientControl.SetShmIndex(shared_client, fServerName);
        JackGlobals::fVerbose = GetEngineControl()->fVerbose;
    } catch (...) {
        jack_error("Map shared memory segments exception");
        goto error;
    }

    SetupDriverSync(false);

    // Connect shared synchro : the synchro must be usable in I/O mode when several clients live in the same process
    assert(JackGlobals::fSynchroMutex);
    JackGlobals::fSynchroMutex->Lock();
    res = fSynchroTable[GetClientControl()->fRefNum].Connect(name_res, fServerName);
    JackGlobals::fSynchroMutex->Unlock();
    if (!res) {
        jack_error("Cannot ConnectSemaphore %s client", name_res);
        goto error;
    }

    JackGlobals::fClientTable[GetClientControl()->fRefNum] = this;
    SetClockSource(GetEngineControl()->fClockSource);
    jack_log("JackLibClient::Open name = %s refnum = %ld", name_res, GetClientControl()->fRefNum);
    return 0;

error:
    fChannel->Stop();
    fChannel->Close();
    return -1;
}