436
#define LOOP_WHILE_EINTR(v,func) do { (v) = (func); } \
437
while ((v) == -1 && errno == EINTR);
439
/* Called with the write_mutex held */
441
gst_sunaudio_sink_do_delay (GstSunAudioSink * sink)
443
GstBaseAudioSink *ba_sink = GST_BASE_AUDIO_SINK (sink);
444
GstClockTime total_sleep;
445
GstClockTime max_sleep;
452
/* This code below ensures that we don't race any further than buffer_time
453
* ahead of the audio output, by sleeping if the next write call would cause
454
* us to advance too far in the ring-buffer */
455
LOOP_WHILE_EINTR (err, ioctl (sink->fd, AUDIO_GETINFO, &ainfo));
459
/* Compute our offset from the output (copes with overflow) */
460
diff = (guint) (sink->segs_written) - ainfo.play.eof;
461
if (diff > sink->segtotal) {
462
/* This implies that reset did a flush just as the sound device aquired
463
* some buffers internally, and it causes us to be out of sync with the
464
* eof measure. This corrects it */
465
sink->segs_written = ainfo.play.eof;
469
if (diff + 1 < sink->segtotal)
470
return; /* no need to sleep at all */
472
/* Never sleep longer than the initial number of undrained segments in the
475
max_sleep = (diff + 1) * (ba_sink->latency_time * GST_USECOND);
476
/* sleep for a segment period between .eof polls */
477
sleep_usecs = ba_sink->latency_time;
479
/* Current time is our reference point */
480
g_get_current_time (&sleep_end);
482
/* If the next segment would take us too far along the ring buffer,
483
* sleep for a bit to free up a slot. If there were a way to find out
484
* when the eof field actually increments, we could use, but the only
485
* notification mechanism seems to be SIGPOLL, which we can't use from
486
* a support library */
487
while (diff + 1 >= sink->segtotal && total_sleep < max_sleep) {
488
GST_LOG_OBJECT (sink, "need to block to drain segment(s). "
489
"Sleeping for %d us", sleep_usecs);
491
g_time_val_add (&sleep_end, sleep_usecs);
493
if (g_cond_timed_wait (sink->sleep_cond, sink->write_mutex, &sleep_end)) {
494
GST_LOG_OBJECT (sink, "Waking up early due to reset");
495
return; /* Got told to wake up */
497
total_sleep += (sleep_usecs * GST_USECOND);
499
LOOP_WHILE_EINTR (err, ioctl (sink->fd, AUDIO_GETINFO, &ainfo));
503
/* Compute our (new) offset from the output (copes with overflow) */
504
diff = (guint) g_atomic_int_get (&sink->segs_written) - ainfo.play.eof;
510
GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, (NULL),
511
("Playback error on device '%s': %s", sink->device, strerror (errno)));
514
GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, (NULL),
515
("Playback error on device '%s': %s", sink->device, strerror (errno)));
374
520
gst_sunaudiosink_write (GstAudioSink * asink, gpointer data, guint length)
376
return write (GST_SUNAUDIO_SINK (asink)->fd, data, length);
522
GstSunAudioSink *sink = GST_SUNAUDIO_SINK (asink);
524
gint bytes_written, err;
526
g_mutex_lock (sink->write_mutex);
527
if (sink->flushing) {
528
/* Exit immediately if reset tells us to */
529
g_mutex_unlock (sink->write_mutex);
533
LOOP_WHILE_EINTR (bytes_written, write (sink->fd, data, length));
534
if (bytes_written < 0) {
539
/* Increment our sample counter, for delay calcs */
540
g_atomic_int_add (&sink->samples_written, length / sink->bytes_per_sample);
542
/* Don't consider the segment written if we didn't output the whole lot yet */
543
if (bytes_written < length) {
544
g_mutex_unlock (sink->write_mutex);
545
return (guint) bytes_written;
548
/* Write a zero length output to trigger increment of the eof field */
549
LOOP_WHILE_EINTR (err, write (sink->fd, NULL, 0));
553
/* Count this extra segment we've written */
554
sink->segs_written += 1;
556
/* Now delay so we don't overrun the ring buffer */
557
gst_sunaudio_sink_do_delay (sink);
559
g_mutex_unlock (sink->write_mutex);
563
g_mutex_unlock (sink->write_mutex);
565
GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, (NULL),
566
("Playback error on device '%s': %s", sink->device, strerror (errno)));
567
return length; /* Say we wrote the segment to let the ringbuffer exit */
380
* Should provide the current delay between writing a sample to the
381
* audio device and that sample being actually played. Returning 0 for
382
* now, but this isn't good for synchronization
571
* Provide the current number of unplayed samples that have been written
385
574
gst_sunaudiosink_delay (GstAudioSink * asink)
576
GstSunAudioSink *sink = GST_SUNAUDIO_SINK (asink);
581
ret = ioctl (sink->fd, AUDIO_GETINFO, &ainfo);
582
if (G_UNLIKELY (ret == -1))
585
offset = (g_atomic_int_get (&sink->samples_written) - ainfo.play.samples);
587
/* If the offset is larger than the total ringbuffer size, then we asked
588
between the write call and when samples_written is updated */
589
if (G_UNLIKELY (offset > sink->segtotal_samples))
391
596
gst_sunaudiosink_reset (GstAudioSink * asink)
598
/* Get current values */
599
GstSunAudioSink *sunaudiosink = GST_SUNAUDIO_SINK (asink);
603
ret = ioctl (sunaudiosink->fd, AUDIO_GETINFO, &ainfo);
606
* Should never happen, but if we couldn't getinfo, then no point
609
GST_ELEMENT_ERROR (sunaudiosink, RESOURCE, SETTINGS, (NULL), ("%s",
615
* Pause the audio - so audio stops playing immediately rather than
616
* waiting for the ringbuffer to empty.
618
ainfo.play.pause = !NULL;
619
ret = ioctl (sunaudiosink->fd, AUDIO_SETINFO, &ainfo);
621
GST_ELEMENT_ERROR (sunaudiosink, RESOURCE, SETTINGS, (NULL), ("%s",
625
/* Flush the audio */
626
ret = ioctl (sunaudiosink->fd, I_FLUSH, FLUSHW);
628
GST_ELEMENT_ERROR (sunaudiosink, RESOURCE, SETTINGS, (NULL), ("%s",
632
/* Now, we take the write_mutex and signal to ensure the write thread
633
* is not busy, and we signal the condition to wake up any sleeper,
634
* then we flush again in case the write wrote something after we flushed,
635
* and finally release the lock and unpause */
636
g_mutex_lock (sunaudiosink->write_mutex);
637
sunaudiosink->flushing = TRUE;
639
g_cond_signal (sunaudiosink->sleep_cond);
641
ret = ioctl (sunaudiosink->fd, I_FLUSH, FLUSHW);
643
GST_ELEMENT_ERROR (sunaudiosink, RESOURCE, SETTINGS, (NULL), ("%s",
647
/* unpause the audio */
648
ainfo.play.pause = NULL;
649
ret = ioctl (sunaudiosink->fd, AUDIO_SETINFO, &ainfo);
651
GST_ELEMENT_ERROR (sunaudiosink, RESOURCE, SETTINGS, (NULL), ("%s",
655
/* After flushing the audio device, we need to remeasure the sample count
656
* and segments written count so we're in sync with the device */
658
sunaudiosink->segs_written = ainfo.play.eof;
659
g_atomic_int_set (&sunaudiosink->samples_written, ainfo.play.samples);
661
sunaudiosink->flushing = FALSE;
662
g_mutex_unlock (sunaudiosink->write_mutex);