// -----------------------------------------------------------------------------
//
//  Copyright (C) 2003-2018 Fons Adriaensen <fons@linuxaudio.org>
//
//  This program is free software; you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation; either version 2 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
//
// -----------------------------------------------------------------------------


#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
#include <signal.h>
#include <jack/jack.h>
#include <jack/statistics.h>


static jack_client_t  *jack_handle;
static bool first = true;
static bool xrun = false;
static uint64_t last_t0, last_t1;
static uint32_t last_ft;
static int fsamp;
static int bsize;
static bool active;



int jack_process_callback (jack_nframes_t nframes, void *arg)
{
    uint64_t  t0, t1;
    uint32_t  cf, ft;
    float     per;
    int       du, df1, df2;

    if (! active) return 0;
    
    ft = jack_last_frame_time (jack_handle);
    jack_get_cycle_times (jack_handle, &cf, &t0, &t1, &per);

    if (! first)
    {
	du = t0 - last_t1;
        df1 = (int)(du * 1e-6 * fsamp + 0.5);
        df2 = ft - last_ft - bsize;
	if (du || df2)
	{
	    printf ("Discontinuity: %10d usecs (%5d), %5d frames,   xrun: %d\n", du, df1, df2, xrun);
	}
	xrun = false;
    }

    last_ft = ft;
    last_t0 = t0;
    last_t1 = t1;
    first = false;
    return 0;
}


int jack_xrun_callback (void *arg)
{
    printf ("XRUN: %10.1lf\n", jack_get_xrun_delayed_usecs (jack_handle));
    xrun = true;
    return 0;
}


static void sigint_handler (int)
{
    signal (SIGINT, SIG_IGN);
    active = false;
}


int main (int ac, char *av [])
{
    jack_status_t stat;

    jack_handle = jack_client_open ("jack_delay", JackNoStartServer, &stat);
    if (jack_handle == 0)
    {
        fprintf (stderr, "Can't connect to Jack, is the server running ?\n");
        return 1;
    }

    jack_set_process_callback (jack_handle, jack_process_callback, 0);
    jack_set_xrun_callback (jack_handle, jack_xrun_callback, 0);
    if (jack_activate (jack_handle))
    {
        fprintf(stderr, "Can't activate Jack");
        return 1;
    }

    fsamp = jack_get_sample_rate (jack_handle);
    bsize = jack_get_buffer_size (jack_handle);

    signal (SIGINT, sigint_handler);
    active = true;
    while (active)
    {
	usleep (250000);
    }

    jack_deactivate (jack_handle);
    jack_client_close (jack_handle);
    return 0;
}

