Logo Search packages:      
Sourcecode: xcdroast version File versions  Download package

wavplay.c

/*
      wavplay.c
      30.05.99 tn

      simple wavfile-player. plays only 44.1khz,16bit,stereo files.
      gui-mode to fully control all play-functions via external interface 

      works fine on little and big endian machines.

      21.11.01 tn
      MacosX code thx to Shawn Hsiao <phsiao@mac.com> 
*/

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#include "largefile.h"

#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#if defined(linux) || defined(__CYGWIN32__)
# include <getopt.h>
#endif
#include <sys/stat.h>
#if defined(linux) || defined(__FreeBSD__)
# include <sys/soundcard.h>
# include <sys/ioctl.h>
#endif
#if defined(sun) || defined(__OpenBSD__)
# include <sys/ioctl.h>
# include <sys/audioio.h>
#endif
#ifdef aix 
#include <errno.h>
#include <sys/audio.h>
#endif
#ifdef hpux
# ifndef hpux_alib
#  include <sys/audio.h>
# else
#  include <sys/socket.h>
#  include <netdb.h>
#  include <netinet/in.h>
#  include <netinet/tcp.h>
#  include <Alib.h>
# endif
#endif

#include <glib.h>
#include "xcdroast.h"

#if (defined(__MACH__) && defined(__APPLE__))
#include <CoreAudio/CoreAudio.h>
#include <machine/limits.h>
#include <pthread.h>
#endif

#if defined(__sgi)
#include <dmedia/audio.h>
#endif

static off_t waveBase ;
static gint abuf_size;
static guchar *audiobuf;

gint read_line(gint fd, gchar *ptr, gint maxlen);
off_t is_std_wav_file(int f, off_t *offset);


#if defined(linux) || defined(__FreeBSD__)
#define DEFAULT_AUDIO_DEVICE "/dev/dsp"
#elif defined (aix)
#define DEFAULT_AUDIO_DEVICE ""
#elif defined(__sgi)
#define DEFAULT_AUDIO_DEVICE ""
#else
#define DEFAULT_AUDIO_DEVICE "/dev/audio"
#endif

#define DEFAULT_BUFFER_SIZE 22050 

#if (defined(__MACH__) && defined(__APPLE__))

#define BUF_SIZE 4096 

static AudioDeviceID gOutputDeviceID;

static float OutputDataBuf[BUF_SIZE];
static int OutputWroteSamples = 0;

static pthread_mutex_t mutexOutput;
static pthread_cond_t condOutput;

static int audioPlaybackStarted = 0;
static int coreaudio_has_output_device = 0;
static int coreaudio_init = 0;

OSStatus PlaybackIOProc(AudioDeviceID inDevice,
                        const AudioTimeStamp *inNow,
                        const AudioBufferList *inInputData,
                        const AudioTimeStamp *inInputTime,
                        AudioBufferList *outOutputData,
                        const AudioTimeStamp *inOutputTime,
                        void *inClientData)
{
  float *bufPtr = outOutputData->mBuffers[0].mData;
  int i;

  pthread_mutex_lock(&mutexOutput);

  for (i = 0; i < OutputWroteSamples; i++)
    bufPtr[i] = OutputDataBuf[i];
  for ( ; i < BUF_SIZE; i++)
    bufPtr[i] = 0;
  OutputWroteSamples = 0;

  pthread_mutex_unlock(&mutexOutput);
  pthread_cond_signal(&condOutput);

  return (kAudioHardwareNoError);
}


/*
 * This is called to reset the device status.
 * Returns -2 to indicate the device failed to initialize;
 * returns  -1 means any of rate/size/{mono,stereo} mismatched.
 */

