Ejemplo n.º 1
0
static sqInt sound_AvailableSpace(void)
{
  PRINTF();
  struct audio_info info;
  int avail;

  if (auFd < 0) return 0;

  if (ioctl(auFd, AUDIO_GETINFO, &info))
    {
      perror("AUDIO_GETINFO");
      sound_Stop();
    }

  avail= auBufBytes * (info.play.eof - auBuffersPlayed + 2);
  PRINTF(("auBufBytes=%d, info.play.eof=%d, auBuffersPlayed=%d, avail=%d",
		auBufBytes, info.play.eof, auBuffersPlayed, avail));

  return avail;
}
Ejemplo n.º 2
0
// start up sound output.
// 
static sqInt sound_Start(sqInt frameCount, sqInt samplesPerSec, sqInt stereo, sqInt semaIndex)
{
  Stream *s= 0;

  debugf("snd_Start frames: %d samplesPerSec: %d stereo: %d semaIndex: %d\n",
	   frameCount, samplesPerSec, stereo, semaIndex);
  
  if (output)	// there might be a change of sample rate
    sound_Stop();

  if ((s= Stream_new(0)))	// 0utput
    {
      if ((  Stream_setFormat(s, frameCount, samplesPerSec, stereo))
	  && Stream_startSema(s, semaIndex))
	{
	  output= s;
	  return 1;
	}
      Stream_delete(s);
    }
  return primitiveFail();
}
static int sound_StopRecording(void) 
{
     return sound_Stop();
}
/* StartRecording: open the device for recording.

   XXX this routine is almost identical to snd_Start().  The two should
   be factored into a single function!
*/
static int sound_StartRecording(int desiredSamplesPerSec, int stereo0, int semaIndex0)
{
  AuElement elements[2];  /* elements for the NAS flow to assemble:
   			        element 0 = physical input
			        element 1 = client export */
  AuDeviceID device;      /* physical device ID to use */
  
  DPRINTF("StartRecording\n");
  
  sound_Stop();

  DPRINTF("opening server\n");
  server = AuOpenServer(NULL, 0, NULL, 0, NULL, NULL);
  if(server == NULL) {
    DPRINTF("failed to open audio server\n");
    return false;
  }

  /* XXX check protocol version of the server */

  semaIndex= semaIndex0;
  stereo= stereo0;
  sampleRate= desiredSamplesPerSec;

  device= choose_nas_device(server, desiredSamplesPerSec, stereo, 1);
  if(device == AuNone) {
    DPRINTF("no available device on the server!\n");
    AuCloseServer(server);
    server = NULL;
    return false;
  }

  /* record format info */
  fmtBytes=2;
  fmtSigned=1;
  fmtStereo=stereo;
  fmtIsBigendian=0;
  recording=1;


  

  /* create a flow to read from */
  DPRINTF("creating flow\n");
  flow = AuCreateFlow(server, NULL);


  /* create client and device elements to record with */
  DPRINTF("creating elements\n");

  
  AuMakeElementImportDevice(&elements[0],
			    desiredSamplesPerSec,  /* XXX should use the actual sampling rate of device */
			    device,
			    AuUnlimitedSamples,
			    0, NULL);

  AuMakeElementExportClient(&elements[1],
			    0,
			    desiredSamplesPerSec,
			    AuFormatLinearSigned16LSB,  /* XXX this should be chosen based on the platform */
			    stereo ? 2 : 1,
			    AuTrue,
			    1000000,  /* was AuUnlimitedSamples */
			    1000, /* water mark: go ahead and send frequently! */
			    0, NULL);
	


  /* set up the flow with these elements */
  AuSetElements(server,	flow,
		AuTrue,
		2, elements,
		NULL);

  /* start her up */
  DPRINTF("starting flow\n");
  AuStartFlow(server, flow, NULL);
  AuFlush(server);
  

  /* initialize the space indication */
  bytesAvail = 0;

  
  /* arrange to be informed when events come in from the server */
  aioEnable(AuServerConnectionNumber(server), NULL, AIO_EXT);
  aioHandle(AuServerConnectionNumber(server), handleAudioEvents, AIO_W);

  return true;
}
/* Process audio events from the NAS server.  The same routine is used
   whether we are recording or playing back */
