/*
Copy samples from input port to output port raising amplitude 2 times (making sound louder).
Compile with: cc -o jack-dev-2 jack-dev-2.c `pkg-config --cflags --libs jack`
*/
#include <stdio.h>
#include <unistd.h> // for sleep()
#include <jack/jack.h>

/*
These variables will hold created jack ports.
We use globals so process() function can access them.

If you want to avoid using globals, make use of user defined argument of process().
See jack_set_process_callback() how to pass data to process() function.
*/
jack_port_t *in;
jack_port_t *out;

/*
This function will be run in separate thread by jack to process audio samples.
Samples are fed in chunks eg. 1024 samples per call.
nframes param tells how many samples are to be processed.

It processes samples in real time, so it shall not make any prints, file reads etc.
*/
int process(jack_nframes_t nframes, void *arg)
{
    float *input_buffer = (float*)jack_port_get_buffer(in, nframes);
    float *output_buffer = (float*)jack_port_get_buffer(out, nframes);

    // copy samples from input to output port, raising amplitude two times
    for(int i=0; i<nframes; ++i)
    {
        output_buffer[i] = input_buffer[i] * 2.0;
    }

    return 0;
}

int main(void)
{
    // connect to jack server
    jack_client_t *client = jack_client_open("jack-dev-2", JackNoStartServer, NULL);
    if(client == NULL)
    {
        fprintf(stderr, "Connecting to jack failed\n");
        return 1;
    }

    // create input port
    in = jack_port_register(client, // client for which to create port
        "in",                    // name of a port
        JACK_DEFAULT_AUDIO_TYPE, // port type telling what kind of data it handles
        JackPortIsInput,         // port flags, most important is telling if this port is input or output
        0);                      // not used, parameter ignored for builtin type ports
    if(in == NULL)
    {
        fprintf(stderr, "Creating input port failed\n");
        jack_client_close(client);
        return 1;
    }

    // create output port
    out = jack_port_register(client, "out", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
    if(out == NULL)
    {
        fprintf(stderr, "Creating output port failed\n");
        // ports are unregistered automatically on client close, so there is no need to unregister in port
        jack_client_close(client);
        return 1;
    }

    // register process function
    jack_set_process_callback(client, process, NULL);

    // start processing audio
    jack_activate(client);

    // wait indefinitely
    /* the only way to stop this sleep is to kill program,
    so there is no need to worry about disconnecting from jack */
    sleep(-1);

    return 0;
}
