/* $Id$ */
/* 
 * Copyright (C) 2008-2011 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 
 */
#include <pjmedia/master_port.h>
#include <pjmedia/clock.h>
#include <pjmedia/errno.h>
#include <pj/assert.h>
#include <pj/lock.h>
#include <pj/pool.h>
#include <pj/string.h>


struct pjmedia_master_port
{
    unsigned	     options;
    pjmedia_clock   *clock;
    pjmedia_port    *u_port;
    pjmedia_port    *d_port;
    unsigned	     buff_size;
    void	    *buff;
    pj_lock_t	    *lock;
};


static void clock_callback(const pj_timestamp *ts, void *user_data);


/*
 * Create a master port.
 *
 */
PJ_DEF(pj_status_t) pjmedia_master_port_create( pj_pool_t *pool,
						pjmedia_port *u_port,
						pjmedia_port *d_port,
						unsigned options,
						pjmedia_master_port **p_m)
{
    pjmedia_master_port *m;
    unsigned clock_rate;
    unsigned channel_count;
    unsigned samples_per_frame;
    unsigned bytes_per_frame;
    pjmedia_audio_format_detail *u_afd, *d_afd;
    pj_status_t status;

    /* Sanity check */
    PJ_ASSERT_RETURN(pool && u_port && d_port && p_m, PJ_EINVAL);

    u_afd = pjmedia_format_get_audio_format_detail(&u_port->info.fmt, PJ_TRUE);
    d_afd = pjmedia_format_get_audio_format_detail(&d_port->info.fmt, PJ_TRUE);

    /* Both ports MUST have equal clock rate */
    PJ_ASSERT_RETURN(u_afd->clock_rate == d_afd->clock_rate,
		     PJMEDIA_ENCCLOCKRATE);

    /* Both ports MUST have equal samples per frame */
    PJ_ASSERT_RETURN(PJMEDIA_PIA_SPF(&u_port->info)==
			PJMEDIA_PIA_SPF(&d_port->info),
		     PJMEDIA_ENCSAMPLESPFRAME);

    /* Both ports MUST have equal channel count */
    PJ_ASSERT_RETURN(u_afd->channel_count == d_afd->channel_count,
		     PJMEDIA_ENCCHANNEL);


    /* Get clock_rate and samples_per_frame from one of the port. */
    clock_rate = u_afd->clock_rate;
    samples_per_frame = PJMEDIA_PIA_SPF(&u_port->info);
    channel_count = u_afd->channel_count;


    /* Get the bytes_per_frame value, to determine the size of the
     * buffer. We take the larger size of the two ports.
     */
    bytes_per_frame = PJMEDIA_AFD_AVG_FSZ(u_afd);
    if (PJMEDIA_AFD_AVG_FSZ(d_afd) > bytes_per_frame)
	bytes_per_frame = PJMEDIA_AFD_AVG_FSZ(d_afd);


    /* Create the master port instance */
    m = PJ_POOL_ZALLOC_T(pool, pjmedia_master_port);
    m->options = options;
    m->u_port = u_port;
    m->d_port = d_port;

    
    /* Create buffer */
    m->buff_size = bytes_per_frame;
    m->buff = pj_pool_alloc(pool, m->buff_size);
    if (!m->buff)
	return PJ_ENOMEM;

    /* Create lock object */
    status = pj_lock_create_simple_mutex(pool, "mport", &m->lock);
    if (status != PJ_SUCCESS)
	return status;

    /* Create media clock */
    status = pjmedia_clock_create(pool, clock_rate, channel_count, 
				  samples_per_frame, options, &clock_callback,
				  m, &m->clock);
    if (status != PJ_SUCCESS) {
	pj_lock_destroy(m->lock);
	return status;
    }

    /* Done */
    *p_m = m;

    return PJ_SUCCESS;
}


/*
 * Start the media flow.
 */
PJ_DEF(pj_status_t) pjmedia_master_port_start(pjmedia_master_port *m)
{
    PJ_ASSERT_RETURN(m && m->clock, PJ_EINVAL);
    PJ_ASSERT_RETURN(m->u_port && m->d_port, PJ_EINVALIDOP);

    return pjmedia_clock_start(m->clock);
}


/*
 * Stop the media flow.
 */
PJ_DEF(pj_status_t) pjmedia_master_port_stop(pjmedia_master_port *m)
{
    PJ_ASSERT_RETURN(m && m->clock, PJ_EINVAL);
    
    return pjmedia_clock_stop(m->clock);
}


/* Poll the master port clock */
PJ_DEF(pj_bool_t) pjmedia_master_port_wait( pjmedia_master_port *m,
					    pj_bool_t wait,
					    pj_timestamp *ts)
{
    PJ_ASSERT_RETURN(m && m->clock, PJ_FALSE);

    return pjmedia_clock_wait(m->clock, wait, ts);
}

