/* $Id$ */ /* * Copyright (C) 2003-2006 Benny Prijono * * 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 #include #include /* atoi() */ #include 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; iname, 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, const 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 to stop"); fgets(tmp, sizeof(tmp), stdin); 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