예제 #1
0
    void JackNetAdapter::EncodeTransportData()
    {
        //is there a timebase master change ?
        int refnum = -1;
        bool conditional = 0;
        //TODO : get the actual timebase master
        if (refnum != fLastTimebaseMaster) {
            //timebase master has released its function
            if (refnum == -1) {
                fReturnTransportData.fTimebaseMaster = RELEASE_TIMEBASEMASTER;
                jack_info("Sending a timebase master release request.");
            } else {
                //there is a new timebase master
                fReturnTransportData.fTimebaseMaster = (conditional) ? CONDITIONAL_TIMEBASEMASTER : TIMEBASEMASTER;
                jack_info("Sending a %s timebase master request.", (conditional) ? "conditional" : "non-conditional");
            }
            fLastTimebaseMaster = refnum;
        } else {
            fReturnTransportData.fTimebaseMaster = NO_CHANGE;
        }

        //update transport state and position
        fReturnTransportData.fState = jack_transport_query(fClient, &fReturnTransportData.fPosition);

        //is it a new state (that the master need to know...) ?
        fReturnTransportData.fNewState = ((fReturnTransportData.fState != fLastTransportState) &&
                                           (fReturnTransportData.fState != fSendTransportData.fState));
        if (fReturnTransportData.fNewState) {
            jack_info("Sending transport state '%s'.", GetTransportState(fReturnTransportData.fState));
        }
        fLastTransportState = fReturnTransportData.fState;
    }
예제 #2
0
JackServer::JackServer(bool sync, bool temporary, int timeout, bool rt, int priority, int port_max, bool verbose, jack_timer_type_t clock, const char* server_name)
{
    if (rt) {
        jack_info("JACK server starting in realtime mode with priority %ld", priority);
    } else {
        jack_info("JACK server starting in non-realtime mode");
    }

    fGraphManager = JackGraphManager::Allocate(port_max);
    fEngineControl = new JackEngineControl(sync, temporary, timeout, rt, priority, verbose, clock, server_name);
    fEngine = new JackLockedEngine(fGraphManager, GetSynchroTable(), fEngineControl);

    // A distinction is made between the threaded freewheel driver and the
    // regular freewheel driver because the freewheel driver needs to run in
    // threaded mode when freewheel mode is active and needs to run as a slave
    // when freewheel mode isn't active.
    JackFreewheelDriver *freewheelDriver =
        new JackFreewheelDriver(fEngine, GetSynchroTable());
    fThreadedFreewheelDriver = new JackThreadedDriver(freewheelDriver);

    fFreewheelDriver = freewheelDriver;
    fDriverInfo = new JackDriverInfo();
    fAudioDriver = NULL;
    fFreewheel = false;
    JackServerGlobals::fInstance = this;   // Unique instance
    JackServerGlobals::fUserCount = 1;     // One user
    JackGlobals::fVerbose = verbose;
}
예제 #3
0
//transport---------------------------------------------------------------------------
    void JackNetAdapter::DecodeTransportData()
    {
        //TODO : we need here to get the actual timebase master to eventually release it from its duty (see JackNetDriver)

        //is there a new transport state ?
        if (fSendTransportData.fNewState &&(fSendTransportData.fState != jack_transport_query(fClient, NULL))) {
            switch (fSendTransportData.fState)
            {
                case JackTransportStopped :
                    jack_transport_stop(fClient);
                    jack_info("NetMaster : transport stops");
                    break;

                case JackTransportStarting :
                    jack_transport_reposition(fClient, &fSendTransportData.fPosition);
                    jack_transport_start(fClient);
                    jack_info("NetMaster : transport starts");
                    break;

                case JackTransportRolling :
                    // TODO, we need to :
                    // - find a way to call TransportEngine->SetNetworkSync()
                    // - turn the transport state to JackTransportRolling
                    jack_info("NetMaster : transport rolls");
                    break;
            }
        }
    }
예제 #4
0
 SERVER_EXPORT void NetTransportDataDisplay ( net_transport_data_t* data )
 {
     jack_info ( "********************Network Transport********************" );
     jack_info ( "Transport new state : %u", data->fNewState );
     jack_info ( "Transport timebase master : %u", data->fTimebaseMaster );
     jack_info ( "Transport cycle state : %u", data->fState );
     jack_info ( "**********************************************" );
 }
예제 #5
0
    int JackNetMasterInterface::SyncRecv()
    {
        packet_header_t* rx_head = reinterpret_cast<packet_header_t*> ( fRxBuffer );
        int rx_bytes = Recv ( fParams.fMtu, MSG_PEEK );
        
        if ( ( rx_bytes == 0 ) || ( rx_bytes == SOCKET_ERROR ) )
            return rx_bytes;

        fCycleOffset = fTxHeader.fCycle - rx_head->fCycle;
      
        switch ( fParams.fNetworkMode )
        {
            case 's' :
                //slow mode : allow to use full bandwidth and heavy process on the slave
                //  - extra latency is set to two cycles, one cycle for send/receive operations + one cycle for heavy process on the slave
                //  - if the network is two fast, just wait the next cycle, this mode allows a shorter cycle duration for the master
                //  - this mode will skip the two first cycles, thus it lets time for data to be processed and queued on the socket rx buffer
                //the slow mode is the safest mode because it wait twice the bandwidth relative time (send/return + process)
                if (fCycleOffset < 2)
                     return 0;
                else
                    rx_bytes = Recv ( rx_head->fPacketSize, 0 );
                    
                if (fCycleOffset > 2) {
                    jack_info("Warning : '%s' runs in slow network mode, but data received too late (%d cycle(s) offset)", fParams.fName, fCycleOffset);
                }
                break;

            case 'n' :
                //normal use of the network :
                //  - extra latency is set to one cycle, what is the time needed to receive streams using full network bandwidth
                //  - if the network is too fast, just wait the next cycle, the benefit here is the master's cycle is shorter
                //  - indeed, data is supposed to be on the network rx buffer, so we don't have to wait for it
                if (fCycleOffset < 1)
                    return 0;
                else
                    rx_bytes = Recv ( rx_head->fPacketSize, 0 );
                    
                if (fCycleOffset != 1) 
                    jack_info("'%s' can't run in normal network mode, data received too late (%d cycle(s) offset)", fParams.fName, fCycleOffset);
                break;

            case 'f' :
                //fast mode suppose the network bandwith is larger than required for the transmission (only a few channels for example)
                //    - packets can be quickly received, quickly is here relative to the cycle duration
                //    - here, receive data, we can't keep it queued on the rx buffer,
                //    - but if there is a cycle offset, tell the user, that means we're not in fast mode anymore, network is too slow
                rx_bytes = Recv ( rx_head->fPacketSize, 0 );
                
                if (fCycleOffset != 0)
                    jack_info("'%s' can't run in fast network mode, data received too late (%d cycle(s) offset)", fParams.fName, fCycleOffset);
                break;
        }

        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
        return rx_bytes;
    }
