예제 #1
0
  void ADR_CALL
  ALSAAudioDevice::update() {
    int           ret;
    int           sample_len;
    int           sample_left;
    char*         sample_buf;

    sample_buf = m_buffer;
    sample_len = m_buffer_size / 4;

    sample_left = read(sample_len, sample_buf);
    while (sample_left > 0) {
      ret = snd_pcm_writei(m_pcm_handle, sample_buf, sample_left);
      if (ret == -EAGAIN || (ret > 0 && ret < sample_left)) {
        snd_pcm_wait(m_pcm_handle, 10);
      } else if (ret == -ESTRPIPE) {
        do {
          snd_pcm_wait(m_pcm_handle, 10);
          ret = snd_pcm_resume(m_pcm_handle);
        } while (ret == -EAGAIN);
        snd_pcm_prepare(m_pcm_handle);
      } else if (ret == -EPIPE) {
        snd_pcm_prepare(m_pcm_handle);
      }
      if (ret > 0) {
        sample_buf += ret * 4;
        sample_left -= ret;
      }
    }
  }
static ssize_t
sa_alsa_read( simpleaudio *sa, void *buf, size_t nframes )
{
    ssize_t frames_read = 0;
    snd_pcm_t *pcm = (snd_pcm_t *)sa->backend_handle;
    while ( frames_read < nframes ) {
	ssize_t r;
	void * data = buf+frames_read*sa->backend_framesize;
	ssize_t count = nframes-frames_read;
	r = snd_pcm_readi(pcm, data, count);
	if ( r >= 0 ) {
	    frames_read += r;
	    if ( r != count )
		fprintf(stderr, "#short+%zd#\n", r);
	    continue;
	}
	if (r == -EPIPE) {	// Underrun
	    fprintf(stderr, "#");
	    snd_pcm_prepare(pcm);
	} else  {
	    fprintf(stderr, "snd_pcm_readi: %s\n", snd_strerror(r));
	    if (r == -EAGAIN || r== -ESTRPIPE)
		snd_pcm_wait(pcm, 1000);
	    else
		return r;
	}
    }
    // fprintf(stderr,("[%zd]\n"), frames_read);
    return frames_read;
}
예제 #3
0
static ssize_t pcm_read(u_char *data, size_t rcount)
{
	ssize_t r;
	size_t result = 0;
	size_t count = rcount;

	if (count != chunk_size) {
		count = chunk_size;
	}

	while (count > 0) {
		r = readi_func(handle, data, count);
		if (r == -EAGAIN || (r >= 0 && (size_t)r < count)) {
			snd_pcm_wait(handle, 1000);
		} else if (r == -EPIPE) {
			xrun();
		} else if (r == -ESTRPIPE) {
			suspend();
		} else if (r < 0) {
			error(_("read error: %s"), snd_strerror(r));
			exit(EXIT_FAILURE);
		}
		if (r > 0) {
			if (vumeter)
				compute_max_peak(data, r * hwparams.channels);
			result += r;
			count -= r;
			data += r * bits_per_frame / 8;
		}
	}
	return rcount;
}
예제 #4
0
파일: au_alsa.c 프로젝트: zeehio/bellbird
int audio_write_alsa(cst_audiodev *ad, void *samples, int num_frames)
{
  size_t frame_size;
  ssize_t res;
  snd_pcm_t *pcm_handle;
  char *buf = (char *) samples;
  int frames_to_write;

  frames_to_write = num_frames;
  pcm_handle = (snd_pcm_t *) ad->platform_data;
  frame_size = BELL_AUDIO_16BIT * ad->channels;

  while (frames_to_write > 0)
  {
	res = snd_pcm_writei(pcm_handle, buf, frames_to_write); //Note pcm_handle open in blocked mode
	if (res != frames_to_write)
	{
	  if (res > 0 && res < frames_to_write)
	  {
		snd_pcm_wait(pcm_handle, 100);
	  }
	  else if (recover_from_error(pcm_handle, res) < 0) 
	  {
		return -1;
	  }
	}

	if (res >0) 
	{
	  frames_to_write -= res;
	  buf += res * frame_size;
	}
  }
  return num_frames;
}
예제 #5
0
static int write_to_pcm(int size, const struct snd_pcm_container *sndpcm,
                        int offset)
{
    int err;

    while (size > 0) {
        err = snd_pcm_writei(sndpcm->handle, sndpcm->buffer + offset,
                             size);
        if (err == -EAGAIN || (err >= 0 && err < size)) {
            snd_pcm_wait(sndpcm->handle, 500);
        } else if (err == -EPIPE) {
            loge(E_WRITEPCM S_UNDERRUN, "%s(%d)",
                 snd_strerror(err), err);
            snd_pcm_prepare(sndpcm->handle);
        } else if (err < 0) {
            loge(E_WRITEPCM, "%s(%d)", snd_strerror(err), err);
            return -1;
        }

        if (err > 0) {
            size -= err;
            offset += err * sndpcm->frame_bits / 8;
        }
    }
    return 0;
}
예제 #6
0
static int read_from_pcm(struct pcm_container *sndpcm,
		int frames, struct bat *bat)
{
	int err = 0;
	int offset = 0;
	int remain = frames;

	while (remain > 0) {
		err = snd_pcm_readi(sndpcm->handle,
				sndpcm->buffer + offset, remain);
		if (err == -EAGAIN || (err >= 0 && err < remain)) {
			snd_pcm_wait(sndpcm->handle, 500);
		} else if (err == -EPIPE) {
			snd_pcm_prepare(sndpcm->handle);
			fprintf(bat->err, _("Overrun: %s(%d)\n"),
					snd_strerror(err), err);
		} else if (err < 0) {
			fprintf(bat->err, _("Read PCM device error: %s(%d)\n"),
					snd_strerror(err), err);
			return err;
		}

		if (err > 0) {
			remain -= err;
			offset += err * sndpcm->frame_bits / 8;
		}
	}

	return 0;
}
예제 #7
0
static ssize_t
pcm_write (short *data, size_t count)
{
  ssize_t r;
  ssize_t result = 0;
  while (count > 0)
    {
      r = snd_pcm_writei (AHandle, data, count);
      if (r == -EAGAIN || (r >= 0 && (size_t) r < count))
	{
	  snd_pcm_wait (AHandle, 1000);
	}
      else if (r == -EPIPE)
	{
	  xrun ();
	}
      else if (r == -ESTRPIPE)
	{
	  suspend ();
	}
      else if (r < 0)
	{
	  fprintf (stderr, "write error: %s", snd_strerror (r));
	  exit (EXIT_FAILURE);
	}
      if (r > 0)
	{
	  result += r;
	  count -= r;
	  data += r;
	}
    }
  return result;
}
예제 #8
0
static size_t pcm_read(snd_pcm_uframes_t chunk_size, u_char *data, size_t rcount)
{
	ssize_t r;
	size_t result = 0;
	size_t count = rcount;

	if (count != chunk_size) {
		count = chunk_size;
	}

	while (count > 0) {
		r = snd_pcm_readi(handle, data, count);
		if (r == -EAGAIN || (r >= 0 && (size_t)r < count)) {
			snd_pcm_wait(handle, 1000);
		}else if (r == -EPIPE){
			xrun(SND_PCM_STREAM_CAPTURE);
		}else if (r < 0) {
			printf("read error: %s", snd_strerror(r));
			exit(EXIT_FAILURE);
		}

		if (r > 0) {
			result += r;
			count -= r;
			data += r * bits_per_frame / 8;
		}
	}

	return result;
}
예제 #9
0
qint64 OutputALSA::writeAudio(unsigned char *data, qint64 maxSize)
{
    if((maxSize = qMin(maxSize, m_prebuf_size - m_prebuf_fill)) > 0)
    {
        memmove(m_prebuf + m_prebuf_fill, data, maxSize);
        m_prebuf_fill += maxSize;
    }

    snd_pcm_uframes_t l = snd_pcm_bytes_to_frames(pcm_handle, m_prebuf_fill);

    while (l >= m_chunk_size)
    {
        snd_pcm_wait(pcm_handle, 10);
        long m;
        if ((m = alsa_write(m_prebuf, m_chunk_size)) >= 0)
        {
            l -= m;
            m = snd_pcm_frames_to_bytes(pcm_handle, m); // convert frames to bytes
            m_prebuf_fill -= m;
            memmove(m_prebuf, m_prebuf + m, m_prebuf_fill); //move data to begin
        }
        else
            return -1;
    }
    return maxSize;
}
예제 #10
0
static guint
gst_alsasink_write (GstAudioSink * asink, gpointer data, guint length)
{
    GstAlsaSink *alsa;
    gint err;
    gint cptr;
    gint16 *ptr = data;

    alsa = GST_ALSA_SINK (asink);

    if (alsa->iec958 && alsa->need_swap) {
        guint i;

        GST_DEBUG_OBJECT (asink, "swapping bytes");
        for (i = 0; i < length / 2; i++) {
            ptr[i] = GUINT16_SWAP_LE_BE (ptr[i]);
        }
    }

    GST_LOG_OBJECT (asink, "received audio samples buffer of %u bytes", length);

    cptr = length / alsa->bytes_per_sample;

    GST_ALSA_SINK_LOCK (asink);
    while (cptr > 0) {
        /* start by doing a blocking wait for free space. Set the timeout
         * to 4 times the period time */
        err = snd_pcm_wait (alsa->handle, (4 * alsa->period_time / 1000));
        if (err < 0) {
            GST_DEBUG_OBJECT (asink, "wait error, %d", err);
        } else {
            GST_DELAY_SINK_LOCK (asink);
            err = snd_pcm_writei (alsa->handle, ptr, cptr);
            GST_DELAY_SINK_UNLOCK (asink);
        }

        GST_DEBUG_OBJECT (asink, "written %d frames out of %d", err, cptr);
        if (err < 0) {
            GST_DEBUG_OBJECT (asink, "Write error: %s", snd_strerror (err));
            if (err == -EAGAIN) {
                continue;
            } else if (xrun_recovery (alsa, alsa->handle, err) < 0) {
                goto write_error;
            }
            continue;
        }

        ptr += snd_pcm_frames_to_bytes (alsa->handle, err);
        cptr -= err;
    }
    GST_ALSA_SINK_UNLOCK (asink);

    return length - (cptr * alsa->bytes_per_sample);

write_error:
    {
        GST_ALSA_SINK_UNLOCK (asink);
        return length;              /* skip one period */
    }
}
예제 #11
0
static int
write_device(AudioDevice *ad, unsigned char *data, int size)
{
  ALSA_data *alsa = (ALSA_data *)ad->private_data;
  snd_pcm_sframes_t r;
  ssize_t unit = snd_pcm_samples_to_bytes(alsa->fd, 1) * ad->channels;
  snd_pcm_uframes_t count = size / unit;

  while (count > 0) {
    if ((r = snd_pcm_writei(alsa->fd, data, count)) == -EAGAIN) {
      //debug_message_fnc(" EAGAIN\n");
      snd_pcm_wait(alsa->fd, 1000);
    } else if (r > 0) {
      //debug_message_fnc(" wrote %d bytes\n", (int)(r * unit));
      ad->bytes_written += r * unit;
      count -= r;
      data += r * unit;
    } else if (r == -EPIPE) {
      debug_message_fnc("EPIPE: ");
      if (snd_pcm_state(alsa->fd) == SND_PCM_STATE_XRUN) {
	if ((r = snd_pcm_prepare(alsa->fd)) < 0) {
	  debug_message("failed\n");
	  warning_fnc("snd_pcm_prepare() failed.");
	} else {
	  debug_message("OK\n");
	}
      }
    } else {
      warning_fnc(" r = %d < 0...\n", (int)r);
    }
  }

  return 1;
}
예제 #12
0
ssize_t SNDWAV_WritePcm(SNDPCMContainer_t *sndpcm, size_t wcount)  
{  
    ssize_t r;  
    ssize_t result = 0;  
    uint8_t *data = sndpcm->data_buf;  
  
    if (wcount < sndpcm->chunk_size) {  
        snd_pcm_format_set_silence(sndpcm->format,   
            data + wcount * sndpcm->bits_per_frame / 8,   
            (sndpcm->chunk_size - wcount) * sndpcm->channels);  
        wcount = sndpcm->chunk_size;  
    }  
    while (wcount > 0) {  
        r = snd_pcm_writei(sndpcm->handle, data, wcount);  
        if (r == -EAGAIN || (r >= 0 && (size_t)r < wcount)) {  
            snd_pcm_wait(sndpcm->handle, 1000);  
        } else if (r == -EPIPE) {  
            snd_pcm_prepare(sndpcm->handle);  
            fprintf(stderr, "<<<<<<<<<<<<<<< Buffer Underrun >>>>>>>>>>>>>>>\n");  
        } else if (r == -ESTRPIPE) {              
            fprintf(stderr, "<<<<<<<<<<<<<<< Need suspend >>>>>>>>>>>>>>>\n");          
        } else if (r < 0) {  
            fprintf(stderr, "Error snd_pcm_writei: [%s]", snd_strerror(r));  
            exit(-1);  
        }  
        if (r > 0) {  
            result += r;  
            wcount -= r;  
            data += r * sndpcm->bits_per_frame / 8;  
        }  
    }  
    return result;  
}  
예제 #13
0
ssize_t SNDWAV_ReadPcm(SNDPCMContainer_t *sndpcm, size_t rcount)  
{  
    ssize_t r;  
    size_t result = 0;  
    size_t count = rcount;  
    uint8_t *data = sndpcm->data_buf;  
  
    if (count != sndpcm->chunk_size) {  
        count = sndpcm->chunk_size;  
    }  
  
    while (count > 0) {  
        r = snd_pcm_readi(sndpcm->handle, data, count);  
          
        if (r == -EAGAIN || (r >= 0 && (size_t)r < count)) {  
            snd_pcm_wait(sndpcm->handle, 1000);  
        } else if (r == -EPIPE) {  
            snd_pcm_prepare(sndpcm->handle);  
            fprintf(stderr, "<<<<<<<<<<<<<<< Buffer Underrun >>>>>>>>>>>>>>>\n");  
        } else if (r == -ESTRPIPE) {  
            fprintf(stderr, "<<<<<<<<<<<<<<< Need suspend >>>>>>>>>>>>>>>\n");  
        } else if (r < 0) {  
            fprintf(stderr, "Error snd_pcm_writei: [%s]", snd_strerror(r));  
            exit(-1);  
        }  
          
        if (r > 0) {  
            result += r;  
            count -= r;  
            data += r * sndpcm->bits_per_frame / 8;  
        }  
    }  
    return rcount;  
}  
예제 #14
0
static ssize_t pcm_write(u_char *data, size_t count)
{
	ssize_t r;
	ssize_t result = 0;

	if (sleep_min == 0 &&
	    count < chunk_size) {
		snd_pcm_format_set_silence(hwparams.format, data + count * bits_per_frame / 8, (chunk_size - count) * hwparams.channels);
		count = chunk_size;
	}
	while (count > 0) {
		r = snd_pcm_writei(handle, data, count);
		if (r == -EAGAIN || (r >= 0 && (size_t)r < count)) {
			snd_pcm_wait(handle, 1000);
		} else if (r == -EPIPE) {
			xrun();
		} else if (r == -ESTRPIPE) {
			suspend();
		} else if (r < 0) {
			error(_("write error: %s"), snd_strerror(r));
			exit(EXIT_FAILURE);
		}
		if (r > 0) {
			result += r;
			count -= r;
			data += r * bits_per_frame / 8;
		}
	}
	return result;
}
예제 #15
0
파일: alsa_in.c 프로젝트: rufferson/jack2
static snd_pcm_t *open_audiofd( char *device_name, int capture, int rate, int channels, int period, int nperiods ) {
  int err;
  snd_pcm_t *handle;
  snd_pcm_hw_params_t *hwparams;
  snd_pcm_sw_params_t *swparams;

  snd_pcm_hw_params_alloca(&hwparams);
  snd_pcm_sw_params_alloca(&swparams);

  if ((err = snd_pcm_open(&(handle), device_name, capture ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK )) < 0) {
      printf("Capture open error: %s\n", snd_strerror(err));
      return NULL;
  }

  if ((err = set_hwparams(handle, hwparams,SND_PCM_ACCESS_RW_INTERLEAVED, rate, channels, period, nperiods )) < 0) {
      printf("Setting of hwparams failed: %s\n", snd_strerror(err));
      return NULL;
  }
  if ((err = set_swparams(handle, swparams, period)) < 0) {
      printf("Setting of swparams failed: %s\n", snd_strerror(err));
      return NULL;
  }

  snd_pcm_start( handle );
  snd_pcm_wait( handle, 200 );

  return handle;
}
예제 #16
0
void PAPlayer::WaitForStream()
{
  // should we wait for our other stream as well?
  // currently we don't.
  if (!m_pStream[m_currentStream])
  {
    snd_pcm_wait(m_pStream[m_currentStream], -1);
  }
}
예제 #17
0
    void write( const char *data, qint64 len )
    {
        if ( !handle )
            return;

        int count=0;

        qLog(QAudioOutput)<<"frames to write out = "<<
            snd_pcm_bytes_to_frames( handle, (int)len )<<" ("<<len<<") bytes";

        while ( len > 0 ) {

            int err=0;
            int frames = snd_pcm_bytes_to_frames( handle, (int)len );

#ifdef ALSA_USE_AVAILABLE
            if(frames < (int)period_size)
                return;

            int available = snd_pcm_avail_update(handle);
            qLog(QAudioOutput) <<"available space = "<<available;
            if(available == 0) {
                while(available < frames) {
                    snd_pcm_wait(handle,period_size/1000);
                    usleep(period_size*10);
                    available = snd_pcm_avail_update(handle);
                    qLog(QAudioOutput) <<"->available space = "<<available;
                    count++;
                    if((count > 5)||(available < 0))
                        return;
                }
            }
#endif

            err = snd_pcm_writei( handle, data, frames );

            // Handle errors
            if ( err >= 0 ) {
                if(err == 0) count++;
                int bytes = snd_pcm_frames_to_bytes( handle, err );
                qLog(QAudioOutput) << QString("write out = %1").arg(bytes).toLatin1().constData();
                data += bytes;
                len -= bytes;
            } else {
                count++;
                qLog(QAudioOutput) <<"err = "<<err;
                err = xrun_recovery(err);
            }
            if(count > 5) {
                qLog(QAudioOutput) <<"failing to write, close() and re-open() to try and recover!";
                close();
                open();
                snd_pcm_prepare(handle);
                break;
            }
        }
    }
