audio backends can be called from different threads, so use a mutex

to protect global objects.

from Thomas Pfaff, thanks
This commit is contained in:
jakemsr 2009-01-16 04:15:46 +00:00
parent ebe658d00d
commit 6cf9c67d51
2 changed files with 67 additions and 37 deletions

View File

@ -1,4 +1,4 @@
# $OpenBSD: Makefile,v 1.60 2008/12/28 22:31:51 jakemsr Exp $ # $OpenBSD: Makefile,v 1.61 2009/01/16 04:15:46 jakemsr Exp $
COMMENT-main= Multimedia player for the X Window System COMMENT-main= Multimedia player for the X Window System
COMMENT-vorbis= Ogg Vorbis input plugin for XMMS COMMENT-vorbis= Ogg Vorbis input plugin for XMMS
@ -9,7 +9,7 @@ SHARED_ONLY= Yes
VERSION= 1.2.11 VERSION= 1.2.11
DISTNAME= xmms-${VERSION} DISTNAME= xmms-${VERSION}
PKGNAME-main= xmms-${VERSION}p3 PKGNAME-main= xmms-${VERSION}p4
PKGNAME-vorbis= xmms-vorbis-${VERSION}p0 PKGNAME-vorbis= xmms-vorbis-${VERSION}p0
PKGNAME-mikmod= xmms-mikmod-${VERSION}p0 PKGNAME-mikmod= xmms-mikmod-${VERSION}p0
PKGNAME-mp3= xmms-mp3-${VERSION}p0 PKGNAME-mp3= xmms-mp3-${VERSION}p0

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2008 Thomas Pfaff <tpfaff@tp76.info> * Copyright (c) 2008,2009 Thomas Pfaff <tpfaff@tp76.info>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -14,23 +14,23 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gtk/gtk.h> #include <gtk/gtk.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <sndio.h>
#include <xmms/plugin.h>
#include <xmms/i18n.h>
#include <libxmms/util.h> #include <libxmms/util.h>
#include <libxmms/configfile.h> #include <libxmms/configfile.h>
#include <pthread.h>
#include <sndio.h>
#include <xmms/i18n.h>
#include <xmms/plugin.h>
#define VERSION "1.0"
#define XMMS_MAXVOL 100 #define XMMS_MAXVOL 100
static void op_about (void);
static void op_init (void); static void op_init (void);
static void op_about (void);
static void op_configure (void); static void op_configure (void);
static void op_get_volume (int *, int *); static void op_get_volume (int *, int *);
static void op_set_volume (int, int); static void op_set_volume (int, int);
@ -57,6 +57,7 @@ static long long wrpos;
static int paused; static int paused;
static int volume = XMMS_MAXVOL; static int volume = XMMS_MAXVOL;
static long bytes_per_sec; static long bytes_per_sec;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static GtkWidget *configure_win; static GtkWidget *configure_win;
static GtkWidget *adevice_entry; static GtkWidget *adevice_entry;
@ -65,7 +66,7 @@ static gchar *audiodev;
static OutputPlugin sndio_op = { static OutputPlugin sndio_op = {
NULL, NULL,
NULL, NULL,
"sndio Output Plugin", "sndio Output Plugin " VERSION,
op_init, op_init,
op_about, op_about,
op_configure, op_configure,
@ -98,7 +99,7 @@ op_about (void)
about = xmms_show_message ( about = xmms_show_message (
"About sndio Output Plugin", "About sndio Output Plugin",
"XMMS sndio Output Plugin\n\n" "XMMS sndio Output Plugin " VERSION "\n\n"
"Written by Thomas Pfaff <tpfaff@tp76.info>\n", "Written by Thomas Pfaff <tpfaff@tp76.info>\n",
"Ok", FALSE, NULL, NULL); "Ok", FALSE, NULL, NULL);
@ -122,16 +123,20 @@ op_init (void)
static void static void
op_get_volume (int *left, int *right) op_get_volume (int *left, int *right)
{ {
pthread_mutex_lock (&mutex);
*left = *right = volume; *left = *right = volume;
pthread_mutex_unlock (&mutex);
} }
static void static void
op_set_volume (int left, int right) op_set_volume (int left, int right)
{ {
/* Ignore balance control, so use unattenuated channel. */ /* Ignore balance control, so use unattenuated channel. */
pthread_mutex_lock (&mutex);
volume = left > right ? left : right; volume = left > right ? left : right;
if (hdl != NULL) if (hdl != NULL)
sio_setvol (hdl, volume * SIO_MAXVOL / XMMS_MAXVOL); sio_setvol (hdl, volume * SIO_MAXVOL / XMMS_MAXVOL);
pthread_mutex_unlock (&mutex);
} }
static int static int
@ -139,13 +144,12 @@ op_open (AFormat fmt, int rate, int nch)
{ {
struct sio_par askpar; struct sio_par askpar;
if (strlen(audiodev) == 0) pthread_mutex_lock (&mutex);
hdl = sio_open (NULL, SIO_PLAY, 0);
else hdl = sio_open (strlen (audiodev) > 0 ? audiodev : NULL, SIO_PLAY, 0);
hdl = sio_open (audiodev, SIO_PLAY, 0);
if (hdl == NULL) { if (hdl == NULL) {
fprintf (stderr, "%s: failed to open audio device\n", __func__); fprintf (stderr, "%s: failed to open audio device\n", __func__);
return 0; goto error;
} }
sio_initpar (&par); sio_initpar (&par);
@ -189,8 +193,7 @@ op_open (AFormat fmt, int rate, int nch)
break; break;
default: default:
fprintf (stderr, "%s: unknown format requested\n", __func__); fprintf (stderr, "%s: unknown format requested\n", __func__);
op_close (); goto error;
return 0;
} }
par.pchan = nch; par.pchan = nch;
par.rate = rate; par.rate = rate;
@ -201,8 +204,7 @@ op_open (AFormat fmt, int rate, int nch)
askpar = par; askpar = par;
if (!sio_setpar (hdl, &par) || !sio_getpar (hdl, &par)) { if (!sio_setpar (hdl, &par) || !sio_getpar (hdl, &par)) {
fprintf (stderr, "%s: failed to set parameters\n", __func__); fprintf (stderr, "%s: failed to set parameters\n", __func__);
op_close (); goto error;
return 0;
} }
if ((par.bits == 16 && par.le != askpar.le) || if ((par.bits == 16 && par.le != askpar.le) ||
@ -215,50 +217,65 @@ op_open (AFormat fmt, int rate, int nch)
"format that is not supported by the audio device.\n\n" "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 aucat(1) server running.",
"OK", FALSE, NULL, NULL); "OK", FALSE, NULL, NULL);
op_close (); goto error;
return 0;
} }
wrpos = 0;
rdpos = 0; rdpos = 0;
wrpos = 0;
sio_onmove (hdl, onmove_cb, NULL); sio_onmove (hdl, onmove_cb, NULL);
op_set_volume (volume, volume);
paused = 0; paused = 0;
if (!sio_start (hdl)) { if (!sio_start (hdl)) {
fprintf (stderr, "%s: failed to start audio device\n", fprintf (stderr, "%s: failed to start audio device\n",
__func__); __func__);
op_close (); goto error;
return 0;
} }
bytes_per_sec = par.bps * par.pchan * par.rate; bytes_per_sec = par.bps * par.pchan * par.rate;
return 1; pthread_mutex_unlock (&mutex);
op_set_volume (volume, volume);
return TRUE;
error:
pthread_mutex_unlock (&mutex);
op_close ();
return FALSE;
} }
static void static void
op_write (void *ptr, int len) op_write (void *ptr, int len)
{ {
if (!paused) if (!paused) {
wrpos += sio_write (hdl, ptr, len); /* Do not lock sio_write as this will cause the GUI thread
to block waiting for a blocked sio_write to return. */
int bytes = sio_write (hdl, ptr, len);
pthread_mutex_lock (&mutex);
wrpos += bytes;
pthread_mutex_unlock (&mutex);
}
} }
static void static void
op_close (void) op_close (void)
{ {
pthread_mutex_lock (&mutex);
if (hdl != NULL) { if (hdl != NULL) {
sio_close (hdl); sio_close (hdl);
hdl = NULL; hdl = NULL;
} }
pthread_mutex_unlock (&mutex);
} }
static void static void
op_seek (int time_ms) op_seek (int time_ms)
{ {
int bufused = (rdpos < 0) ? wrpos : wrpos - rdpos; int bufused;
pthread_mutex_lock (&mutex);
bufused = (rdpos < 0) ? wrpos : wrpos - rdpos;
rdpos = time_ms / 1000 * bytes_per_sec; rdpos = time_ms / 1000 * bytes_per_sec;
wrpos = rdpos + bufused; wrpos = rdpos + bufused;
pthread_mutex_unlock (&mutex);
} }
static void static void
@ -283,22 +300,35 @@ op_playing (void)
static int static int
op_get_output_time (void) op_get_output_time (void)
{ {
return hdl ? rdpos * 1000 / bytes_per_sec : 0; int time_ms;
pthread_mutex_lock (&mutex);
time_ms = hdl ? rdpos * 1000 / bytes_per_sec : 0;
pthread_mutex_unlock (&mutex);
return time_ms;
} }
static int static int
op_get_written_time (void) op_get_written_time (void)
{ {
return hdl ? wrpos * 1000 / bytes_per_sec : 0; int time_ms;
pthread_mutex_lock (&mutex);
time_ms = hdl ? wrpos * 1000 / bytes_per_sec : 0;
pthread_mutex_unlock (&mutex);
return time_ms;
} }
static void static void
onmove_cb (void *addr, int delta) onmove_cb (void *addr, int delta)
{ {
pthread_mutex_lock (&mutex);
rdpos += delta * (int)(par.bps * par.pchan); rdpos += delta * (int)(par.bps * par.pchan);
pthread_mutex_unlock (&mutex);
} }
static void op_configure(void) static void
op_configure(void)
{ {
GtkWidget *dev_vbox; GtkWidget *dev_vbox;
GtkWidget *adevice_frame, *adevice_text, *adevice_vbox; GtkWidget *adevice_frame, *adevice_text, *adevice_vbox;