gint open_macosx_audio() {
#define LEN_DEVICE_NAME 64
  OSStatus status;
  UInt32 propertySize, bufferByteCount;
  char deviceName[LEN_DEVICE_NAME];
  struct AudioStreamBasicDescription streamDesc;
  int rval;

  /*
   * We only need to do this once, the rest are taken cared by
   * disable/enable calback.
   */
  if (coreaudio_init) {
    return (0);
  }

  /* get default output device */
  propertySize = sizeof(gOutputDeviceID);
  status = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice,
                                    &propertySize,
                                    &gOutputDeviceID);
  if (status) {
    fprintf(stderr, "get default output device failed, status = %d\n",
            (int)status);
    return (-2);
  }

  if (gOutputDeviceID != kAudioDeviceUnknown) {
    /* got default output device */
    coreaudio_has_output_device = 1;

    /* get output device name */
    propertySize = sizeof(char)*LEN_DEVICE_NAME;
    status = AudioDeviceGetProperty(gOutputDeviceID,
                                    1,
                                    0,
                                    kAudioDevicePropertyDeviceName,
                                    &propertySize,
                                    deviceName);

    if (status) {
      fprintf(stderr, "get device name failed, status = %d\n",
              (int)status);
      return (-2);
    }

    /* get output format */
    propertySize = sizeof(struct AudioStreamBasicDescription);
    status = AudioDeviceGetProperty(gOutputDeviceID,
                                    1,
                                    0,
                                    kAudioDevicePropertyStreamFormat,
                                    &propertySize,
                                    &streamDesc);
    if (status) {
      fprintf(stderr, "get device property failed, status = %d\n",
              (int)status);
      return (-2);
    }

    if ((streamDesc.mSampleRate != 44100.0) ||
        (streamDesc.mFormatID != kAudioFormatLinearPCM) ||
       !(streamDesc.mFormatFlags & kLinearPCMFormatFlagIsFloat) ||
        (streamDesc.mChannelsPerFrame != 2))
    {
      fprintf (stderr, "unsupported device.\n");
      return (-2);
    }

    /* set buffer size */
    bufferByteCount = BUF_SIZE * sizeof(float);
    propertySize = sizeof(bufferByteCount);
    status = AudioDeviceSetProperty(gOutputDeviceID,
                                    0,
                                    0,
                                    0,
                                    kAudioDevicePropertyBufferSize,
                                    propertySize,
                                    &bufferByteCount);
    if (status) {
      fprintf(stderr, "set device property failed, status = %d\n",
              (int)status);
    }

/*
    fprintf(stderr, "using device %s for output:\n", deviceName);
    fprintf(stderr, "\twith sample rate %f, %ld channels and %ld-bit sample\n",
            streamDesc.mSampleRate,
            streamDesc.mChannelsPerFrame,
            streamDesc.mBitsPerChannel);
*/

    rval = pthread_mutex_init(&mutexOutput, NULL);
    if (rval) {
      fprintf(stderr, "mutex init failed\n");
      return (-1);
    }
    rval = pthread_cond_init(&condOutput, NULL);
    if (rval) {
      fprintf(stderr, "condition init failed\n");
      return (-1);
    }

    /* Registers PlaybackIOProc with the device without activating it. */
    status = AudioDeviceAddIOProc(gOutputDeviceID, PlaybackIOProc, (void *)1);
  }

  if (!coreaudio_has_output_device) {
    fprintf(stderr, "unknown output device.\n");
    return (-2);
  }

  /* Indicates the initialization is done */
  coreaudio_init = 1;

  abuf_size = DEFAULT_BUFFER_SIZE;
 
  return 0;
}

void audio_close()
{
  OSStatus status;

  if (coreaudio_has_output_device && audioPlaybackStarted) {
    status = AudioDeviceStop(gOutputDeviceID, PlaybackIOProc);
    audioPlaybackStarted = 0;
  }
  return;
}

int audio_write( void *buffer, int buf_size )
{
  OSStatus status;
  float scale = 1.0 / SHRT_MAX;
  int remain_to_write = buf_size;

  if (!coreaudio_has_output_device)
    return -1;

  if (!audioPlaybackStarted) {
    status = AudioDeviceStart(gOutputDeviceID, PlaybackIOProc);
    audioPlaybackStarted = 1;
  }

  while (remain_to_write)
  {
    pthread_mutex_lock(&mutexOutput);

    while(OutputWroteSamples == BUF_SIZE)
      pthread_cond_wait(&condOutput, &mutexOutput);

    {
      short *src_data = (short *)buffer + (buf_size - remain_to_write) / sizeof(short);
      float *dst_data = OutputDataBuf + OutputWroteSamples;
      int src_samples = remain_to_write / sizeof(short);
      int dst_samples = BUF_SIZE - OutputWroteSamples;
      int n = (dst_samples < src_samples) ? dst_samples : src_samples;
      int i;

      for (i = 0; i < n; i++)
        dst_data[i] = scale * src_data[i];

      OutputWroteSamples += n;
      remain_to_write -= n * sizeof(short);
    }

    pthread_mutex_unlock(&mutexOutput);
  }

  return (buf_size);
}


