Add Russian translation provided by Валерий Крувялис <valkru@mail.ru>
[xiph-mirror.git] / vorbis-tools / ogg123 / callbacks.c
blobe52beee7acfb6256e14bf9ec3f5865a4ed105978
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$
16 ********************************************************************/
18 #ifdef HAVE_CONFIG_H
19 #include <config.h>
20 #endif
22 #include <stdio.h>
23 #include <string.h>
25 #include "callbacks.h"
26 #include "i18n.h"
28 #define WARNING_VERBOSITY 2
29 #define INFO_VERBOSITY 3
31 /* Audio callbacks */
33 int audio_play_callback (void *ptr, int nbytes, int eos, void *arg)
35 audio_play_arg_t *play_arg = (audio_play_arg_t *) arg;
36 int ret;
38 ret = audio_devices_write(play_arg->devices, ptr, nbytes);
40 return ret ? nbytes : 0;
43 void audio_reopen_action (buf_t *buf, void *arg)
45 audio_reopen_arg_t *reopen_arg = (audio_reopen_arg_t *) arg;
46 audio_device_t *current;
47 ao_sample_format format;
49 close_audio_devices (reopen_arg->devices);
51 /* Record audio device settings and open the devices */
52 format.rate = reopen_arg->format->rate;
53 format.channels = reopen_arg->format->channels;
54 format.bits = reopen_arg->format->word_size * 8;
55 format.byte_format = reopen_arg->format->big_endian ?
56 AO_FMT_BIG : AO_FMT_LITTLE;
57 format.matrix = reopen_arg->format->matrix;
59 current = reopen_arg->devices;
61 while (current != NULL) {
62 ao_info *info = ao_driver_info(current->driver_id);
64 if (current->filename == NULL)
65 current->device = ao_open_live(current->driver_id, &format,
66 current->options);
67 else
68 current->device = ao_open_file(current->driver_id, current->filename,
69 1 /*overwrite*/, &format,
70 current->options);
72 /* Report errors */
73 if (current->device == NULL) {
74 switch (errno) {
75 case AO_ENODRIVER:
76 status_error(_("ERROR: Device not available.\n"));
77 break;
78 case AO_ENOTLIVE:
79 status_error(_("ERROR: %s requires an output filename to be specified with -f.\n"), info->short_name);
80 break;
81 case AO_EBADOPTION:
82 status_error(_("ERROR: Unsupported option value to %s device.\n"),
83 info->short_name);
84 break;
85 case AO_EOPENDEVICE:
86 status_error(_("ERROR: Cannot open device %s.\n"),
87 info->short_name);
88 break;
89 case AO_EFAIL:
90 status_error(_("ERROR: Device %s failure.\n"), info->short_name);
91 break;
92 case AO_ENOTFILE:
93 status_error(_("ERROR: An output file cannot be given for %s device.\n"), info->short_name);
94 break;
95 case AO_EOPENFILE:
96 status_error(_("ERROR: Cannot open file %s for writing.\n"),
97 current->filename);
98 break;
99 case AO_EFILEEXISTS:
100 status_error(_("ERROR: File %s already exists.\n"), current->filename);
101 break;
102 default:
103 status_error(_("ERROR: This error should never happen (%d). Panic!\n"), errno);
104 break;
107 /* We cannot recover from any of these errors */
108 exit(1);
111 current = current->next_device;
114 /* Cleanup argument */
115 if(reopen_arg->format->matrix)
116 free(reopen_arg->format->matrix);
117 free(reopen_arg->format);
118 free(reopen_arg);
122 audio_reopen_arg_t *new_audio_reopen_arg (audio_device_t *devices,
123 audio_format_t *fmt)
125 audio_reopen_arg_t *arg;
127 if ( (arg = calloc(1,sizeof(audio_reopen_arg_t))) == NULL ) {
128 status_error(_("ERROR: Out of memory in new_audio_reopen_arg().\n"));
129 exit(1);
132 if ( (arg->format = calloc(1,sizeof(audio_format_t))) == NULL ) {
133 status_error(_("ERROR: Out of memory in new_audio_reopen_arg().\n"));
134 exit(1);
137 arg->devices = devices;
138 /* Copy format in case fmt is recycled later */
139 *arg->format = *fmt;
140 if(fmt->matrix)
141 arg->format->matrix = strdup(fmt->matrix);
143 return arg;
147 /* Statistics callbacks */
149 void print_statistics_action (buf_t *buf, void *arg)
151 print_statistics_arg_t *stats_arg = (print_statistics_arg_t *) arg;
152 buffer_stats_t *buffer_stats;
154 if (buf != NULL)
155 buffer_stats = buffer_statistics(buf);
156 else
157 buffer_stats = NULL;
159 status_print_statistics(stats_arg->stat_format,
160 buffer_stats,
161 stats_arg->data_source_statistics,
162 stats_arg->decoder_statistics);
164 free(stats_arg->data_source_statistics);
165 free(stats_arg->decoder_statistics);
166 free(stats_arg);
167 free(buffer_stats);
171 print_statistics_arg_t *new_print_statistics_arg (
172 stat_format_t *stat_format,
173 data_source_stats_t *data_source_statistics,
174 decoder_stats_t *decoder_statistics)
176 print_statistics_arg_t *arg;
178 if ( (arg = calloc(1,sizeof(print_statistics_arg_t))) == NULL ) {
179 status_error(_("Error: Out of memory in new_print_statistics_arg().\n"));
180 exit(1);
183 arg->stat_format = stat_format;
184 arg->data_source_statistics = data_source_statistics;
185 arg->decoder_statistics = decoder_statistics;
187 return arg;
191 /* Decoder callbacks */
193 void decoder_error_callback (void *arg, int severity, char *message, ...)
195 va_list ap;
197 va_start(ap, message);
198 switch (severity) {
199 case ERROR:
200 vstatus_error(message, ap);
201 break;
202 case WARNING:
203 vstatus_message(WARNING_VERBOSITY, message, ap);
204 break;
205 case INFO:
206 vstatus_message(INFO_VERBOSITY, message, ap);
207 break;
209 va_end(ap);
213 void decoder_metadata_callback (void *arg, int verbosity, char *message, ...)
215 va_list ap;
217 va_start(ap, message);
218 vstatus_message(verbosity, message, ap);
219 va_end(ap);
223 /* ---------------------------------------------------------------------- */
225 /* These actions are just wrappers for vstatus_message() and vstatus_error() */
227 typedef struct status_message_arg_t {
228 int verbosity;
229 char *message;
230 } status_message_arg_t;
233 status_message_arg_t *new_status_message_arg (int verbosity)
235 status_message_arg_t *arg;
237 if ( (arg = calloc(1,sizeof(status_message_arg_t))) == NULL ) {
238 status_error(_("ERROR: Out of memory in new_status_message_arg().\n"));
239 exit(1);
242 arg->verbosity = verbosity;
244 return arg;
248 void status_error_action (buf_t *buf, void *arg)
250 status_message_arg_t *myarg = (status_message_arg_t *) arg;
252 status_error("%s", myarg->message);
254 free(myarg->message);
255 free(myarg);
259 void status_message_action (buf_t *buf, void *arg)
261 status_message_arg_t *myarg = (status_message_arg_t *) arg;
263 status_message(myarg->verbosity, "%s", myarg->message);
265 free(myarg->message);
266 free(myarg);
269 /* -------------------------------------------------------------- */
271 void decoder_buffered_error_callback (void *arg, int severity,
272 char *message, ...)
274 va_list ap;
275 buf_t *buf = (buf_t *)arg;
276 status_message_arg_t *sm_arg = new_status_message_arg(0);
277 int n, size = 80; /* Guess we need no more than 80 bytes. */
280 /* Preformat the string and allocate space for it. This code taken
281 straight from the vsnprintf() man page. We do this here because
282 we might need to reinit ap several times. */
283 if ((sm_arg->message = calloc (size,1)) == NULL) {
284 status_error(_("Error: Out of memory in decoder_buffered_metadata_callback().\n"));
285 exit(1);
288 while (1) {
289 /* Try to print in the allocated space. */
290 va_start(ap, message);
291 n = vsnprintf (sm_arg->message, size, message, ap);
292 va_end(ap);
294 /* If that worked, return the string. */
295 if (n > -1 && n < size)
296 break;
297 /* Else try again with more space. */
298 if (n > -1) /* glibc 2.1 */
299 size = n+1; /* precisely what is needed */
300 else /* glibc 2.0 */
301 size *= 2; /* twice the old size */
302 if ((sm_arg->message = realloc (sm_arg->message, size)) == NULL) {
303 status_error(_("Error: Out of memory in decoder_buffered_metadata_callback().\n"));
304 exit(1);
309 switch (severity) {
310 case ERROR:
311 buffer_append_action_at_end(buf, &status_error_action, sm_arg);
312 break;
313 case WARNING:
314 sm_arg->verbosity = WARNING_VERBOSITY;
315 buffer_append_action_at_end(buf, &status_message_action, sm_arg);
316 break;
317 case INFO:
318 sm_arg->verbosity = INFO_VERBOSITY;
319 buffer_append_action_at_end(buf, &status_message_action, sm_arg);
320 break;
327 void decoder_buffered_metadata_callback (void *arg, int verbosity,
328 char *message, ...)
330 va_list ap;
331 buf_t *buf = (buf_t *)arg;
332 status_message_arg_t *sm_arg = new_status_message_arg(0);
333 int n, size = 80; /* Guess we need no more than 80 bytes. */
336 /* Preformat the string and allocate space for it. This code taken
337 straight from the vsnprintf() man page. We do this here because
338 we might need to reinit ap several times. */
339 if ((sm_arg->message = calloc (size,1)) == NULL) {
340 status_error(_("ERROR: Out of memory in decoder_buffered_metadata_callback().\n"));
341 exit(1);
344 while (1) {
345 /* Try to print in the allocated space. */
346 va_start(ap, message);
347 n = vsnprintf (sm_arg->message, size, message, ap);
348 va_end(ap);
350 /* If that worked, return the string. */
351 if (n > -1 && n < size)
352 break;
353 /* Else try again with more space. */
354 if (n > -1) /* glibc 2.1 */
355 size = n+1; /* precisely what is needed */
356 else /* glibc 2.0 */
357 size *= 2; /* twice the old size */
358 if ((sm_arg->message = realloc (sm_arg->message, size)) == NULL) {
359 status_error(_("ERROR: Out of memory in decoder_buffered_metadata_callback().\n"));
360 exit(1);
364 sm_arg->verbosity = verbosity;
365 buffer_append_action_at_end(buf, &status_message_action, sm_arg);