예제 #6
0
int JackLoadableInternalClient::Init(const char* so_name)
{
    char path_to_so[JACK_PATH_MAX + 1];
    BuildClientPath(path_to_so, sizeof(path_to_so), so_name);

    fHandle = LoadJackModule(path_to_so);
    jack_log("JackLoadableInternalClient::JackLoadableInternalClient path_to_so = %s", path_to_so);

    if (fHandle == NULL) {
        PrintLoadError(so_name);
        return -1;
    }

    fFinish = (FinishCallback)GetJackProc(fHandle, "jack_finish");
    if (fFinish == NULL) {
        UnloadJackModule(fHandle);
        jack_error("symbol jack_finish cannot be found in %s", so_name);
        return -1;
    }

    fDescriptor = (JackDriverDescFunction)GetJackProc(fHandle, "jack_get_descriptor");
    if (fDescriptor == NULL) {
        jack_info("No jack_get_descriptor entry-point for %s", so_name);
    }
    return 0;
}
예제 #7
0
    bool JackNetSlaveInterface::Init()
    {
        jack_log("JackNetSlaveInterface::Init()");

        // set the parameters to send
        strcpy(fParams.fPacketType, "params");
        fParams.fProtocolVersion = NETWORK_PROTOCOL;
        SetPacketType(&fParams, SLAVE_AVAILABLE);

        // init loop : get a master and start, do it until connection is ok
        net_status_t status;
        do {
            // first, get a master, do it until a valid connection is running
            do {
                status = SendAvailableToMaster();
                if (status == NET_SOCKET_ERROR) {
                    return false;
                }
            }
            while (status != NET_CONNECTED);

            // then tell the master we are ready
            jack_info("Initializing connection with %s...", fParams.fMasterNetName);
            status = SendStartToMaster();
            if (status == NET_ERROR) {
                return false;
            }
        }
        while (status != NET_ROLLING);

        return true;
    }
예제 #8
0
static void
hammerfall_check_sync (hammerfall_t *h, snd_ctl_elem_value_t *ctl)

{
	const char *name;
	int val;
	snd_ctl_elem_id_t *ctl_id;
	
	jack_info ("check sync");

	snd_ctl_elem_id_alloca (&ctl_id);
	snd_ctl_elem_value_get_id (ctl, ctl_id);

	name = snd_ctl_elem_id_get_name (ctl_id);

	if (strcmp (name, "ADAT1 Sync Check") == 0) {
		val = snd_ctl_elem_value_get_enumerated (ctl, 0);
		hammerfall_check_sync_state (h, val, 0);
	} else if (strcmp (name, "ADAT2 Sync Check") == 0) {
		val = snd_ctl_elem_value_get_enumerated (ctl, 0);
		hammerfall_check_sync_state (h, val, 1);
	} else if (strcmp (name, "ADAT3 Sync Check") == 0) {
		val = snd_ctl_elem_value_get_enumerated (ctl, 0);
		hammerfall_check_sync_state (h, val, 2);
	} else {
		jack_error ("Hammerfall: unknown control \"%s\"", name);
	}
}
예제 #9
0
static char* get_control_device_name(const char * device_name)
{
    char * ctl_name;
    regex_t expression;

    regcomp(&expression, "(plug)?hw:[0-9](,[0-9])?", REG_ICASE | REG_EXTENDED);

    if (!regexec(&expression, device_name, 0, NULL, 0)) {
        /* the user wants a hw or plughw device, the ctl name
         * should be hw:x where x is the card number */

        char tmp[5];
        strncpy(tmp, strstr(device_name, "hw"), 4);
        tmp[4] = '\0';
        jack_info("control device %s",tmp);
        ctl_name = strdup(tmp);
    } else {
        ctl_name = strdup(device_name);
    }

    regfree(&expression);

    if (ctl_name == NULL) {
        jack_error("strdup(\"%s\") failed.", ctl_name);
    }

    return ctl_name;
}
예제 #10
0
    void JackNetMasterInterface::Exit()
    {
        jack_log("JackNetMasterInterface::Exit, ID %u", fParams.fID);

        // stop process
        fRunning = false;

        // send a 'multicast euthanasia request' - new socket is required on macosx
        jack_info("Exiting '%s' %s", fParams.fName, fMulticastIP);
        SetPacketType(&fParams, KILL_MASTER);
        JackNetSocket mcast_socket(fMulticastIP, fSocket.GetPort());

        session_params_t net_params;
        memset(&net_params, 0, sizeof(session_params_t));
        SessionParamsHToN(&fParams, &net_params);

        if (mcast_socket.NewSocket() == SOCKET_ERROR) {
            jack_error("Can't create socket : %s", StrError(NET_ERROR_CODE));
        }
        if (mcast_socket.SendTo(&net_params, sizeof(session_params_t), 0, fMulticastIP) == SOCKET_ERROR) {
            jack_error("Can't send suicide request : %s", StrError(NET_ERROR_CODE));
        }

        mcast_socket.Close();
    }
예제 #11
0
 bool JackNetAdapter::Execute()
 {
     try {
         // Keep running even in case of error
         while (fThread.GetStatus() == JackThread::kRunning) {
             if (Process() == SOCKET_ERROR) {
                 return false;
             }
         }
         return false;
     } catch (JackNetException& e) {
         // Otherwise just restart...
         e.PrintMessage();
         jack_info("NetAdapter is restarted");
         Reset();
         fThread.DropSelfRealTime();
         fThread.SetStatus(JackThread::kIniting);
         if (Init()) {
             fThread.SetStatus(JackThread::kRunning);
             return true;
         } else {
             return false;
         }
     }
 }