#endif


#if defined(linux) || defined(__FreeBSD__)

/* open the sound-device of linux and set cd-quality */

gint open_linux_audio(gchar *dev) {
gint audio;
gint tmp;
gint samplesize = 16;
gint dsp_stereo = 1;
gint dsp_speed = 44100;
gint flags;

      /* First try open with O_NONBLOCK so it doesn't hang */
      audio = open (dev, (O_WRONLY | O_NONBLOCK),0);
      if (audio == -1) {
            /* error opening sound device */
            return -1;
      }

      /* now undo NONBLOCK setting again */
      flags = fcntl(audio,F_GETFL);
      fcntl(audio,F_SETFL,flags & ~O_NONBLOCK);

      tmp = samplesize; 
      ioctl(audio, SNDCTL_DSP_SAMPLESIZE, &samplesize);     
      if (tmp != samplesize) {
            /* error setting samplesize */
            g_warning("Unable to set samplesize to 16 bit\n");
            return -1;
      }

      if (ioctl (audio, SNDCTL_DSP_STEREO, &dsp_stereo)==-1) {
            g_warning("Unable to set audio to stereo\n");
            return -1;
      }
      
      if (ioctl (audio, SNDCTL_DSP_SPEED, &dsp_speed) == -1) {
            g_warning("Unable to set audio to 44.1 kHz\n");
            return -1;
      }

      if (ioctl (audio, SNDCTL_DSP_GETBLKSIZE, &abuf_size) == -1) {
            g_warning("Unable to get blocksize for audio-device\n");
            return -1;
      }

      return audio;
}

#endif

#if defined(sun) || defined(__OpenBSD__)

/* open the sound-device of solaris and set cd-quality */

gint open_solaris_audio(gchar *dev) {
gint audio;
audio_info_t info;
gint flags;

      /* First try open with O_NONBLOCK so it doesn't hang */
      if ((audio = open(dev, (O_WRONLY | O_NONBLOCK))) == -1) {
            /* error opening sound device */
            return -1;
      }

      /* now undo NONBLOCK setting again */
      flags = fcntl(audio,F_GETFL);
      fcntl(audio,F_SETFL,flags & ~O_NONBLOCK);

      abuf_size = DEFAULT_BUFFER_SIZE;

      AUDIO_INITINFO(&info);
      info.play.sample_rate = 44100;
      info.play.channels = 2;
      info.play.precision = 16;
      info.play.encoding = AUDIO_ENCODING_LINEAR;
      info.play.buffer_size = abuf_size;
#ifndef __OpenBSD__
      info.output_muted = 0;
#endif

      if (ioctl(audio, AUDIO_SETINFO, &info) == -1) {
            g_warning("Unable to set audio parameters\n");
            return -1;
      }     

      return audio;
}

#endif

#ifdef aix
/* open the audio device of an IBM RS/6000 with AIX Ultimedia Services
   and set cd-quality */

