blob: 7ae80cdc3cc7743b782b8a2d8d73b7bcf398b36b [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
29/* For logging purpose. */
30#define THIS_FILE "confsample.c"
31
32
33/* Shall we put recorder in the conference */
34#define RECORDER 1
35
Benny Prijonocbc1c472006-03-19 00:50:23 +000036
Benny Prijonofa137ca2006-03-20 17:42:37 +000037static const char *desc =
38 " FILE: \n"
39 " \n"
40 " confsample.c \n"
41 " \n"
42 " PURPOSE: \n"
43 " \n"
44 " Demonstrate how to use conference bridge. \n"
45 " \n"
46 " USAGE: \n"
47 " \n"
Benny Prijonobc797312006-03-24 20:44:27 +000048 " confsample [options] [file1.wav] [file2.wav] ... \n"
Benny Prijonofa137ca2006-03-20 17:42:37 +000049 " \n"
Benny Prijonobc797312006-03-24 20:44:27 +000050 " options: \n"
51 SND_USAGE
52 " \n"
Benny Prijonofa137ca2006-03-20 17:42:37 +000053 " fileN.wav are optional WAV files to be connected to the conference \n"
54 " bridge. The WAV files MUST have single channel (mono) and 16 bit PCM \n"
55 " samples. It can have arbitrary sampling rate. \n"
56 " \n"
57 " DESCRIPTION: \n"
58 " \n"
59 " Here we create a conference bridge, with at least one port (port zero \n"
60 " is always created for the sound device). \n"
61 " \n"
62 " If WAV files are specified, the WAV file player ports will be connected \n"
63 " to slot starting from number one in the bridge. The WAV files can have \n"
64 " arbitrary sampling rate; the bridge will convert it to its clock rate. \n"
Benny Prijonobc797312006-03-24 20:44:27 +000065 " However, the files MUST have a single audio channel only (i.e. mono). \n";
Benny Prijonocbc1c472006-03-19 00:50:23 +000066
Benny Prijonofa137ca2006-03-20 17:42:37 +000067
68
Benny Prijonocbc1c472006-03-19 00:50:23 +000069/*
70 * Prototypes:
71 */
72
73/* List the ports in the conference bridge */
74static void conf_list(pjmedia_conf *conf, pj_bool_t detail);
75
76/* Display VU meter */
77static void monitor_level(pjmedia_conf *conf, int slot, int dir, int dur);
78
79
Benny Prijonocbc1c472006-03-19 00:50:23 +000080/* Show usage */
81static void usage(void)
82{
83 puts("");
Benny Prijono84827832006-03-23 13:15:59 +000084 puts(desc);
Benny Prijonocbc1c472006-03-19 00:50:23 +000085}
86
87
88
89/* Input simple string */
Benny Prijonoadb34652006-03-19 12:09:53 +000090static pj_bool_t input(const char *title, char *buf, pj_size_t len)
Benny Prijonocbc1c472006-03-19 00:50:23 +000091{
92 char *p;
93
94 printf("%s (empty to cancel): ", title); fflush(stdout);
95 fgets(buf, len, stdin);
96
97 /* Remove trailing newlines. */
98 for (p=buf; ; ++p) {
99 if (*p=='\r' || *p=='\n') *p='\0';
100 else if (!*p) break;
101 }
102
103 if (!*buf)
104 return PJ_FALSE;
105
106 return PJ_TRUE;
107}
108
109
110/*****************************************************************************
111 * main()
112 */
113int main(int argc, char *argv[])
114{
Benny Prijonobc797312006-03-24 20:44:27 +0000115 int dev_id = -1;
116 int clock_rate = CLOCK_RATE;
117 int channel_count = NCHANNELS;
118 int samples_per_frame = NSAMPLES;
119 int bits_per_sample = NBITS;
120
Benny Prijonocbc1c472006-03-19 00:50:23 +0000121 pj_caching_pool cp;
122 pjmedia_endpt *med_endpt;
123 pj_pool_t *pool;
124 pjmedia_conf *conf;
Benny Prijonocbc1c472006-03-19 00:50:23 +0000125
Benny Prijonoadb34652006-03-19 12:09:53 +0000126 int i, port_count, file_count;
Benny Prijonocbc1c472006-03-19 00:50:23 +0000127 pjmedia_port **file_port; /* Array of file ports */
Benny Prijonobc797312006-03-24 20:44:27 +0000128 pjmedia_port *rec_port = NULL; /* Wav writer port */
Benny Prijonocbc1c472006-03-19 00:50:23 +0000129
130 char tmp[10];
131 pj_status_t status;
132
133
Benny Prijonocbc1c472006-03-19 00:50:23 +0000134 /* Must init PJLIB first: */
135 status = pj_init();
136 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
137
Benny Prijonobc797312006-03-24 20:44:27 +0000138 /* Get command line options. */
139 if (get_snd_options(THIS_FILE, argc, argv, &dev_id, &clock_rate,
140 &channel_count, &samples_per_frame, &bits_per_sample))
141 {
142 usage();
143 return 1;
144 }
145
Benny Prijonocbc1c472006-03-19 00:50:23 +0000146 /* Must create a pool factory before we can allocate any memory. */
147 pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0);
148
149 /*
150 * Initialize media endpoint.
151 * This will implicitly initialize PJMEDIA too.
152 */
Benny Prijono275fd682006-03-22 11:59:11 +0000153 status = pjmedia_endpt_create(&cp.factory, NULL, 1, &med_endpt);
Benny Prijonocbc1c472006-03-19 00:50:23 +0000154 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
155
156 /* Create memory pool to allocate memory */
157 pool = pj_pool_create( &cp.factory, /* pool factory */
158 "wav", /* pool name. */
159 4000, /* init size */
160 4000, /* increment size */
161 NULL /* callback on error */
162 );
163
164
Benny Prijonobc797312006-03-24 20:44:27 +0000165 file_count = argc - pj_optind;
166 port_count = file_count + 1 + RECORDER;
Benny Prijonoadb34652006-03-19 12:09:53 +0000167
Benny Prijonocbc1c472006-03-19 00:50:23 +0000168 /* Create the conference bridge.
169 * With default options (zero), the bridge will create an instance of
170 * sound capture and playback device and connect them to slot zero.
171 */
172 status = pjmedia_conf_create( pool, /* pool to use */
Benny Prijonoadb34652006-03-19 12:09:53 +0000173 port_count,/* number of ports */
Benny Prijonobc797312006-03-24 20:44:27 +0000174 clock_rate,
175 channel_count,
176 samples_per_frame,
177 bits_per_sample,
Benny Prijonocbc1c472006-03-19 00:50:23 +0000178 0, /* options */
179 &conf /* result */
180 );
181 if (status != PJ_SUCCESS) {
182 app_perror(THIS_FILE, "Unable to create conference bridge", status);
183 return 1;
184 }
185
Benny Prijonobc797312006-03-24 20:44:27 +0000186#if RECORDER
Benny Prijono15953012006-04-27 22:37:08 +0000187 status = pjmedia_wav_writer_port_create( pool, "confrecord.wav",
Benny Prijonobc797312006-03-24 20:44:27 +0000188 clock_rate, channel_count,
189 samples_per_frame,
190 bits_per_sample, 0, 0, NULL,
191 &rec_port);
192 if (status != PJ_SUCCESS) {
193 app_perror(THIS_FILE, "Unable to create WAV writer", status);
194 return 1;
195 }
196
197 pjmedia_conf_add_port(conf, pool, rec_port, NULL, NULL);
198#endif
199
Benny Prijonocbc1c472006-03-19 00:50:23 +0000200
Benny Prijonocbc1c472006-03-19 00:50:23 +0000201 /* Create file ports. */
Benny Prijonocbc1c472006-03-19 00:50:23 +0000202 file_port = pj_pool_alloc(pool, file_count * sizeof(pjmedia_port*));
203
204 for (i=0; i<file_count; ++i) {
205
206 /* Load the WAV file to file port. */
Benny Prijono15953012006-04-27 22:37:08 +0000207 status = pjmedia_wav_player_port_create(
Benny Prijonobc797312006-03-24 20:44:27 +0000208 pool, /* pool. */
209 argv[i+pj_optind], /* filename */
Benny Prijono15953012006-04-27 22:37:08 +0000210 0, /* use default ptime */
Benny Prijonobc797312006-03-24 20:44:27 +0000211 0, /* flags */
212 0, /* buf size */
213 NULL, /* user data */
214 &file_port[i] /* result */
215 );
Benny Prijonocbc1c472006-03-19 00:50:23 +0000216 if (status != PJ_SUCCESS) {
217 char title[80];
Benny Prijonobc797312006-03-24 20:44:27 +0000218 pj_ansi_sprintf(title, "Unable to use %s", argv[i+pj_optind]);
Benny Prijonocbc1c472006-03-19 00:50:23 +0000219 app_perror(THIS_FILE, title, status);
220 usage();
221 return 1;
222 }
223
224 /* Add the file port to conference bridge */
225 status = pjmedia_conf_add_port( conf, /* The bridge */
226 pool, /* pool */
227 file_port[i], /* port to connect */
228 NULL, /* Use port's name */
Benny Prijonobc797312006-03-24 20:44:27 +0000229 NULL /* ptr for slot # */
Benny Prijonocbc1c472006-03-19 00:50:23 +0000230 );
231 if (status != PJ_SUCCESS) {
232 app_perror(THIS_FILE, "Unable to add conference port", status);
233 return 1;
234 }
235 }
236
237
238 /*
239 * All ports are set up in the conference bridge.
240 * But at this point, no media will be flowing since no ports are
241 * "connected". User must connect the port manually.
242 */
243
244
Benny Prijonobc797312006-03-24 20:44:27 +0000245 /* Dump memory usage */
246 dump_pool_usage(THIS_FILE, &cp);
247
Benny Prijonocbc1c472006-03-19 00:50:23 +0000248 /* Sleep to allow log messages to flush */
249 pj_thread_sleep(100);
250
251
252 /*
253 * UI Menu:
254 */
255 for (;;) {
256 char tmp1[10];
257 char tmp2[10];
258 char *err;
259 int src, dst, level;
260
261 puts("");
262 conf_list(conf, 0);
263 puts("");
264 puts("Menu:");
265 puts(" s Show ports details");
266 puts(" c Connect one port to another");
267 puts(" d Disconnect port connection");
268 puts(" t Adjust signal level transmitted (tx) to a port");
269 puts(" r Adjust signal level received (rx) from a port");
270 puts(" v Display VU meter for a particular port");
271 puts(" q Quit");
272 puts("");
273
274 printf("Enter selection: "); fflush(stdout);
275
276 fgets(tmp, sizeof(tmp), stdin);
277
278 switch (tmp[0]) {
279 case 's':
280 puts("");
281 conf_list(conf, 1);
282 break;
283
284 case 'c':
285 puts("");
286 puts("Connect source port to destination port");
Benny Prijonoadb34652006-03-19 12:09:53 +0000287 if (!input("Enter source port number", tmp1, sizeof(tmp1)) )
Benny Prijonocbc1c472006-03-19 00:50:23 +0000288 continue;
289 src = strtol(tmp1, &err, 10);
Benny Prijonoadb34652006-03-19 12:09:53 +0000290 if (*err || src < 0 || src >= port_count) {
Benny Prijonocbc1c472006-03-19 00:50:23 +0000291 puts("Invalid slot number");
292 continue;
293 }
294
Benny Prijonoadb34652006-03-19 12:09:53 +0000295 if (!input("Enter destination port number", tmp2, sizeof(tmp2)) )
Benny Prijonocbc1c472006-03-19 00:50:23 +0000296 continue;
297 dst = strtol(tmp2, &err, 10);
Benny Prijonoadb34652006-03-19 12:09:53 +0000298 if (*err || dst < 0 || dst >= port_count) {
Benny Prijonocbc1c472006-03-19 00:50:23 +0000299 puts("Invalid slot number");
300 continue;
301 }
302
303 status = pjmedia_conf_connect_port(conf, src, dst, 0);
304 if (status != PJ_SUCCESS)
305 app_perror(THIS_FILE, "Error connecting port", status);
306
307 break;
308
309 case 'd':
310 puts("");
311 puts("Disconnect port connection");
Benny Prijonoadb34652006-03-19 12:09:53 +0000312 if (!input("Enter source port number", tmp1, sizeof(tmp1)) )
Benny Prijonocbc1c472006-03-19 00:50:23 +0000313 continue;
314 src = strtol(tmp1, &err, 10);
Benny Prijonoadb34652006-03-19 12:09:53 +0000315 if (*err || src < 0 || src >= port_count) {
Benny Prijonocbc1c472006-03-19 00:50:23 +0000316 puts("Invalid slot number");
317 continue;
318 }
319
Benny Prijonoadb34652006-03-19 12:09:53 +0000320 if (!input("Enter destination port number", tmp2, sizeof(tmp2)) )
Benny Prijonocbc1c472006-03-19 00:50:23 +0000321 continue;
322 dst = strtol(tmp2, &err, 10);
Benny Prijonoadb34652006-03-19 12:09:53 +0000323 if (*err || dst < 0 || dst >= port_count) {
Benny Prijonocbc1c472006-03-19 00:50:23 +0000324 puts("Invalid slot number");
325 continue;
326 }
327
328 status = pjmedia_conf_disconnect_port(conf, src, dst);
329 if (status != PJ_SUCCESS)
330 app_perror(THIS_FILE, "Error connecting port", status);
331
332
333 break;
334
335 case 't':
336 puts("");
337 puts("Adjust transmit level of a port");
Benny Prijonoadb34652006-03-19 12:09:53 +0000338 if (!input("Enter port number", tmp1, sizeof(tmp1)) )
Benny Prijonocbc1c472006-03-19 00:50:23 +0000339 continue;
340 src = strtol(tmp1, &err, 10);
Benny Prijonoadb34652006-03-19 12:09:53 +0000341 if (*err || src < 0 || src >= port_count) {
Benny Prijonocbc1c472006-03-19 00:50:23 +0000342 puts("Invalid slot number");
343 continue;
344 }
345
Benny Prijonoadb34652006-03-19 12:09:53 +0000346 if (!input("Enter level (-128 to +127, 0 for normal)",
Benny Prijonocbc1c472006-03-19 00:50:23 +0000347 tmp2, sizeof(tmp2)) )
348 continue;
349 level = strtol(tmp2, &err, 10);
350 if (*err || level < -128 || level > 127) {
351 puts("Invalid level");
352 continue;
353 }
354
355 status = pjmedia_conf_adjust_tx_level( conf, src, level);
356 if (status != PJ_SUCCESS)
357 app_perror(THIS_FILE, "Error adjusting level", status);
358 break;
359
360
361 case 'r':
362 puts("");
363 puts("Adjust receive level of a port");
Benny Prijonoadb34652006-03-19 12:09:53 +0000364 if (!input("Enter port number", tmp1, sizeof(tmp1)) )
Benny Prijonocbc1c472006-03-19 00:50:23 +0000365 continue;
366 src = strtol(tmp1, &err, 10);
Benny Prijonoadb34652006-03-19 12:09:53 +0000367 if (*err || src < 0 || src >= port_count) {
Benny Prijonocbc1c472006-03-19 00:50:23 +0000368 puts("Invalid slot number");
369 continue;
370 }
371
Benny Prijonoadb34652006-03-19 12:09:53 +0000372 if (!input("Enter level (-128 to +127, 0 for normal)",
Benny Prijonocbc1c472006-03-19 00:50:23 +0000373 tmp2, sizeof(tmp2)) )
374 continue;
375 level = strtol(tmp2, &err, 10);
376 if (*err || level < -128 || level > 127) {
377 puts("Invalid level");
378 continue;
379 }
380
381 status = pjmedia_conf_adjust_rx_level( conf, src, level);
382 if (status != PJ_SUCCESS)
383 app_perror(THIS_FILE, "Error adjusting level", status);
384 break;
385
386 case 'v':
387 puts("");
388 puts("Display VU meter");
Benny Prijonoadb34652006-03-19 12:09:53 +0000389 if (!input("Enter port number to monitor", tmp1, sizeof(tmp1)) )
Benny Prijonocbc1c472006-03-19 00:50:23 +0000390 continue;
391 src = strtol(tmp1, &err, 10);
Benny Prijonoadb34652006-03-19 12:09:53 +0000392 if (*err || src < 0 || src >= port_count) {
Benny Prijonocbc1c472006-03-19 00:50:23 +0000393 puts("Invalid slot number");
394 continue;
395 }
396
Benny Prijonoadb34652006-03-19 12:09:53 +0000397 if (!input("Enter r for rx level or t for tx level", tmp2, sizeof(tmp2)))
Benny Prijonocbc1c472006-03-19 00:50:23 +0000398 continue;
399 if (tmp2[0] != 'r' && tmp2[0] != 't') {
400 puts("Invalid option");
401 continue;
402 }
403
Benny Prijonoadb34652006-03-19 12:09:53 +0000404 if (!input("Duration to monitor (in seconds)", tmp1, sizeof(tmp1)) )
Benny Prijonocbc1c472006-03-19 00:50:23 +0000405 continue;
406 strtol(tmp1, &err, 10);
407 if (*err) {
408 puts("Invalid duration number");
409 continue;
410 }
411
412 monitor_level(conf, src, tmp2[0], strtol(tmp1, &err, 10));
413 break;
414
415 case 'q':
416 goto on_quit;
417
418 default:
419 printf("Invalid input character '%c'\n", tmp[0]);
420 break;
421 }
422 }
423
424on_quit:
425
426 /* Start deinitialization: */
427
428 /* Destroy conference bridge */
429 status = pjmedia_conf_destroy( conf );
430 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
431
432
433 /* Destroy file ports */
434 for (i=0; i<file_count; ++i) {
435 status = pjmedia_port_destroy( file_port[i]);
436 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
437 }
438
Benny Prijonobc797312006-03-24 20:44:27 +0000439 /* Destroy recorder port */
440 if (rec_port)
441 pjmedia_port_destroy(rec_port);
442
Benny Prijonocbc1c472006-03-19 00:50:23 +0000443 /* Release application pool */
444 pj_pool_release( pool );
445
446 /* Destroy media endpoint. */
447 pjmedia_endpt_destroy( med_endpt );
448
449 /* Destroy pool factory */
450 pj_caching_pool_destroy( &cp );
451
452
453 /* Done. */
454 return 0;
455}
456
457
458/*
459 * List the ports in conference bridge
460 */
461static void conf_list(pjmedia_conf *conf, int detail)
462{
463 enum { MAX_PORTS = 32 };
464 unsigned i, count;
465 pjmedia_conf_port_info info[MAX_PORTS];
466
467 printf("Conference ports:\n");
468
469 count = PJ_ARRAY_SIZE(info);
470 pjmedia_conf_get_ports_info(conf, &count, info);
471
472 for (i=0; i<count; ++i) {
473 char txlist[4*MAX_PORTS];
474 unsigned j;
475 pjmedia_conf_port_info *port_info = &info[i];
476
477 txlist[0] = '\0';
Benny Prijonoc78c3a32006-06-16 15:54:43 +0000478 for (j=0; j<port_info->listener_cnt; ++j) {
Benny Prijonocbc1c472006-03-19 00:50:23 +0000479 char s[10];
Benny Prijonoc78c3a32006-06-16 15:54:43 +0000480 pj_ansi_sprintf(s, "#%d ", port_info->listener_slots[j]);
481 pj_ansi_strcat(txlist, s);
482
Benny Prijonocbc1c472006-03-19 00:50:23 +0000483 }
484
485 if (txlist[0] == '\0') {
486 txlist[0] = '-';
487 txlist[1] = '\0';
488 }
489
490 if (!detail) {
491 printf("Port #%02d %-25.*s transmitting to: %s\n",
492 port_info->slot,
493 (int)port_info->name.slen,
494 port_info->name.ptr,
495 txlist);
496 } else {
497 unsigned tx_level, rx_level;
498
499 pjmedia_conf_get_signal_level(conf, port_info->slot,
500 &tx_level, &rx_level);
501
502 printf("Port #%02d:\n"
503 " Name : %.*s\n"
504 " Sampling rate : %d Hz\n"
Benny Prijonobc797312006-03-24 20:44:27 +0000505 " Samples per frame : %d\n"
Benny Prijonocbc1c472006-03-19 00:50:23 +0000506 " Frame time : %d ms\n"
507 " Signal level adjustment : tx=%d, rx=%d\n"
508 " Current signal level : tx=%u, rx=%u\n"
509 " Transmitting to ports : %s\n\n",
510 port_info->slot,
511 (int)port_info->name.slen,
512 port_info->name.ptr,
513 port_info->clock_rate,
Benny Prijonobc797312006-03-24 20:44:27 +0000514 port_info->samples_per_frame,
Benny Prijonocbc1c472006-03-19 00:50:23 +0000515 port_info->samples_per_frame*1000/port_info->clock_rate,
516 port_info->tx_adj_level,
517 port_info->rx_adj_level,
518 tx_level,
519 rx_level,
520 txlist);
521 }
522
523 }
524 puts("");
525}
526
527
528/*
529 * Display VU meter
530 */
531static void monitor_level(pjmedia_conf *conf, int slot, int dir, int dur)
532{
Benny Prijonoadb34652006-03-19 12:09:53 +0000533 enum { SLEEP = 20, SAMP_CNT = 2};
Benny Prijonocbc1c472006-03-19 00:50:23 +0000534 pj_status_t status;
Benny Prijonoadb34652006-03-19 12:09:53 +0000535 int i, total_count;
536 unsigned level, samp_cnt;
537
Benny Prijonocbc1c472006-03-19 00:50:23 +0000538
539 puts("");
540 printf("Displaying VU meter for port %d for about %d seconds\n",
541 slot, dur);
542
Benny Prijonoadb34652006-03-19 12:09:53 +0000543 total_count = dur * 1000 / SLEEP;
Benny Prijonocbc1c472006-03-19 00:50:23 +0000544
Benny Prijonoadb34652006-03-19 12:09:53 +0000545 level = 0;
546 samp_cnt = 0;
547
548 for (i=0; i<total_count; ++i) {
Benny Prijonocbc1c472006-03-19 00:50:23 +0000549 unsigned tx_level, rx_level;
Benny Prijonoadb34652006-03-19 12:09:53 +0000550 int j, length;
Benny Prijonocbc1c472006-03-19 00:50:23 +0000551 char meter[21];
552
Benny Prijonoadb34652006-03-19 12:09:53 +0000553 /* Poll the volume every 20 msec */
Benny Prijonocbc1c472006-03-19 00:50:23 +0000554 status = pjmedia_conf_get_signal_level(conf, slot,
555 &tx_level, &rx_level);
556 if (status != PJ_SUCCESS) {
557 app_perror(THIS_FILE, "Unable to read level", status);
558 return;
559 }
560
Benny Prijonoadb34652006-03-19 12:09:53 +0000561 level += (dir=='r' ? rx_level : tx_level);
562 ++samp_cnt;
563
564 /* Accumulate until we have enough samples */
565 if (samp_cnt < SAMP_CNT) {
566 pj_thread_sleep(SLEEP);
567 continue;
568 }
569
570 /* Get average */
571 level = level / samp_cnt;
572
573 /* Draw bar */
574 length = 20 * level / 255;
575 for (j=0; j<length; ++j)
Benny Prijonocbc1c472006-03-19 00:50:23 +0000576 meter[j] = '#';
577 for (; j<20; ++j)
578 meter[j] = ' ';
579 meter[20] = '\0';
580
Benny Prijonoadb34652006-03-19 12:09:53 +0000581 printf("Port #%02d %cx level: [%s] %d \r",
582 slot, dir, meter, level);
583
584 /* Next.. */
585 samp_cnt = 0;
586 level = 0;
Benny Prijonocbc1c472006-03-19 00:50:23 +0000587
588 pj_thread_sleep(SLEEP);
589 }
590
591 puts("");
592}
593