1 /********************************************************************
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. *
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/ *
12 ********************************************************************
16 ********************************************************************/
25 #include "callbacks.h"
28 #define WARNING_VERBOSITY 2
29 #define INFO_VERBOSITY 3
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
;
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
,
68 current
->device
= ao_open_file(current
->driver_id
, current
->filename
,
69 1 /*overwrite*/, &format
,
73 if (current
->device
== NULL
) {
76 status_error(_("ERROR: Device not available.\n"));
79 status_error(_("ERROR: %s requires an output filename to be specified with -f.\n"), info
->short_name
);
82 status_error(_("ERROR: Unsupported option value to %s device.\n"),
86 status_error(_("ERROR: Cannot open device %s.\n"),
90 status_error(_("ERROR: Device %s failure.\n"), info
->short_name
);
93 status_error(_("ERROR: An output file cannot be given for %s device.\n"), info
->short_name
);
96 status_error(_("ERROR: Cannot open file %s for writing.\n"),
100 status_error(_("ERROR: File %s already exists.\n"), current
->filename
);
103 status_error(_("ERROR: This error should never happen (%d). Panic!\n"), errno
);
107 /* We cannot recover from any of these errors */
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
);
122 audio_reopen_arg_t
*new_audio_reopen_arg (audio_device_t
*devices
,
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"));
132 if ( (arg
->format
= calloc(1,sizeof(audio_format_t
))) == NULL
) {
133 status_error(_("ERROR: Out of memory in new_audio_reopen_arg().\n"));
137 arg
->devices
= devices
;
138 /* Copy format in case fmt is recycled later */
141 arg
->format
->matrix
= strdup(fmt
->matrix
);
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
;
155 buffer_stats
= buffer_statistics(buf
);
159 status_print_statistics(stats_arg
->stat_format
,
161 stats_arg
->data_source_statistics
,
162 stats_arg
->decoder_statistics
);
164 free(stats_arg
->data_source_statistics
);
165 free(stats_arg
->decoder_statistics
);
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"));
183 arg
->stat_format
= stat_format
;
184 arg
->data_source_statistics
= data_source_statistics
;
185 arg
->decoder_statistics
= decoder_statistics
;
191 /* Decoder callbacks */
193 void decoder_error_callback (void *arg
, int severity
, char *message
, ...)
197 va_start(ap
, message
);
200 vstatus_error(message
, ap
);
203 vstatus_message(WARNING_VERBOSITY
, message
, ap
);
206 vstatus_message(INFO_VERBOSITY
, message
, ap
);
213 void decoder_metadata_callback (void *arg
, int verbosity
, char *message
, ...)
217 va_start(ap
, message
);
218 vstatus_message(verbosity
, message
, ap
);
223 /* ---------------------------------------------------------------------- */
225 /* These actions are just wrappers for vstatus_message() and vstatus_error() */
227 typedef struct status_message_arg_t
{
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"));
242 arg
->verbosity
= verbosity
;
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
);
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
);
269 /* -------------------------------------------------------------- */
271 void decoder_buffered_error_callback (void *arg
, int severity
,
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"));
289 /* Try to print in the allocated space. */
290 va_start(ap
, message
);
291 n
= vsnprintf (sm_arg
->message
, size
, message
, ap
);
294 /* If that worked, return the string. */
295 if (n
> -1 && n
< size
)
297 /* Else try again with more space. */
298 if (n
> -1) /* glibc 2.1 */
299 size
= n
+1; /* precisely what is needed */
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"));
311 buffer_append_action_at_end(buf
, &status_error_action
, sm_arg
);
314 sm_arg
->verbosity
= WARNING_VERBOSITY
;
315 buffer_append_action_at_end(buf
, &status_message_action
, sm_arg
);
318 sm_arg
->verbosity
= INFO_VERBOSITY
;
319 buffer_append_action_at_end(buf
, &status_message_action
, sm_arg
);
327 void decoder_buffered_metadata_callback (void *arg
, int verbosity
,
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"));
345 /* Try to print in the allocated space. */
346 va_start(ap
, message
);
347 n
= vsnprintf (sm_arg
->message
, size
, message
, ap
);
350 /* If that worked, return the string. */
351 if (n
> -1 && n
< size
)
353 /* Else try again with more space. */
354 if (n
> -1) /* glibc 2.1 */
355 size
= n
+1; /* precisely what is needed */
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"));
364 sm_arg
->verbosity
= verbosity
;
365 buffer_append_action_at_end(buf
, &status_message_action
, sm_arg
);