/* $Id$ */
/* 
 * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.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, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 */

static const char *desc = 
 " sndinfo.c								    \n"
 "									    \n"
 " PURPOSE:								    \n"
 "  Print sound device info and test open device.			    \n"
 "									    \n"
 " USAGE:								    \n"
 "  sndinfo [id rec/play/both clockrate nchan bits]			    \n"
 "									    \n"
 " DESCRIPTION:								    \n"
 "  When invoked without any arguments, it displays information about all   \n"
 "  sound devices in the system.					    \n"
 "									    \n"
 "  When invoked with arguments, the program tests if device can be opened  \n"
 "  with the specified arguments. All these arguments must be specified:    \n"
 "  - id             The device ID (-1 for the first capable device)	    \n"
 "  - rec/play/both  Specify which streams to open.			    \n"
 "  - clockrate      Specify clock rate (e.g. 8000, 11025, etc.)	    \n"
 "  - nchan	     Number of channels (1=mono, 2=stereo).		    \n"
 "  - bits	     Number of bits per sample (normally 16).		    \n";

#include <pjmedia.h>
#include <pjlib.h>

#include <stdlib.h>	/* atoi() */
#include <stdio.h>


static void enum_devices(void)
{
    int i, count;
    
    count = pjmedia_snd_get_dev_count();
    if (count == 0) {
	puts("No devices found");
	return;
    }

    for (i=0; i<count; ++i) {
	const pjmedia_snd_dev_info *info;

	info = pjmedia_snd_get_dev_info(i);
	pj_assert(info != NULL);

	printf( "Device #%02d: \n"
		"  Name                : %s\n"
		"  # of input channels : %d\n"
		"  # of output channels: %d\n"
		"  Default clock rate  : %d Hz\n\n",
		i, info->name, info->input_count, info->output_count,
		info->default_samples_per_sec);
    }
    puts("");
    puts("Run with -h to get more options");
}

static unsigned clock_rate;
static unsigned play_counter;
static unsigned rec_counter;
static unsigned min_delay = 0xFFFF, max_delay;
static char play_delays[1000];
static pj_uint32_t last_play_timestamp, last_rec_timestamp;

static pj_status_t play_cb(void *user_data, pj_uint32_t timestamp,
			   void *output, unsigned size)
{
    static pj_timestamp last_cb;


    PJ_UNUSED_ARG(user_data);
    PJ_UNUSED_ARG(output);
    PJ_UNUSED_ARG(size);


    ++play_counter;
    last_play_timestamp = timestamp;

    if (last_cb.u64 == 0) {
	pj_get_timestamp(&last_cb);
    } else if (play_counter <= PJ_ARRAY_SIZE(play_delays)) {
	pj_timestamp now;
	unsigned delay;

	pj_get_timestamp(&now);
	
	delay = pj_elapsed_msec(&last_cb, &now);
	if (delay < min_delay)
	    min_delay = delay;
	if (delay > max_delay)
	    max_delay = delay;

	last_cb = now;

	play_delays[play_counter-1] = (char)delay;
    }

    return PJ_SUCCESS;
}

static pj_status_t rec_cb(void *user_data, pj_uint32_t timestamp,
			  void *input, unsigned size)
{

    PJ_UNUSED_ARG(size);
    PJ_UNUSED_ARG(input);
    PJ_UNUSED_ARG(user_data);


    ++rec_counter;

    if (timestamp - last_rec_timestamp >= clock_rate && last_play_timestamp) {
	int diff;
	diff = last_play_timestamp - timestamp;
	printf("Play timestamp=%u, capture timestamp=%u, diff=%d\n",
	       last_play_timestamp, timestamp, diff);
	last_rec_timestamp = timestamp;
    }
    return PJ_SUCCESS;
}

static void app_perror(const char *title, pj_status_t status)
{
    char errmsg[PJ_ERR_MSG_SIZE];

    pj_strerror(status, errmsg, sizeof(errmsg));	
    printf( "%s: %s (err=%d)\n",
	    title, errmsg, status);
}