gint open_aix_audio(gchar *dev) {
audio_init ainfo;
audio_control  acontrol;
audio_change   achange;
gint audio;

        if (strlen (dev) == 0) {
                if(getenv("AUDIODEV")) {
                        strcpy (dev, getenv("AUDIODEV"));
                        audio = open (dev, O_WRONLY);
                } else {
                       /* Try to use the device of a machine with PCI bus */
                        strcpy (dev, "/dev/paud0/1");
                        audio = open (dev, O_WRONLY);
                        if ((audio == -1) & (errno == ENOENT)) {
                               /* Try the device of a machine with MCA    */
                                /* bus as last default                     */
                                strcpy (dev, "/dev/baud0/1");
                                audio = open (dev, O_WRONLY);
                       }
              }
       } else {
               /* Try the device given in the commandline */
                audio = open (dev, O_WRONLY);
       }

       if(dev < 0) {
               /* error opening audio device */
               return -1;
       }

        /* Initialize the default audio description  */
       /* (the size of the buffer is given in msec) */
        memset (&ainfo, '\0', sizeof (audio_init));
        ainfo.srate            = 44100;
        ainfo.channels         = 2;
        ainfo.mode             = PCM;
        ainfo.bits_per_sample  = 16;
        ainfo.flags            = BIG_ENDIAN | TWOS_COMPLEMENT;
        ainfo.operation        = PLAY;
        ainfo.bsize            = 8 * 1000 *DEFAULT_BUFFER_SIZE 
               / (ainfo.srate * ainfo.channels * ainfo.bits_per_sample);
 
        if (ioctl (audio, AUDIO_INIT, &ainfo) == -1) {
               g_warning("Unable to set default audio parameters\n");
               return -1;
       }

       memset ( & acontrol, '\0', sizeof (acontrol));
  
       /* Tell the audio device to start output     */
       acontrol.ioctl_request   = AUDIO_START;
       acontrol.request_info    = NULL;
       acontrol.position        = 0;

       if (ioctl (audio, AUDIO_CONTROL, & acontrol) == -1) {
               g_warning("Unable to start audio operation\n");
               return -1;
       }
       abuf_size = DEFAULT_BUFFER_SIZE;

       memset ( & achange, '\0', sizeof (achange));
       memset ( & acontrol, '\0', sizeof (acontrol));
       
        /* set the output to line out + internal speaker          */
       /* else the output device will be set to the predifined   */
       /* value in the cde environment.                          */
       achange.balance        = AUDIO_IGNORE;
       achange.balance_delay  = AUDIO_IGNORE;
       achange.volume         = AUDIO_IGNORE;
       achange.volume_delay   = AUDIO_IGNORE;
       achange.input          = AUDIO_IGNORE;
       achange.output         = EXTERNAL_SPEAKER;
       /* achange.output         = INTERNAL_SPEAKER */
       /* achange.output         = OUTPUT_1         */
       achange.treble         = AUDIO_IGNORE;
       achange.bass           = AUDIO_IGNORE;
       achange.pitch          = AUDIO_IGNORE;
       achange.monitor        = AUDIO_IGNORE;
       achange.dev_info       = (char *) NULL;
       acontrol.ioctl_request = AUDIO_CHANGE;
       acontrol.position      = 0;
       acontrol.request_info  = (char *) & achange;

/*     if ((mix = open(setupdata.mix_device, O_RDWR)) == -1) {
                g_warning("Can't open mixer-device %s\n", setupdata.mix_device);
                return -1;
               }*/
       if (ioctl (audio, AUDIO_CONTROL, & acontrol) == -1) {
               g_warning("Error writing mixer\n");
               return -1;
       }


       return audio;
}
#endif


#ifdef hpux
# ifndef hpux_alib

/* open the audio device on a HP9000 with HP-UX and set cd-quality */

gint open_hpux_audio(gchar *dev) {
gint audio;

      audio = open (dev, O_WRONLY | O_NONBLOCK);
      if (audio == -1) {
            /* error opening audio device */
            return -1;
      }

      if (ioctl(audio, AUDIO_SET_DATA_FORMAT, 
            AUDIO_FORMAT_LINEAR16BIT) == -1) {
            g_warning("Unable to set samplesize to 16 bit\n");
            return -1;
      }

      if (ioctl (audio, AUDIO_SET_CHANNELS, 2)==-1) {
            g_warning("Unable to set audio to stereo\n");
            return -1;
      }

      if (ioctl (audio, AUDIO_SET_SAMPLE_RATE, 44100) == -1) {
            g_warning("Unable to set audio to 44.1 kHz\n");
            return -1;
      }

      abuf_size = DEFAULT_BUFFER_SIZE;

      return audio;
}
# else

/* Some global variables for the hp-ux audio lib       */
/* Code mostly taken from simpleAudio.c sample of hpux */
static Audio *audioServer = (Audio *) NULL;
static struct protoent *tcpProtocolEntry;