예제 #12
0
static OSStatus display_device_names()
{
	UInt32 size;
	Boolean isWritable;
	int i, deviceNum;
	OSStatus err;
	CFStringRef UIname;
	
	err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &size, &isWritable);
    if (err != noErr) 
		return err;
		
	deviceNum = size/sizeof(AudioDeviceID);
	AudioDeviceID devices[deviceNum];
	
	err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &size, devices);
    if (err != noErr) 
		return err;
	
	for (i = 0; i < deviceNum; i++) {
        char device_name[256];
		char internal_name[256];
		
		size = sizeof(CFStringRef);
		UIname = NULL;
		err = AudioDeviceGetProperty(devices[i], 0, false, kAudioDevicePropertyDeviceUID, &size, &UIname);
		if (err == noErr) {
			CFStringGetCString(UIname, internal_name, 256, CFStringGetSystemEncoding());
		} else {
			goto error;
		}
		
		size = 256;
		err = AudioDeviceGetProperty(devices[i], 0, false, kAudioDevicePropertyDeviceName, &size, device_name);
		if (err != noErr) 
			return err; 
		jack_info("ICI");
		jack_info("Device name = \'%s\', internal_name = \'%s\' (to be used as -d parameter)", device_name, internal_name); 
	}
	
	return noErr;

error:
	if (UIname != NULL)
		CFRelease(UIname);
	return err;
}
예제 #13
0
파일: JackDriver.cpp 프로젝트: agraf/jack2
void JackDriver::RestoreConnections()
{
    list<pair<string, string> >::const_iterator it;

    for (it = fConnections.begin(); it != fConnections.end(); it++) {
        pair<string, string> connection = *it;
        jack_info("Restore connection: %s %s", connection.first.c_str(), connection.second.c_str());
        fEngine->PortConnect(fClientControl.fRefNum, connection.first.c_str(), connection.second.c_str());
    }
}
예제 #14
0
    bool JackNetMasterInterface::Init()
    {
        jack_log("JackNetMasterInterface::Init : ID %u", fParams.fID);

        session_params_t host_params;
        uint attempt = 0;
        int rx_bytes = 0;

        // socket
        if (fSocket.NewSocket() == SOCKET_ERROR) {
            jack_error("Can't create socket : %s", StrError(NET_ERROR_CODE));
            return false;
        }

        // timeout on receive (for init)
        if (fSocket.SetTimeOut(MASTER_INIT_TIMEOUT) < 0) {
            jack_error("Can't set init timeout : %s", StrError(NET_ERROR_CODE));
        }

        // connect
        if (fSocket.Connect() == SOCKET_ERROR) {
            jack_error("Can't connect : %s", StrError(NET_ERROR_CODE));
            return false;
        }

        // send 'SLAVE_SETUP' until 'START_MASTER' received
        jack_info("Sending parameters to %s...", fParams.fSlaveNetName);
        do
        {
            session_params_t net_params;
            memset(&net_params, 0, sizeof(session_params_t));
            SetPacketType(&fParams, SLAVE_SETUP);
            SessionParamsHToN(&fParams, &net_params);

            if (fSocket.Send(&net_params, sizeof(session_params_t), 0) == SOCKET_ERROR) {
                jack_error("Error in send : %s", StrError(NET_ERROR_CODE));
            }

            memset(&net_params, 0, sizeof(session_params_t));
            if (((rx_bytes = fSocket.Recv(&net_params, sizeof(session_params_t), 0)) == SOCKET_ERROR) && (fSocket.GetError() != NET_NO_DATA)) {
                jack_error("Problem with network");
                return false;
            }

            SessionParamsNToH(&net_params, &host_params);
        }
        while ((GetPacketType(&host_params) != START_MASTER) && (++attempt < SLAVE_SETUP_RETRY));
        
        if (attempt == SLAVE_SETUP_RETRY) {
            jack_error("Slave doesn't respond, exiting");
            return false;
        }

        return true;
    }
예제 #15
0
 void NetMidiBuffer::DisplayEvents()
 {
     for ( int port_index = 0; port_index < fNPorts; port_index++ )
     {
         for ( uint event = 0; event < fPortBuffer[port_index]->event_count; event++ )
             if ( fPortBuffer[port_index]->IsValid() )
                 jack_info ( "port %d : midi event %u/%u -> time : %u, size : %u",
                             port_index + 1, event + 1, fPortBuffer[port_index]->event_count,
                             fPortBuffer[port_index]->events[event].time, fPortBuffer[port_index]->events[event].size );
     }
 }
예제 #16
0
파일: JackDriver.cpp 프로젝트: agraf/jack2
void JackDriver::SaveConnections()
{
    const char** connections;
    fConnections.clear();
    char alias1[REAL_JACK_PORT_NAME_SIZE];
    char alias2[REAL_JACK_PORT_NAME_SIZE];
    char* aliases[2];

    aliases[0] = alias1;
    aliases[1] = alias2;

    for (int i = 0; i < fCaptureChannels; ++i) {
        if (fCapturePortList[i] && (connections = fGraphManager->GetConnections(fCapturePortList[i])) != 0) {
            for (int j = 0; connections[j]; j++) {
                /*
                fGraphManager->GetPort(fCapturePortList[i])->GetAliases(aliases);
                fConnections.push_back(make_pair(aliases[0], connections[j]));
                jack_info("Save connection: %s %s", aliases[0], connections[j]);
                */
                fConnections.push_back(make_pair(string(fGraphManager->GetPort(fCapturePortList[i])->GetName()), string(connections[j])));
                jack_info("Save connection: %s %s", fGraphManager->GetPort(fCapturePortList[i])->GetName(), connections[j]);
            }
            free(connections);
        }
    }

    for (int i = 0; i < fPlaybackChannels; ++i) {
        if (fPlaybackPortList[i] && (connections = fGraphManager->GetConnections(fPlaybackPortList[i])) != 0) {
            for (int j = 0; connections[j]; j++) {
                /*
                fGraphManager->GetPort(fPlaybackPortList[i])->GetAliases(aliases);
                fConnections.push_back(make_pair(connections[j], aliases[0]));
                jack_info("Save connection: %s %s", connections[j], aliases[0]);
                */
                fConnections.push_back(make_pair(string(connections[j]), string(fGraphManager->GetPort(fPlaybackPortList[i])->GetName())));
                jack_info("Save connection: %s %s", connections[j], fGraphManager->GetPort(fPlaybackPortList[i])->GetName());
            }
            free(connections);
        }
    }
}
예제 #17
0
//open/close--------------------------------------------------------------------------
    int JackNetAdapter::Open()
    {
        jack_info("NetAdapter started in %s mode %s Master's transport sync.",
                    (fParams.fSlaveSyncMode) ? "sync" : "async", (fParams.fTransportSync) ? "with" : "without");

        if (fThread.StartSync() < 0) {
            jack_error("Cannot start netadapter thread");
            return -1;
        }

        return 0;
    }
