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:
parent
ebe658d00d
commit
6cf9c67d51
@ -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
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user