예제 #18
0
파일: alsa.c 프로젝트: ecthiender/mocp-git
/* Play from alsa_buf as many chunks as possible. Move the remaining data
 * to the beginning of the buffer. Return the number of bytes written
 * or -1 on error. */
static int play_buf_chunks ()
{
	int written = 0;
	
	while (alsa_buf_fill >= chunk_size) {
		int err;
		
		err = snd_pcm_writei (handle, alsa_buf + written,
				chunk_size / bytes_per_frame);
		if (err == -EAGAIN) {
			if (snd_pcm_wait(handle, 500) < 0)
				logit ("snd_pcm_wait() failed");
		}
		else if (err == -EPIPE) {
			logit ("underrun!");
			if ((err = snd_pcm_prepare(handle)) < 0) {
				error ("Can't recover after underrun: %s",
						snd_strerror(err));
				/* TODO: reopen the device */
				return -1;
			}
		}
		else if (err == -ESTRPIPE) {
			logit ("Suspend, trying to resume");
			while ((err = snd_pcm_resume(handle))
					== -EAGAIN)
				sleep (1);
			if (err < 0) {
				logit ("Failed, restarting");
				if ((err = snd_pcm_prepare(handle))
						< 0) {
					error ("Failed to restart "
							"device: %s.",
							snd_strerror(err));
					return -1;
				}
			}
		}
		else if (err < 0) {
			error ("Can't play: %s", snd_strerror(err));
			return -1;
		}
		else {
			int written_bytes = err * bytes_per_frame;

			written += written_bytes;
			alsa_buf_fill -= written_bytes;

			debug ("Played %d bytes", written_bytes);
		}
	}

	debug ("%d bytes remain in alsa_buf", alsa_buf_fill);
	memmove (alsa_buf, alsa_buf + written, alsa_buf_fill);

	return written * bytes_per_frame;
}
예제 #19
0
void SoundOutput_alsa::wait()
{
	if(handle == nullptr)
	{
		System::sleep(100);
		return;
	}
	/* wait upto 1 second */
	snd_pcm_wait(handle, 1000);
}
예제 #20
0
void CL_SoundOutput_alsa::wait()
{
	if(handle == NULL)
	{
		CL_System::sleep(100);
		return;
	}
	/* wait upto 1 second */
	snd_pcm_wait(handle, 1000);
}
예제 #21
0
void AlsaLayer::audioCallback()
{
    if (!playbackHandle_ or !captureHandle_)
        return;

    notifyIncomingCall();

    snd_pcm_wait(playbackHandle_, 20);

    int playbackAvailFrames = 0;

    if (not safeUpdate(playbackHandle_, playbackAvailFrames))
        return;

    unsigned framesToGet = urgentRingBuffer_.availableForGet(MainBuffer::DEFAULT_ID);

    if (framesToGet > 0) {
        // Urgent data (dtmf, incoming call signal) come first.
        framesToGet = std::min(framesToGet, (unsigned)playbackAvailFrames);
        playbackBuff_.setFormat(audioFormat_);
        playbackBuff_.resize(framesToGet);
        urgentRingBuffer_.get(playbackBuff_, MainBuffer::DEFAULT_ID);
        playbackBuff_.applyGain(isPlaybackMuted_ ? 0.0 : playbackGain_);
        playbackBuff_.interleave(playbackIBuff_);
        write(playbackIBuff_.data(), framesToGet, playbackHandle_);
        // Consume the regular one as well (same amount of frames)
        Manager::instance().getMainBuffer().discard(framesToGet, MainBuffer::DEFAULT_ID);
    } else {
        // regular audio data
        playback(playbackAvailFrames);
    }

    if (ringtoneHandle_) {
        AudioLoop *file_tone = Manager::instance().getTelephoneFile();
        int ringtoneAvailFrames = 0;

        if (not safeUpdate(ringtoneHandle_, ringtoneAvailFrames))
            return;

        playbackBuff_.setFormat(audioFormat_);
        playbackBuff_.resize(ringtoneAvailFrames);

        if (file_tone) {
            DEBUG("playback gain %d", playbackGain_);
            file_tone->getNext(playbackBuff_, playbackGain_);
        }

        playbackBuff_.interleave(playbackIBuff_);
        write(playbackIBuff_.data(), ringtoneAvailFrames, ringtoneHandle_);
    }

    // Additionally handle the mic's audio stream
    if (is_capture_running_)
        capture();
}
예제 #22
0
static int
alsa_audio_deliver(audio_decoder_t *ad, int samples, int64_t pts, int epoch)
{
  decoder_t *d = (decoder_t *)ad;
  media_pipe_t *mp = ad->ad_mp;
  int c;

 retry:
  c = snd_pcm_wait(d->h, 100);
  if(c >= 0) {
    c = snd_pcm_avail_update(d->h);
  }
  if(c == -EPIPE) {
    snd_pcm_prepare(d->h);
    usleep(100000);
    TRACE(TRACE_DEBUG, "ALSA", "Audio underrun");
    d->samples = 0;
    goto retry;
  }

  c = MIN(d->max_frames_per_write, c);

  uint8_t *planes[8] = {0};
  planes[0] = d->tmp;
  c = avresample_read(ad->ad_avr, planes, c);
  
  snd_pcm_status_t *status;
  int err;
  snd_pcm_status_alloca(&status);
  if ((err = snd_pcm_status(d->h, status)) >= 0) {

    if(pts != AV_NOPTS_VALUE) {
      snd_htimestamp_t hts;
      snd_pcm_status_get_trigger_htstamp(status, &hts);
      int64_t ts = hts.tv_sec * 1000000LL + hts.tv_nsec / 1000;
      ts += d->samples * 1000000LL / ad->ad_out_sample_rate;

      hts_mutex_lock(&mp->mp_clock_mutex);
      mp->mp_audio_clock_avtime = ts;
      mp->mp_audio_clock = pts;
      mp->mp_audio_clock_epoch = epoch;
      hts_mutex_unlock(&mp->mp_clock_mutex);
    }
  }

  snd_pcm_sframes_t fr;
  if(!snd_pcm_delay(d->h, &fr))
    ad->ad_delay = 1000000L * fr / ad->ad_out_sample_rate;

  c = snd_pcm_writei(d->h, d->tmp, c);
  d->samples += c;
  return 0;
}
예제 #23
0
unsigned int CAESinkALSA::AddPackets(uint8_t *data, unsigned int frames, bool hasAudio, bool blocking)
{
  if (!m_pcm)
  {
    SoftResume();
    if(!m_pcm)
      return 0;

    CLog::Log(LOGDEBUG, "CAESinkALSA - the grAEken is hunger, feed it (I am the downmost fallback - fix your code)");
  }

  int ret;

  ret = snd_pcm_avail(m_pcm);
  if (ret < 0) 
  {
    HandleError("snd_pcm_avail", ret);
    ret = 0;
  }

  if ((unsigned int)ret < frames)
  {
    if(blocking)
    {
      ret = snd_pcm_wait(m_pcm, m_timeout);
      if (ret < 0)
        HandleError("snd_pcm_wait", ret);
    }
    else
      return 0;
  }

  ret = snd_pcm_writei(m_pcm, (void*)data, frames);
  if (ret < 0)
  {
    HandleError("snd_pcm_writei(1)", ret);
    ret = snd_pcm_writei(m_pcm, (void*)data, frames);
    if (ret < 0)
    {
      HandleError("snd_pcm_writei(2)", ret);
      ret = 0;
    }
  }

  if ( ret > 0 && snd_pcm_state(m_pcm) == SND_PCM_STATE_PREPARED)
    snd_pcm_start(m_pcm);

  return ret;
}
예제 #24
0
파일: aplaypop.c 프로젝트: vovcat/xcrutchd
int aplaypop()
{
    if (pcm_handle == NULL && aplaypop_open() != 0)
        return -1;

    fprintf(stderr, "snd_pcm_state() = %s\n",
            snd_pcm_state_name(snd_pcm_state(pcm_handle)));

    int err = snd_pcm_prepare(pcm_handle);
    if (err != 0) {
        fprintf(stderr, "snd_pcm_start(): %s\n", snd_strerror(err));
        return -1;
    }

    int16_t *ptr = (int16_t *)bin_data;
    int len = sizeof(bin_data) / frame_bytes;

    while (len > 0) {
        // The unit of the buffersize depends on the function. Sometimes it is
        // given in bytes, sometimes the number of frames has to be specified.
        // One frame is the sample data vector for all channels.
        // For 16 Bit stereo data, one frame has a length of four bytes.
        snd_pcm_sframes_t frames = snd_pcm_writei(pcm_handle, ptr, len);
        fprintf(stderr, "  snd_pcm_writei(h, ptr, %d) = %ld\n", len, frames);
        if (frames == -EAGAIN) {
            frames = 0;
        } else if (frames < 0) { // -EPIPE, -ESTRPIPE
            frames = snd_pcm_recover(pcm_handle, frames, 1/*silent*/);
            if (frames < 0) {
                fprintf(stderr, "writei/recover failed: %s\n", snd_strerror(err));
                break;
            }
        } else if (frames < len) {
            fprintf(stderr, "Short write (expected %d, wrote %ld)\n", len, frames);
        } else {
            break; // All done
        }
        len -= frames * frame_bytes;
        ptr += frames * frame_bytes;
        snd_pcm_wait(pcm_handle, 10/*ms*/);
    }

    err = snd_pcm_drain(pcm_handle);
    if (err != 0) {
        fprintf(stderr, "snd_pcm_start(): %s\n", snd_strerror(err));
        return -1;
    }
    return 0;
}
예제 #25
0
/*****************************************************************************
 * Demux: Processes the audio frame
 *****************************************************************************/
