Added global sound control option in bochsrc and config interface

- added 'sound' option to select the driver and the wave output device
  (see bochsrc sample for details)
- the wave device option of sb16 and es1370 is now only used to set up the
  wave input device (if necessary)
- cleaned up the speaker code to initialize the 'sound' case correctly
This commit is contained in:
Volker Ruppert 2013-06-24 19:19:12 +00:00
parent c42afb0a2d
commit 192aa1f369
20 changed files with 145 additions and 97 deletions

View File

@ -723,6 +723,16 @@ debugger_log: -
#=======================================================================
parport1: enabled=1, file="parport.out"
#=======================================================================
# SOUND:
# This defines the lowlevel sound driver and the wave (PCM) output device
# to be used by sound output devices. Possible values for the driver
# parameter are 'default', 'dummy' (no output), 'alsa' (if present) and
# 'sdl' (if present). For some drivers the wave output device must be
# specified.
#=======================================================================
sound: driver=default, wavedev=/dev/dsp
#=======================================================================
# SPEAKER:
# This defines the PC speaker output mode. In the 'sound' mode the beep
@ -750,7 +760,8 @@ speaker: enabled=1, mode=sound
# 2=SMF file output, including headers
# 3=output the midi data stream to the file (no midi headers and no
# delta times, just command and data bytes)
# wave: This is the device/file where wave output is stored
# wave: This is the device to be used as wave input source. The wave output
device must be specified with the 'sound' bochsrc option if necessary.
# wavemode:
# 0=no data
# 1=output to device (system dependent. wave denotes the device driver)
@ -772,7 +783,6 @@ speaker: enabled=1, mode=sound
# Examples for output devices:
# sb16: midimode=1, midi="", wavemode=1, wave="" # win32
# sb16: midimode=1, midi=alsa:128:0, wavemode=1, wave=alsa # Linux with ALSA
# sb16: wavemode=1, wave=sdl # use SDL audio (if present) for output
#=======================================================================
#sb16: midimode=1, midi=/dev/midi00, wavemode=1, wave=/dev/dsp, loglevel=2, log=sb16.log, dmatimer=600000
@ -786,7 +796,6 @@ speaker: enabled=1, mode=sound
# Examples:
# es1370: enabled=1, wavedev="" # win32
# es1370: enabled=1, wavedev=alsa # Linux with ALSA
# es1370: enabled=1, wavedev=sdl # use SDL audio (if present) for output
#=======================================================================
#es1370: enabled=1, wavedev=alsa

View File

@ -252,6 +252,12 @@ network
bootrom
sound
lowlevel
driver
wavedev
speaker
enabled
mode
sb16
enabled
midifile

View File