예제 #18
0
    int JackNetSlaveInterface::DataRecv()
    {
        uint recvd_midi_pckt = 0;
        uint recvd_audio_pckt = 0;
        int rx_bytes = 0;
        packet_header_t* rx_head = reinterpret_cast<packet_header_t*> ( fRxBuffer );

        while ( !fRxHeader.fIsLastPckt )
        {
            rx_bytes = Recv ( fParams.fMtu, MSG_PEEK );
            //error here, problem with recv, just skip the cycle (return -1)

            if ( rx_bytes == SOCKET_ERROR )
                return rx_bytes;
            if ( rx_bytes && ( rx_head->fDataStream == 's' ) && ( rx_head->fID == fParams.fID ) )
            {
                switch ( rx_head->fDataType )
                {
                    case 'm':   //midi
                        rx_bytes = Recv ( rx_head->fPacketSize, 0 );
                        fRxHeader.fCycle = rx_head->fCycle;
                        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
                        fNetMidiCaptureBuffer->RenderFromNetwork ( rx_head->fSubCycle, rx_bytes - sizeof ( packet_header_t ) );
                        if ( ++recvd_midi_pckt == rx_head->fNMidiPckt )
                            fNetMidiCaptureBuffer->RenderToJackPorts();
                        break;

                    case 'a':   //audio
                        rx_bytes = Recv ( rx_head->fPacketSize, 0 );
                        //SL: 25/01/09
                        // if ( !IsNextPacket() )
                        //    jack_error ( "Packet(s) missing..." );
                        if (recvd_audio_pckt++ != rx_head->fSubCycle) {
                            jack_error("Packet(s) missing from '%s'...", fParams.fMasterNetName);
                        }
                        fRxHeader.fCycle = rx_head->fCycle;
                        fRxHeader.fSubCycle = rx_head->fSubCycle;
                        fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
                        fNetAudioCaptureBuffer->RenderToJackPorts ( rx_head->fSubCycle );
                        break;

                    case 's':   //sync
                        jack_info ( "NetSlave : overloaded, skipping receive." );
                        return 0;
                }
            }
        }
        fRxHeader.fCycle = rx_head->fCycle;
        return 0;
    }
예제 #19
0
파일: JackDriver.cpp 프로젝트: diwic/jack2
void JackDriver::LoadConnections(int alias, bool full_name)
{
    list<pair<string, pair<string, string> > >::const_iterator it;
    
    if (full_name) {
        for (it = fConnections.begin(); it != fConnections.end(); it++) {
            pair<string, string> connection = (*it).second;
            jack_info("Load connection: %s %s", connection.first.c_str(), connection.second.c_str());
            fEngine->PortConnect(fClientControl.fRefNum, connection.first.c_str(), connection.second.c_str());
        }
    } else {
        const char** inputs = fGraphManager->GetPorts(NULL, NULL, JackPortIsInput);
        const char** outputs = fGraphManager->GetPorts(NULL, NULL, JackPortIsOutput);
        
        for (it = fConnections.begin(); it != fConnections.end(); it++) {
            pair<string, string> connection = (*it).second;
            string real_input = MatchPortName(connection.first.c_str(), outputs, alias, (*it).first);
            string real_output = MatchPortName(connection.second.c_str(), inputs, alias, (*it).first);
            if ((real_input != "") && (real_output != "")) {
                jack_info("Load connection: %s %s", real_input.c_str(), real_output.c_str());
                fEngine->PortConnect(fClientControl.fRefNum, real_input.c_str(), real_output.c_str());
            }
        }
        
        // Wait for connection change
        if (fGraphManager->IsPendingChange()) {
            JackSleep(int(fEngineControl->fPeriodUsecs * 1.1f));
        }
        
        if (inputs) {
            free(inputs);
        }
        if (outputs) {
            free(outputs);
        }
    }
}
예제 #20
0
파일: oss_driver.c 프로젝트: Llefjord/jack1
static int oss_driver_bufsize (oss_driver_t *driver, jack_nframes_t nframes)
{
	oss_driver_stop(driver);

	set_period_size(driver, nframes);
	if (driver->engine->set_buffer_size(driver->engine, driver->period_size)) {
		jack_error ("OSS: cannot set engine buffer size to %d (check MIDI)", driver->period_size);
		return -1;
	}
	jack_info("oss_driver: period size update: %u", nframes);

	oss_driver_start(driver);

	return 0;
}
예제 #21
0
SERVER_EXPORT void InitTime()
{
	QueryPerformanceFrequency(&_jack_freq);
    TIMECAPS caps;
    if (timeGetDevCaps(&caps, sizeof(TIMECAPS)) != TIMERR_NOERROR) {
        jack_error("InitTime : could not get timer device");
    } else {
        gPeriod = caps.wPeriodMin;
        if (timeBeginPeriod(gPeriod) != TIMERR_NOERROR) {
            jack_error("InitTime : could not set minimum timer");
            gPeriod = 0;
        } else {
            jack_info("InitTime : multimedia timer resolution set to %d milliseconds", gPeriod);
       }
    }
}
예제 #22
0
파일: thread.c 프로젝트: jackaudio/jack1
static int
jack_process_already_has_real_time_scheduling (int priority)
{
#if defined(__FreeBSD__)
	int res;
	struct rtprio rtp;
	res = rtprio(RTP_LOOKUP, getpid(), &rtp);
	if (res == 0 && rtp.type == RTP_PRIO_REALTIME && rtp.prio <= priority) {
		jack_info("process already runs at sufficient realtime priority %u (<=%d)",
			  (unsigned)rtp.prio,
			  priority);
		return 1; // process priority is sufficient
	}
#endif
	return 0; // no or don't know
}
예제 #23
0
    bool JackNetSlaveInterface::InitRendering()
    {
        jack_log("JackNetSlaveInterface::InitRendering()");

        net_status_t status;
        do {
            // then tell the master we are ready
            jack_info("Initializing connection with %s...", fParams.fMasterNetName);
            status = SendStartToMaster();
            if (status == NET_ERROR) {
                return false;
            }
        }
        while (status != NET_ROLLING);

        return true;
    }
