add an interface for sound libraries

Groundwork for a more versatile interface for using
sound libraries. A lot of sound libraries work across
multiple platforms.

The current NetHack sound stuff is quite limited.

Binaries can have a variety of window ports linked into
them, and it makes sense to have something similar for
sound.

This tries to set things up in a more soundlib-centric way,
rather than inserting things in a platform-centric way.

It establishes a new top-level directory sound (akin to win
for the window interface routines, or "window-port") where
sound-related additions and sndprocs and support files can be
added and used across platforms.

The default interface is nosound and the 'nosound' interface
is in src/sounds.c

The interface for 'windsound', which contains the same minimal
USER_SOUNDS support using built-in routines that has been in the
windows port for a long time is added to
sound/windsound/windsound.c.

For now, the sound interface support for 'qtsound' has been added
to the existing Qt files win/Qt/qt_bind.h and win/Qt/qt_bind.cpp,
and a note has been placed in sound/qtsound/README.md to avoid
confusion.

New header file added: include/sndprocs.h.
This commit is contained in:
nhmall
2023-01-19 18:51:42 -05:00
parent 6e49372d8f
commit ea4a81901d
24 changed files with 705 additions and 85 deletions
-3
View File
@@ -99,9 +99,6 @@
#define DEFAULT_WC_TILED_MAP /* Default to tiles if users doesn't say \
wc_ascii_map */
#endif
#ifndef NOUSER_SOUNDS
#define USER_SOUNDS /* Use sounds */
#endif
#ifndef USE_XPM
#define USE_XPM /* Use XPM format for images (required) */
#endif
+6
View File
@@ -743,6 +743,9 @@ struct instance_globals_a {
/* shk.c */
boolean auto_credit;
/* sounds.c */
enum soundlib_ids active_soundlib;
/* trap.c */
/* context for water_damage(), managed by water_damage_chain();
when more than one stack of potions of acid explode while processing
@@ -852,6 +855,9 @@ struct instance_globals_c {
/* questpgr.c */
char cvt_buf[CVT_BUF_SIZE];
/* sounds.c */
enum soundlib_ids chosen_soundlib;
/* sp_lev.c */
struct sp_coder *coder;
+3
View File
@@ -2600,6 +2600,9 @@ extern void play_usersound(const char *, int);
extern void play_usersound_via_idx(int, int);
#endif
#endif /* USER SOUNDS */
extern void assign_soundlib(int);
extern void activate_chosen_soundlib(void);
extern void get_soundlib_name(char *dest, int maxlen);
/* ### sp_lev.c ### */
+1
View File
@@ -227,6 +227,7 @@ enum misc_arti_nums {
#include "region.h"
#include "trap.h"
#include "display.h"
#include "sndprocs.h"
#include "decl.h"
#include "timeout.h"
+3
View File
@@ -540,6 +540,9 @@ static int optfn_##a(int, int, boolean, char *, char *);
NHOPTC(sortvanquished, Advanced, 0, opt_in, set_in_game,
Yes, Yes, No, Yes, NoAlias,
"preferred order when displaying vanquished monsters")
NHOPTC(soundlib, Advanced, WINTYPELEN, opt_in, set_gameview,
No, Yes, No, No, NoAlias,
"soundlib interface to use (if any)")
NHOPTB(sparkle, Map, 0, opt_out, set_in_game,
On, Yes, No, No, NoAlias, &flags.sparkle)
NHOPTB(splash_screen, Advanced, 0, opt_out, set_in_config,
+180
View File
@@ -0,0 +1,180 @@
/* NetHack 3.7 sndprocs.h $NHDT-Date: $ $NHDT-Branch: $:$NHDT-Revision: $ */
/* Copyright (c) Michael Allison, 2022 */
/* NetHack may be freely redistributed. See license for details. */
#ifndef SNDPROCS_H
#define SNDPROCS_H
/*
*
* Types of potential sound supports (all are optional):
*
* SNDCAP_USERSOUNDS User-specified sounds that play based on config
* file entries that identify a regular expression
* to match against message window text, and identify
* an external sound file to load in response.
* The sound interface function pointer used to invoke
* it:
*
* void (*sound_play_usersound)(char *filename,
* int32_t volume, int32_t idx);
*
* SNDCAP_HEROMUSIC Invoked by the core when the in-game hero is
* playing a tune on an instrument. The sound
* interface function pointer used to invoke it:
*
* void (*sound_hero_playnotes)(int32_t instrument,
* char *str, int32_t volume);
*
* SNDCAP_ACHIEVEMENTS Invoked by the core when an in-game achievement
* is reached. The soundlib routines could play
* appropriate theme or mood music in response.
* There would need to be a way to map the
* achievements to external user-specified sounds.
* The sound interface function pointer used to
* invoke it:
*
* void (*sound_achievement)(schar, schar,
* int32_t);
*
* SNDCAP_SOUNDEFFECTS Invoked by the core when something
* sound-producing happens in the game. The soundlib
* routines could play an appropriate sound effect
* in response. They can be public-domain or
* suitably-licensed stock sounds included with the
* game source and made available during the build
* process, or (not-yet-implemented) a way to
* tie particular sound effects to a user-specified
* sound samples in a config file. The sound
* interface function pointer used to invoke it:
*
* void (*sound_soundeffect)(char *desc, int32_t,
* int32_t volume);
*
* Development notes:
* - gc.chosen_soundlib holds the soundlib_id that will be initialized
* at the appropriate time (startup or after an option change). It
* is initialized to soundlib_nosound, so that is what will be used if
* the initial value isn't replaced via an assign_soundlib() call
* prior to the call to the activate_chosen_soundlib() in
* moveloop_preamble() at the start of the game.
* - ga.active_soundlib holds the soundlib_id of the active soundlib.
* It is initialized to soundlib_unassigned. It will get changed to
* reflect the activated soundlib_id once activate_chosen_soundlib()
* has been called.
*
*/
enum soundlib_ids {
soundlib_unassigned = 0,
#ifdef SND_LIB_QTSOUND
soundlib_qtsound,
#endif
#ifdef SND_LIB_PORTAUDIO
soundlib_portaudio,
#endif
#ifdef SND_LIB_OPENAL
soundlib_openal,
#endif
#ifdef SND_LIB_SDL_MIXER
soundlib_sdl_mixer,
#endif
#ifdef SND_LIB_MINIAUDIO
soundlib_miniaudio,
#endif
#ifdef SND_LIB_FMOD
soundlib_fmod,
#endif
#ifdef SND_LIB_SOUND_ESCCODES
soundlib_sound_esccodes,
#endif
#ifdef SND_LIB_VISSOUND
soundlib_vissound,
#endif
#ifdef SND_LIB_WINDSOUND
soundlib_windsound,
#endif
soundlib_nosound
};
struct sound_procs {
const char *soundname;
enum soundlib_ids soundlib_id;
unsigned long sndcap; /* capabilities in the port */
void (*sound_init_nhsound)(void);
void (*sound_exit_nhsound)(const char *);
void (*sound_achievement)(schar, schar, int32_t);
void (*sound_soundeffect)(char *desc, int32_t, int32_t volume);
void (*sound_hero_playnotes)(int32_t instrument, char *str, int32_t volume);
void (*sound_play_usersound)(char *filename, int32_t volume, int32_t idx);
};
extern struct sound_procs sndprocs;
#define SOUNDID(soundname) #soundname, soundlib_##soundname
/*
* SOUNDCAP
*/
#define SNDCAP_USERSOUNDS 0x0001L
#define SNDCAP_HEROMUSIC 0x0002L
#define SNDCAP_ACHIEVEMENTS 0x0004L
#define SNDCAP_SOUNDEFFECTS 0x0008L
/* 28 free bits */
extern struct sound_procs soundprocs;
/* subset for NetHack */
enum instruments {
ins_choir_aahs = 53, ins_trumpet = 57, ins_trombone = 58,
ins_french_horn = 61, ins_english_horn = 70, ins_piccolo = 73,
ins_flute = 74, ins_pan_flute = 76, ins_blown_bottle = 77,
ins_whistle = 79, ins_tinkle_bell = 113, ins_woodblock = 116,
ins_taiko_drum = 117, ins_melodic_tom = 118, ins_seashore = 123,
ins_fencepost
};
#if 0
enum instruments_broad {
ins_acoustic_grand_piano = 1, ins_bright_acoustic_piano = 2,
ins_electric_grand_piano = 3, ins_honkytonk_piano = 4,
ins_electric_piano_1 = 5, ins_electric_piano_2 = 6,
ins_harpsichord = 7, ins_clavinet = 8, ins_celesta = 9,
ins_glockenspiel = 10, ins_music_box = 11, ins_vibraphone = 12,
ins_marimba = 13, ins_xylophone = 14, ins_tubular_bells = 15,
ins_dulcimer = 16, ins_drawbar_organ = 17,
ins_percussive_organ = 18, ins_rock_organ = 19, ins_church_organ = 20,
ins_reed_organ = 21, ins_french_accordion = 22, ins_harmonica = 23,
ins_tango_accordion = 24, ins_acoustic_guitar__nylon = 25,
ins_acoustic_guitar_steel = 26, ins_electric_guitar_jazz = 27,
ins_electric_guitar_clean = 28, ins_electric_guitar_muted = 29,
ins_overdriven_guitar = 30, ins_distortion_guitar = 31,
ins_guitar_harmonics = 32, ins_acoustic_bass = 33,
ins_electric_bass__fingered = 34, ins_electric_bass_picked = 35,
ins_fretless_bass = 36, ins_slap_bass_1 = 37, ins_slap_bass_2 = 38,
ins_synth_bass_1 = 39, ins_synth_bass_2 = 40, ins_violin = 41,
ins_viola = 42, ins_cello = 43, ins_contrabass = 44,
ins_tremolo_strings = 45, ins_pizzicato_strings = 46,
ins_orchestral_harp = 47, ins_timpani = 48,
ins_string_ensemble_1 = 49, ins_string_ensemble_2 = 50,
ins_synthstrings_1 = 51, ins_synthstrings_2 = 52, ins_choir_aahs = 53,
ins_voice_oohs = 54, ins_synth_voice = 55, ins_orchestra_hit = 56,
ins_trumpet = 57, ins_trombone = 58, ins_tuba = 59, ins_muted_trumpet = 60,
ins_french_horn = 61, ins_brass_section = 62, ins_synthbrass_1 = 63,
ins_synthbrass_2 = 64, ins_soprano_sax = 65, ins_alto_sax = 66,
ins_tenor_sax = 67, ins_baritone_sax = 68, ins_oboe = 69,
ins_english_horn = 70, ins_bassoon = 71, ins_clarinet = 72,
ins_piccolo = 73, ins_flute = 74, ins_recorder = 75,
ins_pan_flute = 76, ins_blown_bottle = 77, ins_shakuhachi = 78,
ins_whistle = 79, ins_ocarina = 80, ins_sitar = 105, ins_banjo = 106,
ins_shamisen = 107, ins_koto = 108, ins_kalimba = 109, ins_bag_pipe = 110,
ins_fiddle = 111, ins_shanai = 112, ins_tinkle_bell = 113, ins_agogo = 114,
ins_steel_drums = 115, ins_woodblock = 116, ins_taiko_drum = 117,
ins_melodic_tom = 118, ins_synth_drum = 119, ins_reverse_cymbal = 120,
ins_guitar_fret_noise = 121, ins_breath_noise = 122, ins_seashore = 123,
ins_bird_tweet = 124, ins_telephone_ring = 125, ins_helicopter = 126,
ins_applause = 127, ins_gunshot = 128,
ins_fencepost
};
#endif
#endif /* SNDPROCS_H */
-3
View File
@@ -28,9 +28,6 @@
/*#define DUMPLOG_FILE "nethack-%n-%d.log"*/
#define DUMPLOG_MSG_COUNT 50
#define USER_SOUNDS
/* #define TTY_SOUND_ESCCODES */
/*#define CHANGE_COLOR*/ /* allow palette changes */
#define QWERTZ_SUPPORT /* when swap_yz is True, numpad 7 is 'z' not 'y' */
-10
View File
@@ -276,16 +276,6 @@ extern
#define MAP_MODE_ASCII_FIT_TO_SCREEN 10
#define MAP_MODE_TILES_FIT_TO_SCREEN 11
#if 0
#define WC_SND_SOUND 0x0001L /* 01 Port has some sound capabilities */
#define WC_SND_SPEAKER 0x0002L /* 02 Sound supported via built-in speaker */
#define WC_SND_STEREO 0x0004L /* 03 Stereo sound supported */
#define WC_SND_RAW 0x0008L /* 04 Raw sound supported */
#define WC_SND_WAVE 0x0010L /* 05 Wave support */
#define WC_SND_MIDI 0x0020L /* 06 Midi support */
/* 26 free bits */
#endif
struct wc_Opt {
const char *wc_name;
unsigned long wc_bit;
+3
View File
@@ -0,0 +1,3 @@
19-Jan-2023
The Qt sound interface is currently housed in win/Qt/qt_bind.h and win/Qt/qt_bind.cpp.
+71
View File
@@ -0,0 +1,71 @@
/* NetHack 3.7 windsound.c $NHDT-Date: $ $NHDT-Branch: $NHDT-Revision: $ */
/* Copyright (c) Michael Allison, 2022 */
/* NetHack may be freely redistributed. See license for details. */
#include "win32api.h"
#include "hack.h"
#include <mmsystem.h>
/*
* The win32api sound interface
*
*/
#include "win32api.h"
#include "hack.h"
#ifdef SND_LIB_WINDSOUND
static void windsound_init_nhsound(void);
static void windsound_exit_nhsound(const char *);
static void windsound_achievement(schar, schar, int32_t);
static void windsound_soundeffect(char *, int32_t, int32_t);
static void windsound_hero_playnotes(int32_t instrument, char *str, int32_t volume);
static void windsound_play_usersound(char *, int32_t, int32_t);
struct sound_procs windsound_procs = {
SOUNDID(windsound),
0L,
windsound_init_nhsound,
windsound_exit_nhsound,
windsound_achievement,
windsound_soundeffect,
windsound_hero_playnotes,
windsound_play_usersound,
};
void
windsound_init_nhsound(void)
{
/* No steps required */
}
void
windsound_exit_nhsound(const char *reason)
{
}
void
windsound_achievement(schar ach1, schar ach2, int32_t repeat)
{
}
void
windsound_soundeffect(char *desc, int32_t seid, int32_t volume)
{
}
void
windsound_hero_playnotes(int32_t instrument, char *str, int32_t volume)
{
}
void
windsound_play_usersound(char *filename, int32_t volume UNUSED, int32_t idx UNUSED)
{
/* pline("play_usersound: %s (%d).", filename, volume); */
(void) sndPlaySound(filename, SND_ASYNC | SND_NODEFAULT);
}
#endif /* SND_LIB_WINDSOUND */
+2
View File
@@ -58,6 +58,8 @@ moveloop_preamble(boolean resuming)
change_luck(-1);
}
activate_chosen_soundlib();
if (!resuming) { /* new game */
gc.context.rndencode = rnd(9000);
set_wear((struct obj *) 0); /* for side-effects of starting gear */
+5
View File
@@ -206,6 +206,9 @@ const struct instance_globals_a g_init_a = {
UNDEFINED_VALUE, /* abort_looting */
/* shk.c */
FALSE, /* auto_credit */
/* sounds.c */
soundlib_unassigned, /* enum soundlib_ids active_soundlib */
/* trap.c */
{ 0, 0, FALSE }, /* acid_ctx */
TRUE, /* havestate*/
@@ -284,6 +287,8 @@ const struct instance_globals_c g_init_c = {
FALSE, /* class_filter */
/* questpgr.c */
UNDEFINED_VALUES, /* cvt_buf */
/* sounds.c */
soundlib_nosound, /* chosen_soundlib */
UNDEFINED_PTR, /* coder */
/* uhitm.c */
NON_PM, /* corpsenm_digested */
+16 -2
View File
@@ -2309,6 +2309,7 @@ void
record_achievement(schar achidx)
{
int i, absidx;
int repeat_achievement = 0;
absidx = abs(achidx);
/* valid achievements range from 1 to N_ACH-1; however, ranks can be
@@ -2325,8 +2326,21 @@ record_achievement(schar achidx)
an attempt to duplicate an achievement can happen if any of Bell,
Candelabrum, Book, or Amulet is dropped then picked up again */
for (i = 0; u.uachieved[i]; ++i)
if (abs(u.uachieved[i]) == absidx)
return; /* already recorded, don't duplicate it */
if (abs(u.uachieved[i]) == absidx) {
repeat_achievement = 1;
break;
}
/*
* We do the sound for an achievement, even if it has already been
* achieved before. Some players might have set up level-based
* theme music or something. We do let the sound interface know
* that it's not the original achievement though.
*/
(*soundprocs.sound_achievement)(achidx, 0, repeat_achievement);
if (repeat_achievement)
return; /* already recorded, don't duplicate it */
u.uachieved[i] = achidx;
/* avoid livelog for achievements recorded during final disclosure:
+37
View File
@@ -3399,6 +3399,43 @@ optfn_scroll_margin(
return optn_ok;
}
static int
optfn_soundlib(int optidx, int req, boolean negated UNUSED,
char *opts, char *op)
{
char soundlibbuf[WINTYPELEN];
if (req == do_init) {
return optn_ok;
}
if (req == do_set) {
/*
* soundlib: option to choose the interface for binaries built
* with support for more than the default interface (nosound).
*
* Option processing sets gc.chosen_soundlib. A later call
* to activate_chosen_soundlib() actually activates it, and
* sets gc.active_soundlib.
*/
if ((op = string_for_env_opt(allopt[optidx].name, opts, FALSE))
!= empty_optstr) {
get_soundlib_name(soundlibbuf, WINTYPELEN);
assign_soundlib(gc.chosen_soundlib);
} else
return optn_err;
return optn_ok;
}
if (req == get_val || req == get_cnf_val) {
if (!opts)
return optn_err;
get_soundlib_name(soundlibbuf, WINTYPELEN);
Sprintf(opts, "%s", soundlibbuf);
return optn_ok;
}
return optn_ok;
}
static int
optfn_sortdiscoveries(
int optidx, int req, boolean negated,
+244 -25
View File
@@ -1502,37 +1502,27 @@ sound_matches_message(const char* msg)
void
play_sound_for_message(const char* msg)
{
audio_mapping *snd = sound_matches_message(msg);
audio_mapping *snd;
if (snd)
play_usersound(snd->filename, snd->volume);
if (soundprocs.sound_play_usersound) {
snd = sound_matches_message(msg);
if (snd)
(*soundprocs.sound_play_usersound)(
snd->filename, snd->volume, snd->idx);
}
}
void
maybe_play_sound(const char* msg)
{
#if defined(WIN32) || defined(QT_GRAPHICS) || defined(TTY_SOUND_ESCCODES)
audio_mapping *snd = sound_matches_message(msg);
audio_mapping *snd;
if (snd
#if defined(WIN32) || defined(QT_GRAPHICS)
#ifdef TTY_SOUND_ESCCODES
&& !iflags.vt_sounddata
#endif
#if defined(QT_GRAPHICS)
&& WINDOWPORT(Qt)
#endif
#if defined(WIN32)
&& (WINDOWPORT(tty) || WINDOWPORT(mswin) || WINDOWPORT(curses))
#endif
#endif /* WIN32 || QT_GRAPHICS */
)
play_usersound(snd->filename, snd->volume);
#if defined(TTY_GRAPHICS) && defined(TTY_SOUND_ESCCODES)
else if (snd && iflags.vt_sounddata && snd->idx >= 0 && WINDOWPORT(tty))
play_usersound_via_idx(snd->idx, snd->volume);
#endif /* TTY_GRAPHICS && TTY_SOUND_ESCCODES */
#endif /* WIN32 || QT_GRAPHICS || TTY_SOUND_ESCCODES */
if (soundprocs.sound_play_usersound) {
snd = sound_matches_message(msg);
if (snd)
(*soundprocs.sound_play_usersound)(
snd->filename, snd->volume, snd->idx);
}
}
void
@@ -1551,7 +1541,236 @@ release_sound_mappings(void)
if (sounddir)
free((genericptr_t) sounddir), sounddir = 0;
}
#endif /* USER_SOUNDS */
struct sound_procs soundprocs;
#ifdef SND_LIB_QTSOUND
extern struct sound_procs qtsound_procs;
#endif
#ifdef SND_LIB_PORTAUDIO
extern struct sound_procs portaudio_procs;
#endif
#ifdef SND_LIB_OPENAL
extern struct sound_procs openal_procs;
#endif
#ifdef SND_LIB_SDL_MIXER
extern struct sound_procs sdl_mixer_procs;
#endif
#ifdef SND_LIB_MINIAUDIO
extern struct sound_procs miniaudio_procs;
#endif
#ifdef SND_LIB_FMOD
extern struct sound_procs fmod_procs;
#endif
#ifdef SND_LIB_SOUND_ESCCODES
extern struct sound_procs esccodes_procs;
#endif
#ifdef SND_LIB_VISSOUND
extern struct sound_procs vissound_procs;
#endif
#ifdef SND_LIB_WINDSOUND
extern struct sound_procs windsound_procs;
#endif
extern struct sound_procs nosound_procs;
/* The order of these array entries must match the
order of the enum soundlib_ids in sndprocs.h */
static struct sound_choices {
struct sound_procs *sndprocs;
} soundlib_choices[] = {
{ (struct sound_procs *) 0 },
#ifdef SND_LIB_QTSOUND
{ &qtsound_procs },
#endif
#ifdef SND_LIB_PORTAUDIO
{ &portaudio_procs },
#endif
#ifdef SND_LIB_OPENAL
{ &openal_procs },
#endif
#ifdef SND_LIB_SDL_MIXER
{ &sdl_mixer_procs },
#endif
#ifdef SND_LIB_MINIAUDIO
{ &miniaudio_procs },
#endif
#ifdef SND_LIB_FMOD
{ &fmod_procs },
#endif
#ifdef SND_LIB_SOUND_ESCCODES
{ &esccodes_procs },
#endif
#ifdef SND_LIB_WINDSOUND
{ &windsound_procs },
#endif
#ifdef SND_LIB_VISSOUND
{ &vissound_procs },
#endif
{ &nosound_procs }, /* default, built-in */
};
void
activate_chosen_soundlib(void)
{
enum soundlib_ids idx = gc.chosen_soundlib;
if (idx <= soundlib_unassigned || idx > soundlib_nosound)
idx = soundlib_nosound;
if (ga.active_soundlib != soundlib_unassigned
|| ga.active_soundlib != idx) {
if (soundprocs.sound_exit_nhsound)
(*soundprocs.sound_exit_nhsound)("assigning a new sound library");
ga.active_soundlib = soundlib_unassigned;
}
soundprocs = *soundlib_choices[idx].sndprocs;
if (soundprocs.sound_init_nhsound)
(*soundprocs.sound_init_nhsound)();
ga.active_soundlib = soundprocs.soundlib_id;
}
void
assign_soundlib(int idx)
{
if (idx <= soundlib_unassigned || idx > soundlib_nosound)
idx = soundlib_nosound;
if (ga.active_soundlib != soundlib_unassigned) {
if (soundprocs.sound_exit_nhsound)
(*soundprocs.sound_exit_nhsound)("assigning a new sound library");
ga.active_soundlib = soundlib_unassigned;
}
gc.chosen_soundlib = soundlib_choices[idx].sndprocs->soundlib_id;
}
#if 0
static void
choose_soundlib(const char *s)
{
int i;
char *tmps = 0;
for (i = 1; soundlib_choices[i].sndprocs; i++) {
if (!strcmpi(s, soundlib_choices[i].sndprocs->soundname)) {
assign_soundlib(i);
return;
}
}
assign_soundlib((int) soundlib_nosound);
/* The code below here mimics that in windows.c error handling
for choosing Window type */
/* 50: arbitrary, no real soundlib names are anywhere near that long;
used to prevent potential raw_printf() overflow if user supplies a
very long string (on the order of 1200 chars) on the command line
(config file options can't get that big; they're truncated at 1023) */
#define SOUNDLIB_NAME_MAXLEN 50
if (strlen(s) >= SOUNDLIB_NAME_MAXLEN) {
tmps = (char *) alloc(SOUNDLIB_NAME_MAXLEN);
(void) strncpy(tmps, s, SOUNDLIB_NAME_MAXLEN - 1);
tmps[SOUNDLIB_NAME_MAXLEN - 1] = '\0';
s = tmps;
}
#undef SOUNDLIB_NAME_MAXLEN
if (!soundlib_choices[1].sndprocs) {
config_error_add(
"Soundlib type %s not recognized. The only choice is: %s",
s, soundlib_choices[0].sndprocs->soundname);
} else {
char buf[BUFSZ];
boolean first = TRUE;
buf[0] = '\0';
for (i = 0; soundlib_choices[i].sndprocs; i++) {
Sprintf(eos(buf), "%s%s",
first ? "" : ", ", soundlib_choices[i].sndprocs->soundname);
first = FALSE;
}
config_error_add("Soundlib type %s not recognized. Choices are: %s",
s, buf);
}
if (tmps)
free((genericptr_t) tmps) /*, tmps = 0*/ ;
}
#endif
/* copy up to maxlen-1 characters; 'dest' must be able to hold maxlen;
treat comma as alternate end of 'src' */
void
get_soundlib_name(char *dest, int maxlen)
{
int count, idx;
const char *src;
idx = ga.active_soundlib;
if (idx > soundlib_unassigned && idx <= soundlib_nosound) {
src = soundlib_choices[idx].sndprocs->soundname;
for (count = 1; count < maxlen; count++) {
if (*src == ',' || *src == '\0')
break; /*exit on \0 terminator*/
*dest++ = *src++;
}
}
*dest = '\0';
}
/*
* The default sound interface
*
* 3rd party sound_procs should be placed in ../sound/x
* and build procedures should reference them there.
*/
#if 0
static void nosound_init_nhsound(void);
static void nosound_exit_nhsound(const char *);
static void nosound_suspend_nhsound(const char *);
static void nosound_resume_nhsound(void);
static void nosound_achievement(schar, schar, int32_t);
static void nosound_soundeffect(int32_t, int32_t);
static void nosound_play_usersound(char *, int32_t, int32_t);
#endif
struct sound_procs nosound_procs = {
SOUNDID(nosound),
0L,
(void (*)(void)) 0, /* init_nhsound */
(void (*)(const char *)) 0, /* exit_nhsound */
(void (*)(schar, schar, int32_t)) 0, /* achievement */
(void (*)(char *, int32_t, int32_t)) 0, /* sound effect */
(void (*)(int32_t, char *, int32_t)) 0, /* hero_playnotes */
(void (*)(char *, int32_t, int32_t)) 0, /* play_usersound */
};
#if 0
static void
nosound_init_nhsound(void)
{
}
static void
nosound_exit_nhsound(const char *reason)
{
}
static void
nosound_achievement(schar ach1, schar ach2, int32_t repeat)
{
}
static void
nosound_soundeffect(int32_t seid, int volume)
{
}
static void
nosound_play_usersound(char *filename, int volume, int idx)
{
}
#endif
/*sounds.c*/
+2
View File
@@ -78,6 +78,7 @@ endif
WINCFLAGS=
WINSRC =
WINOBJ0 =
SND_CFLAGS=
XTRASRC =
XTRAOBJ =
@@ -144,6 +145,7 @@ ifdef WANT_WIN_QT
WINCFLAGS += -DQT_GRAPHICS
WINSRC += $(WINQTSRC)
WINOBJ0 += $(WINQTOBJ)
SNDCFLAGS += -DSND_LIB_QTSOUND -DUSER_SOUNDS
XTRASRC += tile.c
XTRAOBJ += $(TARGETPFX)tile.o
#
+2
View File
@@ -114,9 +114,11 @@ endif #HAVE_NCURSESW
endif #WANT_WIN_CURSES
CFLAGS+= $(WINCFLAGS) #WINCFLAGS set from multiw-2.370
CFLAGS+= $(SNDCFLAGS) #SNDCFLAGS set from multiw-2.370
CFLAGS+= $(NHCFLAGS)
CCXXFLAGS+= $(WINCFLAGS) #WINCFLAGS set from multiw-2.370
CCXXFLAGS+= $(SNDCFLAGS) #SNDCFLAGS set from multiw-2.370
CCXXFLAGS+= $(NHCFLAGS)
VARDATND =
+2
View File
@@ -156,9 +156,11 @@ endif #CURSES_UNIODE=sys
endif #MAKEFILE_SRC
CFLAGS+= $(PKGCFLAGS) $(WINCFLAGS) #WINCFLAGS set from multiw-2.370
CFLAGS+= $(SNDCFLAGS) #SNDCFLAGS set from multiw-2.370
CFLAGS+= $(NHCFLAGS)
CCXXFLAGS+= $(WINCFLAGS) #WINCFLAGS set from multiw-2.370
CCXXFLAGS+= $(SNDCFLAGS) #SNDCFLAGS set from multiw-2.370
CCXXFLAGS+= $(NHCFLAGS)
VARDATND =
+22 -5
View File
@@ -37,6 +37,15 @@ default: install
GAMEDIR = ../binary
#
#---------------------------------------------------------------
# Do you want to include any sound libraries? If so leave the
# appropriate compile macro below uncommented, or add others
# that are available.
#
SOUNDLIBDEFS = -DWINDSOUND -DUSER_SOUNDS
#
#---------------------------------------------------------------
# Do you want debug information in the executable?
@@ -223,6 +232,7 @@ NHV=$(subst ",,$(NHV1))
# MSWIN - window port files (win32)
# WCURSES - window port files (curses)
# WSHR - Tile support files
# SNDSYS - sound suppport files for win32
# QT - QT window support files
INCL =../include
@@ -231,6 +241,7 @@ DOC =../doc
UTIL =../util
SRC =../src
SSYS =../sys/share
SNDSYS =../sound/windsound
MSWSYS =../sys/windows
TTY =../win/tty
MSWIN =../win/win32
@@ -741,15 +752,15 @@ COREOBJS = $(addsuffix .o, allmain alloc apply artifact attrib ball bones botl c
hack hacklib insight invent isaac64 light lock \
mail makemon mcastu mdlib mhitm mhitu minion mklev mkmap mkmaze mkobj mkroom \
mon mondata monmove monst mplayer mthrowu muse music \
nhlobj nhlsel nhlua ntsound o_init objects objnam options \
nhlobj nhlsel nhlua windsound o_init objects objnam options \
pager pickup pline polyself potion pray priest quest questpgr \
random read rect region restore rip rnd role rumors \
safeproc save sfstruct shk shknam sit sounds sp_lev spell steal steed symbols sys \
teleport timeout topten track trap u_init uhitm utf8map vault version vision \
weapon were wield windmain windows windsys wizard worm worn write zap)
CFLAGSW = $(CFLAGS) $(CFLAGSXTRA) $(COMMONDEF) $(DLBFLG) -DTILES -D_WINDOWS -DMSWIN_GRAPHICS -DSAFEPROCS -DNOTTYGRAPHICS
CPPFLAGSW = $(CFLAGS) $(CPPFLAGSXTRA) $(COMMONDEF) $(DLBFLG) -DTILES -D_WINDOWS -DMSWIN_GRAPHICS -DSAFEPROCS -DNOTTYGRAPHICS
CFLAGSW = $(CFLAGS) $(CFLAGSXTRA) $(COMMONDEF) $(DLBFLG) -DTILES -D_WINDOWS -DMSWIN_GRAPHICS -DSAFEPROCS -DNOTTYGRAPHICS $(SOUNDLIBDEFS)
CPPFLAGSW = $(CFLAGS) $(CPPFLAGSXTRA) $(COMMONDEF) $(DLBFLG) -DTILES -D_WINDOWS -DMSWIN_GRAPHICS -DSAFEPROCS -DNOTTYGRAPHICS $(SOUNDLIBDEFS)
ONHW = $(O)nethackw
NHWONLY = $(addsuffix .o, mhaskyn mhdlg mhfont mhinput mhmain mhmap mhmenu \
@@ -786,6 +797,9 @@ $(ONHW)/cppregex.o: $(SSYS)/cppregex.cpp $(NHLUAH) | $(ONHW)
$(ONHW)/%.o: $(SSYS)/%.c $(NHLUAH) | $(ONHW)
$(cc) $(CFLAGSW) $< -o$@
$(ONHW)/%.o: $(SNDSYS)/%.c $(NHLUAH) | $(ONHW)
$(cc) $(CFLAGSW) $< -o$@
$(ONHW)/%.o: $(MSWSYS)/%.c $(NHLUAH) | $(ONHW)
$(cc) $(CFLAGSW) $< -o$@
@@ -814,8 +828,8 @@ CLEAN_FILE += $(NHWTARGETS) $(NHWOBJS) $(NHWRES) $(BMPS)
#==========================================
# nethack
#==========================================
CFLAGSNH = $(CFLAGSU) $(CFLAGSXTRA) -DNO_TILE_C -DSAFEPROCS -D_LIB -DWIN32CON
CPPFLAGSNH = $(CFLAGSU) $(CPPFLAGSXTRA) -DNO_TILE_C -DSAFEPROCS -D_LIB -DWIN32CON
CFLAGSNH = $(CFLAGSU) $(CFLAGSXTRA) -DNO_TILE_C -DSAFEPROCS -D_LIB -DWIN32CON $(SOUNDLIBDEFS)
CPPFLAGSNH = $(CFLAGSU) $(CPPFLAGSXTRA) -DNO_TILE_C -DSAFEPROCS -D_LIB -DWIN32CON $(SOUNDLIBDEFS)
ONH = $(O)nethack
@@ -855,6 +869,9 @@ $(ONH)/cppregex.o: $(SSYS)/cppregex.cpp $(NHLUAH) | $(ONH)
$(ONH)/%.o: $(SSYS)/%.c $(NHLUAH) | $(ONH)
$(cc) $(CFLAGSNH) $< -o$@
$(ONH)/%.o: $(SNDSYS)/%.c $(NHLUAH) | $(ONH)
$(cc) $(CFLAGSNH) $< -o$@
$(ONH)/%.o: $(MSWSYS)/%.c $(NHLUAH) | $(ONH)
$(cc) $(CFLAGSNH) $< -o$@
+6
View File
@@ -66,6 +66,9 @@ $(ONHW)/cppregex.d: $(SSYS)/cppregex.cpp $(NHLUAH) | $(ONHW)
$(ONHW)/%.d: $(SSYS)/%.c $(NHLUAH) | $(ONHW)
$(cce) $(CFLAGSW) $< -o$@
$(ONHW)/%.d: $(SNDSYS)/%.c $(NHLUAH) | $(ONHW)
$(cce) $(CFLAGSW) $< -o$@
$(ONHW)/%.d: $(MSWSYS)/%.c $(NHLUAH) | $(ONHW)
$(cce) $(CFLAGSW) $< -o$@
@@ -84,6 +87,9 @@ $(ONH)/cppregex.d: $(SSYS)/cppregex.cpp $(NHLUAH) | $(ONH)
$(ONH)/%.d: $(SSYS)/%.c $(NHLUAH) | $(ONH)
$(cce) $(CFLAGSNH) $< -o$@
$(ONH)/%.d: $(SNDSYS)/%.c $(NHLUAH) | $(ONH)
$(cce) $(CFLAGSNH) $< -o$@
$(ONH)/%.d: $(MSWSYS)/%.c $(NHLUAH) | $(ONH)
$(cce) $(CFLAGSNH) $< -o$@
+23 -10
View File
@@ -443,7 +443,7 @@ HACKINCL = $(INCL)\align.h $(INCL)\artifact.h $(INCL)\artilist.h \
$(INCL)\timeout.h $(INCL)\tradstdc.h $(INCL)\trap.h \
$(INCL)\unixconf.h $(INCL)\vision.h $(INCL)\vmsconf.h \
$(INCL)\wintty.h $(INCL)\wincurs.h $(INCL)\winX.h \
$(INCL)\winprocs.h $(INCL)\wintype.h $(INCL)\you.h \
$(INCL)\winprocs.h $(INCL)\sndprocs.h $(INCL)\wintype.h $(INCL)\you.h \
$(INCL)\youprop.h
# all .c that are part of the main NetHack program and are not operating- or
@@ -523,7 +523,7 @@ MDLIBTTY = $(OTTY)mdlib.o
DLBOBJTTY = $(OTTY)dlb.o
REGEXTTY = $(OTTY)cppregex.o
LUAOBJTTY = $(OTTY)nhlua.o $(OTTY)nhlsel.o $(OTTY)nhlobj.o
SOUNDTTY = $(OTTY)ntsound.o
SOUNDTTY = $(OTTY)windsound.o
VVOBJTTY = $(OTTY)version.o
SOBJTTY = $(OTTY)windmain.o $(OTTY)windsys.o $(OTTY)win10.o \
@@ -588,7 +588,7 @@ MDLIBGUI = $(OGUI)mdlib.o
DLBOBJGUI = $(OGUI)dlb.o
REGEXGUI = $(OGUI)cppregex.o
LUAOBJGUI = $(OGUI)nhlua.o $(OGUI)nhlsel.o $(OGUI)nhlobj.o
SOUNDGUI = $(OGUI)ntsound.o
SOUNDGUI = $(OGUI)windsound.o
VVOBJGUI = $(OGUI)version.o
SOBJGUI = $(OGUI)windmain.o $(OGUI)windsys.o $(OGUI)win10.o \
@@ -650,6 +650,8 @@ OPTIONS_FILE = $(DAT)\options
DLBOBJ_HOST = $(OTTY)dlb$(HOST).o
!ENDIF
SOUNDLIBDEFS = -DSND_LIB_WINDSOUND -DUSER_SOUNDS
#==========================================
# Header file macros
#==========================================
@@ -675,7 +677,8 @@ HACK_H = $(INCL)\hack.h $(CONFIG_H) $(INCL)\lint.h $(INCL)\align.h \
$(INCL)\obj.h $(INCL)\engrave.h $(INCL)\you.h \
$(INCL)\attrib.h $(INCL)\monst.h $(INCL)\mextra.h \
$(INCL)\skills.h $(INCL)\timeout.h $(INCL)\trap.h \
$(INCL)\flag.h $(INCL)\winprocs.h $(INCL)\sys.h
$(INCL)\flag.h $(INCL)\winprocs.h $(INCL)\sndprocs.h \
$(INCL)\sys.h
TILE_H = ..\win\share\tile.h
@@ -898,8 +901,8 @@ INCLDIR= /I..\include /I..\sys\windows $(LUAINCL)
# Util and console builds
#==========================================
CFLAGS = $(ctmpflags) $(INCLDIR) $(DLBDEF) -DSAFEPROCS
CPPFLAGS = $(cpptmpflags) $(INCLDIR) $(DLBDEF) -DSAFEPROCS
CFLAGS = $(ctmpflags) $(INCLDIR) $(DLBDEF) -DSAFEPROCS $(SOUNDLIBDEFS)
CPPFLAGS = $(cpptmpflags) $(INCLDIR) $(DLBDEF) -DSAFEPROCS $(SOUNDLIBDEFS)
LFLAGS = $(lflags) $(conlibs) $(MACHINE)
#==========================================
@@ -942,6 +945,16 @@ DLB =
{$(SRC)}.c{$(OBJUTIL)}.o:
$(Q)$(CC) $(CFLAGS) $(CROSSCOMPILE) $(CROSSCOMPILE_TARGET) -Fo$@ $<
#==========================================
# Rules for files in sound\wind
#==========================================
{..\sound\windsound}.c{$(OBJTTY)}.o:
$(Q)$(CC) $(CFLAGS) -I$(WSHR) $(TTYDEF) $(CROSSCOMPILE) $(CROSSCOMPILE_TARGET) -Fo$@ $<
{..\sound\windsound}.c{$(OBJGUI)}.o:
$(Q)$(CC) $(CFLAGS) -I$(WSHR) $(GUIDEF) $(CROSSCOMPILE) $(CROSSCOMPILE_TARGET) -Fo$@ $<
#==========================================
# Rules for files in sys\share
#==========================================
@@ -1735,14 +1748,14 @@ $(OLUA)lapi.o: $(LUASRC)\lapi.c
$(OTTY)consoletty.o: $(MSWSYS)\consoletty.c $(WINDHDR) $(HACK_H) $(TILE_H)
$(OTTY)win10.o: $(MSWSYS)\win10.c $(WINDHDR) $(HACK_H)
$(OTTY)windsys.o: $(MSWSYS)\windsys.c $(WINDHDR) $(HACK_H)
$(OTTY)ntsound.o: $(MSWSYS)\ntsound.c $(WINDHDR) $(HACK_H)
$(OTTY)windsound.o: ..\sound\windsound\windsound.c $(HACK_H)
$(OTTY)windmain.o: $(MSWSYS)\windmain.c $(WINDHDR) $(HACK_H)
$(OTTY)safeproc.o: $(WSHR)\safeproc.c $(WINDHDR) $(HACK_H)
$(OGUI)consoletty.o: $(MSWSYS)\consoletty.c $(WINDHDR) $(HACK_H) $(TILE_H)
$(OGUI)win10.o: $(MSWSYS)\win10.c $(WINDHDR) $(HACK_H)
$(OGUI)windsys.o: $(MSWSYS)\windsys.c $(WINDHDR) $(HACK_H)
$(OGUI)ntsound.o: $(MSWSYS)\ntsound.c $(WINDHDR) $(HACK_H)
$(OGUI)windsound.o: ..\sound\windsound\windsound.c $(HACK_H)
$(OGUI)windmain.o: $(MSWSYS)\windmain.c $(WINDHDR) $(HACK_H)
$(OGUI)safeproc.o: $(WSHR)\safeproc.c $(WINDHDR) $(HACK_H)
@@ -2046,7 +2059,7 @@ MOCPATH = moc.exe
# $(INCL)\obj.h $(INCL)\engrave.h $(INCL)\you.h \
# $(INCL)\attrib.h $(INCL)\monst.h $(INCL)\mextra.h \
# $(INCL)\skills.h $(INCL)\timeout.h $(INCL)\flag.h \
# $(INCL)\winprocs.h $(INCL)\sys.h
# $(INCL)\winprocs.h $(INCL)\sndprocs.h $(INCL)\sys.h
# touch $(HACK_H)
#
$(OTTY)pcmain.o: ..\sys\share\pcmain.c $(HACK_H) $(INCL)\dlb.h
@@ -2465,7 +2478,7 @@ MOCPATH = moc.exe
# $(INCL)\obj.h $(INCL)\engrave.h $(INCL)\you.h \
# $(INCL)\attrib.h $(INCL)\monst.h $(INCL)\mextra.h \
# $(INCL)\skills.h $(INCL)\timeout.h $(INCL)\flag.h \
# $(INCL)\winprocs.h $(INCL)\sys.h
# $(INCL)\winprocs.h $(INCL)\sndprocs.h $(INCL)\sys.h
# touch $(HACK_H)
#
$(OGUI)pcmain.o: ..\sys\share\pcmain.c $(HACK_H) $(INCL)\dlb.h
+1
View File
@@ -590,6 +590,7 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/
windowtype = gc.chosen_windowtype;
}
choose_windows(windowtype);
assign_soundlib(soundlib_windsound);
u.uhp = 1; /* prevent RIP on early quits */
u.ux = 0; /* prevent flush_screen() */
+64 -26
View File
@@ -204,6 +204,14 @@ void NetHackQtBind::qt_init_nhwindows(int *argc, char **argv)
// 'statuslines' option can be set in config file but not via 'O'
set_wc2_option_mod_status(WC2_STATUSLINES, set_gameview);
#endif
#if defined(SND_LIB_QTSOUND) && !defined(QT_NO_SOUND)
/* assign_soundlib() just flags to NetHack which soundlib
* should be loaded by activate_chosen_soundlib() shortly.
* gc.chosen_soundlib is initialized to soundlib_nosound.
*/
if (gc.chosen_soundlib == soundlib_nosound)
assign_soundlib(soundlib_qtsound);
#endif
}
int NetHackQtBind::qt_kbhit()
@@ -1030,6 +1038,50 @@ boolean NetHackQtBind::msgs_initd = false;
#if 0
static void Qt_positionbar(char *) {}
#endif
#if defined(SND_LIB_QTSOUND) && !defined(NO_QT_SOUND)
void NetHackQtBind::qtsound_init_nhsound(void)
{
}
void NetHackQtBind::qtsound_exit_nhsound(const char *reason UNUSED)
{
}
void NetHackQtBind::qtsound_achievement(schar ach1 UNUSED, schar ach2 UNUSED, int32_t repeat UNUSED)
{
}
void NetHackQtBind::qtsound_soundeffect(char *desc UNUSED, int32_t seid UNUSED, int32_t volume UNUSED)
{
}
void NetHackQtBind::qtsound_hero_playnotes(int32_t instrument UNUSED, char *str UNUSED, int32_t volume UNUSED)
{
}
#endif
#if defined(USER_SOUNDS) && !defined(QT_NO_SOUND)
QSoundEffect *effect = NULL;
#endif
void NetHackQtBind::qtsound_play_usersound(char *filename, int32_t volume, int32_t idx UNUSED)
{
#if defined(USER_SOUNDS) && !defined(QT_NO_SOUND)
if (!effect)
effect = new QSoundEffect(nethack_qt_::NetHackQtBind::mainWidget());
if (effect) {
effect->setLoopCount(1);
effect->setVolume((1.00f * volume) / 100.0f);
effect->setSource(QUrl::fromLocalFile(filename));
effect->play();
}
#else
nhUse(filename);
nhUse(volume);
#endif
}
} // namespace nethack_qt_
struct window_procs Qt_procs = {
@@ -1117,31 +1169,17 @@ struct window_procs Qt_procs = {
nethack_qt_::NetHackQtBind::qt_ctrl_nhwindow,
};
#ifndef WIN32
extern "C" void play_usersound(const char *, int);
#if defined(USER_SOUNDS) && !defined(QT_NO_SOUND)
QSoundEffect *effect = NULL;
#endif
/* called from core, sounds.c */
void
play_usersound(const char *filename, int volume)
{
#if defined(USER_SOUNDS) && !defined(QT_NO_SOUND)
if (!effect)
effect = new QSoundEffect(nethack_qt_::NetHackQtBind::mainWidget());
if (effect) {
effect->setLoopCount(1);
effect->setVolume((1.00f * volume) / 100.0f);
effect->setSource(QUrl::fromLocalFile(filename));
effect->play();
}
#else
nhUse(filename);
nhUse(volume);
#endif
}
#endif /*!WIN32*/
#if defined(SND_LIB_QTSOUND) && !defined(QT_NO_SOUND)
struct sound_procs qtsound_procs = {
SOUNDID(qtsound),
SNDCAP_USERSOUNDS,
nethack_qt_::NetHackQtBind::qtsound_init_nhsound,
nethack_qt_::NetHackQtBind::qtsound_exit_nhsound,
nethack_qt_::NetHackQtBind::qtsound_achievement,
nethack_qt_::NetHackQtBind::qtsound_soundeffect,
nethack_qt_::NetHackQtBind::qtsound_hero_playnotes,
nethack_qt_::NetHackQtBind::qtsound_play_usersound,
};
#endif /* SND_LIB_QTSOUND and !QT_NO_SOUND */
//qt_bind.cpp
+12 -1
View File
@@ -36,6 +36,9 @@ private:
public:
static void qt_Splash();
/* window interface */
static void qt_init_nhwindows(int* argc, char** argv);
static void qt_player_selection();
static void qt_askname();
@@ -90,8 +93,16 @@ public:
static int qt_kbhit();
static void qt_update_inventory(int);
static win_request_info *qt_ctrl_nhwindow(winid, int, win_request_info *);
static QWidget *mainWidget() { return main; }
#if defined(SND_LIB_QTSOUND) && !defined(QT_NO_SOUND)
/* sound interface */
static void qtsound_init_nhsound(void);
static void qtsound_exit_nhsound(const char *);
static void qtsound_achievement(schar, schar, int32_t);
static void qtsound_soundeffect(char *, int32_t, int32_t);
static void qtsound_hero_playnotes(int32_t instrument, char *str, int32_t volume);
static void qtsound_play_usersound(char *, int32_t, int32_t);
#endif
private:
virtual bool notify(QObject *receiver, QEvent *event);