blob: d87a916a6ef9d8633a0821e546442f0502b81091 [file] [log] [blame]
Benny Prijonocbc1c472006-03-19 00:50:23 +00001/* $Id$ */
2/*
3 * Copyright (C) 2003-2006 Benny Prijono <benny@prijono.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#include <pjmedia.h>
Benny Prijonobc797312006-03-24 20:44:27 +000021#include <pjlib-util.h> /* pj_getopt */
22#include <pjlib.h>
23
24#include <stdlib.h> /* atoi() */
25#include <stdio.h>
26
27#include "util.h"
28
Benny Prijono1ec70b32006-06-20 15:39:07 +000029/**
30 * \page page_pjmedia_samples_confsample_c Samples: Using Conference Bridge
31 *
32 * Sample to mix multiple files in the conference bridge and play the
33 * result to sound device.
34 *
35 * This file is pjsip-apps/src/samples/confsample.c
36 *
37 * \includelineno confsample.c
38 */
39
40
Benny Prijonobc797312006-03-24 20:44:27 +000041/* For logging purpose. */
42#define THIS_FILE "confsample.c"
43
44
45/* Shall we put recorder in the conference */
46#define RECORDER 1
47
Benny Prijonocbc1c472006-03-19 00:50:23 +000048
Benny Prijonofa137ca2006-03-20 17:42:37 +000049static const char *desc =
50 " FILE: \n"
51 " \n"
52 " confsample.c \n"
53 " \n"
54 " PURPOSE: \n"
55 " \n"
56 " Demonstrate how to use conference bridge. \n"
57 " \n"
58 " USAGE: \n"
59 " \n"
Benny Prijonobc797312006-03-24 20:44:27 +000060 " confsample [options] [file1.wav] [file2.wav] ... \n"
Benny Prijonofa137ca2006-03-20 17:42:37 +000061 " \n"
Benny Prijonobc797312006-03-24 20:44:27 +000062 " options: \n"
63 SND_USAGE
64 " \n"
Benny Prijonofa137ca2006-03-20 17:42:37 +000065 " fileN.wav are optional WAV files to be connected to the conference \n"
66 " bridge. The WAV files MUST have single channel (mono) and 16 bit PCM \n"
67 " samples. It can have arbitrary sampling rate. \n"
68 " \n"
69 " DESCRIPTION: \n"
70 " \n"
71 " Here we create a conference bridge, with at least one port (port zero \n"
72 " is always created for the sound device). \n"
73 " \n"
74 " If WAV files are specified, the WAV file player ports will be connected \n"
75 " to slot starting from number one in the bridge. The WAV files can have \n"
76 " arbitrary sampling rate; the bridge will convert it to its clock rate. \n"
Benny Prijonobc797312006-03-24 20:44:27 +000077 " However, the files MUST have a single audio channel only (i.e. mono). \n";
Benny Prijonocbc1c472006-03-19 00:50:23 +000078
Benny Prijonofa137ca2006-03-20 17:42:37 +000079
80
Benny Prijonocbc1c472006-03-19 00:50:23 +000081/*
82 * Prototypes:
83 */
84
85/* List the ports in the conference bridge */
86static void conf_list(pjmedia_conf *conf, pj_bool_t detail);
87
88/* Display VU meter */
89static void monitor_level(pjmedia_conf *conf, int slot, int dir, int dur);
90
91
Benny Prijonocbc1c472006-03-19 00:50:23 +000092/* Show usage */
93static void usage(void)
94{
95 puts("");
Benny Prijono84827832006-03-23 13:15:59 +000096 puts(desc);
Benny Prijonocbc1c472006-03-19 00:50:23 +000097}
98
99
100
101/* Input simple string */
Benny Prijonoadb34652006-03-19 12:09:53 +0000102static pj_bool_t input(const char *title, char *buf, pj_size_t len)
Benny Prijonocbc1c472006-03-19 00:50:23 +0000103{
104 char *p;
105
106 printf("%s (empty to cancel): ", title); fflush(stdout);
107 fgets(buf, len, stdin);
108
109 /* Remove trailing newlines. */
110 for (p=buf; ; ++p) {
111 if (*p=='\r' || *p=='\n') *p='\0';
112 else if (!*p) break;
113 }
114
115 if (!*buf)
116 return PJ_FALSE;
117
118 return PJ_TRUE;
119}
120
121
122/*****************************************************************************
123 * main()
124 */
125int main(int argc, char *argv[])
126{
Benny Prijonobc797312006-03-24 20:44:27 +0000127 int dev_id = -1;
128 int clock_rate = CLOCK_RATE;
129 int channel_count = NCHANNELS;
130 int samples_per_frame = NSAMPLES;
131 int bits_per_sample = NBITS;
132
Benny Prijonocbc1c472006-03-19 00:50:23 +0000133 pj_caching_pool cp;
134 pjmedia_endpt *med_endpt;
135 pj_pool_t *pool;
136 pjmedia_conf *conf;
Benny Prijonocbc1c472006-03-19 00:50:23 +0000137
Benny Prijonoadb34652006-03-19 12:09:53 +0000138 int i, port_count, file_count;
Benny Prijonocbc1c472006-03-19 00:50:23 +0000139 pjmedia_port **file_port; /* Array of file ports */
Benny Prijonobc797312006-03-24 20:44:27 +0000140 pjmedia_port *rec_port = NULL; /* Wav writer port */
Benny Prijonocbc1c472006-03-19 00:50:23 +0000141
142 char tmp[10];
143 pj_status_t status;
144
145
Benny Prijonocbc1c472006-03-19 00:50:23 +0000146 /* Must init PJLIB first: */
147 status = pj_init();
148 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
149
Benny Prijonobc797312006-03-24 20:44:27 +0000150 /* Get command line options. */
151 if (get_snd_options(THIS_FILE, argc, argv, &dev_id, &clock_rate,
152 &channel_count, &samples_per_frame, &bits_per_sample))
153 {
154 usage();
155 return 1;
156 }
157
Benny Prijonocbc1c472006-03-19 00:50:23 +0000158 /* Must create a pool factory before we can allocate any memory. */
159 pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0);
160
161 /*
162 * Initialize media endpoint.
163 * This will implicitly initialize PJMEDIA too.
164 */
Benny Prijono275fd682006-03-22 11:59:11 +0000165 status = pjmedia_endpt_create(&cp.factory, NULL, 1, &med_endpt);
Benny Prijonocbc1c472006-03-19 00:50:23 +0000166 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
167
168 /* Create memory pool to allocate memory */
169 pool = pj_pool_create( &cp.factory, /* pool factory */
170 "wav", /* pool name. */
171 4000, /* init size */
172 4000, /* increment size */
173 NULL /* callback on error */
174 );
175
176
Benny Prijonobc797312006-03-24 20:44:27 +0000177 file_count = argc - pj_optind;
178 port_count = file_count + 1 + RECORDER;
Benny Prijonoadb34652006-03-19 12:09:53 +0000179
Benny Prijonocbc1c472006-03-19 00:50:23 +0000180 /* Create the conference bridge.
181 * With default options (zero), the bridge will create an instance of
182 * sound capture and playback device and connect them to slot zero.
183 */
184 status = pjmedia_conf_create( pool, /* pool to use */
Benny Prijonoadb34652006-03-19 12:09:53 +0000185 port_count,/* number of ports */
Benny Prijonobc797312006-03-24 20:44:27 +0000186 clock_rate,
187 channel_count,
188 samples_per_frame,
189 bits_per_sample,
Benny Prijonocbc1c472006-03-19 00:50:23 +0000190 0, /* options */
191 &conf /* result */
192 );
193 if (status != PJ_SUCCESS) {
194 app_perror(THIS_FILE, "Unable to create conference bridge", status);
195 return 1;
196 }
197
Benny Prijonobc797312006-03-24 20:44:27 +0000198#if RECORDER
Benny Prijono15953012006-04-27 22:37:08 +0000199 status = pjmedia_wav_writer_port_create( pool, "confrecord.wav",
Benny Prijonobc797312006-03-24 20:44:27 +0000200 clock_rate, channel_count,
201 samples_per_frame,
202 bits_per_sample, 0, 0, NULL,
203 &rec_port);
204 if (status != PJ_SUCCESS) {
205 app_perror(THIS_FILE, "Unable to create WAV writer", status);
206 return 1;
207 }
208
209 pjmedia_conf_add_port(conf, pool, rec_port, NULL, NULL);
210#endif
211
Benny Prijonocbc1c472006-03-19 00:50:23 +0000212
Benny Prijonocbc1c472006-03-19 00:50:23 +0000213 /* Create file ports. */
Benny Prijonocbc1c472006-03-19 00:50:23 +0000214 file_port = pj_pool_alloc(pool, file_count * sizeof(pjmedia_port*));
215
216 for (i=0; i<file_count; ++i) {
217
218 /* Load the WAV file to file port. */
Benny Prijono15953012006-04-27 22:37:08 +0000219 status = pjmedia_wav_player_port_create(
Benny Prijonobc797312006-03-24 20:44:27 +0000220 pool, /* pool. */
221 argv[i+pj_optind], /* filename */
Benny Prijono15953012006-04-27 22:37:08 +0000222 0, /* use default ptime */
Benny Prijonobc797312006-03-24 20:44:27 +0000223 0, /* flags */
224 0, /* buf size */
225 NULL, /* user data */
226 &file_port[i] /* result */
227 );
Benny Prijonocbc1c472006-03-19 00:50:23 +0000228 if (status != PJ_SUCCESS) {
229 char title[80];
Benny Prijonobc797312006-03-24 20:44:27 +0000230 pj_ansi_sprintf(title, "Unable to use %s", argv[i+pj_optind]);
Benny Prijonocbc1c472006-03-19 00:50:23 +0000231 app_perror(THIS_FILE, title, status);
232 usage();
233 return 1;
234 }
235
236 /* Add the file port to conference bridge */
237 status = pjmedia_conf_add_port( conf, /* The bridge */
238 pool, /* pool */
239 file_port[i], /* port to connect */
240 NULL, /* Use port's name */
Benny Prijonobc797312006-03-24 20:44:27 +0000241 NULL /* ptr for slot # */
Benny Prijonocbc1c472006-03-19 00:50:23 +0000242 );
243 if (status != PJ_SUCCESS) {
244 app_perror(THIS_FILE, "Unable to add conference port", status);
245 return 1;
246 }
247 }
248
249
250 /*
251 * All ports are set up in the conference bridge.
252 * But at this point, no media will be flowing since no ports are
253 * "connected". User must connect the port manually.
254 */
255
256
Benny Prijonobc797312006-03-24 20:44:27 +0000257 /* Dump memory usage */
258 dump_pool_usage(THIS_FILE, &cp);
259
Benny Prijonocbc1c472006-03-19 00:50:23 +0000260 /* Sleep to allow log messages to flush */
261 pj_thread_sleep(100);
262
263
264 /*
265 * UI Menu:
266 */
267 for (;;) {
268 char tmp1[10];
269 char tmp2[10];
270 char *err;
271 int src, dst, level;
272
273 puts("");
274 conf_list(conf, 0);
275 puts("");
276 puts("Menu:");
277 puts(" s Show ports details");
278 puts(" c Connect one port to another");
279 puts(" d Disconnect port connection");
280 puts(" t Adjust signal level transmitted (tx) to a port");
281 puts(" r Adjust signal level received (rx) from a port");
282 puts(" v Display VU meter for a particular port");
283 puts(" q Quit");
284 puts("");
285
286 printf("Enter selection: "); fflush(stdout);
287
288 fgets(tmp, sizeof(tmp), stdin);
289
290 switch (tmp[0]) {
291 case 's':
292 puts("");
293 conf_list(conf, 1);
294 break;
295
296 case 'c':
297 puts("");
298 puts("Connect source port to destination port");
Benny Prijonoadb34652006-03-19 12:09:53 +0000299 if (!input("Enter source port number", tmp1, sizeof(tmp1)) )
Benny Prijonocbc1c472006-03-19 00:50:23 +0000300 continue;
301 src = strtol(tmp1, &err, 10);
Benny Prijonoadb34652006-03-19 12:09:53 +0000302 if (*err || src < 0 || src >= port_count) {
Benny Prijonocbc1c472006-03-19 00:50:23 +0000303 puts("Invalid slot number");
304 continue;
305 }
306
Benny Prijonoadb34652006-03-19 12:09:53 +0000307 if (!input("Enter destination port number", tmp2, sizeof(tmp2)) )
Benny Prijonocbc1c472006-03-19 00:50:23 +0000308 continue;
309 dst = strtol(tmp2, &err, 10);
Benny Prijonoadb34652006-03-19 12:09:53 +0000310 if (*err || dst < 0 || dst >= port_count) {
Benny Prijonocbc1c472006-03-19 00:50:23 +0000311 puts("Invalid slot number");
312 continue;
313 }
314
315 status = pjmedia_conf_connect_port(conf, src, dst, 0);
316 if (status != PJ_SUCCESS)
317 app_perror(THIS_FILE, "Error connecting port", status);
318
319 break;
320
321 case 'd':
322 puts("");
323 puts("Disconnect port connection");
Benny Prijonoadb34652006-03-19 12:09:53 +0000324 if (!input("Enter source port number", tmp1, sizeof(tmp1)) )
Benny Prijonocbc1c472006-03-19 00:50:23 +0000325 continue;
326 src = strtol(tmp1, &err, 10);
Benny Prijonoadb34652006-03-19 12:09:53 +0000327 if (*err || src < 0 || src >= port_count) {
Benny Prijonocbc1c472006-03-19 00:50:23 +0000328 puts("Invalid slot number");
329 continue;
330 }
331
Benny Prijonoadb34652006-03-19 12:09:53 +0000332 if (!input("Enter destination port number", tmp2, sizeof(tmp2)) )
Benny Prijonocbc1c472006-03-19 00:50:23 +0000333 continue;
334 dst = strtol(tmp2, &err, 10);
Benny Prijonoadb34652006-03-19 12:09:53 +0000335 if (*err || dst < 0 || dst >= port_count) {
Benny Prijonocbc1c472006-03-19 00:50:23 +0000336 puts("Invalid slot number");
337 continue;
338 }
339
340 status = pjmedia_conf_disconnect_port(conf, src, dst);
341 if (status != PJ_SUCCESS)
342 app_perror(THIS_FILE, "Error connecting port", status);
343
344
345 break;
346
347 case 't':
348 puts("");
349 puts("Adjust transmit level of a port");
Benny Prijonoadb34652006-03-19 12:09:53 +0000350 if (!input("Enter port number", tmp1, sizeof(tmp1)) )
Benny Prijonocbc1c472006-03-19 00:50:23 +0000351 continue;
352 src = strtol(tmp1, &err, 10);
Benny Prijonoadb34652006-03-19 12:09:53 +0000353 if (*err || src < 0 || src >= port_count) {
Benny Prijonocbc1c472006-03-19 00:50:23 +0000354 puts("Invalid slot number");
355 continue;
356 }
357
Benny Prijonoadb34652006-03-19 12:09:53 +0000358 if (!input("Enter level (-128 to +127, 0 for normal)",
Benny Prijonocbc1c472006-03-19 00:50:23 +0000359 tmp2, sizeof(tmp2)) )
360 continue;
361 level = strtol(tmp2, &err, 10);
362 if (*err || level < -128 || level > 127) {
363 puts("Invalid level");
364 continue;
365 }
366
367 status = pjmedia_conf_adjust_tx_level( conf, src, level);
368 if (status != PJ_SUCCESS)
369 app_perror(THIS_FILE, "Error adjusting level", status);
370 break;
371
372
373 case 'r':
374 puts("");
375 puts("Adjust receive level of a port");
Benny Prijonoadb34652006-03-19 12:09:53 +0000376 if (!input("Enter port number", tmp1, sizeof(tmp1)) )
Benny Prijonocbc1c472006-03-19 00:50:23 +0000377 continue;
378 src = strtol(tmp1, &err, 10);
Benny Prijonoadb34652006-03-19 12:09:53 +0000379 if (*err || src < 0 || src >= port_count) {
Benny Prijonocbc1c472006-03-19 00:50:23 +0000380 puts("Invalid slot number");
381 continue;
382 }
383
Benny Prijonoadb34652006-03-19 12:09:53 +0000384 if (!input("Enter level (-128 to +127, 0 for normal)",
Benny Prijonocbc1c472006-03-19 00:50:23 +0000385 tmp2, sizeof(tmp2)) )
386 continue;
387 level = strtol(tmp2, &err, 10);
388 if (*err || level < -128 || level > 127) {
389 puts("Invalid level");
390 continue;
391 }
392
393 status = pjmedia_conf_adjust_rx_level( conf, src, level);
394 if (status != PJ_SUCCESS)
395 app_perror(THIS_FILE, "Error adjusting level", status);
396 break;
397
398 case 'v':
399 puts("");
400 puts("Display VU meter");
Benny Prijonoadb34652006-03-19 12:09:53 +0000401 if (!input("Enter port number to monitor", tmp1, sizeof(tmp1)) )
Benny Prijonocbc1c472006-03-19 00:50:23 +0000402 continue;
403 src = strtol(tmp1, &err, 10);
Benny Prijonoadb34652006-03-19 12:09:53 +0000404 if (*err || src < 0 || src >= port_count) {
Benny Prijonocbc1c472006-03-19 00:50:23 +0000405 puts("Invalid slot number");
406 continue;
407 }
408
Benny Prijonoadb34652006-03-19 12:09:53 +0000409 if (!input("Enter r for rx level or t for tx level", tmp2, sizeof(tmp2)))
Benny Prijonocbc1c472006-03-19 00:50:23 +0000410 continue;
411 if (tmp2[0] != 'r' && tmp2[0] != 't') {
412 puts("Invalid option");
413 continue;
414 }
415
Benny Prijonoadb34652006-03-19 12:09:53 +0000416 if (!input("Duration to monitor (in seconds)", tmp1, sizeof(tmp1)) )
Benny Prijonocbc1c472006-03-19 00:50:23 +0000417 continue;
418 strtol(tmp1, &err, 10);
419 if (*err) {
420 puts("Invalid duration number");
421 continue;
422 }
423
424 monitor_level(conf, src, tmp2[0], strtol(tmp1, &err, 10));
425 break;
426
427 case 'q':
428 goto on_quit;
429
430 default:
431 printf("Invalid input character '%c'\n", tmp[0]);
432 break;
433 }
434 }
435
436on_quit:
437
438 /* Start deinitialization: */
439
440 /* Destroy conference bridge */
441 status = pjmedia_conf_destroy( conf );
442 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
443
444
445 /* Destroy file ports */
446 for (i=0; i<file_count; ++i) {
447 status = pjmedia_port_destroy( file_port[i]);
448 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
449 }
450
Benny Prijonobc797312006-03-24 20:44:27 +0000451 /* Destroy recorder port */
452 if (rec_port)
453 pjmedia_port_destroy(rec_port);
454
Benny Prijonocbc1c472006-03-19 00:50:23 +0000455 /* Release application pool */
456 pj_pool_release( pool );
457
458 /* Destroy media endpoint. */
459 pjmedia_endpt_destroy( med_endpt );
460
461 /* Destroy pool factory */
462 pj_caching_pool_destroy( &cp );
463
464
465 /* Done. */
466 return 0;
467}
468
469
470/*
471 * List the ports in conference bridge
472 */
473static void conf_list(pjmedia_conf *conf, int detail)
474{
475 enum { MAX_PORTS = 32 };
476 unsigned i, count;
477 pjmedia_conf_port_info info[MAX_PORTS];
478
479 printf("Conference ports:\n");
480
481 count = PJ_ARRAY_SIZE(info);
482 pjmedia_conf_get_ports_info(conf, &count, info);
483
484 for (i=0; i<count; ++i) {
485 char txlist[4*MAX_PORTS];
486 unsigned j;
487 pjmedia_conf_port_info *port_info = &info[i];
488
489 txlist[0] = '\0';
Benny Prijonoc78c3a32006-06-16 15:54:43 +0000490 for (j=0; j<port_info->listener_cnt; ++j) {
Benny Prijonocbc1c472006-03-19 00:50:23 +0000491 char s[10];
Benny Prijonoc78c3a32006-06-16 15:54:43 +0000492 pj_ansi_sprintf(s, "#%d ", port_info->listener_slots[j]);
493 pj_ansi_strcat(txlist, s);
494
Benny Prijonocbc1c472006-03-19 00:50:23 +0000495 }
496
497 if (txlist[0] == '\0') {
498 txlist[0] = '-';
499 txlist[1] = '\0';
500 }
501
502 if (!detail) {
503 printf("Port #%02d %-25.*s transmitting to: %s\n",
504 port_info->slot,
505 (int)port_info->name.slen,
506 port_info->name.ptr,
507 txlist);
508 } else {
509 unsigned tx_level, rx_level;
510
511 pjmedia_conf_get_signal_level(conf, port_info->slot,
512 &tx_level, &rx_level);
513
514 printf("Port #%02d:\n"
515 " Name : %.*s\n"
516 " Sampling rate : %d Hz\n"
Benny Prijonobc797312006-03-24 20:44:27 +0000517 " Samples per frame : %d\n"
Benny Prijonocbc1c472006-03-19 00:50:23 +0000518 " Frame time : %d ms\n"
519 " Signal level adjustment : tx=%d, rx=%d\n"
520 " Current signal level : tx=%u, rx=%u\n"
521 " Transmitting to ports : %s\n\n",
522 port_info->slot,
523 (int)port_info->name.slen,
524 port_info->name.ptr,
525 port_info->clock_rate,
Benny Prijonobc797312006-03-24 20:44:27 +0000526 port_info->samples_per_frame,
Benny Prijonocbc1c472006-03-19 00:50:23 +0000527 port_info->samples_per_frame*1000/port_info->clock_rate,
528 port_info->tx_adj_level,
529 port_info->rx_adj_level,
530 tx_level,
531 rx_level,
532 txlist);
533 }
534
535 }
536 puts("");
537}
538
539
540/*
541 * Display VU meter
542 */
543static void monitor_level(pjmedia_conf *conf, int slot, int dir, int dur)
544{
Benny Prijonoadb34652006-03-19 12:09:53 +0000545 enum { SLEEP = 20, SAMP_CNT = 2};
Benny Prijonocbc1c472006-03-19 00:50:23 +0000546 pj_status_t status;
Benny Prijonoadb34652006-03-19 12:09:53 +0000547 int i, total_count;
548 unsigned level, samp_cnt;
549
Benny Prijonocbc1c472006-03-19 00:50:23 +0000550
551 puts("");
552 printf("Displaying VU meter for port %d for about %d seconds\n",
553 slot, dur);
554
Benny Prijonoadb34652006-03-19 12:09:53 +0000555 total_count = dur * 1000 / SLEEP;
Benny Prijonocbc1c472006-03-19 00:50:23 +0000556
Benny Prijonoadb34652006-03-19 12:09:53 +0000557 level = 0;
558 samp_cnt = 0;
559
560 for (i=0; i<total_count; ++i) {
Benny Prijonocbc1c472006-03-19 00:50:23 +0000561 unsigned tx_level, rx_level;
Benny Prijonoadb34652006-03-19 12:09:53 +0000562 int j, length;
Benny Prijonocbc1c472006-03-19 00:50:23 +0000563 char meter[21];
564
Benny Prijonoadb34652006-03-19 12:09:53 +0000565 /* Poll the volume every 20 msec */
Benny Prijonocbc1c472006-03-19 00:50:23 +0000566 status = pjmedia_conf_get_signal_level(conf, slot,
567 &tx_level, &rx_level);
568 if (status != PJ_SUCCESS) {
569 app_perror(THIS_FILE, "Unable to read level", status);
570 return;
571 }
572
Benny Prijonoadb34652006-03-19 12:09:53 +0000573 level += (dir=='r' ? rx_level : tx_level);
574 ++samp_cnt;
575
576 /* Accumulate until we have enough samples */
577 if (samp_cnt < SAMP_CNT) {
578 pj_thread_sleep(SLEEP);
579 continue;
580 }
581
582 /* Get average */
583 level = level / samp_cnt;
584
585 /* Draw bar */
586 length = 20 * level / 255;
587 for (j=0; j<length; ++j)
Benny Prijonocbc1c472006-03-19 00:50:23 +0000588 meter[j] = '#';
589 for (; j<20; ++j)
590 meter[j] = ' ';
591 meter[20] = '\0';
592
Benny Prijonoadb34652006-03-19 12:09:53 +0000593 printf("Port #%02d %cx level: [%s] %d \r",
594 slot, dir, meter, level);
595
596 /* Next.. */
597 samp_cnt = 0;
598 level = 0;
Benny Prijonocbc1c472006-03-19 00:50:23 +0000599
600 pj_thread_sleep(SLEEP);
601 }
602
603 puts("");
604}
605