/*
 * Callback to be called for each clock ticks.
 */
static void clock_callback(const pj_timestamp *ts, void *user_data)
{
    pjmedia_master_port *m = (pjmedia_master_port*) user_data;
    pjmedia_frame frame;
    pj_status_t status;

    
    /* Lock access to ports. */
    pj_lock_acquire(m->lock);

    /* Get frame from upstream port and pass it to downstream port */
    pj_bzero(&frame, sizeof(frame));
    frame.buf = m->buff;
    frame.size = m->buff_size;
    frame.timestamp.u64 = ts->u64;

    status = pjmedia_port_get_frame(m->u_port, &frame);
    if (status != PJ_SUCCESS)
	frame.type = PJMEDIA_FRAME_TYPE_NONE;

    status = pjmedia_port_put_frame(m->d_port, &frame);

    /* Get frame from downstream port and pass it to upstream port */
    pj_bzero(&frame, sizeof(frame));
    frame.buf = m->buff;
    frame.size = m->buff_size;
    frame.timestamp.u64 = ts->u64;

    status = pjmedia_port_get_frame(m->d_port, &frame);
    if (status != PJ_SUCCESS)
	frame.type = PJMEDIA_FRAME_TYPE_NONE;

    status = pjmedia_port_put_frame(m->u_port, &frame);

    /* Release lock */
    pj_lock_release(m->lock);
}


/*
 * Change the upstream port.
 */
PJ_DEF(pj_status_t) pjmedia_master_port_set_uport(pjmedia_master_port *m,
						     pjmedia_port *port)
{
    PJ_ASSERT_RETURN(m && port, PJ_EINVAL);

    /* Only supports audio for now */
    PJ_ASSERT_RETURN(port->info.fmt.type==PJMEDIA_TYPE_AUDIO, PJ_ENOTSUP);

    /* If we have downstream port, make sure they have matching samples per
     * frame.
     */
    if (m->d_port) {
	PJ_ASSERT_RETURN(
	    PJMEDIA_PIA_PTIME(&port->info) ==
		PJMEDIA_PIA_PTIME(&m->d_port->info),
	    PJMEDIA_ENCSAMPLESPFRAME
	);
    }

    pj_lock_acquire(m->lock);

    m->u_port = port;

    pj_lock_release(m->lock);

    return PJ_SUCCESS;
}


/*
 * Get the upstream port.
 */
PJ_DEF(pjmedia_port*) pjmedia_master_port_get_uport(pjmedia_master_port*m)
{
    PJ_ASSERT_RETURN(m, NULL);
    return m->u_port;
}


/*
 * Change the downstream port.
 */
PJ_DEF(pj_status_t) pjmedia_master_port_set_dport(pjmedia_master_port *m,
						  pjmedia_port *port)
{
    PJ_ASSERT_RETURN(m && port, PJ_EINVAL);

    /* Only supports audio for now */
    PJ_ASSERT_RETURN(port->info.fmt.type==PJMEDIA_TYPE_AUDIO, PJ_ENOTSUP);

    /* If we have upstream port, make sure they have matching samples per
     * frame.
     */
    if (m->u_port) {
	PJ_ASSERT_RETURN(
	    PJMEDIA_PIA_PTIME(&port->info) ==
		    PJMEDIA_PIA_PTIME(&m->u_port->info),
	    PJMEDIA_ENCSAMPLESPFRAME
	);
    }

    pj_lock_acquire(m->lock);

    m->d_port = port;

    pj_lock_release(m->lock);

    return PJ_SUCCESS;
}


/*
 * Get the downstream port.
 */
PJ_DEF(pjmedia_port*) pjmedia_master_port_get_dport(pjmedia_master_port*m)
{
    PJ_ASSERT_RETURN(m, NULL);
    return m->d_port;
}


/*
 * Destroy the master port, and optionally destroy the u_port and 
 * d_port ports.
 */
PJ_DEF(pj_status_t) pjmedia_master_port_destroy(pjmedia_master_port *m,
						pj_bool_t destroy_ports)
{
    PJ_ASSERT_RETURN(m, PJ_EINVAL);

    if (m->clock) {
	pjmedia_clock_destroy(m->clock);
	m->clock = NULL;
    }

    if (m->u_port && destroy_ports) {
	pjmedia_port_destroy(m->u_port);
	m->u_port = NULL;
    }

    if (m->d_port && destroy_ports) {
	pjmedia_port_destroy(m->d_port);
	m->d_port = NULL;
    }

    if (m->lock) {
	pj_lock_destroy(m->lock);
	m->lock = NULL;
    }

    return PJ_SUCCESS;
}


