blob: c37db4a739a33bb9c61d93937f368868abab8101 [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,
Benny Prijono6fd4b8f2006-06-22 18:51:50 +0000202 bits_per_sample, 0, 0,
Benny Prijonobc797312006-03-24 20:44:27 +0000203 &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 */
Benny Prijonobc797312006-03-24 20:44:27 +0000225 &file_port[i] /* result */
226 );
Benny Prijonocbc1c472006-03-19 00:50:23 +0000227 if (status != PJ_SUCCESS) {
228 char title[80];
Benny Prijonobc797312006-03-24 20:44:27 +0000229 pj_ansi_sprintf(title, "Unable to use %s", argv[i+pj_optind]);
Benny Prijonocbc1c472006-03-19 00:50:23 +0000230 app_perror(THIS_FILE, title, status);
231 usage();
232 return 1;
233 }
234
235 /* Add the file port to conference bridge */
236 status = pjmedia_conf_add_port( conf, /* The bridge */
237 pool, /* pool */
238 file_port[i], /* port to connect */
239 NULL, /* Use port's name */
Benny Prijonobc797312006-03-24 20:44:27 +0000240 NULL /* ptr for slot # */
Benny Prijonocbc1c472006-03-19 00:50:23 +0000241 );
242 if (status != PJ_SUCCESS) {
243 app_perror(THIS_FILE, "Unable to add conference port", status);
244 return 1;
245 }
246 }
247
248
249 /*
250 * All ports are set up in the conference bridge.
251 * But at this point, no media will be flowing since no ports are
252 * "connected". User must connect the port manually.
253 */
254
255
Benny Prijonobc797312006-03-24 20:44:27 +0000256 /* Dump memory usage */
257 dump_pool_usage(THIS_FILE, &cp);
258
Benny Prijonocbc1c472006-03-19 00:50:23 +0000259 /* Sleep to allow log messages to flush */
260 pj_thread_sleep(100);
261
262
263 /*
264 * UI Menu:
265 */
266 for (;;) {
267 char tmp1[10];
268 char tmp2[10];
269 char *err;
270 int src, dst, level;
271
272 puts("");
273 conf_list(conf, 0);
274 puts("");
275 puts("Menu:");
276 puts(" s Show ports details");
277 puts(" c Connect one port to another");
278 puts(" d Disconnect port connection");
279 puts(" t Adjust signal level transmitted (tx) to a port");
280 puts(" r Adjust signal level received (rx) from a port");
281 puts(" v Display VU meter for a particular port");
282 puts(" q Quit");
283 puts("");
284
285 printf("Enter selection: "); fflush(stdout);
286
287 fgets(tmp, sizeof(tmp), stdin);
288
289 switch (tmp[0]) {
290 case 's':
291 puts("");
292 conf_list(conf, 1);
293 break;
294
295 case 'c':
296 puts("");
297 puts("Connect source port to destination port");
Benny Prijonoadb34652006-03-19 12:09:53 +0000298 if (!input("Enter source port number", tmp1, sizeof(tmp1)) )
Benny Prijonocbc1c472006-03-19 00:50:23 +0000299 continue;
300 src = strtol(tmp1, &err, 10);
Benny Prijonoadb34652006-03-19 12:09:53 +0000301 if (*err || src < 0 || src >= port_count) {
Benny Prijonocbc1c472006-03-19 00:50:23 +0000302 puts("Invalid slot number");
303 continue;
304 }
305
Benny Prijonoadb34652006-03-19 12:09:53 +0000306 if (!input("Enter destination port number", tmp2, sizeof(tmp2)) )
Benny Prijonocbc1c472006-03-19 00:50:23 +0000307 continue;
308 dst = strtol(tmp2, &err, 10);
Benny Prijonoadb34652006-03-19 12:09:53 +0000309 if (*err || dst < 0 || dst >= port_count) {
Benny Prijonocbc1c472006-03-19 00:50:23 +0000310 puts("Invalid slot number");
311 continue;
312 }
313
314 status = pjmedia_conf_connect_port(conf, src, dst, 0);
315 if (status != PJ_SUCCESS)
316 app_perror(THIS_FILE, "Error connecting port", status);
317
318 break;
319
320 case 'd':
321 puts("");
322 puts("Disconnect port connection");
Benny Prijonoadb34652006-03-19 12:09:53 +0000323 if (!input("Enter source port number", tmp1, sizeof(tmp1)) )
Benny Prijonocbc1c472006-03-19 00:50:23 +0000324 continue;
325 src = strtol(tmp1, &err, 10);
Benny Prijonoadb34652006-03-19 12:09:53 +0000326 if (*err || src < 0 || src >= port_count) {
Benny Prijonocbc1c472006-03-19 00:50:23 +0000327 puts("Invalid slot number");
328 continue;
329 }
330
Benny Prijonoadb34652006-03-19 12:09:53 +0000331 if (!input("Enter destination port number", tmp2, sizeof(tmp2)) )
Benny Prijonocbc1c472006-03-19 00:50:23 +0000332 continue;
333 dst = strtol(tmp2, &err, 10);
Benny Prijonoadb34652006-03-19 12:09:53 +0000334 if (*err || dst < 0 || dst >= port_count) {
Benny Prijonocbc1c472006-03-19 00:50:23 +0000335 puts("Invalid slot number");
336 continue;
337 }
338
339 status = pjmedia_conf_disconnect_port(conf, src, dst);
340 if (status != PJ_SUCCESS)
341 app_perror(THIS_FILE, "Error connecting port", status);
342
343
344 break;
345
346 case 't':
347 puts("");
348 puts("Adjust transmit level of a port");
Benny Prijonoadb34652006-03-19 12:09:53 +0000349 if (!input("Enter port number", tmp1, sizeof(tmp1)) )
Benny Prijonocbc1c472006-03-19 00:50:23 +0000350 continue;
351 src = strtol(tmp1, &err, 10);
Benny Prijonoadb34652006-03-19 12:09:53 +0000352 if (*err || src < 0 || src >= port_count) {
Benny Prijonocbc1c472006-03-19 00:50:23 +0000353 puts("Invalid slot number");
354 continue;
355 }
356
Benny Prijonoadb34652006-03-19 12:09:53 +0000357 if (!input("Enter level (-128 to +127, 0 for normal)",
Benny Prijonocbc1c472006-03-19 00:50:23 +0000358 tmp2, sizeof(tmp2)) )
359 continue;
360 level = strtol(tmp2, &err, 10);
361 if (*err || level < -128 || level > 127) {
362 puts("Invalid level");
363 continue;
364 }
365
366 status = pjmedia_conf_adjust_tx_level( conf, src, level);
367 if (status != PJ_SUCCESS)
368 app_perror(THIS_FILE, "Error adjusting level", status);
369 break;
370
371
372 case 'r':
373 puts("");
374 puts("Adjust receive level of a port");
Benny Prijonoadb34652006-03-19 12:09:53 +0000375 if (!input("Enter port number", tmp1, sizeof(tmp1)) )
Benny Prijonocbc1c472006-03-19 00:50:23 +0000376 continue;
377 src = strtol(tmp1, &err, 10);
Benny Prijonoadb34652006-03-19 12:09:53 +0000378 if (*err || src < 0 || src >= port_count) {
Benny Prijonocbc1c472006-03-19 00:50:23 +0000379 puts("Invalid slot number");
380 continue;
381 }
382
Benny Prijonoadb34652006-03-19 12:09:53 +0000383 if (!input("Enter level (-128 to +127, 0 for normal)",
Benny Prijonocbc1c472006-03-19 00:50:23 +0000384 tmp2, sizeof(tmp2)) )
385 continue;
386 level = strtol(tmp2, &err, 10);
387 if (*err || level < -128 || level > 127) {
388 puts("Invalid level");
389 continue;
390 }
391
392 status = pjmedia_conf_adjust_rx_level( conf, src, level);
393 if (status != PJ_SUCCESS)
394 app_perror(THIS_FILE, "Error adjusting level", status);
395 break;
396
397 case 'v':
398 puts("");
399 puts("Display VU meter");
Benny Prijonoadb34652006-03-19 12:09:53 +0000400 if (!input("Enter port number to monitor", tmp1, sizeof(tmp1)) )
Benny Prijonocbc1c472006-03-19 00:50:23 +0000401 continue;
402 src = strtol(tmp1, &err, 10);
Benny Prijonoadb34652006-03-19 12:09:53 +0000403 if (*err || src < 0 || src >= port_count) {
Benny Prijonocbc1c472006-03-19 00:50:23 +0000404 puts("Invalid slot number");
405 continue;
406 }
407
Benny Prijonoadb34652006-03-19 12:09:53 +0000408 if (!input("Enter r for rx level or t for tx level", tmp2, sizeof(tmp2)))
Benny Prijonocbc1c472006-03-19 00:50:23 +0000409 continue;
410 if (tmp2[0] != 'r' && tmp2[0] != 't') {
411 puts("Invalid option");
412 continue;
413 }
414
Benny Prijonoadb34652006-03-19 12:09:53 +0000415 if (!input("Duration to monitor (in seconds)", tmp1, sizeof(tmp1)) )
Benny Prijonocbc1c472006-03-19 00:50:23 +0000416 continue;
417 strtol(tmp1, &err, 10);
418 if (*err) {
419 puts("Invalid duration number");
420 continue;
421 }
422
423 monitor_level(conf, src, tmp2[0], strtol(tmp1, &err, 10));
424 break;
425
426 case 'q':
427 goto on_quit;
428
429 default:
430 printf("Invalid input character '%c'\n", tmp[0]);
431 break;
432 }
433 }
434
435on_quit:
436
437 /* Start deinitialization: */
438
439 /* Destroy conference bridge */
440 status = pjmedia_conf_destroy( conf );
441 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
442
443
444 /* Destroy file ports */
445 for (i=0; i<file_count; ++i) {
446 status = pjmedia_port_destroy( file_port[i]);
447 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
448 }
449
Benny Prijonobc797312006-03-24 20:44:27 +0000450 /* Destroy recorder port */
451 if (rec_port)
452 pjmedia_port_destroy(rec_port);
453
Benny Prijonocbc1c472006-03-19 00:50:23 +0000454 /* Release application pool */
455 pj_pool_release( pool );
456
457 /* Destroy media endpoint. */
458 pjmedia_endpt_destroy( med_endpt );
459
460 /* Destroy pool factory */
461 pj_caching_pool_destroy( &cp );
462
463
464 /* Done. */
465 return 0;
466}
467
468
469/*
470 * List the ports in conference bridge
471 */
472static void conf_list(pjmedia_conf *conf, int detail)
473{
474 enum { MAX_PORTS = 32 };
475 unsigned i, count;
476 pjmedia_conf_port_info info[MAX_PORTS];
477
478 printf("Conference ports:\n");
479
480 count = PJ_ARRAY_SIZE(info);
481 pjmedia_conf_get_ports_info(conf, &count, info);
482
483 for (i=0; i<count; ++i) {
484 char txlist[4*MAX_PORTS];
485 unsigned j;
486 pjmedia_conf_port_info *port_info = &info[i];
487
488 txlist[0] = '\0';
Benny Prijonoc78c3a32006-06-16 15:54:43 +0000489 for (j=0; j<port_info->listener_cnt; ++j) {
Benny Prijonocbc1c472006-03-19 00:50:23 +0000490 char s[10];
Benny Prijonoc78c3a32006-06-16 15:54:43 +0000491 pj_ansi_sprintf(s, "#%d ", port_info->listener_slots[j]);
492 pj_ansi_strcat(txlist, s);
493
Benny Prijonocbc1c472006-03-19 00:50:23 +0000494 }
495
496 if (txlist[0] == '\0') {
497 txlist[0] = '-';
498 txlist[1] = '\0';
499 }
500
501 if (!detail) {
502 printf("Port #%02d %-25.*s transmitting to: %s\n",
503 port_info->slot,
504 (int)port_info->name.slen,
505 port_info->name.ptr,
506 txlist);
507 } else {
508 unsigned tx_level, rx_level;
509
510 pjmedia_conf_get_signal_level(conf, port_info->slot,
511 &tx_level, &rx_level);
512
513 printf("Port #%02d:\n"
514 " Name : %.*s\n"
515 " Sampling rate : %d Hz\n"
Benny Prijonobc797312006-03-24 20:44:27 +0000516 " Samples per frame : %d\n"
Benny Prijonocbc1c472006-03-19 00:50:23 +0000517 " Frame time : %d ms\n"
518 " Signal level adjustment : tx=%d, rx=%d\n"
519 " Current signal level : tx=%u, rx=%u\n"
520 " Transmitting to ports : %s\n\n",
521 port_info->slot,
522 (int)port_info->name.slen,
523 port_info->name.ptr,
524 port_info->clock_rate,
Benny Prijonobc797312006-03-24 20:44:27 +0000525 port_info->samples_per_frame,
Benny Prijonocbc1c472006-03-19 00:50:23 +0000526 port_info->samples_per_frame*1000/port_info->clock_rate,
527 port_info->tx_adj_level,
528 port_info->rx_adj_level,
529 tx_level,
530 rx_level,
531 txlist);
532 }
533
534 }
535 puts("");
536}
537
538
539/*
540 * Display VU meter
541 */
542static void monitor_level(pjmedia_conf *conf, int slot, int dir, int dur)
543{
Benny Prijonoadb34652006-03-19 12:09:53 +0000544 enum { SLEEP = 20, SAMP_CNT = 2};
Benny Prijonocbc1c472006-03-19 00:50:23 +0000545 pj_status_t status;
Benny Prijonoadb34652006-03-19 12:09:53 +0000546 int i, total_count;
547 unsigned level, samp_cnt;
548
Benny Prijonocbc1c472006-03-19 00:50:23 +0000549
550 puts("");
551 printf("Displaying VU meter for port %d for about %d seconds\n",
552 slot, dur);
553
Benny Prijonoadb34652006-03-19 12:09:53 +0000554 total_count = dur * 1000 / SLEEP;
Benny Prijonocbc1c472006-03-19 00:50:23 +0000555
Benny Prijonoadb34652006-03-19 12:09:53 +0000556 level = 0;
557 samp_cnt = 0;
558
559 for (i=0; i<total_count; ++i) {
Benny Prijonocbc1c472006-03-19 00:50:23 +0000560 unsigned tx_level, rx_level;
Benny Prijonoadb34652006-03-19 12:09:53 +0000561 int j, length;
Benny Prijonocbc1c472006-03-19 00:50:23 +0000562 char meter[21];
563
Benny Prijonoadb34652006-03-19 12:09:53 +0000564 /* Poll the volume every 20 msec */
Benny Prijonocbc1c472006-03-19 00:50:23 +0000565 status = pjmedia_conf_get_signal_level(conf, slot,
566 &tx_level, &rx_level);
567 if (status != PJ_SUCCESS) {
568 app_perror(THIS_FILE, "Unable to read level", status);
569 return;
570 }
571
Benny Prijonoadb34652006-03-19 12:09:53 +0000572 level += (dir=='r' ? rx_level : tx_level);
573 ++samp_cnt;
574
575 /* Accumulate until we have enough samples */
576 if (samp_cnt < SAMP_CNT) {
577 pj_thread_sleep(SLEEP);
578 continue;
579 }
580
581 /* Get average */
582 level = level / samp_cnt;
583
584 /* Draw bar */
585 length = 20 * level / 255;
586 for (j=0; j<length; ++j)
Benny Prijonocbc1c472006-03-19 00:50:23 +0000587 meter[j] = '#';
588 for (; j<20; ++j)
589 meter[j] = ' ';
590 meter[20] = '\0';
591
Benny Prijonoadb34652006-03-19 12:09:53 +0000592 printf("Port #%02d %cx level: [%s] %d \r",
593 slot, dir, meter, level);
594
595 /* Next.. */
596 samp_cnt = 0;
597 level = 0;
Benny Prijonocbc1c472006-03-19 00:50:23 +0000598
599 pj_thread_sleep(SLEEP);
600 }
601
602 puts("");
603}
604