/*
 * Copyright (c) 2001-2003 Shiman Associates Inc. All Rights Reserved.
 * 
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "mas/mas.h"
#include "mas/mas_core.h"

void
usage( void )
{
    fprintf(stderr, "usage: massource [-h|-?] [-t seconds]\n");
    fprintf(stderr, "       Records data from the anx device and dumps it to standard out.\n\n");
    fprintf(stderr, "options:\n");
    fprintf(stderr, "   -t seconds   wait 'seconds' before starting to record.  This is useful if \n");
    fprintf(stderr, "                run in a piped configuration with massink.\n");
    fprintf(stderr, "\n");
    exit(2);
}


int main(int argc, char* argv[])
{
    int32 err;
    struct mas_data_characteristic* dc;
    mas_device_t anx, endian;
    mas_channel_t dchnl;
    mas_port_t rsrc, rsnk, end_src;
    struct mas_data stack_data;
    struct mas_data* data = &stack_data;
    int timedelay = 0, i;
    
    masc_log_verbosity( MAS_VERBLVL_DEBUG );

    for (i=1; i<argc; i++)
    {
        if ( argv[i][0] != '-' )
        {
            usage();
        }
        else
        {
            switch(argv[i][1])
            {
            case 't':
                if ( i + 1 >= argc )
                {
                    fprintf(stderr, "Not enough options for -t\n\n");
                    usage();
                }
                
                timedelay = strtol(argv[++i], (char **)NULL, 10);
                if ( timedelay == LONG_MIN || timedelay == LONG_MAX )
                {
                    fprintf(stderr, "Invalid value for time.\n\n" );
                    usage();
                }
                break;
            case 'h':
            case '?':
            default:
                usage();
                break;
            }
        }
    }

    masc_log_message( 0, "MAS Source" );
    masc_log_message( 0, "Echoes recorded audio to standard output");
    masc_log_message( 0, "" );
    
    err = mas_init();
    if (err < 0)
    {
	printf("\nconnection with server failed.\n");
	exit(1);
    }

    /** get the display-side anx device - we need the mic output */
    err = mas_asm_get_device_by_name( "anx", &anx );
    if ( err < 0 ) masc_logerror( err, "get anx" );

    err = mas_asm_instantiate_device( "endian", 0, 0, &endian );
    if ( err < 0 ) masc_logerror( err, "couldn't instantiate endian" );
    
    err = mas_asm_get_port_by_name( endian, "source", &end_src );
    if ( err < 0 ) masc_logerror( err, "couldn't get endian source" );

    err = mas_make_data_channel( "massource", &dchnl, &rsrc, &rsnk );
    if ( err < 0 ) masc_logerror( err, "couldn't create data channel" );

    err = mas_asm_connect_devices( anx, endian, "audio_source", "sink" );
    if ( err < 0 ) masc_logerror( err, "couldn't connect anx to endian" );

    dc = masc_make_audio_basic_dc( MAS_LINEAR_FMT, 44100, 16, 2, MAS_LITTLE_ENDIAN_FMT );
    mas_assert( dc != 0, "Memory allocation error" );
    
    err = mas_asm_connect_source_sink( end_src, rsnk, dc );
    if ( err < 0 ) masc_logerror( err, "Couldn't connect endian output to our data channel." );
    masc_strike_dc( dc );
    masc_rtfree( dc );

    if ( timedelay > 0 )
    {
        masc_log_message( 0, "Waiting %d seconds to turn microphone on.", timedelay);
        sleep( timedelay );
    }
    
    /* start recording */
    err = mas_anx_record_start( anx );
    if ( err < 0 ) masc_logerror( err, "can't start recording" );
    masc_log_message( 0, "Mic is ON" );

    while ( 1 )
    {
        err = mas_recv( dchnl, data );
        if ( err < 0 )
        {
            masc_logerror( err, "Couldn't receive data from MAS." );
            masc_log_message( MAS_VERBLVL_ERROR, "Exiting.");
            exit(1);
        }

        fwrite( data->segment, data->length, 1, stdout );
        masc_rtfree( data->segment );
    }
    
    err = mas_anx_record_stop( anx );
    if ( err < 0 ) masc_logerror( err, "can't stop recording" );
    masc_log_message( 0, "Mic is OFF" );
    
    sleep(1);
    
    exit(0);
}