@ -1465,6 +1465,22 @@ void bx_init_options()
// sound subtree
bx_list_c *sound = new bx_list_c(root_param, "sound", "Sound Configuration");
sound->set_options(sound->USE_TAB_WINDOW | sound->SHOW_PARENT);
bx_list_c *soundlow = new bx_list_c(sound, "lowlevel", "Lowlevel Sound Configuration");
soundlow->set_options(soundlow->SHOW_PARENT | soundlow->SERIES_ASK);
soundlow->set_enabled(BX_SUPPORT_SOUNDLOW);
#if BX_SUPPORT_SOUNDLOW
new bx_param_string_c(soundlow,
"driver",
"Sound driver",
"This is the lowlevel driver to use for emulated sound devices",
"default", BX_PATHNAME_LEN);
new bx_param_filename_c(soundlow,
"wavedev",
"Wave output device",
"This is the device where the wave output is sent to",
"", BX_PATHNAME_LEN);
#endif
// sound device options initialized in the devive plugin code
// misc options subtree
@ -2753,6 +2769,23 @@ static int parse_line_formatted(const char *context, int num_params, char *param
}
}
}
else if (!strcmp(params[0], "sound")) {
#if BX_SUPPORT_SOUNDLOW
for (i=1; i<num_params; i++) {
if (!strncmp(params[i], "driver=", 7)) {
SIM->get_param_string(BXPN_SOUND_DRIVER)->set(&params[i][7]);
}
else if (!strncmp(params[i], "wavedev=", 8)) {
SIM->get_param_string(BXPN_SOUND_WAVEDEV)->set(&params[i][8]);
}
else {
BX_ERROR(("%s: unknown parameter for sound ignored.", context));
}
}
#else
PARSE_ERR(("%s: Bochs is not compiled with lowlevel sound support", context));
#endif
}
else if (!strcmp(params[0], "gdbstub")) {
#if BX_GDBSTUB
if (num_params < 2) {

View File

@ -167,8 +167,10 @@ void bx_devices_c::init(BX_MEM_C *newmem)
#endif
#if BX_SUPPORT_SOUNDLOW
sound_enabled = is_sound_enabled();
if (sound_enabled)
if (sound_enabled) {
PLUG_load_plugin(soundmod, PLUGTYPE_CORE);
pluginSoundModCtl->init();
}
#endif
// PCI logic (i440FX)
pci.enabled = SIM->get_param_bool(BXPN_PCI_ENABLED)->get();
@ -1030,7 +1032,8 @@ bx_bool bx_devices_c::is_network_enabled(void)
bx_bool bx_devices_c::is_sound_enabled(void)
{
if (PLUG_device_present("es1370") ||
PLUG_device_present("sb16")) {
PLUG_device_present("sb16") ||
PLUG_device_present("speaker")) {
return 1;
}
return 0;

View File

@ -348,8 +348,8 @@ public:
#if BX_SUPPORT_SOUNDLOW
class BOCHSAPI bx_soundmod_ctl_stub_c : public bx_devmodel_c {
public:
virtual void* init_module(const char *type, logfunctions *dev) {
STUBFUNC(soundmod_ctl, init_module); return NULL;
virtual void* get_module() {
STUBFUNC(soundmod_ctl, get_module); return NULL;
}
virtual bx_bool beep_on(float frequency) {
return 0;

View File

@ -111,7 +111,7 @@ void es1370_init_options(void)
bx_param_filename_c *wavedev = new bx_param_filename_c(menu,
"wavedev",
"Wave device",
"This is the device where the wave output is sent to",
"This is the device to be used as wave input source",
"", BX_PATHNAME_LEN);
bx_list_c *deplist = new bx_list_c(NULL);
deplist->add(wavedev);
@ -172,13 +172,9 @@ bx_es1370_c::bx_es1370_c()
bx_es1370_c::~bx_es1370_c()
{
if (s.dac_outputinit) {
soundmod->closewaveoutput();
}
if (s.adc_inputinit) {
soundmod->closewaveinput();
}
delete soundmod;
SIM->get_bochs_root()->remove("es1370");
BX_DEBUG(("Exit"));
@ -204,19 +200,8 @@ void bx_es1370_c::init(void)
}
BX_ES1370_THIS pci_base_address[0] = 0;
char *wavedev = SIM->get_param_string("wavedev", base)->getptr();
if (!strcmp(wavedev, "sdl")) {
BX_ES1370_THIS soundmod = DEV_sound_init_module("sdl", BX_ES1370_THIS_PTR);
} else {
BX_ES1370_THIS soundmod = DEV_sound_init_module("default", BX_ES1370_THIS_PTR);
}
int ret = BX_ES1370_THIS soundmod->openwaveoutput(wavedev);
if (ret != BX_SOUNDLOW_OK) {
BX_ERROR(("could not open wave output device"));
BX_ES1370_THIS s.dac_outputinit = 0;
} else {
BX_ES1370_THIS s.dac_outputinit = 1;
}
BX_ES1370_THIS soundmod = DEV_sound_get_module();
BX_ES1370_THIS s.dac_outputinit = 1;
BX_ES1370_THIS s.adc_inputinit = 0;
BX_ES1370_THIS s.dac_nr_active = -1;

View File

@ -74,7 +74,7 @@ void sb16_init_options(void)
bx_param_filename_c *wavefile = new bx_param_filename_c(menu,
"wave",
"Wave file",
"This is the device/file where the wave output is stored",
"This is the device to be used as wave input source",
"", BX_PATHNAME_LEN);
bx_param_num_c *loglevel = new bx_param_num_c(menu,
"loglevel",
@ -227,8 +227,6 @@ bx_sb16_c::~bx_sb16_c(void)
finishvocfile();
break;
case 1:
if (DSP.outputinit != 0)
BX_SB16_OUTPUT->closewaveoutput();
if (DSP.inputinit != 0)
BX_SB16_OUTPUT->closewaveinput();
break;
@ -238,8 +236,6 @@ bx_sb16_c::~bx_sb16_c(void)
break;
}
delete(BX_SB16_OUTPUT);
delete [] DSP.dma.chunk;
if ((SIM->get_param_num(BXPN_SB16_LOGLEVEL)->get() > 0) && LOGFILE)
@ -281,15 +277,10 @@ void bx_sb16_c::init(void)
BX_SB16_THIS wavemode = SIM->get_param_num("wavemode", base)->get();
BX_SB16_THIS dmatimer = SIM->get_param_num("dmatimer", base)->get();
BX_SB16_THIS loglevel = SIM->get_param_num("loglevel", base)->get();
char *wavefile = SIM->get_param_string("wave", base)->getptr();
if ((BX_SB16_THIS wavemode == 1) || (BX_SB16_THIS midimode == 1)) {
// let the output functions initialize
if (!strcmp(wavefile, "sdl")) {
BX_SB16_OUTPUT = DEV_sound_init_module("sdl", BX_SB16_THISP);
} else {
BX_SB16_OUTPUT = DEV_sound_init_module("default", BX_SB16_THISP);
}
BX_SB16_OUTPUT = DEV_sound_get_module();
if (BX_SB16_OUTPUT == NULL) {
writelog(MIDILOG(2), "Couldn't initialize output devices. Output disabled.");
@ -301,14 +292,7 @@ void bx_sb16_c::init(void)
DSP.dma.chunk = new Bit8u[BX_SOUNDLOW_WAVEPACKETSIZE];
DSP.dma.chunkindex = 0;
if (BX_SB16_THIS wavemode == 1) {
int ret = BX_SB16_OUTPUT->openwaveoutput(wavefile);
if (ret != BX_SOUNDLOW_OK) {
writelog(WAVELOG(2), "Error: Could not open wave output device.");
BX_SB16_THIS wavemode = 0;
DSP.outputinit = 0;
} else {
DSP.outputinit = 1;
}
DSP.outputinit = 1;
}
DSP.inputinit = 0;
MPU.outputinit = 0;

View File

@ -29,14 +29,14 @@
#if (defined(linux) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)) && BX_SUPPORT_SOUNDLOW
#define LOG_THIS device->
#define LOG_THIS
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/soundcard.h>
bx_sound_linux_c::bx_sound_linux_c(logfunctions *dev)
:bx_sound_lowlevel_c(dev)
bx_sound_linux_c::bx_sound_linux_c()
:bx_sound_lowlevel_c()
{
#if BX_HAVE_ALSASOUND
alsa_seq.handle = NULL;
@ -737,7 +737,7 @@ void bx_sound_linux_c::record_timer_handler(void *this_ptr)
void bx_sound_linux_c::record_timer(void)
{
record_handler(this->device, record_packet_size);
record_handler(this, record_packet_size);
}
#endif

View File

@ -35,7 +35,7 @@
class bx_sound_linux_c : public bx_sound_lowlevel_c {
public:
bx_sound_linux_c(logfunctions *dev);
bx_sound_linux_c();
virtual ~bx_sound_linux_c();
virtual int get_type() {return BX_SOUNDLOW_LINUX;}

View File

@ -68,19 +68,43 @@ bx_soundmod_ctl_c::bx_soundmod_ctl_c()
soundmod = NULL;
}
void* bx_soundmod_ctl_c::init_module(const char *type, logfunctions *device)
bx_soundmod_ctl_c::~bx_soundmod_ctl_c()
{
if (!strcmp(type, "default")) {
soundmod = new BX_SOUND_LOWLEVEL_C(device);
#if BX_WITH_SDL
} else if (!strcmp(type, "sdl")) {
soundmod = new bx_sound_sdl_c(device);
#endif
} else if (!strcmp(type, "dummy")) {
soundmod = new bx_sound_lowlevel_c(device);
} else {
BX_PANIC(("unknown sound module type '%s'", type));
if (soundmod != NULL) {
soundmod->closewaveoutput();
}
delete soundmod;
}
void bx_soundmod_ctl_c::init()
{
const char *driver = SIM->get_param_string(BXPN_SOUND_DRIVER)->getptr();
const char *wavedev = SIM->get_param_string(BXPN_SOUND_WAVEDEV)->getptr();
if (!strcmp(driver, "default")) {
soundmod = new BX_SOUND_LOWLEVEL_C();
#if BX_HAVE_ALSASOUND
} else if (!strcmp(driver, "alsa")) {
soundmod = new bx_sound_linux_c();
wavedev = "alsa";
#endif
#if BX_WITH_SDL
} else if (!strcmp(driver, "sdl")) {
soundmod = new bx_sound_sdl_c();
#endif
} else if (!strcmp(driver, "dummy")) {
soundmod = new bx_sound_lowlevel_c();
} else {
BX_PANIC(("unknown lowlevel sound driver '%s'", driver));
return;
}
int ret = soundmod->openwaveoutput(wavedev);
if (ret != BX_SOUNDLOW_OK) {
BX_PANIC(("Could not open wave output device"));
}
}
void* bx_soundmod_ctl_c::get_module()
{
return soundmod;
}
@ -171,9 +195,9 @@ bx_bool bx_soundmod_ctl_c::beep_off()
}
// The dummy sound lowlevel functions. They don't do anything.
bx_sound_lowlevel_c::bx_sound_lowlevel_c(logfunctions *dev)
bx_sound_lowlevel_c::bx_sound_lowlevel_c()
{
device = dev;
put("sound", "SOUND");
record_timer_index = BX_NULL_TIMER_HANDLE;
}
@ -302,7 +326,7 @@ void bx_sound_lowlevel_c::record_timer_handler(void *this_ptr)
void bx_sound_lowlevel_c::record_timer(void)
{
record_handler(this->device, record_packet_size);
record_handler(this, record_packet_size);
}
#endif

View File

@ -44,8 +44,9 @@ class bx_sound_lowlevel_c;
class bx_soundmod_ctl_c : public bx_soundmod_ctl_stub_c {
public:
bx_soundmod_ctl_c();
virtual ~bx_soundmod_ctl_c() {}
virtual void* init_module(const char *type, logfunctions *device);
virtual ~bx_soundmod_ctl_c();
virtual void init(void);
virtual void* get_module();
virtual bx_bool beep_on(float frequency);
virtual bx_bool beep_off();
private:
@ -63,7 +64,7 @@ public:
non-portable, while everything in the soundcard code is portable
*/
bx_sound_lowlevel_c(logfunctions *dev);
bx_sound_lowlevel_c();
virtual ~bx_sound_lowlevel_c();
virtual int get_type() {return BX_SOUNDLOW_DUMMY;}
@ -90,7 +91,6 @@ public:
static void record_timer_handler(void *);
void record_timer(void);
protected:
logfunctions *device;
int record_timer_index;
int record_packet_size;
sound_record_handler_t record_handler;

View File

@ -30,7 +30,7 @@
#if defined(macintosh) && BX_SUPPORT_SOUNDLOW
#define LOG_THIS device->
#define LOG_THIS
#if BX_WITH_MACOS
#include <QuickTimeMusic.h>
@ -76,8 +76,8 @@ AudioUnit WaveOutputUnit = NULL;
AudioConverterRef WaveConverter = NULL;
#endif
bx_sound_osx_c::bx_sound_osx_c(logfunctions *dev)
:bx_sound_lowlevel_c(dev)
bx_sound_osx_c::bx_sound_osx_c()
:bx_sound_lowlevel_c()
{
MidiOpen = 0;
WaveOpen = 0;
@ -634,7 +634,7 @@ void bx_sound_osx_c::record_timer_handler(void *this_ptr)
void bx_sound_osx_c::record_timer(void)
{
record_handler(this->device, record_packet_size);
record_handler(this, record_packet_size);
}
#endif // defined(macintosh)

View File

@ -38,7 +38,7 @@
class bx_sound_osx_c : public bx_sound_lowlevel_c {
public:
bx_sound_osx_c(logfunctions *dev);
bx_sound_osx_c();
virtual ~bx_sound_osx_c();
virtual int get_type() {return BX_SOUNDLOW_OSX;}

View File

@ -26,7 +26,7 @@
#if BX_WITH_SDL && BX_SUPPORT_SOUNDLOW
#define LOG_THIS device->
#define LOG_THIS
#if BX_WITH_SDL
#include <SDL.h>
@ -41,8 +41,8 @@ static struct {
} audio_buffer;
bx_sound_sdl_c::bx_sound_sdl_c(logfunctions *dev)
:bx_sound_lowlevel_c(dev)
bx_sound_sdl_c::bx_sound_sdl_c()
:bx_sound_lowlevel_c()
{
WaveOpen = 0;
if (SDL_InitSubSystem(SDL_INIT_AUDIO)) {

View File

@ -27,7 +27,7 @@
class bx_sound_sdl_c : public bx_sound_lowlevel_c {
public:
bx_sound_sdl_c(logfunctions *dev);
bx_sound_sdl_c();
virtual ~bx_sound_sdl_c();
virtual int get_type() {return BX_SOUNDLOW_SDL;}

View File

@ -32,10 +32,10 @@
#if defined(WIN32) && BX_SUPPORT_SOUNDLOW
#define LOG_THIS device->
#define LOG_THIS
bx_sound_windows_c::bx_sound_windows_c(logfunctions *dev)
:bx_sound_lowlevel_c(dev)
bx_sound_windows_c::bx_sound_windows_c()
:bx_sound_lowlevel_c()
{
MidiOpen = 0;
WaveOutOpen = 0;
@ -640,7 +640,7 @@ void bx_sound_windows_c::record_timer_handler(void *this_ptr)
void bx_sound_windows_c::record_timer(void)
{
record_handler(this->device, record_packet_size);
record_handler(this, record_packet_size);
}
#endif // defined(WIN32)

View File

@ -166,7 +166,7 @@ typedef struct {
class bx_sound_windows_c : public bx_sound_lowlevel_c {
public:
bx_sound_windows_c(logfunctions *dev);
bx_sound_windows_c();
virtual ~bx_sound_windows_c();
virtual int get_type() {return BX_SOUNDLOW_WIN;}

View File

@ -156,7 +156,15 @@ void bx_speaker_c::init(void)
const char *mode = SIM->get_param_enum("mode", base)->get_selected();
if (!strcmp(mode, "sound")) {
output_mode = BX_SPK_MODE_SOUND;
BX_INFO(("Using lowlevel sound support for output"));
outputinit = 0;
#if BX_SUPPORT_SOUNDLOW
if (DEV_soundmod_beep_off()) {
BX_INFO(("Using lowlevel sound support for output"));
outputinit = 1;
} else {
BX_ERROR(("Failed to use lowlevel sound support for output"));
}
#endif
} else if (!strcmp(mode, "system")) {
output_mode = BX_SPK_MODE_SYSTEM;
#ifdef __linux__
@ -176,20 +184,10 @@ void bx_speaker_c::init(void)
} else {
output_mode = BX_SPK_MODE_NONE;
}
outputinit = 0;
}
void bx_speaker_c::reset(unsigned type)
{
if (!outputinit) {
outputinit = 1;
#if BX_SUPPORT_SOUNDLOW
if (!DEV_soundmod_beep_off()) {
BX_ERROR(("Failed to use lowlevel sound support for output"));
}
#endif
}
beep_off();
}
@ -204,7 +202,9 @@ void bx_speaker_c::beep_on(float frequency)
if (output_mode == BX_SPK_MODE_SOUND) {
#if BX_SUPPORT_SOUNDLOW
DEV_soundmod_beep_on(frequency);
if (outputinit) {
DEV_soundmod_beep_on(frequency);
}
#endif
} else if (output_mode == BX_SPK_MODE_SYSTEM) {
#ifdef __linux__
@ -245,7 +245,9 @@ void bx_speaker_c::beep_off()
{
if (output_mode == BX_SPK_MODE_SOUND) {
#if BX_SUPPORT_SOUNDLOW
DEV_soundmod_beep_off();
if (outputinit) {
DEV_soundmod_beep_off();
}
#endif
} else if (output_mode == BX_SPK_MODE_SYSTEM) {
if (beep_frequency != 0.0) {

View File

@ -172,6 +172,8 @@
#define BXPN_PNIC_ENABLED "network.pcipnic.enabled"
#define BXPN_E1000 "network.e1000"
#define BXPN_E1000_ENABLED "network.e1000.enabled"
#define BXPN_SOUND_DRIVER "sound.lowlevel.driver"
#define BXPN_SOUND_WAVEDEV "sound.lowlevel.wavedev"
#define BXPN_SOUND_SPEAKER "sound.speaker"
#define BXPN_SOUND_SB16 "sound.sb16"
#define BXPN_SB16_DMATIMER "sound.sb16.dmatimer"

View File

@ -251,9 +251,9 @@ extern "C" {
#define DEV_usb_init_device(a,b,c,d) (usbdev_type)bx_devices.pluginUsbDevCtl->init_device(a,b,(void**)c,d)
#define DEV_usb_send_msg(a,b) bx_devices.pluginUsbDevCtl->usb_send_msg((void*)a,b)
///////// Sound module macro
#define DEV_sound_init_module(a,b) \
((bx_sound_lowlevel_c*)bx_devices.pluginSoundModCtl->init_module(a,b))
///////// Sound module macros
#define DEV_sound_get_module() \
((bx_sound_lowlevel_c*)bx_devices.pluginSoundModCtl->get_module())
#define DEV_soundmod_beep_on(a) bx_devices.pluginSoundModCtl->beep_on(a)
#define DEV_soundmod_beep_off() bx_devices.pluginSoundModCtl->beep_off()