static void handleAudioEvents(int fd, void *data, int flags)
{
  if(!server) {
    DPRINTF( "handleAudioEvents called while unconnected!\n");
    return;
  }

  /* read events once */
  AuEventsQueued(server, AuEventsQueuedAfterReading);

  /* then loop through the read queue */
  while(AuEventsQueued(server, AuEventsQueuedAlready)) {
    AuEvent event;
    AuNextEvent(server, AuTrue, &event);
    DPRINTF("event of type %d\n", event.type);
    
    switch(event.type) {
    case 0:
      {
	AuErrorEvent *errEvent = (AuErrorEvent *) &event;
	char errdesc[1000];
      
	AuGetErrorText(server, errEvent->error_code, errdesc, sizeof(errdesc));
	fprintf(stderr, "audio error: %s\n", errdesc);
	sound_Stop();
	return;  /* return, not break, so that we don't
		    process the now-closed server any longer! */
      }
    

    case AuEventTypeElementNotify:
      {
	AuElementNotifyEvent *enEvent = (AuElementNotifyEvent *)&event;

	switch(enEvent->kind) {
	case AuElementNotifyKindLowWater:
	  DPRINTF("low water event\n");
	  bytesAvail += enEvent->num_bytes;
	  break;
	case AuElementNotifyKindHighWater:
	  DPRINTF("high water event\n");
	  bytesAvail += enEvent->num_bytes;
	  break;
	case AuElementNotifyKindState:
	  DPRINTF("state change (%d->%d)\n",
		  enEvent->prev_state,
		  enEvent->cur_state);
	  bytesAvail += enEvent->num_bytes;
	  if(enEvent->cur_state == AuStatePause) {
	       /* if the flow has stopped, then arrange for it to get started again */
	       /* XXX there is probably a more intelligent place to do
                  this, in case there is a real reason it has paused */
	       DPRINTF("unpausing\n");
	       AuStartFlow(server, flow, NULL);
	       AuFlush(server);
	  }

	  break;
	}
      }
    }
  }

  if(bytesAvail > 0) {
    DPRINTF("bytesAvail: %d\n", bytesAvail);
    signalSemaphoreWithIndex(semaIndex);
  }

  aioHandle(fd, handleAudioEvents, flags & AIO_RW);
}
Ejemplo n.º 6
0
static sqInt sound_Start(sqInt frameCount, sqInt samplesPerSec, sqInt stereo, sqInt semaIndex)
{
  PRINTF(("(frameCount=%d, samplesPerSec=%d, stereo=%d, semaIndex=%d)",
		frameCount, samplesPerSec, stereo, semaIndex));
  int bytesPerFrame= (stereo ? 4 : 2);
  struct audio_info info;
  int err;

  if (auFd != -1) sound_Stop();
  auPlaySemaIndex= semaIndex;
  fmtStereo= stereo;
  auBufBytes= bytesPerFrame * frameCount;

  if ((auFd= open("/dev/audio", O_WRONLY|O_NONBLOCK)) == -1)
    {
      perror("/dev/audio");
      return false;
    }
  PRINTF(("auFd=%d", auFd));

  if ((auCtlFd= open("/dev/audioctl", O_WRONLY|O_NONBLOCK)) == -1)
    {
      perror("/dev/audioctl");
      return false;
    }
  PRINTF(("auCtlFd=%d", auCtlFd));

  /* set up device */
  if (ioctl(auFd, AUDIO_GETINFO, &info))
    {
      perror("AUDIO_GETINFO");
      goto closeAndFail;
    }
  info.play.gain= 255;
  info.play.precision= 16;
  info.play.encoding= AUDIO_ENCODING_LINEAR;
  info.play.channels= fmtStereo ? 2 : 1;
  info.play.sample_rate= samplesPerSec;

  auBuffersPlayed= info.play.eof;

  while ((err= ioctl(auFd, AUDIO_SETINFO, &info)) && errno == EINTR)
    ;
  if (err)
    {
      perror("AUDIO_SETINFO");
      goto closeAndFail;
    }

  action.sa_handler= auHandle;
  sigemptyset(&action.sa_mask);
  action.sa_flags= 0;
  action.sa_flags|= SA_RESTART;

  if (sigaction(SIGIO, &action, &oldAction) < 0) /* On Solaris, SIGIO == SIGPOLL */
    {
      perror("sigaction(SIGIO, auHandle)");
    }
  if (ioctl(auCtlFd, I_SETSIG, S_MSG))	/* send SIGIO whenever EOF arrives */
    {
      perror("ioctl(auFd, I_SETSIG, S_MSG)");
    }

  return true;

closeAndFail:
  close(auFd);    auFd= -1;
  close(auCtlFd); auCtlFd= -1;
  return false;
}