Mercurial > oggdemo
changeset 0:4d04dc4239b4
Simple demo programs for libao and libvorbisfile.
author | Eris Caffee <discordia@eldalin.com> |
---|---|
date | Tue, 22 Jul 2014 14:42:26 -0500 |
parents | |
children | 03892700ff0d |
files | .hgignore Makefile list_drivers.c playogg.c playogg.h |
diffstat | 5 files changed, 511 insertions(+), 0 deletions(-) [+] |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/.hgignore Tue Jul 22 14:42:26 2014 -0500 1.3 @@ -0,0 +1,3 @@ 1.4 +^list_drivers$ 1.5 +^playogg$ 1.6 +^.*~$
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/Makefile Tue Jul 22 14:42:26 2014 -0500 2.3 @@ -0,0 +1,12 @@ 2.4 +SHELL = /bin/sh 2.5 + 2.6 +all: playogg list_drivers 2.7 + 2.8 +playogg: playogg.c playogg.h 2.9 + gcc -o playogg playogg.c --std=gnu99 -lao -lvorbisfile 2.10 + 2.11 +list_drivers: list_drivers.c 2.12 + gcc -o list_drivers list_drivers.c --std=gnu99 -lao 2.13 + 2.14 +clean: 2.15 + rm -f list_drivers playogg
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/list_drivers.c Tue Jul 22 14:42:26 2014 -0500 3.3 @@ -0,0 +1,77 @@ 3.4 +#include <stdio.h> 3.5 +#include <stdlib.h> 3.6 + 3.7 +#include <ao/ao.h> 3.8 + 3.9 +/******************************************************************************/ 3.10 + 3.11 +void err_exit( char * msg ) 3.12 + { 3.13 + fprintf(stderr, "FATAL ERROR: %s\n", msg ? msg : "Unknown error" ); 3.14 + exit( EXIT_FAILURE ); 3.15 + } 3.16 + 3.17 + 3.18 +/******************************************************************************/ 3.19 + 3.20 +int main ( int argc, char** argv ) 3.21 + { 3.22 + ao_initialize(); 3.23 + 3.24 + ao_info ** driver_list = NULL; 3.25 + int driver_count = -1; 3.26 + 3.27 + driver_list = ao_driver_info_list( &driver_count ); 3.28 + if ( driver_list == NULL ) 3.29 + { 3.30 + err_exit("Unable to get list of drivers"); 3.31 + } 3.32 + 3.33 + printf( "Endianness: %s\n", ao_is_big_endian() ? "big" : "little" ); 3.34 + 3.35 + int default_driver_id = ao_default_driver_id(); 3.36 + if ( -1 == default_driver_id ) 3.37 + { 3.38 + printf( "No default driver available\n" ); 3.39 + } 3.40 + 3.41 + for ( int i = 0; i < driver_count; ++i ) 3.42 + { 3.43 + printf( "%s\n", driver_list[i]->name ); 3.44 + int driver_id = ao_driver_id( driver_list[i]->short_name ); 3.45 + if ( default_driver_id == driver_id ) 3.46 + { 3.47 + printf( "\tDEFAULT DRIVER\n" ); 3.48 + } 3.49 + printf( "\tshort name :\t%s\n", driver_list[i]->short_name ); 3.50 + printf( "\ttype :\t%s\n", 3.51 + driver_list[i]->type == AO_TYPE_LIVE ? "live" : 3.52 + (driver_list[i]->type == AO_TYPE_FILE ? "file" : 3.53 + "unknown") 3.54 + ); 3.55 + printf( "\tpriority :\t%d\n", driver_list[i]->priority ); 3.56 + printf( "\tpreferred byte format:\t%s\n", 3.57 + driver_list[i]->preferred_byte_format == AO_FMT_LITTLE ? "little" : 3.58 + (driver_list[i]->preferred_byte_format == AO_FMT_BIG ? "big" : "unknown" ) 3.59 + ); 3.60 + 3.61 +#if 0 3.62 + // Appears that ao-file_extension is not in my version of libao 3.63 + char * ext = NULL; 3.64 + ext = ao_file_extension( driver_id ); 3.65 + printf( "\tnormal file extension:\t%s\n", ext == NULL ? "[none]" : ext ); 3.66 +#endif 3.67 + 3.68 + printf( "\toptions :\t", driver_list[i]->comment); 3.69 + for ( int j = 0; j < driver_list[i]->option_count ; ++j ) 3.70 + { 3.71 + printf( "%s ", driver_list[i]->options[j]); 3.72 + } 3.73 + printf("\n"); 3.74 + 3.75 + printf( "\tcomment :\t%s\n", driver_list[i]->comment); 3.76 + } 3.77 + 3.78 + ao_shutdown(); 3.79 + } 3.80 +
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/playogg.c Tue Jul 22 14:42:26 2014 -0500 4.3 @@ -0,0 +1,399 @@ 4.4 +#include <stdio.h> 4.5 +#include <stdlib.h> 4.6 +#include <string.h> 4.7 + 4.8 +#include <getopt.h> 4.9 +#include <signal.h> 4.10 + 4.11 +#include <ao/ao.h> 4.12 +#include <vorbis/vorbisfile.h> 4.13 + 4.14 +#include "playogg.h" 4.15 + 4.16 +/******************************************************************************/ 4.17 +static struct opts { 4.18 + int debug; 4.19 + int verbose; 4.20 + int list_devices; 4.21 + char* device; 4.22 + char **files; 4.23 + int skip_next; 4.24 + int ao_endian; 4.25 + int ao_device_id; 4.26 + ao_device *ao_device; 4.27 + ao_info *ao_driver_info; 4.28 + ao_sample_format ao_format; 4.29 + } options; 4.30 + 4.31 +int 4.32 +main (int argc, char **argv ) { 4.33 + 4.34 + init(); 4.35 + parse_command_line( argc, argv ); 4.36 + 4.37 + if ( ! sound_init() ) { 4.38 + exit( EXIT_FAILURE ); 4.39 + } 4.40 + 4.41 + if ( options.list_devices ) { 4.42 + exit( sound_list_devices() ); 4.43 + } 4.44 + 4.45 + char **file = options.files; 4.46 + int ok = 1; 4.47 + while (ok && file && *file) { 4.48 + if ( options.verbose ) { 4.49 + printf( "Next file: %s\n", *file ); 4.50 + } 4.51 + ok = sound_play_file( *file ); 4.52 + file++; 4.53 + } 4.54 + 4.55 + exit( EXIT_SUCCESS ); 4.56 + } 4.57 + 4.58 +/******************************************************************************/ 4.59 +void 4.60 +sig_handler ( int sig ) { 4.61 + if ( SIGINT == sig ) { 4.62 + options.skip_next = 1; 4.63 + } 4.64 + } 4.65 + 4.66 +/******************************************************************************/ 4.67 +void 4.68 +err_exit ( char * msg ) { 4.69 + fprintf(stderr, "FATAL ERROR: %s\n", msg ? msg : "Unknown error" ); 4.70 + exit( EXIT_FAILURE ); 4.71 + } 4.72 + 4.73 +/******************************************************************************/ 4.74 +void 4.75 +init ( void ) { 4.76 + atexit( shutdown ); 4.77 + 4.78 + options.debug = 0; 4.79 + options.verbose = 0; 4.80 + options.device = NULL; 4.81 + options.list_devices = 0; 4.82 + options.files = NULL; 4.83 + options.skip_next = 0; 4.84 + options.ao_endian = 1; 4.85 + options.ao_device_id = -1; 4.86 + options.ao_device = NULL; 4.87 + options.ao_driver_info = NULL; 4.88 + memset( &options.ao_format, 0, sizeof(ao_sample_format) ); 4.89 + 4.90 + struct sigaction sigact; 4.91 + memset( &sigact, 0, sizeof(sigact) ); 4.92 + sigact.sa_handler = sig_handler; 4.93 + sigaction( SIGINT, &sigact, NULL ); 4.94 + 4.95 + } 4.96 + 4.97 +/******************************************************************************/ 4.98 +int 4.99 +min ( int a, int b ) { 4.100 + if (a <= b) { 4.101 + return a; 4.102 + } 4.103 + else { 4.104 + return b; 4.105 + } 4.106 + } 4.107 + 4.108 + 4.109 +/******************************************************************************/ 4.110 +void 4.111 +parse_command_line (int argc, char **argv ) { 4.112 + 4.113 + static const char *short_options = "hd:l"; 4.114 + static const struct option long_options[] = { 4.115 + { "help", 0, 0, 'h' }, 4.116 + { "verbose", 0, 0, 0 }, 4.117 + { "debug", 0, 0, 0 }, 4.118 + { "device", 1, 0, 'd' }, 4.119 + { "list-devices", 0, 0, 'l' }, 4.120 + { NULL, 0, NULL, 0} 4.121 + }; 4.122 + 4.123 + int c; 4.124 + int option_index = 0; 4.125 + while (1) { 4.126 + c = getopt_long( argc, argv, short_options, long_options, &option_index ); 4.127 + 4.128 + if ( -1 == c ) { 4.129 + break; 4.130 + } 4.131 + 4.132 + switch (c) { 4.133 + 4.134 + case 0: 4.135 + 1; 4.136 + int len = strlen( long_options[option_index].name ); 4.137 + if ( 0 == strncmp( long_options[option_index].name, "verbose", min(len, 7) ) ) { 4.138 + options.verbose = 1; 4.139 + } 4.140 + else if ( 0 == strncmp( long_options[option_index].name, "debug", min(len, 5) ) ) { 4.141 + options.debug = 1; 4.142 + } 4.143 + else { 4.144 + fprintf( stderr, "Unrecognized option on command line: --%s\n", optarg ); 4.145 + show_help(); 4.146 + exit( EXIT_FAILURE ); 4.147 + } 4.148 + 4.149 + break; 4.150 + 4.151 + case 'h': 4.152 + show_help(); 4.153 + exit( EXIT_SUCCESS ); 4.154 + break; 4.155 + 4.156 + case 'd': 4.157 + options.device = strdup(optarg); 4.158 + break; 4.159 + 4.160 + case 'l': 4.161 + options.list_devices = 1; 4.162 + break; 4.163 + 4.164 + case 'v': 4.165 + options.verbose = 1; 4.166 + break; 4.167 + 4.168 + default: 4.169 + fprintf( stderr, "Unrecognized option on command line: -%c\n", c ); 4.170 + show_help(); 4.171 + exit( EXIT_FAILURE ); 4.172 + break; 4.173 + } 4.174 + } 4.175 + 4.176 + if (optind < argc) { 4.177 + options.files = calloc( argc - optind + 1, sizeof(char *) ); 4.178 + int i = 0; 4.179 + while ( optind < argc) { 4.180 + options.files[i++] = argv[optind++]; 4.181 + } 4.182 + } 4.183 + 4.184 + if (options.debug) { 4.185 + fprintf( stderr, "verbose: %d\n", options.verbose ); 4.186 + fprintf( stderr, "debug : %d\n", options.debug ); 4.187 + fprintf( stderr, "device : %s\n", options.device ); 4.188 + fprintf( stderr, "list_devices : %d\n", options.list_devices ); 4.189 + fprintf( stderr, "files : "); 4.190 + char **ptr = options.files; 4.191 + while (ptr && *ptr) { 4.192 + fprintf( stderr, "%s ", *ptr ); 4.193 + ptr++; 4.194 + } 4.195 + fprintf( stderr, "\n" ); 4.196 + } 4.197 + 4.198 + } 4.199 + 4.200 +/******************************************************************************/ 4.201 +void 4.202 +shutdown ( void ) { 4.203 + if ( options.device ) { 4.204 + free( options.device ); 4.205 + } 4.206 + } 4.207 + 4.208 +/******************************************************************************/ 4.209 +void 4.210 +show_help ( void ) { 4.211 + printf( 4.212 + "Usage: myplayogg [-hlv] filename\n" 4.213 + "\n" 4.214 + "Play the Ogg Vorbis encoded file.\n" 4.215 + "\n" 4.216 + "Options:\n" 4.217 + "\n" 4.218 + "-h --help Show these instructions.\n" 4.219 + " --verbose Print extra information.\n" 4.220 + " --debug Print debugging information.\n" 4.221 + "-d --device Specify the output device to use.\n" 4.222 + "-l --list-devices Print a list fo available output devices.\n" 4.223 + "\n" 4.224 + ); 4.225 + } 4.226 + 4.227 +/******************************************************************************/ 4.228 +int 4.229 +sound_list_devices ( void ) { 4.230 + ao_info ** driver_list = NULL; 4.231 + int driver_count = -1; 4.232 + 4.233 + driver_list = ao_driver_info_list( &driver_count ); 4.234 + if ( driver_list == NULL ) { 4.235 + fprintf( stderr, "Unable to get list of drivers" ); 4.236 + return EXIT_FAILURE; 4.237 + } 4.238 + 4.239 + int default_driver_id = ao_default_driver_id(); 4.240 + 4.241 + for ( int i = 0; i < driver_count; ++i ) 4.242 + { 4.243 + printf( "%s\n", driver_list[i]->name ); 4.244 + int driver_id = ao_driver_id( driver_list[i]->short_name ); 4.245 + if ( default_driver_id == driver_id ) { 4.246 + printf( "\tDEFAULT DRIVER\n" ); 4.247 + } 4.248 + printf( "\tshort name :\t%s\n", driver_list[i]->short_name ); 4.249 + printf( "\ttype :\t%s\n", 4.250 + driver_list[i]->type == AO_TYPE_LIVE ? "live" : 4.251 + (driver_list[i]->type == AO_TYPE_FILE ? "file" : 4.252 + "unknown") 4.253 + ); 4.254 + printf( "\tcomment :\t%s\n", driver_list[i]->comment); 4.255 + } 4.256 + 4.257 + return EXIT_SUCCESS; 4.258 + } 4.259 + 4.260 +/******************************************************************************/ 4.261 +int 4.262 +sound_init ( void ) { 4.263 + 4.264 + ao_initialize(); 4.265 + atexit( sound_shutdown ); 4.266 + 4.267 + options.ao_endian = ao_is_big_endian(); 4.268 + options.ao_device_id = ao_default_driver_id(); 4.269 + if ( options.device ) { 4.270 + options.ao_device_id = ao_driver_id( options.device ); 4.271 + } 4.272 + if ( -1 == options.ao_device_id ) { 4.273 + fprintf( stderr, "Unable to open output device.\n" ); 4.274 + return 0; 4.275 + } 4.276 + 4.277 + options.ao_driver_info = ao_driver_info( options.ao_device_id ); 4.278 + 4.279 + options.ao_format.bits = 16; 4.280 + options.ao_format.channels = 2; 4.281 + options.ao_format.rate = 44100; 4.282 + options.ao_format.byte_format = options.ao_driver_info->preferred_byte_format; 4.283 + 4.284 + if ( AO_TYPE_LIVE == options.ao_driver_info->type ) { 4.285 + options.ao_device = ao_open_live( options.ao_device_id, &options.ao_format, NULL ); 4.286 + } 4.287 + else { 4.288 + fprintf( stderr, "error: Only live output devices are supported.\n" ); 4.289 + return 0; 4.290 + } 4.291 + 4.292 + return 1; 4.293 + } 4.294 + 4.295 +/******************************************************************************/ 4.296 +int 4.297 +sound_play_file ( char *file ) { 4.298 + OggVorbis_File vf; 4.299 + int ok = 1; 4.300 + 4.301 + int err = ov_fopen( file, &vf ); 4.302 + if ( err ) { 4.303 + fprintf( stderr, "Unable to open file: %d\n", err ); 4.304 + ok = 0; 4.305 + return ok; 4.306 + } 4.307 + 4.308 + sound_print_comments( &vf ); 4.309 + 4.310 + if ( options.debug ) { 4.311 + vorbis_info *vi = ov_info( &vf, -1 ); 4.312 + printf( "Encoded by: %s\n\n", ov_comment( &vf, -1 )->vendor ); 4.313 + printf( "Bitstream is %d channel, %ldHz\n", vi->channels, vi->rate); 4.314 + printf( "Decoded length: %ld samples\n", (long) ov_pcm_total( &vf, -1 ) ); 4.315 + } 4.316 + 4.317 + char pcm[PCM_BUFFER_SIZE]; 4.318 + int current_section; 4.319 + int done = 0; 4.320 + 4.321 + while ( ! done && ! options.skip_next ) { 4.322 + long bytes_read = ov_read( &vf, pcm, sizeof(pcm), options.ao_endian, 2, 1, ¤t_section ); 4.323 + 4.324 + if ( 0 == bytes_read ) { 4.325 + done = 1; 4.326 + } 4.327 + else if ( OV_HOLE == bytes_read ) { 4.328 + if (options.verbose ) { 4.329 + fprintf( stderr, "error: hole in data\n" ); 4.330 + } 4.331 + } 4.332 + else if ( OV_EBADLINK == bytes_read ) { 4.333 + if (options.verbose ) { 4.334 + fprintf( stderr, "error: invalid stream section in data\n" ); 4.335 + } 4.336 + } 4.337 + else if ( OV_EINVAL == bytes_read ) { 4.338 + fprintf( stderr, "error: Unable to read file headers.\n" ); 4.339 + done = 1; 4.340 + } 4.341 + else { 4.342 + // Play it! 4.343 + if ( ! ao_play( options.ao_device, pcm, bytes_read ) ) { 4.344 + done = 1; 4.345 + ok = 0; 4.346 + } 4.347 + } 4.348 + 4.349 + } 4.350 + 4.351 + ov_clear( &vf ); 4.352 + 4.353 + if ( options.skip_next ) { 4.354 + options.skip_next = 0; 4.355 + } 4.356 + 4.357 + return ok; 4.358 + } 4.359 + 4.360 +/******************************************************************************/ 4.361 +void 4.362 +sound_print_comments ( OggVorbis_File *vf) { 4.363 + 4.364 + char **comments = ov_comment( vf, -1 )->user_comments; 4.365 + 4.366 + char *track_title = NULL; 4.367 + char **ptr = comments; 4.368 + while ( ptr && *ptr ) { 4.369 + char * pos = strstr( *ptr, "title" ); 4.370 + if ( NULL != pos ) { 4.371 + pos = strchr( *ptr, '=' ); 4.372 + if ( pos ) { 4.373 + track_title = pos + 1; 4.374 + } 4.375 + } 4.376 + ++ptr; 4.377 + } 4.378 + 4.379 + printf( "Now playing: %s\n", track_title ? track_title : "[unknown]" ); 4.380 + 4.381 + if ( options.verbose ) { 4.382 + ptr = comments; 4.383 + while ( ptr && *ptr ) { 4.384 + char * pos = strstr( *ptr, "title" ); 4.385 + if ( NULL == pos ) { 4.386 + char *temp = strdup(*ptr); 4.387 + pos = strchr( temp, '=' ); 4.388 + *pos = '\0'; 4.389 + printf( "\t%s: %s\n", temp, pos+1); 4.390 + free(temp); 4.391 + } 4.392 + ++ptr; 4.393 + } 4.394 + } 4.395 + } 4.396 + 4.397 +/******************************************************************************/ 4.398 +void 4.399 +sound_shutdown ( void ) { 4.400 + ao_shutdown(); 4.401 + } 4.402 +
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/playogg.h Tue Jul 22 14:42:26 2014 -0500 5.3 @@ -0,0 +1,20 @@ 5.4 +#ifndef PLAYOGG_H_ 5.5 +#define PLAYOGG_H_ 5.6 + 5.7 +#define PCM_BUFFER_SIZE 4096 5.8 + 5.9 +void err_exit ( char *msg ); 5.10 +void init ( void ); 5.11 +int min ( int a, int b ); 5.12 +void parse_command_line (int argc, char **argv ); 5.13 +void show_help ( void ); 5.14 +void shutdown ( void ); 5.15 +void sig_handler( int sig ); 5.16 +int sound_list_devices ( void ); 5.17 +int sound_init ( void ); 5.18 +int sound_play_file ( char *file ); 5.19 +void sound_print_comments ( OggVorbis_File *vf); 5.20 +void sound_shutdown ( void ); 5.21 + 5.22 + 5.23 +#endif