Ejemplo n.º 1
0
int JackPortAudioDriver::Render(const void* inputBuffer, void* outputBuffer, PaStreamCallbackFlags statusFlags)
{
    fInputBuffer = (jack_default_audio_sample_t**)inputBuffer;
    fOutputBuffer = (jack_default_audio_sample_t**)outputBuffer;

    if (statusFlags) {
        if (statusFlags & paOutputUnderflow)
            jack_error("JackPortAudioDriver::Render paOutputUnderflow");
        if (statusFlags & paInputUnderflow)
            jack_error("JackPortAudioDriver::Render paInputUnderflow");
        if (statusFlags & paOutputOverflow)
            jack_error("JackPortAudioDriver::Render paOutputOverflow");
        if (statusFlags & paInputOverflow)
            jack_error("JackPortAudioDriver::Render paInputOverflow");
        if (statusFlags & paPrimingOutput)
            jack_error("JackPortAudioDriver::Render paOutputUnderflow");

        if (statusFlags != paPrimingOutput) {
            jack_time_t cur_time = GetMicroSeconds();
            NotifyXRun(cur_time, float(cur_time - fBeginDateUst));   // Better this value than nothing...
        }
    }

    // Setup threaded based log function
    set_threaded_log_function();
    CycleTakeBeginTime();
    return (Process() == 0) ? paContinue : paAbort;
}
Ejemplo n.º 2
0
/*!
\brief Called once when the thread starts.
*/
bool JackClient::Init()
{
    /*
        Execute buffer_size callback.

        Since StartThread uses fThread.StartSync, we are sure that buffer_size callback
        is executed before StartThread returns (and then IsActive will be true).
        So no RT callback can be called at the same time.
    */
    jack_log("JackClient::kBufferSizeCallback buffer_size = %ld", GetEngineControl()->fBufferSize);
    if (fBufferSize) {
        fBufferSize(GetEngineControl()->fBufferSize, fBufferSizeArg);
    }

    // Init callback
    InitAux();

    // Setup context
    if (!jack_tls_set(JackGlobals::fRealTimeThread, this)) {
        jack_error("Failed to set thread realtime key");
    }

    // Setup RT
    if (GetEngineControl()->fRealTime) {
        set_threaded_log_function();
        SetupRealTime();
    }

    return true;
}
int JackPortAudioDriver::Render(const void* inputBuffer, void* outputBuffer,
                                unsigned long framesPerBuffer,
                                const PaStreamCallbackTimeInfo* timeInfo,
                                PaStreamCallbackFlags statusFlags,
                                void* userData)
{
    JackPortAudioDriver* driver = (JackPortAudioDriver*)userData;
    driver->fInputBuffer = (jack_default_audio_sample_t**)inputBuffer;
    driver->fOutputBuffer = (jack_default_audio_sample_t**)outputBuffer;

    //MMCSSAcquireRealTime(GetCurrentThread());

    if (statusFlags) {
        if (statusFlags & paOutputUnderflow)
            jack_error("JackPortAudioDriver::Render paOutputUnderflow");
        if (statusFlags & paInputUnderflow)
            jack_error("JackPortAudioDriver::Render paInputUnderflow");
        if (statusFlags & paOutputOverflow)
            jack_error("JackPortAudioDriver::Render paOutputOverflow");
        if (statusFlags & paInputOverflow)
            jack_error("JackPortAudioDriver::Render paInputOverflow");
        if (statusFlags & paPrimingOutput)
            jack_error("JackPortAudioDriver::Render paOutputUnderflow");

        if (statusFlags != paPrimingOutput) {
            jack_time_t cur_time = GetMicroSeconds();
            driver->NotifyXRun(cur_time, float(cur_time - driver->fBeginDateUst));   // Better this value than nothing...
        }
    }

    // Setup threadded based log function
    set_threaded_log_function();
    driver->CycleTakeBeginTime();
    return (driver->Process() == 0) ? paContinue : paAbort;
}
Ejemplo n.º 4
0
    bool JackNetAdapter::Init()
    {
        jack_log("JackNetAdapter::Init");

        //init network connection
        if (!JackNetSlaveInterface::Init()) {
            jack_error("JackNetSlaveInterface::Init() error...");
            return false;
        }

        //then set global parameters
        if (!SetParams()) {
            jack_error("SetParams error...");
            return false;
        }

        //set buffers
        if (fCaptureChannels > 0) {
            fSoftCaptureBuffer = new sample_t*[fCaptureChannels];
            for (int port_index = 0; port_index < fCaptureChannels; port_index++) {
                fSoftCaptureBuffer[port_index] = new sample_t[fParams.fPeriodSize];
                fNetAudioCaptureBuffer->SetBuffer(port_index, fSoftCaptureBuffer[port_index]);
            }
        }

        if (fPlaybackChannels > 0) {
            fSoftPlaybackBuffer = new sample_t*[fPlaybackChannels];
            for (int port_index = 0; port_index < fPlaybackChannels; port_index++) {
                fSoftPlaybackBuffer[port_index] = new sample_t[fParams.fPeriodSize];
                fNetAudioPlaybackBuffer->SetBuffer(port_index, fSoftPlaybackBuffer[port_index]);
            }
        }

        //set audio adapter parameters
        SetAdaptedBufferSize(fParams.fPeriodSize);
        SetAdaptedSampleRate(fParams.fSampleRate);

        // Will do "something" on OSX only...
        fThread.SetParams(GetEngineControl()->fPeriod, GetEngineControl()->fComputation, GetEngineControl()->fConstraint);

        if (fThread.AcquireSelfRealTime(GetEngineControl()->fClientPriority) < 0) {
            jack_error("AcquireSelfRealTime error");
        } else {
            set_threaded_log_function();
        }

        //init done, display parameters
        SessionParamsDisplay(&fParams);
        return true;
    }