static int open_device(int dev_id, pjmedia_dir dir,
		       int nchannel, int bits)
{
    pj_status_t status = PJ_SUCCESS;
    unsigned nsamples;
    pjmedia_snd_stream *strm;
    const char *dirtype;
    char tmp[10];
    unsigned i;

    switch (dir) {
    case PJMEDIA_DIR_CAPTURE:
	dirtype = "capture"; break;    
    case PJMEDIA_DIR_PLAYBACK:
	dirtype = "playback"; break;    
    case PJMEDIA_DIR_CAPTURE_PLAYBACK:
	dirtype = "capture/playback"; break;    
    default:
	return 1;
    }
    
    nsamples = clock_rate * 20 / 1000;

    printf( "Opening device %d for %s: clockrate=%d, nchannel=%d, "
	    "bits=%d, nsamples=%d..\n",
	    dev_id, dirtype, clock_rate, nchannel, bits, nsamples);

    if (dir == PJMEDIA_DIR_CAPTURE) {
	status = pjmedia_snd_open_rec( dev_id, clock_rate, nchannel,
				       nsamples, bits, &rec_cb, NULL,
				       &strm);
    } else if (dir == PJMEDIA_DIR_PLAYBACK) {
	status = pjmedia_snd_open_player( dev_id, clock_rate, nchannel,
					  nsamples, bits, &play_cb, NULL,
					  &strm);
    } else {
	status = pjmedia_snd_open( dev_id, dev_id, clock_rate, nchannel,
				   nsamples, bits, &rec_cb, &play_cb, NULL,
				   &strm);
    }
    
    if (status != PJ_SUCCESS) {
        app_perror("Unable to open device for capture", status);
        return 1;
    }

    status = pjmedia_snd_stream_start(strm);
    if (status != PJ_SUCCESS) {
        app_perror("Unable to start capture stream", status);
        return 1;
    }
    
    /* Let playback/capture runs for a while */
    //pj_thread_sleep(1000);
    puts("Press <ENTER> to stop");
    if (fgets(tmp, sizeof(tmp), stdin) == NULL) {
	puts("EOF while reading stdin, will quit now..");
    }

    pjmedia_snd_stream_close(strm);

    if ((dir & PJMEDIA_DIR_CAPTURE) && rec_counter==0) {
	printf("Error: capture stream was not running\n");
	return 1;
    }

    if ((dir & PJMEDIA_DIR_PLAYBACK) && play_counter==0) {
	printf("Error: playback stream was not running\n");
	return 1;
    }

    puts("Success.");

    printf("Delay: ");
    for (i=0; i<play_counter; ++i)
	printf("%d ", play_delays[i]);

    puts("");
    if (dir & PJMEDIA_DIR_PLAYBACK) {
	printf("Callback interval: min interval=%d ms, max interval=%d ms\n",
	       min_delay, max_delay);
    }
    

    return 0;
}


int main(int argc, char *argv[])
{
    pj_caching_pool cp;
    pjmedia_endpt *med_endpt;
    pj_status_t status;

    /* Init pjlib */
    status = pj_init();
    PJ_ASSERT_RETURN(status==PJ_SUCCESS, 1);
    
    /* Must create a pool factory before we can allocate any memory. */
    pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0);

    /* 
     * Initialize media endpoint.
     * This will implicitly initialize PJMEDIA too.
     */
    status = pjmedia_endpt_create(&cp.factory, NULL, 1, &med_endpt);
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);

    
    if (argc == 1) {
	enum_devices();
    } else if (argc == 6) {
	
	int dev_id;
	pjmedia_dir dir = PJMEDIA_DIR_NONE;
	int nchannel;
	int bits;

	dev_id = atoi(argv[1]);

	if (strcmp(argv[2], "rec")==0)
	    dir = PJMEDIA_DIR_CAPTURE;
	else if (strcmp(argv[2], "play")==0)
	    dir = PJMEDIA_DIR_PLAYBACK;
	else if (strcmp(argv[2], "both")==0)
	    dir = PJMEDIA_DIR_CAPTURE_PLAYBACK;

	clock_rate = atoi(argv[3]);
	nchannel = atoi(argv[4]);
	bits = atoi(argv[5]);

	return open_device(dev_id, dir, nchannel, bits);

    } else {
	puts("Error: invalid arguments");
	puts(desc);
	return 1;
    }

    /* Shutdown PJLIB */
    pj_shutdown();

    return 0;
}


