"Fossies" - the Fresh Open Source Software Archive

Member "xcdroast-1.19/src/wavplay.c" (8 Nov 2018, 21608 Bytes) of package /linux/misc/xcdroast-1.19.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "wavplay.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.18_vs_1.19.

    1 /*
    2  *  wavplay.c
    3  *
    4  *  simple wavfile-player. plays only 44.1khz,16bit,stereo files.
    5  *  gui-mode to fully control all play-functions via external interface 
    6  *
    7  *  works fine on little and big endian machines.
    8  *  30.05.99 tn
    9  *  07.11.18 tn - add ALSA support for linux
   10  *
   11  *
   12  *  Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
   13  *
   14  *  This file is part of xcdroast.
   15  *
   16  *  This program is free software; you can redistribute it and/or modify
   17  *  it under the terms of the GNU General Public License as published by
   18  *  the Free Software Foundation; either version 2 of the License, or
   19  *  (at your option) any later version.
   20  *
   21  *  This program is distributed in the hope that it will be useful,
   22  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   23  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   24  *  GNU General Public License for more details.
   25  *
   26  *  You should have received a copy of the GNU General Public License
   27  *  along with this program; if not, write to the Free Software
   28  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   29  */
   30 
   31 #ifdef HAVE_CONFIG_H
   32 # include <config.h>
   33 #endif
   34 
   35 #include "largefile.h"
   36 
   37 #include <stdio.h>
   38 #include <sys/types.h>
   39 #include <stdlib.h>
   40 #include <unistd.h>
   41 #include <fcntl.h>
   42 #include <string.h>
   43 #if defined(linux) || defined(__CYGWIN32__)
   44 # include <getopt.h>
   45 #endif
   46 #include <sys/stat.h>
   47 #if defined(linux)
   48 # include <alsa/asoundlib.h>
   49 #endif
   50 #if defined(__FreeBSD__)
   51 # include <sys/soundcard.h>
   52 # include <sys/ioctl.h>
   53 #endif
   54 #if defined(sun) || defined(__OpenBSD__)
   55 # include <sys/ioctl.h>
   56 # include <sys/audioio.h>
   57 #endif
   58 #ifdef aix 
   59 #include <errno.h>
   60 #include <sys/audio.h>
   61 #endif
   62 #ifdef hpux
   63 # ifndef hpux_alib
   64 #  include <sys/audio.h>
   65 # else
   66 #  include <sys/socket.h>
   67 #  include <netdb.h>
   68 #  include <netinet/in.h>
   69 #  include <netinet/tcp.h>
   70 #  include <Alib.h>
   71 # endif
   72 #endif
   73 
   74 #include <glib.h>
   75 #include "xcdroast.h"
   76 
   77 #if defined(__sgi)
   78 #include <dmedia/audio.h>
   79 #endif
   80 
   81 static off_t waveBase ;
   82 static gint abuf_size;
   83 #if defined(linux) 
   84 static gint alsa_frame_size;
   85 #endif
   86 static guchar *audiobuf;
   87 
   88 gint read_line(gint fd, gchar *ptr, gint maxlen);
   89 off_t is_std_wav_file(int f, off_t *offset);
   90 
   91 
   92 #if defined(linux) 
   93 #define DEFAULT_AUDIO_DEVICE "default"
   94 #elif defined(__FreeBSD__)
   95 #define DEFAULT_AUDIO_DEVICE "/dev/dsp"
   96 #elif defined (aix)
   97 #define DEFAULT_AUDIO_DEVICE ""
   98 #elif defined(__sgi)
   99 #define DEFAULT_AUDIO_DEVICE ""
  100 #else
  101 #define DEFAULT_AUDIO_DEVICE "/dev/audio"
  102 #endif
  103 
  104 #define DEFAULT_BUFFER_SIZE 22050 
  105 
  106 
  107 #if defined(linux) 
  108 
  109 /*
  110  * open the alsa-device of linux and set cd-quality
  111  */
  112 snd_pcm_t *open_alsa_audio(gchar *dev) {
  113 snd_pcm_t *playback_handle;
  114 snd_pcm_hw_params_t *hw_params;
  115 snd_pcm_uframes_t buffer_size, periods;
  116 gint err;
  117 
  118     if ((err = snd_pcm_open (&playback_handle, dev, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
  119             g_warning("cannot open audio device %s (%s)\n", dev, snd_strerror (err));
  120             return(NULL);
  121     }
  122     if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) {
  123             g_warning("cannot allocate hardware parameter structure (%s)\n",
  124                  snd_strerror (err));
  125             return(NULL);
  126     }
  127                  
  128     if ((err = snd_pcm_hw_params_any (playback_handle, hw_params)) < 0) {
  129             g_warning("cannot initialize hardware parameter structure (%s)\n",
  130                  snd_strerror (err));
  131             return(NULL);
  132     }
  133     
  134     if ((err = snd_pcm_hw_params_set_access (playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
  135             g_warning("cannot set access type (%s)\n", snd_strerror (err));
  136             return(NULL);
  137     }
  138     
  139     if ((err = snd_pcm_hw_params_set_format (playback_handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) {
  140             g_warning("cannot set sample format (%s)\n", snd_strerror (err));
  141             return(NULL);
  142     }
  143     
  144     if ((err = snd_pcm_hw_params_set_rate (playback_handle, hw_params, 44100, 0)) < 0) {
  145             g_warning("cannot set sample rate (%s)\n", snd_strerror (err));
  146             return(NULL);
  147     }
  148     
  149     if ((err = snd_pcm_hw_params_set_channels (playback_handle, hw_params, 2)) < 0) {
  150             g_warning("cannot set channel count (%s)\n", snd_strerror (err));
  151             return(NULL);
  152     }
  153 
  154     periods = 4;
  155     if ((err = snd_pcm_hw_params_set_periods (playback_handle, hw_params, periods, 0)) < 0) {
  156             g_warning("cannot set periode size (%s)\n", snd_strerror (err));
  157             return(NULL);
  158     }
  159 
  160     buffer_size = CDDAFRAME * periods;
  161     if ((err = snd_pcm_hw_params_set_buffer_size_near (playback_handle, hw_params, &buffer_size)) < 0) {
  162             g_warning("cannot set buffer size (%s)\n", snd_strerror (err));
  163             return(NULL);
  164     }
  165     
  166     if ((err = snd_pcm_hw_params (playback_handle, hw_params)) < 0) {
  167             g_warning("cannot set parameters (%s)\n", snd_strerror (err));
  168             return(NULL);
  169     }
  170     
  171     /* determine real buffer size */
  172     snd_pcm_hw_params_get_buffer_size(hw_params, &buffer_size);
  173     alsa_frame_size = snd_pcm_format_size(SND_PCM_FORMAT_S16_LE, 2);
  174     abuf_size = (gint)buffer_size * alsa_frame_size;
  175 
  176     snd_pcm_hw_params_free (hw_params);
  177 
  178     if ((err = snd_pcm_prepare (playback_handle)) < 0) {
  179             g_warning("cannot prepare audio interface for use (%s)\n",
  180                  snd_strerror (err));
  181             return(NULL);
  182         }
  183 
  184     return (playback_handle);
  185 }
  186 
  187 #endif
  188 
  189 #if defined(__FreeBSD__)
  190 
  191 /*
  192  * open the sound-device of linux and set cd-quality
  193  */
  194 gint open_linux_audio(gchar *dev) {
  195 gint audio;
  196 gint tmp;
  197 gint samplesize = 16;
  198 gint dsp_stereo = 1;
  199 gint dsp_speed = 44100;
  200 gint flags;
  201 
  202     /* First try open with O_NONBLOCK so it doesn't hang */
  203     audio = open (dev, (O_WRONLY | O_NONBLOCK),0);
  204     if (audio == -1) {
  205         /* error opening sound device */
  206         return -1;
  207     }
  208 
  209     /* now undo NONBLOCK setting again */
  210     flags = fcntl(audio,F_GETFL);
  211     fcntl(audio,F_SETFL,flags & ~O_NONBLOCK);
  212 
  213     tmp = samplesize; 
  214     ioctl(audio, SNDCTL_DSP_SAMPLESIZE, &samplesize);   
  215     if (tmp != samplesize) {
  216         /* error setting samplesize */
  217         g_warning("Unable to set samplesize to 16 bit\n");
  218         return -1;
  219     }
  220 
  221     if (ioctl (audio, SNDCTL_DSP_STEREO, &dsp_stereo)==-1) {
  222         g_warning("Unable to set audio to stereo\n");
  223         return -1;
  224     }
  225     
  226     if (ioctl (audio, SNDCTL_DSP_SPEED, &dsp_speed) == -1) {
  227         g_warning("Unable to set audio to 44.1 kHz\n");
  228         return -1;
  229     }
  230 
  231     if (ioctl (audio, SNDCTL_DSP_GETBLKSIZE, &abuf_size) == -1) {
  232         g_warning("Unable to get blocksize for audio-device\n");
  233         return -1;
  234     }
  235 
  236     return audio;
  237 }
  238 
  239 #endif
  240 
  241 #if defined(sun) || defined(__OpenBSD__)
  242 
  243 /*
  244  * open the sound-device of solaris and set cd-quality
  245  */
  246 gint open_solaris_audio(gchar *dev) {
  247 gint audio;
  248 audio_info_t info;
  249 gint flags;
  250 
  251     /* First try open with O_NONBLOCK so it doesn't hang */
  252     if ((audio = open(dev, (O_WRONLY | O_NONBLOCK))) == -1) {
  253         /* error opening sound device */
  254         return -1;
  255     }
  256 
  257     /* now undo NONBLOCK setting again */
  258     flags = fcntl(audio,F_GETFL);
  259     fcntl(audio,F_SETFL,flags & ~O_NONBLOCK);
  260 
  261     abuf_size = DEFAULT_BUFFER_SIZE;
  262 
  263     AUDIO_INITINFO(&info);
  264     info.play.sample_rate = 44100;
  265     info.play.channels = 2;
  266     info.play.precision = 16;
  267     info.play.encoding = AUDIO_ENCODING_LINEAR;
  268     info.play.buffer_size = abuf_size;
  269 #ifndef __OpenBSD__
  270     info.output_muted = 0;
  271 #endif
  272 
  273     if (ioctl(audio, AUDIO_SETINFO, &info) == -1) {
  274         g_warning("Unable to set audio parameters\n");
  275         return -1;
  276     }   
  277 
  278     return audio;
  279 }
  280 
  281 #endif
  282 
  283 #ifdef aix
  284 /*
  285  * open the audio device of an IBM RS/6000 with AIX Ultimedia Services
  286  * and set cd-quality
  287  */
  288 gint open_aix_audio(gchar *dev) {
  289 audio_init ainfo;
  290 audio_control  acontrol;
  291 audio_change   achange;
  292 gint audio;
  293 
  294     if (strlen (dev) == 0) {
  295         if(getenv("AUDIODEV")) {
  296             strcpy (dev, getenv("AUDIODEV"));
  297             audio = open (dev, O_WRONLY);
  298         } else {
  299             /* Try to use the device of a machine with PCI bus */
  300             strcpy (dev, "/dev/paud0/1");
  301             audio = open (dev, O_WRONLY);
  302             if ((audio == -1) & (errno == ENOENT)) {
  303                 /* Try the device of a machine with MCA    */
  304                 /* bus as last default                     */
  305                 strcpy (dev, "/dev/baud0/1");
  306                 audio = open (dev, O_WRONLY);
  307             }
  308         }
  309     } else {
  310         /* Try the device given in the commandline */
  311         audio = open (dev, O_WRONLY);
  312     }
  313 
  314     if(dev < 0) {
  315         /* error opening audio device */
  316         return -1;
  317     }
  318 
  319     /* Initialize the default audio description  */
  320     /* (the size of the buffer is given in msec) */
  321     memset (&ainfo, '\0', sizeof (audio_init));
  322     ainfo.srate            = 44100;
  323     ainfo.channels         = 2;
  324     ainfo.mode             = PCM;
  325     ainfo.bits_per_sample  = 16;
  326     ainfo.flags            = BIG_ENDIAN | TWOS_COMPLEMENT;
  327     ainfo.operation        = PLAY;
  328     ainfo.bsize            = 8 * 1000 *DEFAULT_BUFFER_SIZE 
  329         / (ainfo.srate * ainfo.channels * ainfo.bits_per_sample);
  330  
  331     if (ioctl (audio, AUDIO_INIT, &ainfo) == -1) {
  332         g_warning("Unable to set default audio parameters\n");
  333         return -1;
  334     }
  335 
  336     memset ( & acontrol, '\0', sizeof (acontrol));
  337   
  338     /* Tell the audio device to start output     */
  339     acontrol.ioctl_request   = AUDIO_START;
  340     acontrol.request_info    = NULL;
  341     acontrol.position        = 0;
  342 
  343     if (ioctl (audio, AUDIO_CONTROL, & acontrol) == -1) {
  344         g_warning("Unable to start audio operation\n");
  345         return -1;
  346     }
  347     abuf_size = DEFAULT_BUFFER_SIZE;
  348 
  349     memset ( & achange, '\0', sizeof (achange));
  350     memset ( & acontrol, '\0', sizeof (acontrol));
  351        
  352     /* set the output only to external speaker                */
  353     /* else the output device will be set to the predefined   */
  354     /* value in the cde environment.                          */
  355     achange.balance        = AUDIO_IGNORE;
  356     achange.balance_delay  = AUDIO_IGNORE;
  357     achange.volume         = AUDIO_IGNORE;
  358     achange.volume_delay   = AUDIO_IGNORE;
  359     achange.input          = AUDIO_IGNORE;
  360     achange.output         = EXTERNAL_SPEAKER;
  361     /* achange.output         = INTERNAL_SPEAKER */
  362     /* achange.output         = OUTPUT_1         */
  363     achange.treble         = AUDIO_IGNORE;
  364     achange.bass           = AUDIO_IGNORE;
  365     achange.pitch          = AUDIO_IGNORE;
  366     achange.monitor        = AUDIO_IGNORE;
  367     achange.dev_info       = (char *) NULL;
  368     acontrol.ioctl_request = AUDIO_CHANGE;
  369     acontrol.position      = 0;
  370     acontrol.request_info  = (char *) & achange;
  371 
  372     if (ioctl (audio, AUDIO_CONTROL, & acontrol) == -1) {
  373         g_warning("Error writing mixer\n");
  374         return -1;
  375     }
  376 
  377 
  378     return audio;
  379 }
  380 #endif
  381 
  382 
  383 #ifdef hpux
  384 # ifndef hpux_alib
  385 
  386 /*
  387  * open the audio device on a HP9000 with HP-UX and set cd-quality
  388  */
  389 gint open_hpux_audio(gchar *dev) {
  390 gint audio;
  391 
  392     audio = open (dev, O_WRONLY | O_NONBLOCK);
  393     if (audio == -1) {
  394         /* error opening audio device */
  395         return -1;
  396     }
  397 
  398     if (ioctl(audio, AUDIO_SET_DATA_FORMAT, 
  399         AUDIO_FORMAT_LINEAR16BIT) == -1) {
  400         g_warning("Unable to set samplesize to 16 bit\n");
  401         return -1;
  402     }
  403 
  404     if (ioctl (audio, AUDIO_SET_CHANNELS, 2)==-1) {
  405         g_warning("Unable to set audio to stereo\n");
  406         return -1;
  407     }
  408 
  409     if (ioctl (audio, AUDIO_SET_SAMPLE_RATE, 44100) == -1) {
  410         g_warning("Unable to set audio to 44.1 kHz\n");
  411         return -1;
  412     }
  413 
  414     abuf_size = DEFAULT_BUFFER_SIZE;
  415 
  416     return audio;
  417 }
  418 # else
  419 
  420 /*
  421  * Some global variables for the hp-ux audio lib
  422  * Code mostly taken from simpleAudio.c sample of hpux
  423  */
  424 static Audio *audioServer = (Audio *) NULL;
  425 static struct protoent *tcpProtocolEntry;
  426 
  427 gint open_hpux_audio(gchar *dev) {
  428 int            streamSocket;
  429 long            status;
  430 SSPlayParams    playParams;
  431 AGainEntry      gainEntry[4];
  432 AudioAttrMask   AttribsMask;
  433 AudioAttributes Attribs;
  434 SStream         audioStream;
  435 int             i;
  436 ATransID        xid;
  437 
  438 /*
  439  * a_name specifies the audio controller name as a string.
  440  * We specify NULL, so the value of the AUDIO environment
  441  * variable is used.
  442  */
  443 char a_name = '\0';
  444 
  445         /* open audio connection */ 
  446         audioServer = AOpenAudio(&a_name, NULL);
  447         if (audioServer == NULL) {
  448         /* error opening audio device */
  449         g_warning("Unable to open audio device\n");
  450         return -1;
  451     }
  452     tcpProtocolEntry=getprotobyname("tcp");
  453 
  454     streamSocket = socket (AF_INET, SOCK_STREAM, 0);
  455     if( streamSocket < 0 ) {
  456         g_warning("Unable to request audio socket stream\n");
  457         return -1;
  458     }
  459     /* Set the default audio description */
  460     Attribs.type = ATSampled;
  461     Attribs.attr.sampled_attr.sampling_rate = 44100;
  462     Attribs.attr.sampled_attr.channels = 2;
  463     Attribs.attr.sampled_attr.data_format = ADFLin16;
  464     AttribsMask = ASSamplingRateMask | ASChannelsMask  | ASDataFormatMask;
  465     /* Use the transmit gain and the output channel defined */
  466     /* by the SPEAKER environment                           */
  467     gainEntry[0].u.o.out_ch = AOCTMono;
  468     gainEntry[0].gain = AUnityGain;
  469     gainEntry[0].u.o.out_dst = AODTDefaultOutput;
  470     playParams.gain_matrix.type = AGMTOutput;
  471     playParams.gain_matrix.num_entries = 1;
  472     playParams.gain_matrix.gain_entries = gainEntry;
  473     playParams.play_volume = AUnityGain;
  474     playParams.priority = APriorityNormal;
  475     playParams.event_mask = 0;
  476 
  477     /* Create an audio stream */
  478     xid = APlaySStream( audioServer, AttribsMask, &Attribs, 
  479                 &playParams, &audioStream, NULL);
  480 
  481     /* Connect the stream socket to the audio stream port */
  482     status = connect( streamSocket, (struct sockaddr *)&audioStream.tcp_sockaddr,
  483               sizeof(struct sockaddr_in));
  484     if (status < 0) {
  485       printf ("Errno: %d\n", errno);
  486         g_warning ("Connection of an audio stream socket failed\n");
  487     /*  close (streamSocket);*/
  488         return -1;
  489     }
  490 
  491     /* Tell TCP to not delay sending data written to this socket */
  492     i = -1;
  493     setsockopt( streamSocket, tcpProtocolEntry->p_proto, TCP_NODELAY,
  494             &i, sizeof(i) );
  495 
  496     abuf_size = DEFAULT_BUFFER_SIZE;
  497     return (streamSocket);
  498 }
  499 
  500 # endif
  501 #endif
  502 
  503 
  504 #if defined(__sgi)
  505 
  506 static ALport  irixAudioPort = NULL;   /* Our interface to SGI audio device */
  507 static int     irixAudioRate = 44100;  /* The samples rate */
  508 
  509 gint open_irix_audio(gchar *devName) {
  510 
  511     ALvalue     v [1];
  512     ALpv        pv [2], q [1];
  513     ALconfig    audioConfig;
  514     int     dev;
  515 
  516     if (irixAudioPort != NULL)      /* The device is already open. */
  517         return 0;
  518 
  519     /* Find the selected audio device */
  520     if (devName[0] == '\0') {
  521         dev = AL_DEFAULT_OUTPUT;
  522     }
  523     else {
  524         q[0].param = AL_LABEL;
  525         q[0].value.ptr = devName;
  526         q[0].sizeIn = strlen(devName) + 1;
  527         if (alQueryValues(AL_SYSTEM, AL_DEVICES, v, 1, q, 1) <= 0) {
  528             g_warning("Invalid audio port name\n");
  529             return -1;
  530         }
  531         dev = v[0].i;
  532     }
  533 
  534     /* Allocate a config structure */
  535     audioConfig = alNewConfig();
  536 
  537     /* Set the audio device */
  538     if (alSetDevice(audioConfig, dev) < 0) {
  539         g_warning("Unable to set the audio device\n");
  540         return -1;
  541     }
  542 
  543     /* Set the buffer size to contain 1/2 second of samples */
  544     abuf_size = irixAudioRate;
  545     if (alSetQueueSize(audioConfig, abuf_size / 2) < 0) {
  546         g_warning("Unable to set queue size\n");
  547         return -1;
  548     }
  549 
  550     /* Set the samples width */
  551     if (alSetWidth(audioConfig, AL_SAMPLE_16) < 0) {
  552         g_warning("Unable to set sample size to 16 bit\n");
  553         return -1;
  554     }
  555 
  556     /* Set the number of channels */
  557     if (alSetChannels(audioConfig, AL_STEREO) < 0) {
  558         g_warning("Unable to set audio to stereo\n");
  559         return -1;
  560     }
  561 
  562     /* Open the audio port */
  563     if ((irixAudioPort = alOpenPort("wavplay", "w", audioConfig) ) == NULL) {
  564         g_warning("Unable to open audio port\n");
  565         return -1;
  566     }
  567 
  568     /* Set the samples rate */
  569     pv[0].param = AL_RATE;
  570     pv[0].value.ll = alDoubleToFixed((double) irixAudioRate);
  571     if (alSetParams(dev, pv, 1) < 0 ) {
  572         g_warning("Unable to set audio to 44.1 kHz\n");
  573         return -1;
  574     }
  575 
  576     return 0;
  577 }
  578 
  579 void close_irix_audio() {
  580 
  581     if (irixAudioPort != NULL) {
  582         (void) alClosePort(irixAudioPort);
  583         irixAudioPort = NULL;
  584     }
  585 }
  586 
  587 void write_irix_audio(void *buffer, int bufferSize) {
  588 
  589     int frames = bufferSize / 4;
  590 
  591     while (alGetFillable(irixAudioPort) < frames) {
  592         usleep(100);
  593     }
  594     if (alWriteFrames(irixAudioPort, buffer, frames) < 0) {
  595         g_warning("Error while writing to the audio port\n");
  596     }
  597 }
  598 
  599 #endif
  600 
  601 
  602 /*
  603  * print usage info
  604  */
  605 void usage(gchar *cmd) {
  606 
  607     g_print("Usage: %s [options] filename  (Version: %s)\n", cmd, XCDROAST_VERSION);
  608     g_print("Options:\n");
  609     g_print("   -d audio-device\n");
  610     g_print("   -g : gui-mode\n");
  611     g_print("   -q : quiet-mode\n");
  612 }
  613 
  614 
  615 /*
  616  * main programm
  617  */
  618 gint main(gint argc, gchar **argv) {
  619 gint c;
  620 gchar audio_dev[MAXLINE];
  621 gchar wavname[MAXLINE];
  622 gint fd;
  623 gint l;
  624 gint guimode = 0;
  625 gint quiet = 0;
  626 gint doplay = 1;
  627 gint tick = 0;
  628 gint oldtick = 0;
  629 off_t bytessofar = 0;
  630 off_t totalbytes;
  631 gint min,sec;
  632 gchar keybuffer[MAXLINE];
  633 #if !(defined(linux))
  634  gint audio = -1;
  635  gint ii;
  636  guchar tmpswap;
  637 #endif
  638 #if defined(linux)
  639  snd_pcm_t *playback_handle;
  640  snd_pcm_sframes_t frames, wroteframes;
  641 #endif
  642 
  643     /* if no device given, set default device */
  644     strcpy(audio_dev,DEFAULT_AUDIO_DEVICE);
  645     strcpy(wavname,"");
  646 
  647     while ((c = getopt(argc, argv, "d:gq")) != EOF) 
  648     switch ((gchar)c) {
  649     
  650     case 'd':
  651         strncpy(audio_dev,optarg,MAXLINE);
  652         break;
  653     
  654     case 'g':
  655         guimode = 1;
  656         quiet = 1;
  657         break;
  658     
  659     case 'q':
  660         quiet = 1;
  661         break;
  662     
  663     default:
  664         usage(argv[0]);
  665         exit(1);
  666     }
  667     
  668     /* additional parameter given? */
  669     if (optind > argc -1) {
  670         usage(argv[0]);
  671         exit(1);
  672     } else {
  673         strncpy(wavname,argv[optind++],MAXLINE);
  674     }
  675 
  676     /* the open sets also the global abuf_size-variable */
  677 
  678 #if defined(linux) 
  679     playback_handle = open_alsa_audio(audio_dev);
  680 #endif
  681 #if defined(__FreeBSD__)
  682     audio = open_linux_audio(audio_dev);
  683 #endif
  684 #if defined(sun) || defined(__OpenBSD__)
  685     audio = open_solaris_audio(audio_dev);
  686 #endif
  687 #ifdef aix
  688     audio = open_aix_audio(audio_dev);
  689 #endif
  690 #ifdef hpux
  691     audio = open_hpux_audio(audio_dev);
  692 #endif
  693 #if defined(__sgi)
  694     audio = open_irix_audio(audio_dev);
  695 #endif
  696 
  697 #if defined(linux)
  698     if (playback_handle == NULL) {
  699         g_warning("Can't init sound-system\n");
  700         exit(1); 
  701     }
  702 #endif
  703 #if !(defined(linux))
  704     if (audio < 0) {
  705         g_warning("Can't init sound-system\n");
  706         exit(1); 
  707     }
  708 #endif
  709 
  710     if ((audiobuf = (guchar *)g_new(guchar *,abuf_size)) == NULL) {
  711         g_warning("Unable to allocate audio-buffer\n");
  712         exit(1);
  713     }
  714 
  715     /* open wavfile */
  716     fd = open (wavname, O_RDONLY, 0);
  717 
  718     if (fd == -1) {
  719         g_warning("Can't open wav-file\n");
  720         exit(1);
  721     }
  722 
  723     /* get filesize */
  724     totalbytes = is_std_wav_file(fd, &waveBase) ;
  725 
  726     /* is it a wav-file? */
  727     if (totalbytes == 0) {
  728         g_warning("No valid wavfile, or not in cd-quality\n");
  729         exit(0);
  730     }
  731 
  732     if (!quiet) {
  733         min = (gint) (totalbytes/(CDDAFRAME*75*60));
  734         sec = (gint) ((totalbytes/CDDAFRAME) % (60*75))/75;
  735         g_print("Playing: %s [%d:%02d]\n", wavname,
  736             min,sec);   
  737     }
  738 
  739     if (guimode) {
  740         /* in gui-mode we communicate via stdin and stdout */
  741         /* stdin must be nonblocking */
  742         fcntl(STDIN_FILENO,F_SETFL,O_NONBLOCK);
  743         
  744         /* update display */
  745         g_print("secs%d\n",(gint) (totalbytes/CDDAFRAME)/75);
  746         fflush(stdout);
  747     }
  748 
  749     /* ok..all set now, start playing */
  750     while (1) {
  751 
  752         /* guimode: look for commands from stdin */
  753         if (guimode && (read_line(STDIN_FILENO,keybuffer,MAXLINE) > 0)) {
  754             /* stop command */
  755             if (g_ascii_strncasecmp(keybuffer,"stop",4) == 0) {
  756                 lseek(fd, waveBase, SEEK_SET);
  757 #if defined(linux)
  758                 snd_pcm_drain(playback_handle);
  759 #endif
  760                 bytessofar = 0;
  761                 tick = 0;
  762                 doplay = 0;
  763                 g_print("stop0\n");
  764                 fflush(stdout);
  765             }
  766 
  767             /* play command */
  768             if (g_ascii_strncasecmp(keybuffer,"play",4) == 0) {
  769 #if defined(linux)
  770                 snd_pcm_prepare(playback_handle);
  771 #endif
  772                 doplay = 1;
  773             }   
  774 
  775             /* pause command */
  776             if (g_ascii_strncasecmp(keybuffer,"pause",5) == 0) {
  777                 if (doplay) {
  778                     doplay = 0;
  779                     g_print("%s%d\n","stop",tick);
  780                     fflush(stdout);
  781                 }
  782             }
  783     
  784             /* setxxx command */
  785             if (g_ascii_strncasecmp(keybuffer,"set",3) == 0) {
  786                 tick = atoi(keybuffer+3);
  787                 bytessofar = (off_t)tick *CDDAFRAME*75; 
  788                 lseek(fd, waveBase+bytessofar,
  789                     SEEK_SET);
  790                 g_print("%s%d\n",doplay?"play":"stop",tick);
  791                 fflush(stdout);
  792             }
  793 
  794             /* quit command */
  795             if (g_ascii_strncasecmp(keybuffer,"quit",4) == 0) {
  796                 break;
  797             }
  798         }
  799 
  800         /* we are in play mode right now */
  801         if (doplay) {   
  802 
  803             /* read from wav-file */
  804             /* but only up until we reach totalbytes */
  805             l = totalbytes - bytessofar ;
  806             if (l > abuf_size)
  807                 l = abuf_size ;
  808             if (l < 0)
  809                 l = 0 ;
  810 
  811             if (l > 0)
  812                 l = read(fd, audiobuf, l);
  813             if (l > 0) {
  814 #if !(defined(linux))
  815             /* turn byte order only on non linux platforms */
  816             /* linux on spark won't work with that */
  817                 if (G_BYTE_ORDER == G_BIG_ENDIAN) { 
  818                     /* turn endian-ness */
  819                     for (ii=0; ii<l; ii+=2) {
  820                         tmpswap=audiobuf[ii];
  821                         audiobuf[ii]=audiobuf[ii+1];
  822                         audiobuf[ii+1]=tmpswap;
  823                     }
  824                 }
  825 #endif
  826                 if (guimode) {
  827                     /* at which second are we right now? */
  828                     tick=(gint)(bytessofar/CDDAFRAME/75);
  829                     if (tick != oldtick) {
  830                         g_print("play%d\n",tick);
  831                         fflush(stdout);
  832                         oldtick = tick;
  833                     }
  834                 }
  835 
  836 #if defined(__sgi)
  837                 write_irix_audio(audiobuf, l);
  838 #elif defined(linux)
  839                 frames = (snd_pcm_sframes_t) (l/alsa_frame_size);
  840                 wroteframes = snd_pcm_writei (playback_handle, audiobuf, frames);
  841                 if (wroteframes != frames) {
  842                     g_print("write error to audio-device (wrote %d/%d)\n", (gint)wroteframes, (gint)frames);
  843                     exit(-1);
  844                 }
  845 #else
  846                 if (write(audio, audiobuf, l) != l) {
  847                     g_print("write error to audio-device\n");
  848                     exit(-1);
  849                 }
  850 #endif
  851                 bytessofar+=(off_t)l;
  852 
  853             } else {
  854                 /* read error on wav-file */
  855                 if (l == -1) {
  856                     g_print("read error on wav-file\n");
  857                     exit(-1);
  858                 }
  859                 
  860                 /* EOF reached */
  861                 doplay = 0;
  862                 if (guimode) {
  863                     /* roll back */
  864                     lseek(fd, waveBase, SEEK_SET);
  865                     bytessofar = 0;
  866                     tick = 0;
  867                     g_print("done%d\n",tick);
  868                     fflush(stdout);
  869                 } else { 
  870                     break;
  871                 }
  872             }
  873         } else {
  874             /* we are in pause-mode */
  875             /* wait a short while and then look for commands again */
  876             usleep(100);
  877         }
  878     }
  879 
  880     close(fd);
  881 
  882 #if defined(__sgi)
  883     close_irix_audio();
  884 #elif defined(linux)
  885     snd_pcm_close (playback_handle);
  886 #else
  887     close(audio);
  888 #endif
  889 
  890 #if (defined hpux) && (defined hpux_alib)
  891     ASetCloseDownMode( audioServer, AKeepTransactions, NULL );
  892     ACloseAudio( audioServer, NULL );
  893 #endif
  894 
  895     return 0;
  896 }