Ejemplo n.º 5
0
void JackThreadedDriver::SetRealTime()
{
    if (fDriver->IsRealTime()) {
        jack_log("JackThreadedDriver::Init real-time");
        // Will do "something" on OSX only...
        GetEngineControl()->fPeriod = GetEngineControl()->fConstraint = GetEngineControl()->fPeriodUsecs * 1000;
        GetEngineControl()->fComputation = JackTools::ComputationMicroSec(GetEngineControl()->fBufferSize) * 1000;
        fThread.SetParams(GetEngineControl()->fPeriod, GetEngineControl()->fComputation, GetEngineControl()->fConstraint);
        if (fThread.AcquireSelfRealTime(GetEngineControl()->fServerPriority) < 0) {
            jack_error("AcquireSelfRealTime error");
        } else {
            set_threaded_log_function();
        }
    } else {
        jack_log("JackThreadedDriver::Init non-realtime");
    }
}
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;
        }
	}
}
Ejemplo n.º 7
0
static
void *midi_thread(void *arg)
{
    midi_stream_t *str = arg;
    alsa_rawmidi_t *midi = str->owner;
    struct pollfd pfds[MAX_PFDS];
    int npfds;
    jack_time_t wait_nsec = 1000*1000*1000; // 1 sec
    process_midi_t proc;

    proc.midi = midi;
    proc.mode = str->mode;

    pfds[0].fd = str->wake_pipe[0];
    pfds[0].events = POLLIN|POLLERR|POLLNVAL;
    npfds = 1;

    if (jack_is_realtime(midi->client))
        set_threaded_log_function();

    //debug_log("midi_thread(%s): enter", str->name);

    while (midi->keep_walking) {
        int poll_timeout;
        int wait_nanosleep;
        int r=1, w=1; // read,write pos in pfds
        int rp=0, wp=0; // read, write pos in ports

        // sleep
        //if (wait_nsec != 1000*1000*1000) {
        //	debug_log("midi_thread(%s): ", str->name);
        //	assert (wait_nsec == 1000*1000*1000);
        //}
        poll_timeout = wait_nsec / (1000*1000);
        wait_nanosleep = wait_nsec % (1000*1000);
        if (wait_nanosleep > NANOSLEEP_RESOLUTION) {
            struct timespec ts;
            ts.tv_sec = 0;
            ts.tv_nsec = wait_nanosleep;
            clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);
        }
        int res = poll((struct pollfd*)&pfds, npfds, poll_timeout);
        //debug_log("midi_thread(%s): poll exit: %d", str->name, res);
        if (!midi->keep_walking)
            break;
        if (res < 0) {
            if (errno == EINTR)
                continue;
            error_log("midi_thread(%s) poll failed: %s", str->name, strerror(errno));
            break;
        }

        // check wakeup pipe
        if (pfds[0].revents & ~POLLIN)
            break;
        if (pfds[0].revents & POLLIN) {
            char c;
            read(pfds[0].fd, &c, 1);
        }

        // add new ports
        while (jack_ringbuffer_read_space(str->midi.new_ports) >= sizeof(midi_port_t*) && str->midi.nports < MAX_PORTS) {
            midi_port_t *port;
            jack_ringbuffer_read(str->midi.new_ports, (char*)&port, sizeof(port));
            str->midi.ports[str->midi.nports++] = port;
            debug_log("midi_thread(%s): added port %s", str->name, port->name);
        }

//		if (res == 0)
//			continue;

        // process ports
        proc.cur_time = 0; //jack_frame_time(midi->client);
        proc.next_time = NFRAMES_INF;

        for (rp = 0; rp < str->midi.nports; ++rp) {
            midi_port_t *port = str->midi.ports[rp];
            proc.cur_time = jack_frame_time(midi->client);
            proc.port = port;
            proc.rpfds = &pfds[r];
            proc.wpfds = &pfds[w];
            proc.max_pfds = MAX_PFDS - w;
            r += port->npfds;
            if (!(str->process_midi)(&proc)) {
                port->state = PORT_REMOVED_FROM_MIDI; // this signals to jack thread
                continue; // this effectively removes port from array
            }
            w += port->npfds;
            if (rp != wp)
                str->midi.ports[wp] = port;
            ++wp;
        }
        if (str->midi.nports != wp)
            debug_log("midi_%s: nports %d -> %d", str->name, str->midi.nports, wp);
        str->midi.nports = wp;
        if (npfds != w)
            debug_log("midi_%s: npfds %d -> %d", str->name, npfds, w);
        npfds = w;

        /*
         * Input : ports do not set proc.next_time.
         * Output: port sets proc.next_time ONLY if it does not have queued data.
         * So, zero timeout will not cause busy-looping.
         */
        if (proc.next_time < proc.cur_time) {
            debug_log("%s: late: next_time = %d, cur_time = %d", str->name, (int)proc.next_time, (int)proc.cur_time);
            wait_nsec = 0; // we are late
        } else if (proc.next_time != NFRAMES_INF) {
            jack_time_t wait_frames = proc.next_time - proc.cur_time;
            jack_nframes_t rate = jack_get_sample_rate(midi->client);
            wait_nsec = (wait_frames * (1000*1000*1000)) / rate;
            debug_log("midi_%s: timeout = %d", str->name, (int)wait_frames);
        } else
            wait_nsec = 1000*1000*1000;
        //debug_log("midi_thread(%s): wait_nsec = %lld", str->name, wait_nsec);
    }
    return NULL;
}