gint open_hpux_audio(gchar *dev) {
int            streamSocket;
long            status;
SSPlayParams    playParams;
AGainEntry      gainEntry[4];
AudioAttrMask   AttribsMask;
AudioAttributes Attribs;
SStream         audioStream;
int             i;
ATransID        xid;

/* a_name specifies the audio controller name as a string.  */
/* We specify NULL, so the value of the AUDIO environment   */
/* variable is used.                                        */
char a_name = '\0';

        /* open audio connection */ 
        audioServer = AOpenAudio(&a_name, NULL);
        if (audioServer == NULL) {
            /* error opening audio device */
            g_warning("Unable to open audio device\n");
            return -1;
      }
      tcpProtocolEntry=getprotobyname("tcp");

      streamSocket = socket (AF_INET, SOCK_STREAM, 0);
      if( streamSocket < 0 ) {
            g_warning("Unable to request audio socket stream\n");
            return -1;
      }
      /* Set the default audio description */
      Attribs.type = ATSampled;
      Attribs.attr.sampled_attr.sampling_rate = 44100;
      Attribs.attr.sampled_attr.channels = 2;
      Attribs.attr.sampled_attr.data_format = ADFLin16;
      AttribsMask = ASSamplingRateMask | ASChannelsMask  | ASDataFormatMask;
      /* Use the transmit gain and the output channel defined */
      /* by the SPEAKER environment                           */
      gainEntry[0].u.o.out_ch = AOCTMono;
      gainEntry[0].gain = AUnityGain;
      gainEntry[0].u.o.out_dst = AODTDefaultOutput;
      playParams.gain_matrix.type = AGMTOutput;
      playParams.gain_matrix.num_entries = 1;
      playParams.gain_matrix.gain_entries = gainEntry;
      playParams.play_volume = AUnityGain;
      playParams.priority = APriorityNormal;
      playParams.event_mask = 0;

      /* Create an audio stream */
      xid = APlaySStream( audioServer, AttribsMask, &Attribs, 
                      &playParams, &audioStream, NULL);

      /* Connect the stream socket to the audio stream port */
      status = connect( streamSocket, (struct sockaddr *)&audioStream.tcp_sockaddr,
                    sizeof(struct sockaddr_in));
      if (status < 0) {
        printf ("Errno: %d\n", errno);
            g_warning ("Connection of an audio stream socket failed\n");
      /*    close (streamSocket);*/
            return -1;
      }

      /* Tell TCP to not delay sending data written to this socket */
      i = -1;
      setsockopt( streamSocket, tcpProtocolEntry->p_proto, TCP_NODELAY,
                &i, sizeof(i) );

      abuf_size = DEFAULT_BUFFER_SIZE;
      return (streamSocket);
}

# endif
#endif


#if defined(__sgi)

static ALport  irixAudioPort = NULL;   /* Our interface to SGI audio device */
static int     irixAudioRate = 44100;  /* The samples rate */

gint open_irix_audio(gchar *devName) {

      ALvalue           v [1];
      ALpv        pv [2], q [1];
      ALconfig    audioConfig;
      int         dev;

      if (irixAudioPort != NULL)      /* The device is already open. */
            return 0;

      /* Find the selected audio device */
      if (devName[0] == '\0') {
            dev = AL_DEFAULT_OUTPUT;
      }
      else {
            q[0].param = AL_LABEL;
            q[0].value.ptr = devName;
            q[0].sizeIn = strlen(devName) + 1;
            if (alQueryValues(AL_SYSTEM, AL_DEVICES, v, 1, q, 1) <= 0) {
                  g_warning("Invalid audio port name\n");
                  return -1;
            }
            dev = v[0].i;
      }

      /* Allocate a config structure */
      audioConfig = alNewConfig();

      /* Set the audio device */
      if (alSetDevice(audioConfig, dev) < 0) {
            g_warning("Unable to set the audio device\n");
            return -1;
      }

      /* Set the buffer size to contain 1/2 second of samples */
      abuf_size = irixAudioRate;
      if (alSetQueueSize(audioConfig, abuf_size / 2) < 0) {
            g_warning("Unable to set queue size\n");
            return -1;
      }

      /* Set the samples width */
      if (alSetWidth(audioConfig, AL_SAMPLE_16) < 0) {
            g_warning("Unable to set sample size to 16 bit\n");
            return -1;
      }

      /* Set the number of channels */
      if (alSetChannels(audioConfig, AL_STEREO) < 0) {
            g_warning("Unable to set audio to stereo\n");
            return -1;
      }

      /* Open the audio port */
      if ((irixAudioPort = alOpenPort("wavplay", "w", audioConfig) ) == NULL) {
            g_warning("Unable to open audio port\n");
            return -1;
      }

      /* Set the samples rate */
      pv[0].param = AL_RATE;
      pv[0].value.ll = alDoubleToFixed((double) irixAudioRate);
      if (alSetParams(dev, pv, 1) < 0 ) {
            g_warning("Unable to set audio to 44.1 kHz\n");
            return -1;
      }

      return 0;
}

