/* 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); }
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; }
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; }
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; }
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; }
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; }
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(); } }