1 /* ogg123.c by Kenneth Arnold <kcarnold-xiph@arnoldnet.net> */
2 /* Maintained by Stan Seibert <volsung@xiph.org>, Monty <monty@xiph.org> */
4 /********************************************************************
6 * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
7 * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY *
8 * THE GNU PUBLIC LICENSE 2, WHICH IS INCLUDED WITH THIS SOURCE. *
9 * PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
11 * THE Ogg123 SOURCE CODE IS (C) COPYRIGHT 2000-2005 *
12 * by Stan Seibert <volsung@xiph.org> AND OTHER CONTRIBUTORS *
13 * http://www.xiph.org/ *
15 ********************************************************************
19 ********************************************************************/
25 #include <sys/types.h>
41 #include "callbacks.h"
42 #include "cfgfile_options.h"
43 #include "cmdline_options.h"
45 #include "transport.h"
54 extern int exit_status
; /* from status.c */
56 void play (char *source_string
);
58 #define PRIMAGIC (2*2*2*2*3*3*3*5*7)
59 /* take buffer out of the data segment, not the stack */
60 #define AUDIO_CHUNK_SIZE ((16384 + PRIMAGIC - 1)/ PRIMAGIC * PRIMAGIC)
61 unsigned char convbuffer
[AUDIO_CHUNK_SIZE
];
62 int convsize
= AUDIO_CHUNK_SIZE
;
64 ogg123_options_t options
;
65 stat_format_t
*stat_format
;
66 buf_t
*audio_buffer
=NULL
;
68 audio_play_arg_t audio_play_arg
;
71 /* ------------------------- config file options -------------------------- */
73 /* This macro is used to create some dummy variables to hold default values
75 #define INIT(type, value) type type##_##value = value
79 file_option_t file_opts
[] = {
80 /* found, name, description, type, ptr, default */
81 {0, "default_device", N_("default output device"), opt_type_string
,
82 &options
.default_device
, NULL
},
83 {0, "shuffle", N_("shuffle playlist"), opt_type_bool
,
84 &options
.shuffle
, &int_0
},
85 {0, "repeat", N_("repeat playlist forever"), opt_type_bool
,
86 &options
.repeat
, &int_0
},
87 {0, NULL
, NULL
, 0, NULL
, NULL
}
91 /* Flags set by the signal handler to control the threads */
92 signal_request_t sig_request
= {0, 0, 0, 0, 0};
95 /* ------------------------------- signal handler ------------------------- */
98 void signal_handler (int signo
)
105 gettimeofday(&tv
, 0);
107 /* Units of milliseconds (need the cast to force 64 arithmetics) */
108 now
= (ogg_int64_t
) tv
.tv_sec
* 1000 + tv
.tv_usec
/ 1000;
110 if ( (now
- sig_request
.last_ctrl_c
) <= options
.delay
)
111 sig_request
.exit
= 1;
113 sig_request
.skipfile
= 1;
115 sig_request
.cancel
= 1;
116 sig_request
.last_ctrl_c
= now
;
120 sig_request
.exit
= 1;
124 sig_request
.pause
= 1;
125 /* buffer_Pause (Options.outputOpts.buffer);
126 buffer_WaitForPaused (Options.outputOpts.buffer);
128 if (Options.outputOpts.devicesOpen == 0) {
129 close_audio_devices (Options.outputOpts.devices);
130 Options.outputOpts.devicesOpen = 0;
133 /* open_audio_devices();
134 if (Options.outputOpts.buffer) {
135 buffer_Unpause (Options.outputOpts.buffer);
141 break; /* Don't need to do anything special to resume */
145 /* -------------------------- util functions ---------------------------- */
147 void options_init (ogg123_options_t
*opts
)
155 opts
->endpos
= -1.0; /* Mark as unset */
156 opts
->seekmode
= DECODER_SEEK_NONE
;
157 opts
->buffer_size
= 128 * 1024;
158 opts
->prebuffer
= 0.0f
;
159 opts
->input_buffer_size
= 64 * 1024;
160 opts
->input_prebuffer
= 50.0f
;
161 opts
->default_device
= NULL
;
163 opts
->status_freq
= 10.0;
164 opts
->playlist
= NULL
;
170 double strtotime(char *s
)
174 time
= strtod(s
, &s
);
177 time
= 60 * time
+ strtod(s
+ 1, &s
);
182 void set_seek_opt(ogg123_options_t
*ogg123_opts
, char *buf
) {
187 while (*b
&& (*b
== ' ')) b
++;
190 /* relative seek back */
191 ogg123_opts
->seekoff
= -1 * strtotime(b
+1);
192 ogg123_opts
->seekmode
= DECODER_SEEK_CUR
;
195 /* relative seek forward */
196 ogg123_opts
->seekoff
= strtotime(b
+1);
197 ogg123_opts
->seekmode
= DECODER_SEEK_CUR
;
200 ogg123_opts
->seekoff
= strtotime(b
);
201 ogg123_opts
->seekmode
= DECODER_SEEK_START
;
205 int handle_seek_opt(ogg123_options_t
*options
, decoder_t
*decoder
, format_t
*format
) {
207 float pos
=decoder
->format
->statistics(decoder
)->current_time
;
209 /* this functions handles a seek request. It prevents seeking out
210 of band, i.e. before the beginning or after the end. Instead,
211 it seeks to the start or near-end resp. */
213 if (options
->seekmode
!= DECODER_SEEK_NONE
) {
215 if (options
->seekmode
== DECODER_SEEK_START
) {
216 pos
= options
->seekoff
;
218 pos
+= options
->seekoff
;
225 if (pos
> decoder
->format
->statistics(decoder
)->total_time
) {
226 /* seek to almost the end of the stream */
227 pos
= decoder
->format
->statistics(decoder
)->total_time
- 0.01;
230 if (!format
->seek(decoder
, pos
, DECODER_SEEK_START
)) {
231 status_error(_("Could not skip to %f in audio stream."), options
->seekoff
);
233 /* Handle this fatally -- kill the audio thread */
234 if (audio_buffer
!= NULL
)
235 buffer_thread_kill(audio_buffer
);
240 options
->seekmode
= DECODER_SEEK_NONE
;
245 /* This function selects which statistics to display for our
246 particular configuration. This does not have anything to do with
247 verbosity, but rather with which stats make sense to display. */
248 void select_stats (stat_format_t
*stats
, ogg123_options_t
*opts
,
249 data_source_t
*source
, decoder_t
*decoder
,
252 data_source_stats_t
*data_source_stats
;
254 if (audio_buffer
!= NULL
) {
255 /* Turn on output buffer stats */
256 stats
[8].enabled
= 1; /* Fill */
257 stats
[9].enabled
= 1; /* State */
259 stats
[8].enabled
= 0;
260 stats
[9].enabled
= 0;
263 data_source_stats
= source
->transport
->statistics(source
);
264 if (data_source_stats
->input_buffer_used
) {
265 /* Turn on input buffer stats */
266 stats
[6].enabled
= 1; /* Fill */
267 stats
[7].enabled
= 1; /* State */
269 stats
[6].enabled
= 0;
270 stats
[7].enabled
= 0;
272 free(data_source_stats
);
274 /* Assume we need total time display, and let display_statistics()
275 determine at what point it should be turned off during playback */
276 stats
[2].enabled
= 1; /* Remaining playback time */
277 stats
[3].enabled
= 1; /* Total playback time */
281 /* Handles printing statistics depending upon whether or not we have
282 buffering going on */
283 void display_statistics (stat_format_t
*stat_format
,
285 data_source_t
*source
,
288 print_statistics_arg_t
*pstats_arg
;
289 buffer_stats_t
*buffer_stats
;
291 pstats_arg
= new_print_statistics_arg(stat_format
,
292 source
->transport
->statistics(source
),
293 decoder
->format
->statistics(decoder
));
295 if (options
.remote
) {
297 /* Display statistics via the remote interface */
298 remote_time(pstats_arg
->decoder_statistics
->current_time
,
299 pstats_arg
->decoder_statistics
->total_time
);
303 /* Disable/Enable statistics as needed */
305 if (pstats_arg
->decoder_statistics
->total_time
<
306 pstats_arg
->decoder_statistics
->current_time
) {
307 stat_format
[2].enabled
= 0; /* Remaining playback time */
308 stat_format
[3].enabled
= 0; /* Total playback time */
311 if (pstats_arg
->data_source_statistics
->input_buffer_used
) {
312 stat_format
[6].enabled
= 1; /* Input buffer fill % */
313 stat_format
[7].enabled
= 1; /* Input buffer state */
317 /* Place a status update into the buffer */
318 buffer_append_action_at_end(audio_buffer
,
319 &print_statistics_action
,
322 /* And if we are not playing right now, do an immediate
323 update just the output buffer */
324 buffer_stats
= buffer_statistics(audio_buffer
);
325 if (buffer_stats
->paused
|| buffer_stats
->prebuffering
) {
326 pstats_arg
= new_print_statistics_arg(stat_format
,
329 print_statistics_action(audio_buffer
, pstats_arg
);
334 print_statistics_action(NULL
, pstats_arg
);
339 void display_statistics_quick (stat_format_t
*stat_format
,
341 data_source_t
*source
,
344 print_statistics_arg_t
*pstats_arg
;
346 pstats_arg
= new_print_statistics_arg(stat_format
,
347 source
->transport
->statistics(source
),
348 decoder
->format
->statistics(decoder
));
351 print_statistics_action(audio_buffer
, pstats_arg
);
353 print_statistics_action(NULL
, pstats_arg
);
356 double current_time (decoder_t
*decoder
)
358 decoder_stats_t
*stats
;
361 stats
= decoder
->format
->statistics(decoder
);
362 ret
= stats
->current_time
;
369 void print_audio_devices_info(audio_device_t
*d
)
374 info
= ao_driver_info(d
->driver_id
);
376 status_message(2, _("\nAudio Device: %s"), info
->name
);
377 status_message(3, _("Author: %s"), info
->author
);
378 status_message(3, _("Comments: %s"), info
->comment
);
379 status_message(2, "");
387 /* --------------------------- main code -------------------------------- */
391 int main(int argc
, char **argv
)
394 char **playlist_array
;
396 struct stat stat_buf
;
399 setlocale(LC_ALL
, "");
400 bindtextdomain(PACKAGE
, LOCALEDIR
);
404 stat_format
= stat_format_create();
405 options_init(&options
);
406 file_options_init(file_opts
);
408 parse_std_configs(file_opts
);
409 options
.playlist
= playlist_create();
410 optind
= parse_cmdline_options(argc
, argv
, &options
, file_opts
);
412 audio_play_arg
.devices
= options
.devices
;
413 audio_play_arg
.stat_format
= stat_format
;
415 /* Add remaining arguments to playlist */
416 for (i
= optind
; i
< argc
; i
++) {
417 if (stat(argv
[i
], &stat_buf
) == 0) {
419 if (S_ISDIR(stat_buf
.st_mode
)) {
420 if (playlist_append_directory(options
.playlist
, argv
[i
]) == 0)
422 _("WARNING: Could not read directory %s.\n"), argv
[i
]);
424 playlist_append_file(options
.playlist
, argv
[i
]);
426 } else /* If we can't stat it, it might be a non-disk source */
427 playlist_append_file(options
.playlist
, argv
[i
]);
433 /* Do we have anything left to play? */
434 if (playlist_length(options
.playlist
) == 0) {
438 playlist_array
= playlist_to_array(options
.playlist
, &items
);
439 playlist_destroy(options
.playlist
);
440 options
.playlist
= NULL
;
443 /* Don't use status_message until after this point! */
444 status_init(options
.verbosity
);
446 print_audio_devices_info(options
.devices
);
450 if (options
.buffer_size
> 0) {
451 /* Keep sample size alignment for surround sound with up to 10 channels */
452 options
.buffer_size
= (options
.buffer_size
+ PRIMAGIC
- 1) / PRIMAGIC
* PRIMAGIC
;
453 audio_buffer
= buffer_create(options
.buffer_size
,
454 options
.buffer_size
* options
.prebuffer
/ 100,
455 audio_play_callback
, &audio_play_arg
,
457 if (audio_buffer
== NULL
) {
458 status_error(_("Error: Could not create audio buffer.\n"));
465 /* Setup signal handlers and callbacks */
467 signal (SIGINT
, signal_handler
);
468 signal (SIGTSTP
, signal_handler
);
469 signal (SIGCONT
, signal_handler
);
470 signal (SIGTERM
, signal_handler
);
472 if (options
.remote
) {
473 /* run the mainloop for the remote interface */
479 /* Shuffle playlist */
480 if (options
.shuffle
) {
485 for (i
= 0; i
< items
; i
++) {
486 int j
= i
+ random() % (items
- i
);
487 char *temp
= playlist_array
[i
];
488 playlist_array
[i
] = playlist_array
[j
];
489 playlist_array
[j
] = temp
;
493 /* Play the files/streams */
495 while (i
< items
&& !sig_request
.exit
) {
496 play(playlist_array
[i
]);
499 } while (options
.repeat
);
502 playlist_array_destroy(playlist_array
, items
);
505 if (audio_buffer
!= NULL
) {
506 buffer_destroy (audio_buffer
);
510 ao_onexit (options
.devices
);
515 void play (char *source_string
)
517 transport_t
*transport
;
519 data_source_t
*source
;
522 decoder_callbacks_t decoder_callbacks
;
523 void *decoder_callbacks_arg
;
525 /* Preserve between calls so we only open the audio device when we
527 static audio_format_t old_audio_fmt
= { 0, 0, 0, 0, 0 };
528 audio_format_t new_audio_fmt
;
529 audio_reopen_arg_t
*reopen_arg
;
531 /* Flags and counters galore */
532 int eof
= 0, eos
= 0, ret
;
533 int nthc
= 0, ntimesc
= 0;
535 static int status_interval
= 0;
537 /* Reset all of the signal flags */
538 sig_request
.cancel
= 0;
539 sig_request
.skipfile
= 0;
540 sig_request
.exit
= 0;
541 sig_request
.pause
= 0;
543 /* Set preferred audio format (used by decoder) */
544 new_audio_fmt
.big_endian
= ao_is_big_endian();
545 new_audio_fmt
.signed_sample
= 1;
546 new_audio_fmt
.word_size
= 2;
548 /* Select appropriate callbacks */
549 if (audio_buffer
!= NULL
) {
550 decoder_callbacks
.printf_error
= &decoder_buffered_error_callback
;
551 decoder_callbacks
.printf_metadata
= &decoder_buffered_metadata_callback
;
552 decoder_callbacks_arg
= audio_buffer
;
554 decoder_callbacks
.printf_error
= &decoder_error_callback
;
555 decoder_callbacks
.printf_metadata
= &decoder_metadata_callback
;
556 decoder_callbacks_arg
= NULL
;
559 /* Locate and use transport for this data source */
560 if ( (transport
= select_transport(source_string
)) == NULL
) {
561 status_error(_("No module could be found to read from %s.\n"), source_string
);
565 if ( (source
= transport
->open(source_string
, &options
)) == NULL
) {
566 status_error(_("Cannot open %s.\n"), source_string
);
570 /* Detect the file format and initialize a decoder */
571 if ( (format
= select_format(source
)) == NULL
) {
572 status_error(_("The file format of %s is not supported.\n"), source_string
);
576 if ( (decoder
= format
->init(source
, &options
, &new_audio_fmt
,
578 decoder_callbacks_arg
)) == NULL
) {
580 /* We may have failed because of user command */
581 if (!sig_request
.cancel
)
582 status_error(_("Error opening %s using the %s module."
583 " The file may be corrupted.\n"), source_string
,
588 /* Decide which statistics are valid */
589 select_stats(stat_format
, &options
, source
, decoder
, audio_buffer
);
591 /* Start the audio playback thread before we begin sending data */
592 if (audio_buffer
!= NULL
) {
594 /* First reset mutexes and other synchronization variables */
595 buffer_reset (audio_buffer
);
596 buffer_thread_start (audio_buffer
);
599 /* Show which file we are playing */
600 decoder_callbacks
.printf_metadata(decoder_callbacks_arg
, 1,
601 _("Playing: %s"), source_string
);
603 /* Skip over audio */
604 if (options
.seekoff
> 0.0) {
605 /* Note: it may be simpler to handle this condition by just calling:
606 * handle_seek_opt(&options, decoder, format);
607 * which was introduced with the remote control interface. However, that
608 * function does not call buffer_thread_kill() on error, which is
609 * necessary in this situation.
611 if (!format
->seek(decoder
, options
.seekoff
, DECODER_SEEK_START
)) {
612 status_error(_("Could not skip %f seconds of audio."), options
.seekoff
);
613 if (audio_buffer
!= NULL
)
614 buffer_thread_kill(audio_buffer
);
619 /* Main loop: Iterates over all of the logical bitstreams in the file */
620 while (!eof
&& !sig_request
.exit
) {
622 /* Loop through data within a logical bitstream */
624 while (!eos
&& !sig_request
.exit
) {
627 if (sig_request
.skipfile
) {
632 if (options
.remote
) {
634 /* run the playloop for the remote interface */
635 if (remote_playloop()) {
636 /* end song requested */
641 /* Skip over audio */
642 handle_seek_opt(&options
, decoder
, format
);
645 if (sig_request
.pause
) {
647 buffer_thread_pause (audio_buffer
);
649 kill (getpid(), SIGSTOP
); /* We block here until we unpause */
653 buffer_thread_unpause (audio_buffer
);
655 sig_request
.pause
= 0;
659 /* Read another block of audio data */
660 ret
= format
->read(decoder
, convbuffer
, convsize
, &eos
, &new_audio_fmt
);
662 /* Bail if we need to */
666 } else if (ret
< 0) {
667 status_error(_("ERROR: Decoding failure.\n"));
671 /* Check to see if the audio format has changed */
672 if (!audio_format_equal(&new_audio_fmt
, &old_audio_fmt
)) {
673 old_audio_fmt
= new_audio_fmt
;
675 /* Update our status printing interval */
676 status_interval
= new_audio_fmt
.word_size
* new_audio_fmt
.channels
*
677 new_audio_fmt
.rate
/ options
.status_freq
;
680 reopen_arg
= new_audio_reopen_arg(options
.devices
, &new_audio_fmt
);
683 buffer_insert_action_at_end(audio_buffer
, &audio_reopen_action
,
686 audio_reopen_action(NULL
, reopen_arg
);
690 /* Update statistics display if needed */
691 if (next_status
<= 0) {
692 display_statistics(stat_format
, audio_buffer
, source
, decoder
);
693 next_status
= status_interval
;
697 if (options
.endpos
> 0.0 && options
.endpos
<= current_time(decoder
)) {
703 /* Write audio data block to output, skipping or repeating chunks
709 if (!buffer_submit_data(audio_buffer
, convbuffer
, ret
)) {
710 status_error(_("ERROR: buffer write failed.\n"));
715 audio_play_callback(convbuffer
, ret
, eos
, &audio_play_arg
);
717 nthc
= options
.nth
- 1;
720 } while (!sig_request
.exit
&& !sig_request
.skipfile
&&
721 ++ntimesc
< options
.ntimes
);
725 } /* End of data loop */
727 } /* End of logical bitstream loop */
729 /* Done playing this logical bitstream. Clean up house. */
733 if (!sig_request
.exit
&& !sig_request
.skipfile
) {
734 buffer_mark_eos(audio_buffer
);
735 buffer_wait_for_empty(audio_buffer
);
738 buffer_thread_kill(audio_buffer
);
741 /* Print final stats */
742 display_statistics_quick(stat_format
, audio_buffer
, source
, decoder
);
744 format
->cleanup(decoder
);
745 transport
->close(source
);
746 status_reset_output_lock(); /* In case we were killed mid-output */
748 status_message(1, _("Done."));
750 if (sig_request
.exit
)