/* $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 
 */
#include <pjmedia.h>
#include <pjlib-util.h>
#include <pjlib.h>

#include <stdio.h>
#include <stdlib.h>

#include "util.h"

/* For logging purpose. */
#define THIS_FILE   "resampleplay.c"


static const char *desc = 
" FILE		    						    \n"
"		    						    \n"
"  resampleplay.c	    					    \n"
"		    						    \n"
" PURPOSE	    						    \n"
"		    						    \n"
"  Demonstrate how use resample port to play a WAV file to sound    \n"
"  device using different sampling rate.			    \n"
"		    						    \n"
" USAGE		    						    \n"
"		    						    \n"
"  resampleplay [options] FILE.WAV				    \n"
"		    						    \n"
" where options:						    \n"
SND_USAGE
"		    						    \n"
"  The WAV file could have mono or stereo channels with arbitrary   \n"
"  sampling rate, but MUST contain uncompressed (i.e. 16bit) PCM.   \n";


int main(int argc, char *argv[])
{
    pj_caching_pool cp;
    pjmedia_endpt *med_endpt;
    pj_pool_t *pool;
    pjmedia_port *file_port;
    pjmedia_port *resample_port;
    pjmedia_snd_port *snd_port;
    char tmp[10];
    pj_status_t status;

    int dev_id = -1;
    int sampling_rate = CLOCK_RATE;
    int channel_count = NCHANNELS;
    int samples_per_frame = NSAMPLES;
    int bits_per_sample = NBITS;
    //int ptime;
    //int down_samples;

    /* Must init PJLIB first: */
    status = pj_init();
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);


    /* Get options */
    if (get_snd_options(THIS_FILE, argc, argv, &dev_id, &sampling_rate,
			&channel_count, &samples_per_frame, &bits_per_sample))
    {
	puts("");
	puts(desc);
	return 1;
    }

    if (!argv[pj_optind]) {
	puts("Error: no file is specified");
	puts(desc);
	return 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);

    /* Create memory pool for our file player */
    pool = pj_pool_create( &cp.factory,	    /* pool factory	    */
			   "app",	    /* pool name.	    */
			   4000,	    /* init size	    */
			   4000,	    /* increment size	    */
			   NULL		    /* callback on error    */
			   );

    /* Create the file port. */
    status = pjmedia_file_player_port_create( pool, argv[pj_optind], 0,
					      0, 0, &file_port);
    if (status != PJ_SUCCESS) {
	app_perror(THIS_FILE, "Unable to open file", status);
	return 1;
    }

    /* File must have same number of channels. */
    if (file_port->info.channel_count != (unsigned)channel_count) {
	PJ_LOG(3,(THIS_FILE, "Error: file has different number of channels. "
			     "Perhaps you'd need -c option?"));
	pjmedia_port_destroy(file_port);
	return 1;
    }

    /* Calculate number of samples per frame to be taken from file port */
    //ptime = samples_per_frame * 1000 / sampling_rate;

    /* Create the resample port. */
    status = pjmedia_resample_port_create( pool, 1, 1,
					   file_port->info.sample_rate,
					   sampling_rate,
					   channel_count,
					   (unsigned)(
					   samples_per_frame * 1.0 *
					    file_port->info.sample_rate / 
					    sampling_rate),
					   &resample_port);
    if (status != PJ_SUCCESS) {
	app_perror(THIS_FILE, "Unable to create resample port", status);
	return 1;
    }

    /* Connect resample port to file port */
    status = pjmedia_port_connect( pool, resample_port, file_port);
    if (status != PJ_SUCCESS) {
	app_perror(THIS_FILE, "Error connecting ports", status);
	return 1;
    }

    /* Create sound player port. */
    status = pjmedia_snd_port_create( 
		 pool,			/* pool			    */
		 dev_id,		/* device		    */
		 dev_id,		/* device		    */
		 sampling_rate,		/* clock rate.		    */
		 channel_count,		/* # of channels.	    */
		 samples_per_frame,	/* samples per frame.	    */
		 bits_per_sample,	/* bits per sample.	    */
		 0,			/* options		    */
		 &snd_port		/* returned port	    */
		 );
    if (status != PJ_SUCCESS) {
	app_perror(THIS_FILE, "Unable to open sound device", status);
	return 1;
    }

    /* Connect resample port to sound device */
    status = pjmedia_snd_port_connect( snd_port, resample_port);
    if (status != PJ_SUCCESS) {
	app_perror(THIS_FILE, "Error connecting sound ports", status);
	return 1;
    }


    /* Dump memory usage */
    dump_pool_usage(THIS_FILE, &cp);

    /* 
     * File should be playing and looping now, using sound device's thread. 
     */


    /* Sleep to allow log messages to flush */
    pj_thread_sleep(100);


    printf("Playing %s at sampling rate %d (original file sampling rate=%d)\n",
	   argv[pj_optind], sampling_rate, file_port->info.sample_rate);
    puts("");
    puts("Press <ENTER> to stop playing and quit");

    fgets(tmp, sizeof(tmp), stdin);

    
    /* Start deinitialization: */


    /* Destroy sound device */
    status = pjmedia_snd_port_destroy( snd_port );
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);


    /* Destroy resample port. 
     * This will destroy all downstream ports (e.g. the file port)
     */
    status = pjmedia_port_destroy( resample_port );
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);


    /* Release application pool */
    pj_pool_release( pool );

    /* Destroy media endpoint. */
    pjmedia_endpt_destroy( med_endpt );

    /* Destroy pool factory */
    pj_caching_pool_destroy( &cp );


    /* Done. */
    return 0;

}