static int Demux( demux_t *p_demux )
{
    demux_sys_t *p_sys = p_demux->p_sys;

    block_t *p_block = NULL;

    do
    {
        if( p_block )
        {
            es_out_Send( p_demux->out, p_sys->p_es, p_block );
            p_block = NULL;
        }

        /* Wait for data */
        int i_wait = snd_pcm_wait( p_sys->p_alsa_pcm, 10 ); /* See poll() comment in oss.c */
        switch( i_wait )
        {
            case 1:
            {
                p_block = GrabAudio( p_demux );
                if( p_block )
                    es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_block->i_pts );
            }

            /* FIXME: this is a copy paste from below. Shouldn't be needed
             * twice. */
            case -EPIPE:
                /* xrun */
                snd_pcm_prepare( p_sys->p_alsa_pcm );
                break;
            case -ESTRPIPE:
            {
                /* suspend */
                int i_resume = snd_pcm_resume( p_sys->p_alsa_pcm );
                if( i_resume < 0 && i_resume != -EAGAIN ) snd_pcm_prepare( p_sys->p_alsa_pcm );
                break;
            }
            /* </FIXME> */
        }
    } while( p_block && p_sys->i_next_demux_date > 0 &&
             p_block->i_pts < p_sys->i_next_demux_date );

    if( p_block )
        es_out_Send( p_demux->out, p_sys->p_es, p_block );

    return 1;
}
예제 #26
0
BOOL auTransferData(Audio* self, snd_pcm_sframes_t (*transfer)(snd_pcm_t*, void*, snd_pcm_uframes_t))
{
  int    numFramesTransferred = 0, error = 0;
  int    numFramesLeft        = self->bufferNumFrames;
  auSample_t*    p            = self->sampleBuffer;

   while((numFramesLeft > 0) && self->threadShouldContinueRunning)
     {
       error = numFramesTransferred = transfer(self->device, p, numFramesLeft);

       if(numFramesTransferred < 0)
         {  
           //fprintf(stderr, "Audio.c: audio device error while transferring samples: %s, attempting to recover... ", snd_strerror(error));
           switch(error)
            {
              case -EPIPE:   //overflow / underflow
                snd_pcm_wait(self->device, 100);
                if((error = snd_pcm_avail(self->device)) < 0)          //broken pipe
                  usleep(10000);                                       //wait for more samples to come
                else numFramesLeft = 0;                                //overrun, skip remaining samples;

                error = snd_pcm_prepare(self->device); 
                break;
             
             case -ESTRPIPE: 
              while(((error = snd_pcm_resume(self->device)) == -EAGAIN) && self->threadShouldContinueRunning) 
                sleep(1);
              if(error == -ENOSYS) error = snd_pcm_prepare(self->device); 
              break;
             
           }
           if(error < 0)
             {
               //fprintf(stderr, "Aborting\n");
               self->threadShouldContinueRunning = NO;
               break;
             }
           else
             {
               //fprintf(stderr, "Okay\n");
               numFramesTransferred = 0;
             } 
         }
        p +=  numFramesTransferred * self->numChannels;
        numFramesLeft -= numFramesTransferred;
     }
  return (numFramesLeft == 0) ? YES : NO;     
}
예제 #27
0
snd_pcm_sframes_t
XcapAlsaReadiQueue::readi(snd_pcm_t *handle, unsigned char *samples, int chunksize, int queue) {
	unsigned char *qdata;
	snd_pcm_sframes_t ret = 0;
	// not initialized or error
	if(n == 0 || this->chunksize != chunksize)
		return -1;
	if(samples == NULL)
		return 0;
	// no more queue
	if(queue==0) {
		// queue is empty
		if(datapool.size() == 0)
			return snd_pcm_readi(handle, samples, chunksize);
		// queue is not empty, dequeue
		qdata = datapool.front();
		ret = *((snd_pcm_sframes_t*) qdata);
		bcopy(qdata+sizeof(snd_pcm_sframes_t), samples, this->chunkbyte);
		datapool.pop_front();
		freepool.push_front(qdata);
	}
	// read and queue
	if(freepool.size() == 0) {
		ga_error("AlsaReadiQueue: no more queue, dropping eldest\n");
		qdata = datapool.front();
		datapool.pop_front();
	} else {
		qdata = freepool.front();
		freepool.pop_front();
	}
	*((snd_pcm_sframes_t*) qdata) = snd_pcm_readi(handle,
						qdata+sizeof(snd_pcm_sframes_t),
						chunksize);
	if(*((snd_pcm_sframes_t*) qdata) < 0) {
		freepool.push_front(qdata);
		if(ret > 0 && *((snd_pcm_sframes_t*) qdata) == -EAGAIN) {
			ga_error("DEBUG: snd_pcm_wait in queue->readi (qsize=%d)\n", datapool.size());
			snd_pcm_wait(handle, 1000);
			return ret;
		}
		return *((snd_pcm_sframes_t*) qdata);
	}
	datapool.push_back(qdata);
	//
	return ret;
}
예제 #28
0
void *write_pcmdata(void *arg)
{
	dbg("Enter write_pcmdata thread.....\n");

	int ret;
	msg_t pcm_data;
	snd_pcm_sframes_t avail;

	common_data_t *p_common_data = (common_data_t *)arg;
	dbg("PCM handle name = '%s'\n",snd_pcm_name(p_common_data->handle));
	dbg("period szie = %lu\n",p_common_data->period_size);

	while (1) {
		sem_wait(&p_common_data->queue.wait);
		if((read_item_from_queue(&p_common_data->queue, &pcm_data)) == EMPTY){
			dbg("queue is empty...\n");
			//TODO:block?
			continue;
		}
		snd_pcm_prepare(p_common_data->handle);
		ret = snd_pcm_writei(p_common_data->handle, pcm_data.pcm_msg, p_common_data->period_size);
		if (ret == -EAGAIN) { //means try again
			/* wait 1000ms for pcm device to become ready */
			dbg_alsa("EAGAIN error, Sleep for 1000ms\n");
			snd_pcm_wait(p_common_data->handle, 1000);
		}
		else if (ret == -EPIPE) {
			/* EPIPE means underrun */
			snd_pcm_prepare(p_common_data->handle);
			dbg_alsa("underrun occurred\n");
		} 
		else if(ret == -ESTRPIPE) {
			dbg_alsa("Need suspend\n");
		}
		else if (ret < 0) {
			dbg_alsa("error from writei: %s\n", snd_strerror(ret));
		}  
		ret = snd_pcm_state(p_common_data->handle);
		dbg("state is %d\n", ret);
		sem_post(&p_common_data->queue.full);
	}
}
예제 #29
0
파일: alsa-audio.c 프로젝트: raphui/wMusic
static void* alsa_audio_start(void *aux)
{
	audio_fifo_t *af = aux;
	snd_pcm_t *h = NULL;
	int c;
	int cur_channels = 0;
	int cur_rate = 0;

	audio_fifo_data_t *afd;

	for (;;) {
		afd = audio_get(af);

		if (!h || cur_rate != afd->rate || cur_channels != afd->channels) {
			if (h) snd_pcm_close(h);

			cur_rate = afd->rate;
			cur_channels = afd->channels;

            h = alsa_open("default", cur_rate, cur_channels);

            if (!h) {
                fprintf(stderr, "Unable to open ALSA device (%d channels, %d Hz), dying\n",
                        cur_channels, cur_rate);
                exit(1);
            }
		}

		c = snd_pcm_wait(h, 1000);

		if (c >= 0)
			c = snd_pcm_avail_update(h);

		if (c == -EPIPE)
			snd_pcm_prepare(h);

        snd_pcm_writei(h, afd->samples, afd->nsamples);
        writeFile( &afd->samples );
        zfree(afd);
	}
}
예제 #30
0
void *
asource_threadproc(void *arg) {
	int r;
	unsigned char *fbuffer;
	//
	if(asource_init(NULL) < 0) {
		exit(-1);
	}
	if((fbuffer = (unsigned char*) malloc(audioparam.chunk_bytes)) == NULL) {
		ga_error("Audio source: malloc failed (%d bytes) - %s\n",
			audioparam.chunk_bytes, strerror(errno));
		exit(-1);
	}
	//
	ga_error("Audio source thread started: tid=%ld\n", ga_gettid());
	//
	while(true) {
#ifdef WIN32
		r = ga_wasapi_read(&audioparam, fbuffer, audioparam.chunk_size);
		if(r < 0) {
			ga_error("Audio source: WASAPI read failed.\n");
			break;
		}
#else
		r = snd_pcm_readi(audioparam.handle, fbuffer, audioparam.chunk_size);
		if(r == -EAGAIN) {
			snd_pcm_wait(audioparam.handle, 1000);
			continue;
		} else if(r < 0) {
			ga_error("Audio source: ALSA read failed - %s\n",
				snd_strerror(r));
			break;
		}
#endif
		audio_source_buffer_fill(fbuffer, r);
	}
	//
	ga_error("audio capture thread terminated.\n");
	//
	return NULL;
}