Here's the "final" xmms diff; I got two test reports only, but I
believe this is correct.
ok?
-- Alexandre
Index: Makefile
===================================================================
RCS file: /cvs/ports/audio/xmms/Makefile,v
retrieving revision 1.79
diff -u -p -r1.79 Makefile
--- Makefile 9 Aug 2012 17:54:47 -0000 1.79
+++ Makefile 6 Sep 2012 06:49:30 -0000
@@ -10,7 +10,7 @@ SHARED_ONLY= Yes
VERSION= 1.2.11
DISTNAME= xmms-${VERSION}
PKGNAME-main= xmms-${VERSION}
-REVISION-main= 10
+REVISION-main= 11
PKGNAME-vorbis= xmms-vorbis-${VERSION}
REVISION-vorbis= 4
PKGNAME-mikmod= xmms-mikmod-${VERSION}
Index: files/audio_sndio.c
===================================================================
RCS file: /cvs/ports/audio/xmms/files/audio_sndio.c,v
retrieving revision 1.3
diff -u -p -r1.3 audio_sndio.c
--- files/audio_sndio.c 5 Dec 2010 15:52:19 -0000 1.3
+++ files/audio_sndio.c 6 Sep 2012 06:49:30 -0000
@@ -14,9 +14,12 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <errno.h>
+#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include <gtk/gtk.h>
#include <libxmms/util.h>
@@ -44,8 +47,6 @@ static int op_playing (void);
static int op_get_output_time (void);
static int op_get_written_time (void);
-static void onmove_cb (void *, int);
-
static void configure_win_ok_cb(GtkWidget *, gpointer);
static void configure_win_cancel_cb(GtkWidget *, gpointer);
static void configure_win_destroy(void);
@@ -54,8 +55,8 @@ static struct sio_par par;
static struct sio_hdl *hdl;
static long long rdpos;
static long long wrpos;
-static int paused;
-static int volume = XMMS_MAXVOL;
+static int paused, restarted, volume;
+static int pause_pending, flush_pending, volume_pending;
static long bytes_per_sec;
static AFormat afmt;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
@@ -91,6 +92,74 @@ get_oplugin_info (void)
}
static void
+reset(void)
+{
+ if (!restarted) {
+ restarted = 1;
+ sio_stop(hdl);
+ sio_start(hdl);
+ rdpos = wrpos;
+ }
+}
+static void
+onmove_cb (void *addr, int delta)
+{
+ rdpos += delta * (int)(par.bps * par.pchan);
+}
+
+static void
+onvol_cb(void *addr, unsigned ctl)
+{
+ /* Update volume only if it actually changed */
+ if (ctl != volume * SIO_MAXVOL / 100)
+ volume = ctl * 100 / SIO_MAXVOL;
+}
+
+static void
+pending_events(void)
+{
+ if (volume_pending) {
+ sio_setvol(hdl, volume * SIO_MAXVOL / 100);
+ volume_pending = 0;
+ }
+ if (flush_pending) {
+ reset();
+ flush_pending = 0;
+ }
+ if (pause_pending) {
+ if (paused)
+ reset();
+ pause_pending = 0;
+ }
+}
+
+static void
+wait_ready(void)
+{
+ int n;
+ struct pollfd pfds[16];
+
+ if (paused) {
+ pthread_mutex_unlock(&mutex);
+ usleep(20000);
+ pthread_mutex_lock(&mutex);
+ return;
+ }
+ n = sio_pollfd(hdl, pfds, POLLOUT);
+ if (n != 0) {
+ pthread_mutex_unlock(&mutex);
+ while (poll(pfds, n, -1) < 0) {
+ if (errno != EINTR) {
+ perror("poll");
+ exit(1);
+ }
+ }
+ pthread_mutex_lock(&mutex);
+ }
+ (void)sio_revents(hdl, pfds);
+}
+
+static void
op_about (void)
{
static GtkWidget *about;
@@ -118,7 +187,7 @@ op_init (void)
xmms_cfg_free(cfgfile);
if (!audiodev)
- audiodev = g_strdup("");
+ audiodev = g_strdup(SIO_DEVANY);
}
static void
@@ -135,8 +204,7 @@ op_set_volume (int left, int right)
/* Ignore balance control, so use unattenuated channel. */
pthread_mutex_lock (&mutex);
volume = left > right ? left : right;
- if (hdl != NULL)
- sio_setvol (hdl, volume * SIO_MAXVOL / XMMS_MAXVOL);
+ volume_pending = 1;
pthread_mutex_unlock (&mutex);
}
@@ -146,8 +214,7 @@ op_open (AFormat fmt, int rate, int nch)
struct sio_par askpar;
pthread_mutex_lock (&mutex);
-
- hdl = sio_open (strlen (audiodev) > 0 ? audiodev : NULL, SIO_PLAY, 0);
+ hdl = sio_open (audiodev, SIO_PLAY, 1);
if (hdl == NULL) {
fprintf (stderr, "%s: failed to open audio device\n", __func__);
goto error;
@@ -217,7 +284,7 @@ op_open (AFormat fmt, int rate, int nch)
fprintf (stderr, "%s: parameters not supported\n", __func__);
xmms_show_message ("Unsupported format", "XMMS requested a "
"format that is not supported by the audio device.\n\n"
- "Please try again with the aucat(1) server running.",
+ "Please try again with the sndiod(1) server running.",
"OK", FALSE, NULL, NULL);
goto error;
}
@@ -225,17 +292,18 @@ op_open (AFormat fmt, int rate, int nch)
rdpos = 0;
wrpos = 0;
sio_onmove (hdl, onmove_cb, NULL);
+ sio_onvol (hdl, onvol_cb, NULL);
+ bytes_per_sec = par.bps * par.pchan * par.rate;
+ pause_pending = flush_pending = volume_pending = 0;
+ restarted = 1;
paused = 0;
if (!sio_start (hdl)) {
fprintf (stderr, "%s: failed to start audio device\n",
__func__);
goto error;
}
-
- bytes_per_sec = par.bps * par.pchan * par.rate;
pthread_mutex_unlock (&mutex);
- op_set_volume (volume, volume);
return TRUE;
error:
@@ -247,11 +315,9 @@ error:
static void
op_write (void *ptr, int len)
{
+ unsigned n;
EffectPlugin *ep;
- if (paused)
- return;
-
/* This sucks but XMMS totally broke the effect plugin code when
they added support for multiple enabled effects. Complain to
the non-existent XMMS team if a plugin does not work, however
@@ -259,13 +325,23 @@ op_write (void *ptr, int len)
ep = get_current_effect_plugin ();
ep->mod_samples (&ptr, len, afmt, par.rate, par.pchan);
- /* Do not lock sio_write as this will cause the GUI thread
- to block waiting for a blocked sio_write to return. */
- len = sio_write (hdl, ptr, len);
-
- pthread_mutex_lock (&mutex);
- wrpos += len;
- pthread_mutex_unlock (&mutex);
+ pthread_mutex_lock(&mutex);
+ for (;;) {
+ pending_events();
+ if (paused)
+ break;
+ restarted = 0;
+ n = sio_write(hdl, ptr, len);
+ if (n == 0 && sio_eof(hdl))
+ break;
+ wrpos += n;
+ len -= n;
+ ptr = (char *)ptr + n;
+ if (len == 0)
+ break;
+ wait_ready();
+ }
+ pthread_mutex_unlock(&mutex);
}
static void
@@ -285,8 +361,8 @@ op_seek (int time_ms)
int bufused;
pthread_mutex_lock (&mutex);
- bufused = (rdpos < 0) ? wrpos : wrpos - rdpos;
- rdpos = time_ms / 1000 * bytes_per_sec;
+ bufused = wrpos - rdpos;
+ rdpos = (long long)time_ms * bytes_per_sec / 1000;
wrpos = rdpos + bufused;
pthread_mutex_unlock (&mutex);
}
@@ -294,20 +370,30 @@ op_seek (int time_ms)
static void
op_pause (short flag)
{
+ pthread_mutex_lock(&mutex);
paused = flag;
+ pause_pending = 1;
+ pthread_mutex_unlock(&mutex);
}
static int
op_buffer_free (void)
{
#define MAGIC 1000000 /* See Output/{OSS,sun,esd}/audio.c */
- return paused ? 0 : MAGIC;
+ int ret;
+
+ pthread_mutex_lock(&mutex);
+ pending_events();
+ ret = paused ? 0 : MAGIC;
+ pthread_mutex_unlock(&mutex);
+ return ret;
}
static int
op_playing (void)
{
- return paused ? TRUE : FALSE;
+ /* sndio drains in the background, do as we're done */
+ return FALSE;
}
static int
@@ -333,18 +419,10 @@ op_get_written_time (void)
}
static void
-onmove_cb (void *addr, int delta)
-{
- pthread_mutex_lock (&mutex);
- rdpos += delta * (int)(par.bps * par.pchan);
- pthread_mutex_unlock (&mutex);
-}
-
-static void
op_configure(void)
{
GtkWidget *dev_vbox;
- GtkWidget *adevice_frame, *adevice_text, *adevice_vbox;
+ GtkWidget *adevice_frame, *adevice_vbox;
GtkWidget *bbox, *ok, *cancel;
if (configure_win) {
@@ -370,9 +448,6 @@ op_configure(void)
adevice_vbox = gtk_vbox_new(FALSE, 5);
gtk_container_set_border_width(GTK_CONTAINER(adevice_vbox), 5);
gtk_container_add(GTK_CONTAINER(adevice_frame), adevice_vbox);
-
- adevice_text = gtk_label_new(_("(empty means default)"));
- gtk_box_pack_start_defaults(GTK_BOX(adevice_vbox), adevice_text);
adevice_entry = gtk_entry_new();
gtk_entry_set_text(GTK_ENTRY(adevice_entry), audiodev);