/* $Id$ */
/* 
 * Copyright (C) 2003-2006 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 int play_counter;
static int rec_counter;
static int min_delay = 0xFFFF, max_delay;
static char play_delays[1000];

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

    ++play_counter;

    if (last_cb.u64 == 0) {
	pj_get_timestamp(&last_cb);
    } else {
	pj_timestamp now;
	int 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] = delay;
    }

    return PJ_SUCCESS;
}

static pj_status_t rec_cb(void *user_data, pj_uint32_t timestamp,
			  const void *input, unsigned size)
{
    ++rec_counter;
    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 clock_rate, int nchannel, int bits)
{
    pj_status_t status = PJ_SUCCESS;
    unsigned nsamples;
    pjmedia_snd_stream *strm;
    const char *dirtype;
    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);

    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();
	return 0;
    } else if (argc == 6) {
	
	int dev_id;
	pjmedia_dir dir;
	int clock_rate;
	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, clock_rate, nchannel, bits);

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

    return 0;
}


