mmol, esd and compiling from 0.9.48 source


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