Recognizes if input is ogg or not.
[xiph.git] / vorbis-tools / ogg123 / status.c
blobf567a232f853d6c96b8218ccb38e709d0f8318fc
1 /********************************************************************
2 * *
3 * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
4 * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY *
5 * THE GNU PUBLIC LICENSE 2, WHICH IS INCLUDED WITH THIS SOURCE. *
6 * PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
7 * *
8 * THE Ogg123 SOURCE CODE IS (C) COPYRIGHT 2000-2001 *
9 * by Stan Seibert <volsung@xiph.org> AND OTHER CONTRIBUTORS *
10 * http://www.xiph.org/ *
11 * *
12 ********************************************************************
14 last mod: $Id: status.c,v 1.8 2002/03/19 09:50:09 msmith Exp $
16 ********************************************************************/
18 #ifdef HAVE_CONFIG_H
19 #include "config.h"
20 #endif
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <pthread.h>
26 #ifdef HAVE_UNISTD_H
27 #include <unistd.h>
28 #endif
30 #ifdef HAVE_FCNTL_H
31 #include <fcntl.h>
32 #endif
34 #include "status.h"
35 #include "i18n.h"
37 char temp_buffer[200];
38 int last_line_len = 0;
39 int max_verbosity = 0;
40 int exit_status = EXIT_SUCCESS;
42 pthread_mutex_t output_lock = PTHREAD_MUTEX_INITIALIZER;
45 /* ------------------- Private functions ------------------ */
47 void unlock_output_lock (void *arg)
49 pthread_mutex_unlock(&output_lock);
53 void write_buffer_state_string (char *dest, buffer_stats_t *buf_stats)
55 char *cur = dest;
56 char *comma = ", ";
57 char *sep = "(";
59 if (buf_stats->prebuffering) {
60 cur += sprintf (cur, _("%sPrebuf to %.1f%%"), sep,
61 100.0f * buf_stats->prebuffer_fill);
62 sep = comma;
64 if (buf_stats->paused) {
65 cur += sprintf (cur, _("%sPaused"), sep);
66 sep = comma;
68 if (buf_stats->eos) {
69 cur += sprintf (cur, _("%sEOS"), sep);
70 sep = comma;
72 if (cur != dest)
73 cur += sprintf (cur, ")");
74 else
75 *cur = '\0';
79 /* Write a min:sec.msec style string to dest corresponding to time.
80 The time parameter is in seconds. Returns the number of characters
81 written */
82 int write_time_string (char *dest, double time)
84 long min = (long) time / (long) 60;
85 double sec = time - 60.0f * min;
87 return sprintf (dest, "%02li:%05.2f", min, sec);
91 void clear_line (int len)
93 fputc('\r', stderr);
95 while (len > 0) {
96 fputc (' ', stderr);
97 len--;
100 fputc ('\r', stderr);
104 int sprintf_clear_line(int len, char *buf)
106 int i = 0;
108 buf[i] = '\r';
109 i++;
111 while (len > 0) {
112 buf[i] = ' ';
113 len--;
114 i++;
117 buf[i] = '\r';
118 i++;
120 /* Null terminate just in case */
121 buf[i] = '\0';
123 return i;
126 int print_statistics_line (stat_format_t stats[])
128 int len = 0;
129 char *str = temp_buffer;
131 if (max_verbosity == 0)
132 return 0;
134 /* Put the clear line text into the same string buffer so that the
135 line is cleared and redrawn all at once. This reduces
136 flickering. Don't count characters used to clear line in len */
137 str += sprintf_clear_line(last_line_len, str);
139 while (stats->formatstr != NULL) {
141 if (stats->verbosity > max_verbosity || !stats->enabled) {
142 stats++;
143 continue;
146 if (len != 0)
147 len += sprintf(str+len, " ");
149 switch (stats->type) {
150 case stat_noarg:
151 len += sprintf(str+len, stats->formatstr);
152 break;
153 case stat_intarg:
154 len += sprintf(str+len, stats->formatstr, stats->arg.intarg);
155 break;
156 case stat_stringarg:
157 len += sprintf(str+len, stats->formatstr, stats->arg.stringarg);
158 break;
159 case stat_floatarg:
160 len += sprintf(str+len, stats->formatstr, stats->arg.floatarg);
161 break;
162 case stat_doublearg:
163 len += sprintf(str+len, stats->formatstr, stats->arg.doublearg);
164 break;
167 stats++;
170 len += sprintf(str+len, "\r");
172 fprintf(stderr, "%s", temp_buffer);
174 return len;
178 void vstatus_print_nolock (const char *fmt, va_list ap)
180 if (last_line_len != 0)
181 fputc ('\n', stderr);
183 vfprintf (stderr, fmt, ap);
185 fputc ('\n', stderr);
187 last_line_len = 0;
191 /* ------------------- Public interface -------------------- */
193 #define TIME_STR_SIZE 20
194 #define STATE_STR_SIZE 25
195 #define NUM_STATS 10
197 stat_format_t *stat_format_create ()
199 stat_format_t *stats;
200 stat_format_t *cur;
202 stats = calloc(NUM_STATS + 1, sizeof(stat_format_t)); /* One extra for end flag */
203 if (stats == NULL) {
204 fprintf(stderr, _("Memory allocation error in stats_init()\n"));
205 exit(1);
208 cur = stats + 0; /* currently playing file / stream */
209 cur->verbosity = 3;
210 cur->enabled = 0;
211 cur->formatstr = _("File: %s");
212 cur->type = stat_stringarg;
214 cur = stats + 1; /* current playback time (preformatted) */
215 cur->verbosity = 1;
216 cur->enabled = 1;
217 cur->formatstr = _("Time: %s");
218 cur->type = stat_stringarg;
219 cur->arg.stringarg = calloc(TIME_STR_SIZE, sizeof(char));
221 if (cur->arg.stringarg == NULL) {
222 fprintf(stderr, _("Memory allocation error in stats_init()\n"));
223 exit(1);
225 write_time_string(cur->arg.stringarg, 0.0);
228 cur = stats + 2; /* remaining playback time (preformatted) */
229 cur->verbosity = 1;
230 cur->enabled = 1;
231 cur->formatstr = "[%s]";
232 cur->type = stat_stringarg;
233 cur->arg.stringarg = calloc(TIME_STR_SIZE, sizeof(char));
235 if (cur->arg.stringarg == NULL) {
236 fprintf(stderr, _("Memory allocation error in stats_init()\n"));
237 exit(1);
239 write_time_string(cur->arg.stringarg, 0.0);
242 cur = stats + 3; /* total playback time (preformatted) */
243 cur->verbosity = 1;
244 cur->enabled = 1;
245 cur->formatstr = _("of %s");
246 cur->type = stat_stringarg;
247 cur->arg.stringarg = calloc(TIME_STR_SIZE, sizeof(char));
249 if (cur->arg.stringarg == NULL) {
250 fprintf(stderr, _("Memory allocation error in stats_init()\n"));
251 exit(1);
253 write_time_string(cur->arg.stringarg, 0.0);
256 cur = stats + 4; /* instantaneous bitrate */
257 cur->verbosity = 2;
258 cur->enabled = 1;
259 cur->formatstr = " (%5.1f kbps)";
260 cur->type = stat_doublearg;
262 cur = stats + 5; /* average bitrate (not yet implemented) */
263 cur->verbosity = 2;
264 cur->enabled = 0;
265 cur->formatstr = _("Avg bitrate: %5.1f");
266 cur->type = stat_doublearg;
268 cur = stats + 6; /* input buffer fill % */
269 cur->verbosity = 2;
270 cur->enabled = 0;
271 cur->formatstr = _(" Input Buffer %5.1f%%");
272 cur->type = stat_doublearg;
274 cur = stats + 7; /* input buffer status */
275 cur->verbosity = 2;
276 cur->enabled = 0;
277 cur->formatstr = "%s";
278 cur->type = stat_stringarg;
279 cur->arg.stringarg = calloc(STATE_STR_SIZE, sizeof(char));
281 if (cur->arg.stringarg == NULL) {
282 fprintf(stderr, _("Memory allocation error in stats_init()\n"));
283 exit(1);
287 cur = stats + 8; /* output buffer fill % */
288 cur->verbosity = 2;
289 cur->enabled = 0;
290 cur->formatstr = _(" Output Buffer %5.1f%%");
291 cur->type = stat_doublearg;
293 cur = stats + 9; /* output buffer status */
294 cur->verbosity = 1;
295 cur->enabled = 0;
296 cur->formatstr = "%s";
297 cur->type = stat_stringarg;
298 cur->arg.stringarg = calloc(STATE_STR_SIZE, sizeof(char));
300 if (cur->arg.stringarg == NULL) {
301 fprintf(stderr, _("Memory allocation error in stats_init()\n"));
302 exit(1);
306 cur = stats + 10; /* End flag */
307 cur->formatstr = NULL;
309 return stats;
313 void stat_format_cleanup (stat_format_t *stats)
315 free(stats[1].arg.stringarg);
316 free(stats[2].arg.stringarg);
317 free(stats[3].arg.stringarg);
318 free(stats[7].arg.stringarg);
319 free(stats[9].arg.stringarg);
320 free(stats);
324 void status_init (int verbosity)
326 #if defined(HAVE_FCNTL) && defined(HAVE_UNISTD_H)
327 fcntl (STDERR_FILENO, F_SETFL, O_NONBLOCK);
328 #endif
330 max_verbosity = verbosity;
334 void status_reset_output_lock ()
336 pthread_mutex_unlock(&output_lock);
340 void status_clear_line ()
342 pthread_cleanup_push(unlock_output_lock, NULL);
344 pthread_mutex_lock(&output_lock);
345 clear_line(last_line_len);
346 pthread_mutex_unlock(&output_lock);
348 pthread_cleanup_pop(0);
351 void status_print_statistics (stat_format_t *stats,
352 buffer_stats_t *audio_statistics,
353 data_source_stats_t *transport_statistics,
354 decoder_stats_t *decoder_statistics)
356 pthread_cleanup_push(unlock_output_lock, NULL);
358 /* Updating statistics is not critical. If another thread is
359 already doing output, we skip it. */
360 if (pthread_mutex_trylock(&output_lock) == 0) {
362 if (decoder_statistics != NULL) {
363 /* Current playback time */
364 write_time_string(stats[1].arg.stringarg,
365 decoder_statistics->current_time);
367 /* Remaining playback time */
368 write_time_string(stats[2].arg.stringarg,
369 decoder_statistics->total_time -
370 decoder_statistics->current_time);
372 /* Total playback time */
373 write_time_string(stats[3].arg.stringarg,
374 decoder_statistics->total_time);
376 /* Instantaneous bitrate */
377 stats[4].arg.doublearg = decoder_statistics->instant_bitrate / 1000.0f;
379 /* Instantaneous bitrate */
380 stats[5].arg.doublearg = decoder_statistics->avg_bitrate / 1000.0f;
384 if (transport_statistics != NULL &&
385 transport_statistics->input_buffer_used) {
387 /* Input buffer fill % */
388 stats[6].arg.doublearg = transport_statistics->input_buffer.fill;
390 /* Input buffer state */
391 write_buffer_state_string(stats[7].arg.stringarg,
392 &transport_statistics->input_buffer);
396 if (audio_statistics != NULL) {
398 /* Output buffer fill % */
399 stats[8].arg.doublearg = audio_statistics->fill;
401 /* Output buffer state */
402 write_buffer_state_string(stats[9].arg.stringarg, audio_statistics);
405 last_line_len = print_statistics_line(stats);
407 pthread_mutex_unlock(&output_lock);
410 pthread_cleanup_pop(0);
414 void status_message (int verbosity, const char *fmt, ...)
416 va_list ap;
418 if (verbosity > max_verbosity)
419 return;
421 pthread_cleanup_push(unlock_output_lock, NULL);
423 pthread_mutex_lock(&output_lock);
425 clear_line(last_line_len);
427 va_start (ap, fmt);
428 vstatus_print_nolock(fmt, ap);
429 va_end (ap);
431 pthread_mutex_unlock(&output_lock);
433 pthread_cleanup_pop(0);
437 void vstatus_message (int verbosity, const char *fmt, va_list ap)
439 if (verbosity > max_verbosity)
440 return;
442 pthread_cleanup_push(unlock_output_lock, NULL);
444 pthread_mutex_lock(&output_lock);
446 clear_line(last_line_len);
447 vstatus_print_nolock(fmt, ap);
449 pthread_mutex_unlock(&output_lock);
451 pthread_cleanup_pop(0);
455 void status_error (const char *fmt, ...)
457 va_list ap;
459 pthread_cleanup_push(unlock_output_lock, NULL);
461 pthread_mutex_lock(&output_lock);
462 va_start (ap, fmt);
463 clear_line(last_line_len);
464 vstatus_print_nolock (fmt, ap);
465 va_end (ap);
466 pthread_mutex_unlock(&output_lock);
468 pthread_cleanup_pop(0);
470 exit_status = EXIT_FAILURE;
474 void vstatus_error (const char *fmt, va_list ap)
476 pthread_cleanup_push(unlock_output_lock, NULL);
478 pthread_mutex_lock(&output_lock);
479 clear_line(last_line_len);
480 vstatus_print_nolock (fmt, ap);
481 pthread_mutex_unlock(&output_lock);
483 pthread_cleanup_pop(0);
485 exit_status = EXIT_FAILURE;