Subject: mmol, esd and compiling from 0.9.48 source
anvil@digithought.net
Date: Fri Jun 16 2000 - 01:08:15 MDT
> There are various software mixing solutions (such as esound) which
attempt
> to solve this problem, but the applications need to support them
> explicitly.
I wrote a little quick modification to samuels driver to support esd ,
although it's far from perfect
(NOTE , quick) so the startup sound might sound very weird, however once
in macos it should work
good (it's hardcoded to 44khz / 16bit stereo , so don't change unless
you want funny sounds)
I attatched my mod.
You will also need to include -lesd in the Makefile of MOL.
> In file included from monitor.c:38:
> ../include/dis-asm.h:13: bfd.h: No such file or directory
The bfd.h file should be in the kernel includes I think , I had that
problem too
but I don't remember what was lacking.
/Fredrik
/*
* Creation Date: <2000/05/28 02:37:51 samuel>
* Time-stamp: <2000/06/03 18:11:08 samuel>
*
* <osi_sound.c>
*
* Sound Driver
*
* Copyright (C) 2000 Samuel Rydh (samuel@ibrium.se)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation
*
*/
#include "mol_config.h"
#define VERBOSE
#include <linux/soundcard.h>
#include <signal.h>
#include <sys/ioctl.h>
#include "driver_mgr.h"
#include "debugger.h"
#include "os_interface.h"
#include "verbose.h"
#include "memory.h"
#include "thread.h"
#include "res_manager.h"
#include <esd.h>
esd_format_t esd_format;
SET_VERBOSE_NAME("osi_sound");
static int osi_sound_init( void );
static void osi_sound_cleanup( void );
static int osip_write( int sel, int *params );
static int osip_cntl( int sel, int *params );
static int osip_volume( int sel, int *params );
static int osip_flush( int sel, int *params );
static int osip_syncval( int sel, int *params );
static void play_startboing_entry( void *dummy );
driver_interface_t osi_sound_driver = {
"osi_sound", osi_sound_init, osi_sound_cleanup
};
typedef struct
{
int fd; /* /dev/dsp */
int esd; /* esd */
volatile int syncing;
volatile int th_active;
int mute;
int syncval;
} soundstate_t;
#define MAX_SYNC 10000
#define MIN_SYNC 101
#define DEFAULT_SYNC 400
static soundstate_t ss[1];
/************************************************************************/
/* FUNCTIONS */
/************************************************************************/
static int
osi_sound_init( void )
{
int newsync;
memset( &ss, 0, sizeof(ss) );
printm("osi_sound driver opened\n");
ss->fd = -1;
ss->esd= 0;
/* The osi procs must be registered even if /dev/dsp is unavailable */
os_interface_add_proc( OSI_SOUND_WRITE, osip_write );
os_interface_add_proc( OSI_SOUND_CNTL, osip_cntl );
os_interface_add_proc( OSI_SET_SOUND_VOLUME, osip_volume );
os_interface_add_proc( OSI_SOUND_FLUSH, osip_flush );
os_interface_add_proc( OSI_GETSET_SOUND_SYNCVAL, osip_syncval );
/* Note that we return 1 even if we fail (we run in "silent" mode) */
if( get_bool_res("disable_osi_sound")==1 ){
LOG("*** sound disabled by user ***\n");
return 1;
}
newsync = -1;
osip_syncval( OSI_GETSET_SOUND_SYNCVAL, &newsync );
if( get_bool_res("use_esd")==1)
{
esd_format=ESD_BITS16|ESD_STEREO|ESD_STREAM|ESD_PLAY;
ss->fd=esd_open_sound(NULL);
esd_unlock(ss->fd);
close(ss->fd);
if(ss->fd>=0)
{
printm("osi_sound : using EsounD\n");
ss->esd=1;
ss->fd=esd_play_stream_fallback(esd_format,44100,NULL,"MacOnLinux");
}
else
{
printm("----> Failed to open EsounD connection - Sound Disabled\n");
printm("osi_sound : try unlock the esd demon\n");
ss->esd=0;
}
}
else
{
printm("dsp\n");
ss->fd = open( "/dev/dsp", O_WRONLY | O_NONBLOCK );
if( ss->fd < 0 ){
printm("----> Failed to open /dev/dsp - Sound Disabled\n");
return 1;
}
}
if( get_bool_res("play_startboing") )
create_thread( play_startboing_entry, NULL, "startboing" );
return 1;
}
static void
osi_sound_cleanup( void )
{
os_interface_remove_proc( OSI_SOUND_WRITE );
os_interface_remove_proc( OSI_SOUND_CNTL );
os_interface_remove_proc( OSI_SET_SOUND_VOLUME );
os_interface_remove_proc( OSI_SOUND_FLUSH );
os_interface_remove_proc( OSI_GETSET_SOUND_SYNCVAL );
}
/* phys_buffer len */
static int
osip_write( int sel, int *params )
{
char *buf;
int ret, s=params[1];
if( ss->fd < 0)
return s;
ss->syncing=0;
if( mphys_to_lvptr( params[0], &buf ) < 0 ) {
LOG("osi_sound: Bad address %08X!\n", params[0] );
return -1;
}
if( !ss->mute )
ret = write( ss->fd , buf, s );
else
ret = s;
if( ret < 0 )
return (errno == EAGAIN)? 0 : -1;
return ret;
}
static void
_do_flush( void *dummy )
{
/* thread entry */
if( !ss->syncing )
return;
ss->syncing=0;
if( ss->fd != -1 ) {
sigset_t set, oldmask;
sigfillset( &set );
pthread_sigmask( SIG_BLOCK, &set, &oldmask );
TEMP_FAILURE_RETRY( ioctl( ss->fd, SNDCTL_DSP_SYNC, NULL ));
pthread_sigmask( SIG_SETMASK, &oldmask, NULL );
}
ss->th_active--;
}
/* phys_buffer len */
static int
osip_flush( int sel, int *params )
{
if (ss->fd < 0 )
return 0;
/* Is there a way to force /dev/dsp to flush the pipe *without*
* blocking? SNDCTL_DSP_SYNC does block...
*/
if( !ss->syncing ) {
ss->syncing=1;
if( ss->th_active <= 0 ) {
ss->th_active++;
create_thread( _do_flush, NULL, "sound_sync" );
}
}
return 0;
}
/* hwVolume, speakerVolume, hwMute */
static int
osip_volume( int sel, int *params )
{
/* XXX: Verify that lvol och rvol are not interchanged... */
int vol, lvol = (params[0] & 0xffff0000) >> 16;
int rvol = params[0] & 0xffff;
if( ss->fd < 0 )
return 0;
/* printm("New volume %x ", params[0]); */
lvol = lvol * 0x64/0x100;
rvol = rvol * 0x64/0x100;
if( lvol > 0x64 )
lvol = 0x64;
if( rvol > 0x64 )
rvol = 0x64;
vol = lvol*0x100 | rvol;
/* printm("(%x)\n", vol); */
ss->mute = params[2] ? 1:0;
ioctl( ss->fd, SOUND_MIXER_WRITE_VOLUME, &vol );
/* ioctl( ss->fd, SOUND_MIXER_WRITE_SPEAKER, &vol ); */
return 0;
}
/* new_value [-0=read, -1=default] */
static int
osip_syncval( int sel, int *params )
{
int newsync = params[0];
int oldsync = ss->syncval;
if( newsync < 0 )
if( (newsync = get_numeric_res( "sound_sync_value" )) < 0 )
newsync = DEFAULT_SYNC;
if( newsync > 0 && newsync < MIN_SYNC )
newsync = MIN_SYNC;
if( newsync > MAX_SYNC )
newsync = MAX_SYNC;
if( newsync > 0 )
ss->syncval = newsync;
printm("Sound syncvalue: %ld\n", ss->syncval );
return oldsync;
}
/* format, sampleRate, sampleSize, numChannels */
static int
osip_cntl( int sel, int *params )
{
#define MULTIBYTE_CHARS
ulong rate, format, stereo;
enum {
rate48khz = (long)0xBB800000, /* 48000.00000 in fixed-point */
rate44khz = (long)0xAC440000, /* 44100.00000 in fixed-point */
rate22050hz = 0x56220000, /* 22050.00000 in fixed-point */
rate22khz = 0x56EE8BA3, /* 22254.54545 in fixed-point */
rate11khz = 0x2B7745D1, /* 11127.27273 in fixed-point */
rate11025hz = 0x2B110000 /* 11025.00000 in fixed-point */
};
if( ss->fd < 0 )
return 0;
/* printm("osip_cntl: %d %d %d %d\n", params[0], params[1], params[2], params[3] ); */
ioctl( ss->fd, SNDCTL_DSP_RESET, 0);
switch( (unsigned long)params[0] ){
case 'raw ':
format = AFMT_U8;
/* printm("Sound format 'raw '\n"); */
break;
default:
case 'twos':
format = AFMT_S16_BE;
/* printm("Sound format 'twos'\n"); */
break;
}
ioctl(ss->fd, SNDCTL_DSP_SETFMT, &format);
stereo = (params[3] == 2 );
ioctl(ss->fd, SNDCTL_DSP_STEREO, &stereo );
switch( params[1] ){
case rate48khz:
rate = 48200; /* probably unsupported by driver */
break;
case rate44khz:
rate = 44100;
break;
case rate22050hz:
case rate22khz:
rate = 22050;
break;
case rate11khz:
case rate11025hz:
rate = 11025;
break;
default:
printm("Unknown sample rate!\n");
rate = 22050;
}
/* printm("rate: %ld\n", rate ); */
ioctl( ss->fd, SNDCTL_DSP_SPEED, &rate );
return 0;
}
static void
play_startboing_entry( void *dummy )
{
sigset_t oldmask, set;
char *name = get_str_res("startboing_file");
char buf[512], *p;
int fd, n, n2, ret;
int format = AFMT_S16_BE;
int rate = 22050;
int stereo = 1;
if( ss->fd < 0 )
return;
fd = open( name, O_RDONLY );
if( fd < 0 ) {
printm("Could not open '%s'", name);
return;
}
if(!ss->esd)
{
ioctl( ss->fd, SNDCTL_DSP_RESET, 0);
ioctl( ss->fd, SNDCTL_DSP_SETFMT, &format);
ioctl( ss->fd, SNDCTL_DSP_SPEED, &rate);
ioctl( ss->fd, SNDCTL_DSP_STEREO, &stereo );
n = lseek( fd, 0, SEEK_END );
lseek( fd, 0, SEEK_SET );
}
while( n>0) {
ret = read( fd, buf, sizeof(buf) );
if( ret < 0 )
break;
n -= ret;
for( p=buf; ret>0; p+=n2, ret-=n2 ) {
n2 = write( ss->fd , p, ret );
if( n2 == -1 && (errno != EAGAIN && errno != EINTR) ) {
printm("X\n");
break;
} else if( n2 == -1 ) {
n2 = 0;
usleep(1);
}
}
}
if(!ss->esd)
{
sigfillset( &set );
pthread_sigmask( SIG_BLOCK, &set, &oldmask );
TEMP_FAILURE_RETRY( ioctl( ss->fd, SNDCTL_DSP_SYNC, NULL ));
pthread_sigmask( SIG_SETMASK, &oldmask, NULL );
}
close( fd );
}
This archive was generated by hypermail 2a24 : Fri Jun 16 2000 - 01:12:10 MDT