예제 #24
0
static jack_driver_t *
dummy_driver_new (jack_client_t * client,
		  char *name,
		  unsigned int capture_ports,
		  unsigned int playback_ports,
		  jack_nframes_t sample_rate,
		  jack_nframes_t period_size,
		  unsigned long wait_time)
{
	dummy_driver_t * driver;

	jack_info ("creating dummy driver ... %s|%" PRIu32 "|%" PRIu32
		"|%lu|%u|%u", name, sample_rate, period_size, wait_time,
		capture_ports, playback_ports);

	driver = (dummy_driver_t *) calloc (1, sizeof (dummy_driver_t));

	jack_driver_nt_init ((jack_driver_nt_t *) driver);

	driver->write         = (JackDriverReadFunction)       dummy_driver_write;
	driver->null_cycle    = (JackDriverNullCycleFunction)  dummy_driver_null_cycle;
	driver->nt_attach     = (JackDriverNTAttachFunction)   dummy_driver_attach;
	driver->nt_start      = (JackDriverNTStartFunction)    dummy_driver_nt_start;
	driver->nt_detach     = (JackDriverNTDetachFunction)   dummy_driver_detach;
	driver->nt_bufsize    = (JackDriverNTBufSizeFunction)  dummy_driver_bufsize;
	driver->nt_run_cycle  = (JackDriverNTRunCycleFunction) dummy_driver_run_cycle;

	driver->period_usecs =
		(jack_time_t) floor ((((float) period_size) / sample_rate)
				     * 1000000.0f);
	driver->sample_rate = sample_rate;
	driver->period_size = period_size;
	driver->wait_time   = wait_time;
	//driver->next_time   = 0; // not needed since calloc clears the memory
	driver->last_wait_ust = 0;

	driver->capture_channels  = capture_ports;
	driver->capture_ports     = NULL;
	driver->playback_channels = playback_ports;
	driver->playback_ports    = NULL;

	driver->client = client;
	driver->engine = NULL;

	return (jack_driver_t *) driver;
}
bool JackWaitThreadedDriver::Execute()
{
    try {
        // Process a null cycle until NetDriver has started
        while (!fStarter.fRunning && fThread.GetStatus() == JackThread::kRunning) {
            fDriver->ProcessNull();
        }

        // Set RT
        if (fDriver->IsRealTime()) {
            jack_log("JackWaitThreadedDriver::Init IsRealTime");
            // Will do "something" on OSX only...
            GetEngineControl()->fPeriod = GetEngineControl()->fConstraint = GetEngineControl()->fPeriodUsecs * 1000;
            fThread.SetParams(GetEngineControl()->fPeriod, GetEngineControl()->fComputation, GetEngineControl()->fConstraint);
            if (fThread.AcquireSelfRealTime(GetEngineControl()->fServerPriority) < 0) {
                jack_error("AcquireSelfRealTime error");
            } else {
                set_threaded_log_function();
            }
        }

        // Switch to keep running even in case of error
        while (fThread.GetStatus() == JackThread::kRunning) {
            fDriver->Process();
        }
        return false;
    } catch (JackNetException& e) {
        e.PrintMessage();
        jack_info("Driver is restarted");
        fThread.DropSelfRealTime();
        // Thread in kIniting status again...
        fThread.SetStatus(JackThread::kIniting);
        if (Init()) {
            // Thread in kRunning status again...
            fThread.SetStatus(JackThread::kRunning);
            return true;
        } else {
            return false;
        }
	}
}
예제 #26
0
파일: JackEngine.cpp 프로젝트: Andux/jack2
// this check is to prevent apps to self connect to other apps
// TODO: make this work with multiple clients per app
int JackEngine::CheckPortsConnect(int refnum, jack_port_id_t src, jack_port_id_t dst)
{
    if (fSelfConnectMode == ' ') return 1;

    JackPort* src_port = fGraphManager->GetPort(src);
    JackPort* dst_port = fGraphManager->GetPort(dst);

    jack_log("JackEngine::CheckPortsConnect(ref = %d, src = %d, dst = %d)", refnum, src_port->GetRefNum(), dst_port->GetRefNum());

    //jack_log("%s -> %s", src_port->GetName(), dst_port->GetName());
    //jack_log("mode = '%c'", fSelfConnectMode);

    int src_self = src_port->GetRefNum() == refnum ? 1 : 0;
    int dst_self = dst_port->GetRefNum() == refnum ? 1 : 0;

    //jack_log("src_self is %s", src_self ? "true" : "false");
    //jack_log("dst_self is %s", dst_self ? "true" : "false");

    // 0 means client is connecting other client ports (control app patchbay functionality)
    // 1 means client is connecting its own port to port of other client (e.g. self connecting into "system" client)
    // 2 means client is connecting its own ports (for app internal functionality)
    int sum = src_self + dst_self;
    //jack_log("sum = %d", sum);
    if (sum == 0) return 1;
    char lmode = tolower(fSelfConnectMode);
    //jack_log("lmode = '%c'", lmode);
    if (sum == 2 && lmode == 'e') return 1;
    bool fail = lmode != fSelfConnectMode; // fail modes are upper case
    //jack_log("fail = %d", (int)fail);

    jack_info(
        "%s port self connect request%s (%s -> %s)",
        fail ? "rejecting" : "ignoring",
        sum == 1 ? " to external port" : "",
        src_port->GetName(),
        dst_port->GetName());

    return fail ? -1 : 0;
}
예제 #27
0
    int JackNetMasterInterface::SyncRecv()
    {
        int rx_bytes = 0;
        packet_header_t* rx_head = reinterpret_cast<packet_header_t*>(fRxBuffer);

        // receive sync (launch the cycle)
        do {
            rx_bytes = Recv(fParams.fMtu, MSG_PEEK);
            // connection issue (return -1)
            if (rx_bytes == SOCKET_ERROR) {
                return SOCKET_ERROR;
            }
        }
        while (strcmp(rx_head->fPacketType, "header") != 0);
        //PacketHeaderDisplay(rx_head);
        
        if (rx_head->fDataType != 's') {
            jack_error("Wrong packet type : %c", rx_head->fDataType);
            // not the last packet..
            fRxHeader.fIsLastPckt = 0;
            return SYNC_PACKET_ERROR;
        }
    
        fCurrentCycleOffset = fTxHeader.fCycle - rx_head->fCycle;

        if (fCurrentCycleOffset < fMaxCycleOffset && !fSynched) {
            jack_info("Synching with latency = %d", fCurrentCycleOffset);
            return NET_SYNCHING;
        } else {
            if (fCurrentCycleOffset == fMaxCycleOffset) {
                // when the sync offset is reached 
                fSynched = true;
            }
            rx_bytes = Recv(rx_head->fPacketSize, 0);
            fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
            return rx_bytes;
        }
    }
