// -----------------------------------------------------------------------------
//
//  Copyright (C) 2012-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 <math.h>
#include <unistd.h>
#include <signal.h>
#include <jack/jack.h>


static jack_client_t  *jack_handle;
static jack_port_t    *jack_capt;
static bool            active = false;
static volatile bool   reset = true;
static int   nnan = 0;
static int   ninf = 0;
static int   nden = 0;


int jack_callback (jack_nframes_t nframes, void *arg)
{
    unsigned int i, t;
    float *ip;

    if (!active) return 0;
    if (reset)
    {
	nnan = ninf = nden = 0;
	reset = false;
    }
    ip = (float *)(jack_port_get_buffer (jack_capt, nframes));
    for (i = 0; i < nframes; i++)
    {
	t = fpclassify (*ip++);
	switch (t)
	{
	case FP_NAN:
	    nnan++;
	    break;
	case FP_INFINITE:
	    ninf++;
	    break;
	case FP_SUBNORMAL:
	    nden++;
	    break;
	}
    }
    return 0;
}


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


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

    jack_handle = jack_client_open ("jack_fpmon", JackNoStartServer, &s);
    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_callback, 0);
    if (jack_activate (jack_handle))
    {
        fprintf(stderr, "Can't activate Jack");
        return 1;
    }

    jack_capt = jack_port_register (jack_handle, "in",  JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);

    signal (SIGINT, sigint_handler);
    active = true;
    while (active)
    {
	usleep (1000000);
	printf ("nan:%6d   inf:%6d   den:%6d\n", nnan, ninf, nden);
	reset = true;
    }

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

