[Liboss-commit] CVS: liboss/lib esddsp.c,NONE,1.1 Makefile.am,1.12,1.13
Brought to you by:
thesin
|
From: Alexander S. <mrv...@us...> - 2002-10-18 22:11:46
|
Update of /cvsroot/liboss/liboss/lib
In directory usw-pr-cvs1:/tmp/cvs-serv7103/lib
Modified Files:
Makefile.am
Added Files:
esddsp.c
Log Message:
Oops, this is kinda needed
--- NEW FILE: esddsp.c ---
/* Evil evil evil hack to get OSS apps to cooperate with esd
* Copyright (C) 1998, 1999 Manish Singh <yo...@gi...>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#define DSP_DEBUG
/* This lets you run multiple instances of x11amp by setting the X11AMPNUM
environment variable. Only works on glibc2.
*/
/* #define MULTIPLE_X11AMP */
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
#ifdef DSP_DEBUG
#define DPRINTF(format, args...) printf(format, ## args)
#else
#define DPRINTF(format, args...)
#endif
#include "config.h"
#include <dlfcn.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#ifdef HAVE_MACHINE_SOUNDCARD_H
# include <machine/soundcard.h>
#else
# ifdef HAVE_SOUNDCARD_H
# include <soundcard.h>
# else
# include <sys/soundcard.h>
# endif
#endif
#include <esd.h>
/* BSDI has this functionality, but not define :() */
#if defined(RTLD_NEXT)
#define REAL_LIBC RTLD_NEXT
#else
#define REAL_LIBC ((void *) -1L)
#endif
#if defined(__FreeBSD__) || defined(__bsdi__)
typedef unsigned long request_t;
#else
typedef int request_t;
#endif
static int sndfd = -1, mixfd = -1;
static int settings = 0, done = 0;
static char *ident = NULL, *mixer = NULL;
static int use_mixer = 0;
#define OSS_VOLUME_BASE 50
#define ESD_VOL_TO_OSS(left, right) (short int) \
(((OSS_VOLUME_BASE * (right) / ESD_VOLUME_BASE) << 8) | \
(OSS_VOLUME_BASE * (left) / ESD_VOLUME_BASE))
#define OSS_VOL_TO_ESD_LEFT(vol) \
(ESD_VOLUME_BASE * (vol & 0xff) / OSS_VOLUME_BASE)
#define OSS_VOL_TO_ESD_RIGHT(vol) \
(ESD_VOLUME_BASE * ((vol >> 8) & 0xff) / OSS_VOLUME_BASE)
static void
get_volume (int *left, int *right)
{
int vol;
if (read (mixfd, &vol, sizeof (vol)) != sizeof (vol))
*left = *right = ESD_VOLUME_BASE;
else
{
*left = OSS_VOL_TO_ESD_LEFT (vol);
*right = OSS_VOL_TO_ESD_RIGHT (vol);
}
}
static void
set_volume (int left, int right)
{
int vol = ESD_VOL_TO_OSS (left, right);
write (mixfd, &vol, sizeof (vol));
}
static void
dsp_init (void)
{
if (!ident)
{
char *str = getenv ("ESDDSP_NAME");
ident = malloc (ESD_NAME_MAX);
strncpy (ident, (str ? str : "esddsp"), ESD_NAME_MAX);
if (getenv ("ESDDSP_MIXER"))
{
use_mixer = 1;
str = getenv ("HOME");
if (str)
{
mixer = malloc (strlen (str) + strlen (ident) + 10);
sprintf (mixer, "%s/.esddsp_%s", str, ident);
}
else
{
fprintf (stderr, "esddsp: can't get home directory\n");
exit (1);
}
DPRINTF ("mixer settings file: %s\n", mixer);
}
}
}
static void
mix_init (int *esd, int *player)
{
esd_info_t *all_info;
esd_player_info_t *player_info;
if (*esd < 0 && (*esd = esd_open_sound (NULL)) < 0)
return;
if (*player < 0)
{
all_info = esd_get_all_info (*esd);
if (all_info)
{
for (player_info = all_info->player_list; player_info;
player_info = player_info->next)
if (!strcmp(player_info->name, ident))
{
*player = player_info->source_id;
break;
}
esd_free_all_info (all_info);
}
}
}
int
oss_open (const char *pathname, int flags, ...)
{
static int (*func) (const char *, int, mode_t) = NULL;
va_list args;
mode_t mode;
if (!func)
func = (int (*) (const char *, int, mode_t)) dlsym (REAL_LIBC, "open");
dsp_init ();
va_start (args, flags);
mode = va_arg (args, int);
va_end (args);
if (!strcmp (pathname, "/dev/dsp"))
{
if (!getenv ("ESPEAKER"))
{
int ret;
flags |= O_NONBLOCK;
if ((ret = (*func) (pathname, flags, mode)) >= 0)
return ret;
}
DPRINTF ("hijacking /dev/dsp open, and taking it to esd...\n");
settings = done = 0;
return (sndfd = esd_open_sound (NULL));
}
else if (use_mixer && !strcmp (pathname, "/dev/mixer"))
{
DPRINTF ("hijacking /dev/mixer open, and taking it to esd...\n");
return (mixfd = (*func) (mixer, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR));
}
else
return (*func) (pathname, flags, mode);
}
static int
dspctl (int fd, request_t request, void *argp)
{
static esd_format_t fmt = ESD_STREAM | ESD_PLAY | ESD_MONO;
static int speed;
int *arg = (int *) argp;
DPRINTF ("hijacking /dev/dsp ioctl, and sending it to esd "
"(%d : %x - %p)\n", fd, request, argp);
switch (request)
{
case SNDCTL_DSP_RESET:
case SNDCTL_DSP_POST:
break;
case SNDCTL_DSP_SETFMT:
fmt |= (*arg & 0x30) ? ESD_BITS16 : ESD_BITS8;
settings |= 1;
break;
case SNDCTL_DSP_SPEED:
speed = *arg;
settings |= 2;
break;
case SNDCTL_DSP_STEREO:
fmt &= ~ESD_MONO;
fmt |= (*arg) ? ESD_STEREO : ESD_MONO;
break;
case SNDCTL_DSP_GETBLKSIZE:
*arg = ESD_BUF_SIZE;
break;
case SNDCTL_DSP_GETFMTS:
*arg = 0x38;
break;
#ifdef SNDCTL_DSP_GETCAPS
case SNDCTL_DSP_GETCAPS:
*arg = 0;
break;
#endif
case SNDCTL_DSP_GETOSPACE:
{
audio_buf_info *bufinfo = (audio_buf_info *) argp;
bufinfo->bytes = ESD_BUF_SIZE;
}
break;
default:
DPRINTF ("unhandled /dev/dsp ioctl (%x - %p)\n", request, argp);
break;
}
if (settings == 3 && !done)
{
int proto = ESD_PROTO_STREAM_PLAY;
done = 1;
if (write (sndfd, &proto, sizeof (proto)) != sizeof (proto))
return -1;
if (write (sndfd, &fmt, sizeof (fmt)) != sizeof (fmt))
return -1;
if (write (sndfd, &speed, sizeof (speed)) != sizeof (speed))
return -1;
if (write (sndfd, ident, ESD_NAME_MAX) != ESD_NAME_MAX)
return -1;
fmt = ESD_STREAM | ESD_PLAY | ESD_MONO;
speed = 0;
if (use_mixer)
{
int esd = -1, player = -1;
int left, right;
while (player < 0)
mix_init (&esd, &player);
get_volume (&left, &right);
DPRINTF ("panning %d - %d %d\n", player, left, right);
esd_set_stream_pan (esd, player, left, right);
}
}
return 0;
}
int
mixctl (int fd, request_t request, void *argp)
{
static int esd = -1, player = -1;
static int left, right;
int *arg = (int *) argp;
DPRINTF ("hijacking /dev/mixer ioctl, and sending it to esd "
"(%d : %x - %p)\n", fd, request, argp);
switch (request)
{
case SOUND_MIXER_READ_DEVMASK:
*arg = 5113;
break;
case SOUND_MIXER_READ_PCM:
mix_init (&esd, &player);
if (player > 0)
{
esd_info_t *all_info;
all_info = esd_get_all_info (esd);
if (all_info)
{
esd_player_info_t *player_info;
for (player_info = all_info->player_list; player_info;
player_info = player_info->next)
if (player_info->source_id == player)
{
*arg = ESD_VOL_TO_OSS (player_info->left_vol_scale,
player_info->right_vol_scale);
}
esd_free_all_info (all_info);
}
else
return -1;
}
else
{
get_volume (&left, &right);
*arg = ESD_VOL_TO_OSS (left, right);
}
break;
case SOUND_MIXER_WRITE_PCM:
mix_init (&esd, &player);
left = OSS_VOL_TO_ESD_LEFT (*arg);
right = OSS_VOL_TO_ESD_RIGHT (*arg);
set_volume (left, right);
if (player > 0)
{
DPRINTF ("panning %d - %d %d\n", player, left, right);
esd_set_stream_pan (esd, player, left, right);
}
break;
default:
DPRINTF ("unhandled /dev/mixer ioctl (%x - %p)\n", request, argp);
break;
}
return 0;
}
int
oss_ioctl (int fd, request_t request, ...)
{
static int (*func) (int, request_t, void *) = NULL;
va_list args;
void *argp;
if (!func)
func = (int (*) (int, request_t, void *)) dlsym (REAL_LIBC, "ioctl");
va_start (args, request);
argp = va_arg (args, void *);
va_end (args);
if (fd == sndfd)
return dspctl (fd, request, argp);
else if (fd == mixfd) {
if(use_mixer)
return mixctl (fd, request, argp);
} else { /* (fd != sndfd && fd != mixfd) */
return (*func) (fd, request, argp);
}
return 0;
}
int
oss_close (int fd)
{
static int (*func) (int) = NULL;
if (!func)
func = (int (*) (int)) dlsym (REAL_LIBC, "close");
if (fd == sndfd)
sndfd = -1;
else if (fd == mixfd)
mixfd = -1;
return (*func) (fd);
}
#ifdef MULTIPLE_X11AMP
#include <socketbits.h>
#include <sys/param.h>
#include <sys/un.h>
#define ENVSET "X11AMPNUM"
int
unlink (const char *filename)
{
static int (*func) (const char *) = NULL;
char *num;
if (!func)
func = (int (*) (const char *)) dlsym (REAL_LIBC, "unlink");
if (!strcmp (filename, "/tmp/X11Amp_CTRL") && (num = getenv (ENVSET)))
{
char buf[PATH_MAX] = "/tmp/X11Amp_CTRL";
strcat (buf, num);
return (*func) (buf);
}
else
return (*func) (filename);
}
typedef int (*sa_func_t) (int, struct sockaddr *, int);
static int
sockaddr_mangle (sa_func_t func, int fd, struct sockaddr *addr, int len)
{
char *num;
if (!strcmp (((struct sockaddr_un *) addr)->sun_path, "/tmp/X11Amp_CTRL")
&& (num = getenv(ENVSET)))
{
int ret;
char buf[PATH_MAX] = "/tmp/X11Amp_CTRL";
struct sockaddr_un *new_addr = malloc (len);
strcat (buf, num);
memcpy (new_addr, addr, len);
strcpy (new_addr->sun_path, buf);
ret = (*func) (fd, (struct sockaddr *) new_addr, len);
free (new_addr);
return ret;
}
else
return (*func) (fd, addr, len);
}
int
bind (int fd, struct sockaddr *addr, int len)
{
static sa_func_t func = NULL;
if (!func)
func = (sa_func_t) dlsym (REAL_LIBC, "bind");
return sockaddr_mangle (func, fd, addr, len);
}
int
connect (int fd, struct sockaddr *addr, int len)
{
static sa_func_t func = NULL;
if (!func)
func = (sa_func_t) dlsym (REAL_LIBC, "connect");
return sockaddr_mangle (func, fd, addr, len);
}
#endif /* MULTIPLE_X11AMP */
#else /* __GNUC__ */
void
nogcc (void)
{
ident = NULL;
}
#endif /* __GNUC__ */
Index: Makefile.am
===================================================================
RCS file: /cvsroot/liboss/liboss/lib/Makefile.am,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- Makefile.am 18 Oct 2002 22:00:25 -0000 1.12
+++ Makefile.am 18 Oct 2002 22:11:41 -0000 1.13
@@ -2,7 +2,7 @@
## Process this file with automake to produce Makefile.in
##
-CFLAGS = @CFLAGS@ $(COREAUDIO_CFLAGS) -DHAVE_SOUNDCARD_H -DLIBOSS_INTERNAL
+CFLAGS = @CFLAGS@ $(COREAUDIO_CFLAGS) -DHAVE_SOUNDCARD_H -DLIBOSS_INTERNAL -Ddlsym=dlsym_prepend_underscore
lib_LTLIBRARIES = liboss.la
|