예제 #28
0
    int JackNetSlaveInterface::DataRecv()
    {
        int rx_bytes = 0;
        uint recvd_midi_pckt = 0;
        packet_header_t* rx_head = reinterpret_cast<packet_header_t*>(fRxBuffer);

        while (!fRxHeader.fIsLastPckt) {
            // how much data is queued on the rx buffer ?
            rx_bytes = Recv(fParams.fMtu, MSG_PEEK);

            // error here, just skip the cycle (return -1)
            if (rx_bytes == SOCKET_ERROR) {
                return rx_bytes;
            }

            if (rx_bytes && (rx_head->fDataStream == 's') && (rx_head->fID == fParams.fID)) {
                // read data
                switch (rx_head->fDataType) {

                    case 'm':   // midi
                        rx_bytes = MidiRecv(rx_head, fNetMidiCaptureBuffer, recvd_midi_pckt);
                        break;

                    case 'a':   // audio
                        rx_bytes = AudioRecv(rx_head, fNetAudioCaptureBuffer);
                        break;

                    case 's':   // sync
                        jack_info("NetSlave : missing last data packet");
                        return FinishRecv(fNetAudioCaptureBuffer);
                }
            }
        }

        fRxHeader.fCycle = rx_head->fCycle;
        return rx_bytes;
    }