void close_irix_audio() {

      if (irixAudioPort != NULL) {
            (void) alClosePort(irixAudioPort);
            irixAudioPort = NULL;
      }
}

void write_irix_audio(void *buffer, int bufferSize) {

      int   frames = bufferSize / 4;

      while (alGetFillable(irixAudioPort) < frames) {
            usleep(100);
      }
      if (alWriteFrames(irixAudioPort, buffer, frames) < 0) {
            g_warning("Error while writing to the audio port\n");
      }
}

#endif


/* print usage info */

void usage(gchar *cmd) {

      g_print("Usage: %s [options] filename  (Version: %s)\n", cmd, XCDROAST_VERSION);
      g_print("Options:\n");
      g_print("   -d audio-device\n");
      g_print("   -g : gui-mode\n");
      g_print("   -q : quiet-mode\n");
}


/* main programm */

gint main(gint argc, gchar **argv) {
gint c;
gchar audio_dev[MAXLINE];
gchar wavname[MAXLINE];
gint audio = -1;
gint fd;
gint l;
gint guimode = 0;
gint quiet = 0;
gint doplay = 1;
gint tick = 0;
gint oldtick = 0;
off_t bytessofar = 0;
off_t totalbytes;
gint min,sec;
gchar keybuffer[MAXLINE];
#if !(defined(linux))
 gint ii;
 guchar tmpswap;
#endif
      /* if no device given, set default device */
      strcpy(audio_dev,DEFAULT_AUDIO_DEVICE);
      strcpy(wavname,"");

      while ((c = getopt(argc, argv, "d:gq")) != EOF) 
      switch ((gchar)c) {
      
      case 'd':
            strncpy(audio_dev,optarg,MAXLINE);
            break;
      
      case 'g':
            guimode = 1;
            quiet = 1;
            break;
      
      case 'q':
            quiet = 1;
            break;
      
      default:
            usage(argv[0]);
            exit(1);
      }
      
      /* additional parameter given? */
      if (optind > argc -1) {
            usage(argv[0]);
            exit(1);
      } else {
            strncpy(wavname,argv[optind++],MAXLINE);
      }

      /* the open sets also the global abuf_size-variable */

#if defined(linux) || defined(__FreeBSD__)
      audio = open_linux_audio(audio_dev);
#endif
#if defined(sun) || defined(__OpenBSD__)
      audio = open_solaris_audio(audio_dev);
#endif
#ifdef aix
      audio = open_aix_audio(audio_dev);
#endif
#ifdef hpux
      audio = open_hpux_audio(audio_dev);
#endif
#if (defined(__MACH__) && defined(__APPLE__))
      audio = open_macosx_audio();
#endif
#if defined(__sgi)
      audio = open_irix_audio(audio_dev);
#endif

      if (audio < 0) {
            g_warning("Can't init sound-system\n");
            exit(1); 
      }

      if ((audiobuf = (guchar *)g_new(guchar *,abuf_size)) == NULL) {
            g_warning("Unable to allocate audio-buffer\n");
            exit(1);
      }

      /* open wavfile */
      fd = open (wavname, O_RDONLY, 0);

      if (fd == -1) {
#if !(defined(__MACH__) && defined(__APPLE__))
            close(audio);
#endif
            g_warning("Can't open wav-file\n");
            exit(1);
      }

      /* get filesize */
      totalbytes = is_std_wav_file(fd, &waveBase) ;

      /* is it a wav-file? */
      if (totalbytes == 0) {
            g_warning("No valid wavfile, or not in cd-quality\n");
            exit(0);
      }

      if (!quiet) {
            min = (gint) (totalbytes/(CDDAFRAME*75*60));
            sec = (gint) ((totalbytes/CDDAFRAME) % (60*75))/75;
            g_print("Playing: %s [%d:%02d]\n", wavname,
                  min,sec);   
      }

      if (guimode) {
            /* in gui-mode we communicate via stdin and stdout */
            /* stdin must be nonblocking */
            fcntl(STDIN_FILENO,F_SETFL,O_NONBLOCK);
            
            /* update display */
            g_print("secs%d\n",(gint) (totalbytes/CDDAFRAME)/75);
            fflush(stdout);
      }

      /* ok..all set now, start playing */
      while (1) {

            /* guimode: look for commands from stdin */
            if (guimode && (read_line(STDIN_FILENO,keybuffer,MAXLINE) > 0)) {
                  /* stop command */
                  if (g_strncasecmp(keybuffer,"stop",4) == 0) {
                        lseek(fd, waveBase, SEEK_SET);
                        bytessofar = 0;
                        tick = 0;
                        doplay = 0;
                        g_print("stop0\n");
                        fflush(stdout);
                  }

                  /* play command */
                  if (g_strncasecmp(keybuffer,"play",4) == 0) {
                        doplay = 1;
                  }     

                  /* pause command */
                  if (g_strncasecmp(keybuffer,"pause",5) == 0) {
                        doplay=1-doplay;
                        g_print("%s%d\n",doplay?"play":"stop",tick);
                        fflush(stdout);
                  }
      
                  /* setxxx command */
                  if (g_strncasecmp(keybuffer,"set",3) == 0) {
                        tick = atoi(keybuffer+3);
                        bytessofar = (off_t)tick *CDDAFRAME*75; 
                        lseek(fd, waveBase+bytessofar,
                              SEEK_SET);
                        g_print("%s%d\n",doplay?"play":"stop",tick);
                        fflush(stdout);
                  }

                  /* quit command */
                  if (g_strncasecmp(keybuffer,"quit",4) == 0) {
                        break;
                  }
            }

            /* we are in play mode right now */
            if (doplay) {     

                  /* read from wav-file */
                  /* but only up until we reach totalbytes */
                  l = totalbytes - bytessofar ;
                  if (l > abuf_size)
                        l = abuf_size ;
                  if (l < 0)
                        l = 0 ;

                  if (l > 0)
                        l = read(fd, audiobuf, l);
                  if (l > 0) {
#if !(defined(linux))
                  /* turn byte order only on non linux platforms */
                  /* linux on spark wont work with that */
                        if (G_BYTE_ORDER == G_BIG_ENDIAN) { 
                              /* turn endian-ness */
                              for (ii=0; ii<l; ii+=2) {
                                    tmpswap=audiobuf[ii];
                                    audiobuf[ii]=audiobuf[ii+1];
                                    audiobuf[ii+1]=tmpswap;
                              }
                        }
#endif
                        if (guimode) {
                              /* at which second are we right now? */
                              tick=(gint)(bytessofar/CDDAFRAME/75);
                              if (tick != oldtick) {
                                    g_print("play%d\n",tick);
                                    fflush(stdout);
                                    oldtick = tick;
                              }
                        }

#if (defined(__MACH__) && defined(__APPLE__))
                        audio_write(audiobuf,l);
#elif defined(__sgi)
                        write_irix_audio(audiobuf, l);
#else
                        if (write(audio, audiobuf, l) != l) {
                              g_print("write error to audio-device\n");
                              exit(-1);
                        }
#endif
                        bytessofar+=(off_t)l;

                  } else {
                        /* read error on wav-file */
                        if (l == -1) {
                              g_print("read error on wav-file\n");
                              exit(-1);
                        }
                        
                        /* EOF reached */
                        doplay = 0;
                        if (guimode) {
                              /* roll back */
                              lseek(fd, waveBase, SEEK_SET);
                              bytessofar = 0;
                              tick = 0;
                              g_print("done%d\n",tick);
                              fflush(stdout);
                        } else { 
                              break;
                        }
                  }
            } else {
                  /* we are in pause-mode */
                  /* wait a short while and then look for commands again */
                  usleep(100);
            }
      }

      close(fd);

#if (defined(__MACH__) && defined(__APPLE__))
      audio_close();
#elif defined(__sgi)
      close_irix_audio();
#else
      close(audio);
#endif

#if (defined hpux) && (defined hpux_alib)
      ASetCloseDownMode( audioServer, AKeepTransactions, NULL );
      ACloseAudio( audioServer, NULL );
#endif

      return 0;
}

Generated by  Doxygen 1.6.0   Back to index