示例#1
0
/*
    plays 'len' bytes of 'data'
    returns: number of bytes played
*/
static int play(void* data, int len, int flags)
{
    int got_len;

    if (!len)
	return 0;

    if ((got_len = snd_pcm_write(alsa_handler, data, len)) < 0)
    {
	if (got_len == -EPIPE) /* underrun? */
	{
	    mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ALSA5_Underrun);
	    if ((got_len = snd_pcm_channel_prepare(alsa_handler, SND_PCM_CHANNEL_PLAYBACK)) < 0)
	    {
		mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ALSA5_PlaybackPrepareError, snd_strerror(got_len));
		return 0;
	    }
	    if ((got_len = snd_pcm_write(alsa_handler, data, len)) < 0)
	    {
		mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ALSA5_WriteErrorAfterReset,
		    snd_strerror(got_len));
		return 0;
	    }
	    return got_len; /* 2nd write was ok */
	}
	mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ALSA5_OutPutError, snd_strerror(got_len));
	return 0;
    }
    return got_len;
}
static void
alsa_poll_ready_playing (gpointer data,
			gint source,
			GdkInputCondition condition)
{
    alsa_driver * const d = data;
    int byte_count = (d->stereo + 1) * (d->bits / 8) * d->fragsize;
    int w;
    struct timeval tv;

    w = snd_pcm_write(d->soundfd, d->sndbuf, byte_count);
    if(w != byte_count) {
      if(w < 0) {
	fprintf(stderr, "driver_alsa2: write() returned -1.\n--- \"%s\"", snd_strerror(w));
      } else {
	fprintf(stderr, "driver_alsa2: write not completely done.\n");
      }
    }
    
    gettimeofday(&tv, NULL);
    d->outtime = tv.tv_sec + tv.tv_usec / 1e6;
    d->playtime += (double) d->fragsize / d->playrate;

    audio_mix(d->sndbuf, d->fragsize, d->playrate, d->mf);
}
示例#3
0
static int audio_write(audiodevice_t *dev, unsigned char *buf, int cnt) {
	audio_alsa05_t *alsa = (audio_alsa05_t *)dev->data_pcm;
	snd_pcm_channel_status_t st;
	int ret;
	
	if (alsa->pcm_handle == NULL) return NG;
	
	if (cnt == 0) return 0;
	
	if (cnt < dev->buf.len) {
		memset(buf + cnt, alsa->silence, dev->buf.len - cnt);
	}
	
	memset(&st, 0, sizeof(st));
	if (0 > (ret = snd_pcm_channel_status(alsa->pcm_handle, &st))) {
		WARNING("cannot get status %s\n", snd_strerror(ret));
		return 0;
	}
	
	if (st.status != SND_PCM_STATUS_RUNNING &&
	    st.status != SND_PCM_STATUS_PREPARED) {
		snd_pcm_channel_prepare(alsa->pcm_handle, SND_PCM_CHANNEL_PLAYBACK);
	}
	
	ret = snd_pcm_write(alsa->pcm_handle, buf, dev->buf.len);
	if (ret < 0) {
		WARNING("write %s\n", snd_strerror(ret));
	}
	
	return dev->buf.len;
}
示例#4
0
int audio_play_samples(struct audio_info_struct *ai,unsigned char *buf,int len)
{
	ssize_t ret;

	ret=snd_pcm_write(ai->handle, buf, len);

	return ret;
}
示例#5
0
int pal_pcm_play(void)
{
	FRESULT f_sta;
	FIL fp;
	FATFS fs;

	int ret = 0;
	uint32_t read_len = 0;

	f_sta = f_mount(&fs, MMC_DISK_TAG, 1);
	if(f_sta != FR_OK) {
		LOG("fail to mount\n");
		return -1;
	}

	ret = snd_pcm_open(&pal_pcm_cfg, SOUND_CARD_ID, PCM_OUT);
	if (ret != 0) {
		LOG("pcm open error\n");
		return -1;
	}

	//aud_mgr_handler(AUDIO_DEVICE_MANAGER_VOLUME, 25);
	f_open (&fp, MMC_MUSIC_DIR, FA_READ);
	LOG("play voice start!\n");

	while(1) {
		f_sta = f_read (&fp, pcm_data_buf, PCM_BUF_SIZE, &read_len);
		if(f_sta != FR_OK) {
			LOG("fs read error\n");
			ret = -1;
			goto over;
		}
		if(read_len != PCM_BUF_SIZE)
			break;
		ret = snd_pcm_write(&pal_pcm_cfg, SOUND_CARD_ID, pcm_data_buf, PCM_BUF_SIZE);
		if(ret != PCM_BUF_SIZE) {
			LOG("pcm write error, %d\n", ret);
			ret = -1;
			goto over;
		}
	}
	ret = snd_pcm_flush(&pal_pcm_cfg, SOUND_CARD_ID);
	if (ret != 0) 
		printf("pcm flush error\n");

over:	
	LOG("play voice over!\n");
	snd_pcm_close(SOUND_CARD_ID, PCM_OUT);
	f_close(&fp);

	return ret;
}
示例#6
0
int _alsa_write_buffer(ao_alsa_internal *s)
{
	snd_pcm_channel_status_t status;
	snd_pcm_t *pcm_handle = s->pcm_handle;
	int len = s->buf_end;
	ssize_t written, snd_pcm_write_ret;

	s->buf_end = 0;

	snd_pcm_write_ret = written = 0;
	while ((snd_pcm_write_ret >= 0) && (written < len)) {
		while ((snd_pcm_write_ret = snd_pcm_write(pcm_handle, s->buf, len)) == -EINTR)
			;
		if (snd_pcm_write_ret > 0)
			written += snd_pcm_write_ret;
	}

	memset(&status, 0, sizeof(status));
	if (snd_pcm_channel_status(pcm_handle, &status) < 0) {
		fprintf(stderr, "ALSA: could not get channel status\n");
		return 0;
	}       
	if (status.underrun) {
		/* fprintf(stderr, "ALSA: underrun. resetting channel\n"); */
		snd_pcm_channel_flush(pcm_handle, SND_PCM_CHANNEL_PLAYBACK);
		snd_pcm_playback_prepare(pcm_handle);
		snd_pcm_write(pcm_handle, s->buf, len);
		if (snd_pcm_channel_status(pcm_handle, &status) < 0) {
			fprintf(stderr, "ALSA: could not get channel status. giving up\n");
			return 0;
		}
		if (status.underrun) {
			fprintf(stderr, "ALSA: write error. giving up\n");
					return 0;
		}               
	}

	return 1;
}	
示例#7
0
static ssize_t alsa_qsa_write(void *data, const void *buf, size_t size)
{
   alsa_t              *alsa = (alsa_t*)data;
   snd_pcm_sframes_t written = 0;

   while (size)
   {
      size_t avail_write = MIN(alsa->buf_size - alsa->buffer_ptr, size);

      if (avail_write)
      {
         memcpy(alsa->buffer[alsa->buffer_index] +
               alsa->buffer_ptr, buf, avail_write);

         alsa->buffer_ptr      += avail_write;
         buf                    = (void*)((uint8_t*)buf + avail_write);
         size                  -= avail_write;
         written               += avail_write;
      }

      if (alsa->buffer_ptr >= alsa->buf_size)
      {
         snd_pcm_sframes_t frames = snd_pcm_write(alsa->pcm,
               alsa->buffer[alsa->buffer_index], alsa->buf_size);

         alsa->buffer_index = (alsa->buffer_index + 1) % alsa->buf_count;
         alsa->buffer_ptr   = 0;

         if (frames <= 0)
         {
            int ret;

            if (frames == -EAGAIN)
               continue;

            ret = check_pcm_status(alsa, SND_PCM_CHANNEL_PLAYBACK);

            if (ret == -EPROTO || ret == -EBADF)
               return -1;
         }
      }

   }

   return written;
}
示例#8
0
void AlsaPMO::WorkerThread(void)
{
   void                      *pBuffer;
   Error                      eErr;
   int                        iRet = -1;
   Event                     *pEvent;
   snd_pcm_channel_status_t  ainfo;

   // Don't do anything until resume is called.
   m_pPauseSem->Wait();

   // Sleep for a pre buffer period
   PreBuffer();

   // The following should be abstracted out into the general thread
   // classes:
#ifdef __linux__
   struct sched_param sParam;

   sParam.sched_priority = sched_get_priority_max(SCHED_OTHER);
   pthread_setschedparam(pthread_self(), SCHED_OTHER, &sParam);
#endif

   ainfo.channel = SND_PCM_CHANNEL_PLAYBACK;
   for(; !m_bExit;)
   {
      if (m_bPause)
      {
          m_pPauseSem->Wait();
          continue;
      }

      // Loop until we get an Init event from the LMC
      if (!m_properlyInitialized)
      {
          pEvent = ((EventBuffer *)m_pInputBuffer)->GetEvent();

          if (pEvent == NULL)
          {
              m_pLmc->Wake();
              WasteTime();

              continue;
          }

          if (pEvent->Type() == PMO_Init)
          {
              if (IsError(Init(((PMOInitEvent *)pEvent)->GetInfo())))
              {
                  delete pEvent;
                  break;
              }
          }
          delete pEvent;

          continue;
      }

      // Set up reading a block from the buffer. If not enough bytes are
      // available, sleep for a little while and try again.
      for(;;)
      {
          eErr = ((EventBuffer *)m_pInputBuffer)->BeginRead(pBuffer, 
                                                             m_iDataSize);
          if (eErr == kError_EndOfStream || eErr == kError_Interrupt)
             break;

          if (eErr == kError_NoDataAvail)
          {
              m_pLmc->Wake();
              CheckForBufferUp();

              WasteTime();
              continue;
          }

          // Is there an event pending that we need to take care of
          // before we play this block of samples?
          if (eErr == kError_EventPending)
          {
              pEvent = ((EventBuffer *)m_pInputBuffer)->PeekEvent();
			  if (pEvent == NULL)
				  continue;
                  
              if (pEvent->Type() == PMO_Quit && 
                  ((EventBuffer *)m_pInputBuffer)->GetNumBytesInBuffer() > 0) 
              {
                  if (WaitForDrain())
				  {
                     Reset(true);
                     m_pTarget->AcceptEvent(new Event(INFO_DoneOutputting));
                     return;
				  }
                  continue;
              }
              
              pEvent = ((EventBuffer *)m_pInputBuffer)->GetEvent();

              if (pEvent->Type() == PMO_Init)
                  Init(((PMOInitEvent *)pEvent)->GetInfo());
    
              if (pEvent->Type() == PMO_Reset)
                  Reset(false);
    
              if (pEvent->Type() == PMO_Info) 
                  HandleTimeInfoEvent((PMOTimeInfoEvent *)pEvent);
    
              if (pEvent->Type() == PMO_Quit) 
              {
                  delete pEvent;
                  m_pTarget->AcceptEvent(new Event(INFO_DoneOutputting));
                  return;
              }
 
              delete pEvent;
    
              continue;
          }
          
          if (IsError(eErr))
          {
              ReportError("Internal error occured.");
              m_pContext->log->Error("Cannot read from buffer in PMO "
                                    "worker tread: %d\n", eErr);
              break;
          }
          break;
      }

      // Now write the block to the audio device. If the block doesn't
      // all fit, pause and loop until the entire block has been played.
      // This loop could be written using non-blocking io...
      for(;!m_bExit && !m_bPause;)
      {
          iRet = snd_pcm_write(m_handle,pBuffer,m_iDataSize);
          if (iRet == -EAGAIN)
          {
               CheckForBufferUp();
               WasteTime();
               continue;
          }
          if (iRet == -EIO)
          {
               snd_pcm_channel_prepare(m_handle, SND_PCM_CHANNEL_PLAYBACK);
               continue;
          }
          break;
      }
      if (m_bExit)
      {
          m_pInputBuffer->EndRead(0);
          return;
      }

      if (m_bPause)
      {
         if (iRet == -EAGAIN)
             m_pInputBuffer->EndRead(0);
         else
         {
             m_pInputBuffer->EndRead(iRet);
             UpdateBufferStatus();
         }
         continue;   
      }

      if (iRet < 0)
      {
         m_pInputBuffer->EndRead(0);
         ReportError("Could not write sound data to the soundcard.");
         m_pContext->log->Error("Failed to write to the soundcard: %s\n", 
                               strerror(errno));
         break;
      }

      m_pInputBuffer->EndRead(iRet);
      m_pLmc->Wake();
      UpdateBufferStatus();
   }
}