예제 #29
0
파일: netjack.c 프로젝트: adiknoth/tschack
int netjack_wait( netjack_driver_state_t *netj )
{
    int we_have_the_expected_frame = 0;
    jack_nframes_t next_frame_avail;
    jack_time_t packet_recv_time_stamp;
    jacknet_packet_header *pkthdr;

    if( !netj->next_deadline_valid ) {
	    netj->next_deadline = jack_get_time() + netj->period_usecs;
	    netj->next_deadline_valid = 1;
    }

    // Increment expected frame here.

    if( netj->expected_framecnt_valid ) {
	netj->expected_framecnt += 1;
    } else {
	// starting up.... lets look into the packetcache, and fetch the highest packet.
	packet_cache_drain_socket( netj->packcache, netj->sockfd );
	if( packet_cache_get_highest_available_framecnt( netj->packcache, &next_frame_avail ) ) {
	    netj->expected_framecnt = next_frame_avail;
	    netj->expected_framecnt_valid = 1;
	} else {
	    // no packets there... start normally.
	    netj->expected_framecnt = 0;
	    netj->expected_framecnt_valid = 1;
	}

    }

    //jack_log( "expect %d", netj->expected_framecnt );
    // Now check if required packet is already in the cache.
    // then poll (have deadline calculated)
    // then drain socket, rinse and repeat.
    while(1) {
	if( packet_cache_get_next_available_framecnt( netj->packcache, netj->expected_framecnt, &next_frame_avail) ) {
	    if( next_frame_avail == netj->expected_framecnt ) {
		we_have_the_expected_frame = 1;
		if( !netj->always_deadline )
			break;
	    }
	}
	if( ! netjack_poll_deadline( netj->sockfd, netj->next_deadline ) ) {
	    break;
	}

	packet_cache_drain_socket( netj->packcache, netj->sockfd );
    }

    // check if we know who to send our packets too.
    if (!netj->srcaddress_valid)
	if( netj->packcache->master_address_valid ) {
	    memcpy (&(netj->syncsource_address), &(netj->packcache->master_address), sizeof( struct sockaddr_in ) );
	    netj->srcaddress_valid = 1;
	}

    // XXX: switching mode unconditionally is stupid.
    //      if we were running free perhaps we like to behave differently
    //      ie. fastforward one packet etc.
    //      well... this is the first packet we see. hmm.... dunno ;S
    //      it works... so...
    netj->running_free = 0;

    //if( !we_have_the_expected_frame )
    //    jack_error( "netxrun... %d", netj->expected_framecnt );

    if( we_have_the_expected_frame ) {

	jack_time_t now =  jack_get_time();
	if( now < netj->next_deadline )
		netj->time_to_deadline = netj->next_deadline - now;
	else
		netj->time_to_deadline = 0;

	packet_cache_retreive_packet_pointer( netj->packcache, netj->expected_framecnt, (char **) &(netj->rx_buf), netj->rx_bufsize , &packet_recv_time_stamp);
	pkthdr = (jacknet_packet_header *) netj->rx_buf;
	packet_header_ntoh(pkthdr);
	netj->deadline_goodness = (int)pkthdr->sync_state;
	netj->packet_data_valid = 1;

	int want_deadline;
	if( netj->jitter_val != 0 )
		want_deadline = netj->jitter_val;
	else if( netj->latency < 4 )
		want_deadline = -netj->period_usecs/2;
	else
		want_deadline = (netj->period_usecs/4+10*(int)netj->period_usecs*netj->latency/100);

	if( netj->deadline_goodness != MASTER_FREEWHEELS ) {
		if( netj->deadline_goodness < want_deadline ) {
			netj->next_deadline -= netj->period_usecs/100;
			//jack_log( "goodness: %d, Adjust deadline: --- %d\n", netj->deadline_goodness, (int) netj->period_usecs*netj->latency/100 );
		}
		if( netj->deadline_goodness > want_deadline ) {
			netj->next_deadline += netj->period_usecs/100;
			//jack_log( "goodness: %d, Adjust deadline: +++ %d\n", netj->deadline_goodness, (int) netj->period_usecs*netj->latency/100 );
		}
	}
//	if( netj->next_deadline < (netj->period_usecs*70/100) ) {
//		jack_error( "master is forcing deadline_offset to below 70%% of period_usecs... increase latency setting on master" );
//		netj->deadline_offset = (netj->period_usecs*90/100);
//	}

	netj->next_deadline += netj->period_usecs;
    } else {
	netj->time_to_deadline = 0;
	netj->next_deadline += netj->period_usecs;
	// bah... the packet is not there.
	// either
	// - it got lost.
	// - its late
	// - sync source is not sending anymore.

	// lets check if we have the next packets, we will just run a cycle without data.
	// in that case.

	if( packet_cache_get_next_available_framecnt( netj->packcache, netj->expected_framecnt, &next_frame_avail) )
	{
	    jack_nframes_t offset = next_frame_avail - netj->expected_framecnt;

	    //XXX: hmm... i need to remember why resync_threshold wasnt right.
	    //if( offset < netj->resync_threshold )
	    if( offset < 10 ) {
		// ok. dont do nothing. we will run without data.
		// this seems to be one or 2 lost packets.
		//
		// this can also be reordered packet jitter.
		// (maybe this is not happening in real live)
		//  but it happens in netem.

		netj->packet_data_valid = 0;

		// I also found this happening, when the packet queue, is too full.
		// but wtf ? use a smaller latency. this link can handle that ;S
		if( packet_cache_get_fill( netj->packcache, netj->expected_framecnt ) > 80.0 )
		    netj->next_deadline -= netj->period_usecs/2;


	    } else {
		// the diff is too high. but we have a packet in the future.
		// lets resync.
		netj->expected_framecnt = next_frame_avail;
		packet_cache_retreive_packet_pointer( netj->packcache, netj->expected_framecnt, (char **) &(netj->rx_buf), netj->rx_bufsize, NULL );
		pkthdr = (jacknet_packet_header *) netj->rx_buf;
		packet_header_ntoh(pkthdr);
		//netj->deadline_goodness = 0;
		netj->deadline_goodness = (int)pkthdr->sync_state - (int)netj->period_usecs * offset;
		netj->next_deadline_valid = 0;
		netj->packet_data_valid = 1;
	    }

	} else {
	    // no packets in buffer.
	    netj->packet_data_valid = 0;

	    //printf( "frame %d No Packet in queue. num_lost_packets = %d \n", netj->expected_framecnt, netj->num_lost_packets );
	    if( netj->num_lost_packets < 5 ) {
		// ok. No Packet in queue. The packet was either lost,
		// or we are running too fast.
		//
		// Adjusting the deadline unconditionally resulted in
		// too many xruns on master.
		// But we need to adjust for the case we are running too fast.
		// So lets check if the last packet is there now.
		//
		// It would not be in the queue anymore, if it had been
		// retrieved. This might break for redundancy, but
		// i will make the packet cache drop redundant packets,
		// that have already been retreived.
		//
		if( packet_cache_get_highest_available_framecnt( netj->packcache, &next_frame_avail) ) {
		    if( next_frame_avail == (netj->expected_framecnt - 1) ) {
			// Ok. the last packet is there now.
			// and it had not been retrieved.
			//
			// TODO: We are still dropping 2 packets.
			//       perhaps we can adjust the deadline
			//       when (num_packets lost == 0)

			// This might still be too much.
			netj->next_deadline += netj->period_usecs;
		    }
		}
	    } else if( (netj->num_lost_packets <= 100) ) {
		// lets try adjusting the deadline harder, for some packets, we might have just ran 2 fast.
		netj->next_deadline += netj->period_usecs*netj->latency/8;
	    } else {

		// But now we can check for any new frame available.
		//
		if( packet_cache_get_highest_available_framecnt( netj->packcache, &next_frame_avail) ) {
		    netj->expected_framecnt = next_frame_avail;
		    packet_cache_retreive_packet_pointer( netj->packcache, netj->expected_framecnt, (char **) &(netj->rx_buf), netj->rx_bufsize, NULL );
		    pkthdr = (jacknet_packet_header *) netj->rx_buf;
		    packet_header_ntoh(pkthdr);
		    netj->deadline_goodness = pkthdr->sync_state;
		    netj->next_deadline_valid = 0;
		    netj->packet_data_valid = 1;
		    netj->running_free = 0;
		    jack_info( "resync after freerun... %d", netj->expected_framecnt );
		} else {
		    if( netj->num_lost_packets == 101 ) {
			jack_info( "master seems gone... entering freerun mode", netj->expected_framecnt );
		    }

		    netj->running_free = 1;

		    // when we really dont see packets.
		    // reset source address. and open possibility for new master.
		    // maybe dsl reconnect. Also restart of netsource without fix
		    // reply address changes port.
		    if (netj->num_lost_packets > 200 ) {
			netj->srcaddress_valid = 0;
			packet_cache_reset_master_address( netj->packcache );
		    }
		}
	    }
	}
    }

    int retval = 0;

    if( !netj->packet_data_valid ) {
	netj->num_lost_packets += 1;
	if( netj->num_lost_packets == 1 )
	    retval = netj->period_usecs;
    } else {
	if( (netj->num_lost_packets>1) && !netj->running_free )
	    retval = (netj->num_lost_packets-1) * netj->period_usecs;

	netj->num_lost_packets = 0;
    }

    return retval;
}
예제 #30
0
파일: netjack.c 프로젝트: adiknoth/tschack
int
netjack_startup( netjack_driver_state_t *netj )
{
    int first_pack_len;
    struct sockaddr_in address;
    // Now open the socket, and wait for the first packet to arrive...
    netj->sockfd = socket (AF_INET, SOCK_DGRAM, 0);
#ifdef WIN32
    if (netj->sockfd == INVALID_SOCKET)
#else
    if (netj->sockfd == -1)
#endif
    {
        jack_info ("socket error");
        return -1;
    }
    address.sin_family = AF_INET;
    address.sin_port = htons(netj->listen_port);
    address.sin_addr.s_addr = htonl(INADDR_ANY);
    if (bind (netj->sockfd, (struct sockaddr *) &address, sizeof (address)) < 0)
    {
        jack_info("bind error");
        return -1;
    }

    netj->outsockfd = socket (AF_INET, SOCK_DGRAM, 0);
#ifdef WIN32
    if (netj->outsockfd == INVALID_SOCKET)
#else
    if (netj->outsockfd == -1)
#endif
    {
        jack_info ("socket error");
        return -1;
    }
    netj->srcaddress_valid = 0;
    if (netj->use_autoconfig)
    {
	jacknet_packet_header *first_packet = alloca (sizeof (jacknet_packet_header));
#ifdef WIN32
    int address_size = sizeof( struct sockaddr_in );
#else
	socklen_t address_size = sizeof (struct sockaddr_in);
#endif
	//jack_info ("Waiting for an incoming packet !!!");
	//jack_info ("*** IMPORTANT *** Dont connect a client to jackd until the driver is attached to a clock source !!!");

    while(1) {
    if( ! netjack_poll( netj->sockfd, 1000 ) ) {
	    jack_info ("Waiting aborted");
	    return -1;
    }
    first_pack_len = recvfrom (netj->sockfd, (char *)first_packet, sizeof (jacknet_packet_header), 0, (struct sockaddr*) & netj->syncsource_address, &address_size);
#ifdef WIN32
        if( first_pack_len == -1 ) {
            first_pack_len = sizeof(jacknet_packet_header);
            break;
        }
#else
        if (first_pack_len == sizeof (jacknet_packet_header))
            break;
#endif
    }
	netj->srcaddress_valid = 1;

	if (first_pack_len == sizeof (jacknet_packet_header))
	{
	    packet_header_ntoh (first_packet);

	    jack_info ("AutoConfig Override !!!");
	    if (netj->sample_rate != first_packet->sample_rate)
	    {
		jack_info ("AutoConfig Override: Master JACK sample rate = %d", first_packet->sample_rate);
		netj->sample_rate = first_packet->sample_rate;
	    }

	    if (netj->period_size != first_packet->period_size)
	    {
		jack_info ("AutoConfig Override: Master JACK period size is %d", first_packet->period_size);
		netj->period_size = first_packet->period_size;
	    }
	    if (netj->capture_channels_audio != first_packet->capture_channels_audio)
	    {
		jack_info ("AutoConfig Override: capture_channels_audio = %d", first_packet->capture_channels_audio);
		netj->capture_channels_audio = first_packet->capture_channels_audio;
	    }
	    if (netj->capture_channels_midi != first_packet->capture_channels_midi)
	    {
		jack_info ("AutoConfig Override: capture_channels_midi = %d", first_packet->capture_channels_midi);
		netj->capture_channels_midi = first_packet->capture_channels_midi;
	    }
	    if (netj->playback_channels_audio != first_packet->playback_channels_audio)
	    {
		jack_info ("AutoConfig Override: playback_channels_audio = %d", first_packet->playback_channels_audio);
		netj->playback_channels_audio = first_packet->playback_channels_audio;
	    }
	    if (netj->playback_channels_midi != first_packet->playback_channels_midi)
	    {
		jack_info ("AutoConfig Override: playback_channels_midi = %d", first_packet->playback_channels_midi);
		netj->playback_channels_midi = first_packet->playback_channels_midi;
	    }

	    netj->mtu = first_packet->mtu;
	    jack_info ("MTU is set to %d bytes", first_packet->mtu);
	    netj->latency = first_packet->latency;
	}
    }
    netj->capture_channels  = netj->capture_channels_audio + netj->capture_channels_midi;
    netj->playback_channels = netj->playback_channels_audio + netj->playback_channels_midi;

    if( (netj->capture_channels * netj->period_size * netj->latency * 4) > 100000000 ) {
	    jack_error( "autoconfig requests more than 100MB packet cache... bailing out" );
	    exit(1);
    }

    if( netj->playback_channels > 1000 ) {
	    jack_error( "autoconfig requests more than 1000 playback channels... bailing out" );
	    exit(1);
    }


    if( netj->mtu < (2*sizeof( jacknet_packet_header )) ) {
	    jack_error( "bullshit mtu requested by autoconfig" );
	    exit(1);
    }

    if( netj->sample_rate == 0 ) {
	    jack_error( "sample_rate 0 requested by autoconfig" );
	    exit(1);
    }

    // After possible Autoconfig: do all calculations...
    netj->period_usecs =
        (jack_time_t) floor ((((float) netj->period_size) / (float)netj->sample_rate)
                             * 1000000.0f);

    if( netj->latency == 0 )
	netj->deadline_offset = 50*netj->period_usecs;
    else
	netj->deadline_offset = netj->period_usecs + 10*netj->latency*netj->period_usecs/100;

    if( netj->bitdepth == CELT_MODE ) {
	// celt mode.
	// TODO: this is a hack. But i dont want to change the packet header.
	netj->resample_factor = (netj->resample_factor * netj->period_size * 1024 / netj->sample_rate / 8)&(~1);
	netj->resample_factor_up = (netj->resample_factor_up * netj->period_size * 1024 / netj->sample_rate / 8)&(~1);

	netj->net_period_down = netj->resample_factor;
	netj->net_period_up = netj->resample_factor_up;
    } else {
	netj->net_period_down = (float) netj->period_size / (float) netj->resample_factor;
	netj->net_period_up = (float) netj->period_size / (float) netj->resample_factor_up;
    }

    netj->rx_bufsize = sizeof (jacknet_packet_header) + netj->net_period_down * netj->capture_channels * get_sample_size (netj->bitdepth);
    netj->packcache = packet_cache_new (netj->latency + 50, netj->rx_bufsize, netj->mtu);

    netj->expected_framecnt_valid = 0;
    netj->num_lost_packets = 0;
    netj->next_deadline_valid = 0;
    netj->deadline_goodness = 0;
    netj->time_to_deadline = 0;

    // Special handling for latency=0
    if( netj->latency == 0 )
	netj->resync_threshold = 0;
    else
	netj->resync_threshold = MIN( 15, netj->latency-1 );

    netj->running_free = 0;

    return 0;
}