예제 #1
0
/*!
\brief We need to start thread before activating in the server, otherwise the FW driver
connected to the client may not be activated.
*/
int JackClient::Activate()
{
    jack_log("JackClient::Activate");
    if (IsActive()) {
        return 0;
    }

    // RT thread is started only when needed...
    if (IsRealTime()) {
        if (StartThread() < 0) {
            return -1;
        }
    }

    /*
    Insertion of client in the graph will cause a kGraphOrderCallback notification
    to be delivered by the server, the client wants to receive it.
    */
    GetClientControl()->fActive = true;

    // Transport related callback become "active"
    GetClientControl()->fTransportSync = true;
    GetClientControl()->fTransportTimebase = true;

    int result = -1;
    GetClientControl()->fCallback[kRealTimeCallback] = IsRealTime();
    fChannel->ClientActivate(GetClientControl()->fRefNum, IsRealTime(), &result);
    return result;
}
예제 #2
0
// Notifications received from the server
// TODO this should be done once for all clients in the process, when a shared notification channel
// will be shared by all clients...
int JackLibClient::ClientNotifyImp(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2)
{
    int res = 0;
    assert(JackGlobals::fSynchroMutex);
    JackGlobals::fSynchroMutex->Lock();

    // Done all time
    switch (notify) {

        case kAddClient:
            jack_log("JackClient::AddClient name = %s, ref = %ld ", name, refnum);
            // the synchro must be usable in I/O mode when several clients live in the same process
            res = fSynchroTable[refnum].Connect(name, fServerName) ? 0 : -1;
            break;

        case kRemoveClient:
            jack_log("JackClient::RemoveClient name = %s, ref = %ld ", name, refnum);
            if (GetClientControl() && strcmp(GetClientControl()->fName, name) != 0) {
                res = fSynchroTable[refnum].Disconnect() ? 0 : -1;
            }
            break;
    }

    JackGlobals::fSynchroMutex->Unlock();
    return res;
}
예제 #3
0
int JackClient::PortRegister(const char* port_name, const char* port_type, unsigned long flags, unsigned long buffer_size)
{
    // Check if port name is empty
    string port_short_name_str = string(port_name);
    if (port_short_name_str.size() == 0) {
        jack_error("port_name is empty");
        return 0; // Means failure here...
    }

    // Check port name length
    string port_full_name_str = string(GetClientControl()->fName) + string(":") + port_short_name_str;
    if (port_full_name_str.size() >= REAL_JACK_PORT_NAME_SIZE) {
        jack_error("\"%s:%s\" is too long to be used as a JACK port name.\n"
                   "Please use %lu characters or less",
                   GetClientControl()->fName,
                   port_name,
                   JACK_PORT_NAME_SIZE - 1);
        return 0; // Means failure here...
    }

    int result = -1;
    jack_port_id_t port_index = NO_PORT;
    fChannel->PortRegister(GetClientControl()->fRefNum, port_full_name_str.c_str(), port_type, flags, buffer_size, &port_index, &result);

    if (result == 0) {
        jack_log("JackClient::PortRegister ref = %ld name = %s type = %s port_index = %ld", GetClientControl()->fRefNum, port_full_name_str.c_str(), port_type, port_index);
        fPortList.push_back(port_index);
        return port_index;
    } else {
        return 0;
    }
}
예제 #4
0
inline void JackClient::End()
{
    jack_log("JackClient::Execute end 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);
    fThread.Terminate();
}
예제 #5
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();
}
예제 #6
0
int JackClient::ReleaseTimebase()
{
    int result = -1;
    fChannel->ReleaseTimebase(GetClientControl()->fRefNum, &result);
    if (result == 0) {
        GetClientControl()->fTransportTimebase = false;
        fTimebase = NULL;
        fTimebaseArg = NULL;
    }
    return result;
}
예제 #7
0
int JackClient::SetPortConnectCallback(JackPortConnectCallback callback, void *arg)
{
    if (IsActive()) {
        jack_error("You cannot set callbacks on an active client");
        return -1;
    } else {
        GetClientControl()->fCallback[kPortConnectCallback] = (callback != NULL);
        GetClientControl()->fCallback[kPortDisconnectCallback] = (callback != NULL);
        fPortConnectArg = arg;
        fPortConnect = callback;
        return 0;
    }
}
예제 #8
0
int JackClient::SetFreewheelCallback(JackFreewheelCallback callback, void *arg)
{
    if (IsActive()) {
        jack_error("You cannot set callbacks on an active client");
        return -1;
    } else {
        GetClientControl()->fCallback[kStartFreewheelCallback] = (callback != NULL);
        GetClientControl()->fCallback[kStopFreewheelCallback] = (callback != NULL);
        fFreewheelArg = arg;
        fFreewheel = callback;
        return 0;
    }
}
예제 #9
0
char* JackClient::GetClientNameByUUID(const char* uuid)
{
    char name_res[JACK_CLIENT_NAME_SIZE + 1];
    int result = -1;
    fChannel->GetClientNameForUUID(GetClientControl()->fRefNum, uuid, name_res, &result);
    return (result) ? NULL : strdup(name_res);
}
예제 #10
0
char* JackClient::GetUUIDForClientName(const char* client_name)
{
    char uuid_res[JACK_UUID_SIZE];
    int result = -1;
    fChannel->GetUUIDForClientName(GetClientControl()->fRefNum, client_name, uuid_res, &result);
    return (result) ? NULL : strdup(uuid_res);
}
예제 #11
0
int JackClient::InternalClientLoad(const char* client_name, jack_options_t options, jack_status_t* status, jack_varargs_t* va)
{
    if (strlen(client_name) >= JACK_CLIENT_NAME_SIZE) {
        jack_error ("\"%s\" is too long for a JACK client name.\n"
                    "Please use %lu characters or less.",
                    client_name, JACK_CLIENT_NAME_SIZE);
        return 0;
    }

    if (va->load_name && (strlen(va->load_name) >= JACK_PATH_MAX)) {
        jack_error("\"%s\" is too long for a shared object name.\n"
                   "Please use %lu characters or less.",
                   va->load_name, JACK_PATH_MAX);
        int my_status1 = *status | (JackFailure | JackInvalidOption);
        *status = (jack_status_t)my_status1;
        return 0;
    }

    if (va->load_init && (strlen(va->load_init) >= JACK_LOAD_INIT_LIMIT)) {
        jack_error ("\"%s\" is too long for internal client init "
                    "string.\nPlease use %lu characters or less.",
                    va->load_init, JACK_LOAD_INIT_LIMIT);
        int my_status1 = *status | (JackFailure | JackInvalidOption);
        *status = (jack_status_t)my_status1;
        return 0;
    }

    int int_ref, result = -1;
    fChannel->InternalClientLoad(GetClientControl()->fRefNum, client_name, va->load_name, va->load_init, options, (int*)status, &int_ref, -1, &result);
    return int_ref;
}
예제 #12
0
char* JackClient::GetInternalClientName(int ref)
{
    char name_res[JACK_CLIENT_NAME_SIZE+1];
    int result = -1;
    fChannel->GetInternalClientName(GetClientControl()->fRefNum, ref, name_res, &result);
    return (result < 0) ? NULL : strdup(name_res);
}
예제 #13
0
int JackClient::PortDisconnect(jack_port_id_t src)
{
    jack_log("JackClient::PortDisconnect src = %ld", src);
    int result = -1;
    fChannel->PortDisconnect(GetClientControl()->fRefNum, src, ALL_PORTS, &result);
    return result;
}
예제 #14
0
/* Call the server if the client is active, otherwise keeps the arguments */
int JackClient::SetSyncCallback(JackSyncCallback sync_callback, void* arg)
{
    GetClientControl()->fTransportSync = (fSync != NULL);
    fSyncArg = arg;
    fSync = sync_callback;
    return ActivateAux();
}
예제 #15
0
int JackClient::SetTimebaseCallback(int conditional, JackTimebaseCallback timebase_callback, void* arg)
{
    int result = -1;
    fChannel->SetTimebaseCallback(GetClientControl()->fRefNum, conditional, &result);

    if (result == 0) {
        GetClientControl()->fTransportTimebase = true;
        fTimebase = timebase_callback;
        fTimebaseArg = arg;
        return ActivateAux();
    } else {
        fTimebase = NULL;
        fTimebaseArg = NULL;
        return result;
    }
}
예제 #16
0
inline void JackClient::SignalSync()
{
    // Resume: signal output clients connected to the running client
    if (GetGraphManager()->ResumeRefNum(GetClientControl(), fSynchroTable) < 0) {
        jack_error("ResumeRefNum error");
    }
}
예제 #17
0
inline bool JackClient::WaitSync()
{
    // Suspend itself: wait on the input synchro
    if (GetGraphManager()->SuspendRefNum(GetClientControl(), fSynchroTable, 0x7FFFFFFF) < 0) {
        jack_error("SuspendRefNum error");
        return false;
    } else {
        return true;
    }
}
예제 #18
0
inline void JackClient::CallSyncCallbackAux()
{
    if (GetClientControl()->fTransportSync) {

        JackTransportEngine& transport = GetEngineControl()->fTransport;
        jack_position_t* cur_pos = transport.ReadCurrentState();
        jack_transport_state_t transport_state = transport.GetState();

        if (fSync != NULL) {
            if (fSync(transport_state, cur_pos, fSyncArg)) {
                GetClientControl()->fTransportState = JackTransportRolling;
                GetClientControl()->fTransportSync = false;
            }
        } else {
            GetClientControl()->fTransportState = JackTransportRolling;
            GetClientControl()->fTransportSync = false;
        }
    }
}
예제 #19
0
void JackClient::OnInfoShutdown(JackInfoShutdownCallback callback, void *arg)
{
    if (IsActive()) {
        jack_error("You cannot set callbacks on an active client");
    } else {
        // Shutdown callback will either be an old API version or the new version (with info)
        GetClientControl()->fCallback[kShutDownCallback] = (callback != NULL);
        fInfoShutdownArg = arg;
        fInfoShutdown = callback;
    }
}
예제 #20
0
int JackClient::Close()
{
    jack_log("JackClient::Close ref = %ld", GetClientControl()->fRefNum);
    int result = 0;

    Deactivate();
    
    // Channels is stopped first to avoid receiving notifications while closing
    fChannel->Stop();  
    // Then close client
    fChannel->ClientClose(GetClientControl()->fRefNum, &result);
  
    fChannel->Close();
    assert(JackGlobals::fSynchroMutex);
    JackGlobals::fSynchroMutex->Lock();
    fSynchroTable[GetClientControl()->fRefNum].Disconnect();
    JackGlobals::fSynchroMutex->Unlock();
    JackGlobals::fClientTable[GetClientControl()->fRefNum] = NULL;
    return result;
}
예제 #21
0
int JackClient::SetSessionCallback(JackSessionCallback callback, void *arg)
{
    if (IsActive()) {
        jack_error("You cannot set callbacks on an active client");
        return -1;
    } else {
        GetClientControl()->fCallback[kSessionCallback] = (callback != NULL);
        fSessionArg = arg;
        fSession = callback;
        return 0;
    }
}
예제 #22
0
int JackClient::SetBufferSizeCallback(JackBufferSizeCallback callback, void *arg)
{
    if (IsActive()) {
        jack_error("You cannot set callbacks on an active client");
        return -1;
    } else {
        GetClientControl()->fCallback[kBufferSizeCallback] = (callback != NULL);
        fBufferSizeArg = arg;
        fBufferSize = callback;
        return 0;
    }
}
예제 #23
0
inline int JackClient::ActivateAux()
{
    // If activated without RT thread...
    if (IsActive() && fThread.GetStatus() != JackThread::kRunning) {

        jack_log("JackClient::ActivateAux");

        // RT thread is started
        if (StartThread() < 0) {
            return -1;
        }

        int result = -1;
        GetClientControl()->fCallback[kRealTimeCallback] = IsRealTime();
        fChannel->ClientActivate(GetClientControl()->fRefNum, IsRealTime(), &result);
        return result;

    } else {
        return 0;
    }
}
예제 #24
0
int JackClient::SetGraphOrderCallback(JackGraphOrderCallback callback, void *arg)
{
    if (IsActive()) {
        jack_error("You cannot set callbacks on an active client");
        return -1;
    } else {
        GetClientControl()->fCallback[kGraphOrderCallback] = (callback != NULL);
        fGraphOrder = callback;
        fGraphOrderArg = arg;
        return 0;
    }
}
예제 #25
0
inline void JackClient::CallTimebaseCallbackAux()
{
    JackTransportEngine& transport = GetEngineControl()->fTransport;
    int master;
    bool unused;

    transport.GetTimebaseMaster(master, unused);

    if (GetClientControl()->fRefNum == master && fTimebase) { // Client *is* timebase...

        jack_transport_state_t transport_state = transport.GetState();
        jack_position_t* cur_pos = transport.WriteNextStateStart(1);

        if (GetClientControl()->fTransportTimebase) {
            fTimebase(transport_state, GetEngineControl()->fBufferSize, cur_pos, true, fTimebaseArg);
            GetClientControl()->fTransportTimebase = false; // Callback is called only once with "new_pos" = true
        } else if (transport_state == JackTransportRolling) {
            fTimebase(transport_state, GetEngineControl()->fBufferSize, cur_pos, false, fTimebaseArg);
        }

        transport.WriteNextStateStop(1);
    }
}
예제 #26
0
int JackClient::PortDisconnect(const char* src, const char* dst)
{
    jack_log("JackClient::Disconnect src = %s dst = %s", src, dst);
    if (strlen(src) >= REAL_JACK_PORT_NAME_SIZE) {
        jack_error("\"%s\" is too long to be used as a JACK port name.\n", src);
        return -1; 
    }
    if (strlen(dst) >= REAL_JACK_PORT_NAME_SIZE) {
        jack_error("\"%s\" is too long to be used as a JACK port name.\n", src);
        return -1; 
    }
    int result = -1;
    fChannel->PortDisconnect(GetClientControl()->fRefNum, src, dst, &result);
    return result;
}
예제 #27
0
int JackClient::PortUnRegister(jack_port_id_t port_index)
{
    jack_log("JackClient::PortUnRegister port_index = %ld", port_index);
    list<jack_port_id_t>::iterator it = find(fPortList.begin(), fPortList.end(), port_index);

    if (it != fPortList.end()) {
        fPortList.erase(it);
        int result = -1;
        fChannel->PortUnRegister(GetClientControl()->fRefNum, port_index, &result);
        return result;
    } else {
        jack_error("unregistering a port %ld that is not own by the client", port_index);
        return -1;
    }
}
예제 #28
0
int JackClient::SessionReply(jack_session_event_t* ev)
{
    if (ev->command_line) {
        strncpy(GetClientControl()->fSessionCommand, ev->command_line, sizeof(GetClientControl()->fSessionCommand));
    } else {
        GetClientControl()->fSessionCommand[0] = '\0';
    }

    GetClientControl()->fSessionFlags = ev->flags;

    jack_log("JackClient::SessionReply... we are here");
    if (fChannel->IsChannelThread()) {
        jack_log("JackClient::SessionReply... in callback reply");
        // OK, immediate reply...
        fSessionReply = kImmediateSessionReply;
        return 0;
    }

    jack_log("JackClient::SessionReply... out of cb");

    int result = -1;
    fChannel->SessionReply(GetClientControl()->fRefNum, &result);
    return result;
}
예제 #29
0
/*!
\brief Need to stop thread after deactivating in the server.
*/
int JackClient::Deactivate()
{
    jack_log("JackClient::Deactivate");
    if (!IsActive()) {
        return 0;
    }

    GetClientControl()->fActive = false;

    // Transport related callback become "unactive"
    GetClientControl()->fTransportSync = false;
    GetClientControl()->fTransportTimebase = false;

    // We need to wait for the new engine cycle before stopping the RT thread, but this is done by ClientDeactivate
    int result = -1;
    fChannel->ClientDeactivate(GetClientControl()->fRefNum, &result);
    jack_log("JackClient::Deactivate res = %ld", result);

    // RT thread is stopped only when needed...
    if (IsRealTime()) {
        fThread.Kill();
    }
    return result;
}
예제 #30
0
int JackClient::SetSampleRateCallback(JackSampleRateCallback callback, void *arg)
{
    if (IsActive()) {
        jack_error("You cannot set callbacks on an active client");
        return -1;
    } else {
        GetClientControl()->fCallback[kSampleRateCallback] = (callback != NULL);
        fSampleRateArg = arg;
        fSampleRate = callback;
        // Now invoke it
        if (callback) {
            callback(GetEngineControl()->fSampleRate, arg);
        }
        return 0;
    }
}