diff --git a/src/common.h b/src/common.h
index fb0d9a6..24d1890 100644
--- a/src/common.h
+++ b/src/common.h
@@ -1,4 +1,6 @@
+#define MAX_DRV_PARM 10
+
struct options {
int start; /* start order */
int amplify; /* amplification factor */
@@ -15,6 +17,7 @@ struct options {
char *drv_id; /* sound driver ID */
char *out_file; /* output file name */
char *ins_path; /* instrument path */
+ char *driver_parm[MAX_DRV_PARM]; /* driver parameters */
char mute[XMP_MAX_CHANNELS];
};
diff --git a/src/main.c b/src/main.c
index c28600e..fb30468 100644
--- a/src/main.c
+++ b/src/main.c
@@ -166,8 +166,8 @@ int main(int argc, char **argv)
if (options.silent) {
sound = &sound_null;
} else {
- sound = select_sound_driver(options.drv_id,
- &options.freq, &options.format);
+ sound = select_sound_driver(options.drv_id, &options.freq,
+ &options.format, options.driver_parm);
}
if (sound == NULL) {
diff --git a/src/options.c b/src/options.c
index 98df0a4..60883fa 100644
--- a/src/options.c
+++ b/src/options.c
@@ -19,7 +19,6 @@
#include "list.h"
extern char *optarg;
-static int o, i;
static char *token;
#ifdef HAVE_SYS_RTPRIO_H
@@ -50,21 +49,6 @@ static void usage(char *s)
printf("Usage: %s [options] [modules]\n", s);
-#if 0
- printf("\nRegistered module loaders:\n");
- xmp_get_fmt_info(&fmt);
- list_wrap(NULL, 3, 78, 1);
-
- for (i = 0, f = fmt; f; i++, f = f->next) {
- snprintf(buf, 80, "%s (%s)", f->id, f->tracker);
- list_wrap(buf, 3, 0, 1);
- }
-
- snprintf(buf, 80, "[%d registered loaders]", i);
- list_wrap(buf, 3, 0, 0);
- printf("\n");
-#endif
-
printf("\nAvailable drivers:\n");
list_for_each(head, &sound_driver_list) {
@@ -146,8 +130,10 @@ static struct option lopt[] = {
void get_options(int argc, char **argv, struct options *options)
{
int optidx = 0;
+ int dparm = 0;
+ int o;
+
#define OPTIONS "a:b:cD:d:f:hI:iLlM:mno:qRS:s:T:t:uVv"
- i = 0;
while ((o = getopt_long(argc, argv, OPTIONS, lopt, &optidx)) != -1) {
switch (o) {
case 'a':
@@ -161,11 +147,9 @@ void get_options(int argc, char **argv, struct options *options)
case 'c':
options->out_file = "-";
break;
-#if 0
case 'D':
- xmp_set_driver_parameter(opt, optarg);
+ options->driver_parm[dparm++] = optarg;
break;
-#endif
case 'd':
options->drv_id = optarg;
break;
diff --git a/src/sound.c b/src/sound.c
index 75c2a27..831c7ff 100644
--- a/src/sound.c
+++ b/src/sound.c
@@ -38,7 +38,7 @@ void init_sound_drivers()
#endif
}
-struct sound_driver *select_sound_driver(char *pref, int *rate, int *format)
+struct sound_driver *select_sound_driver(char *pref, int *rate, int *format, char **parm)
{
struct list_head *head;
struct sound_driver *sd;
@@ -47,7 +47,7 @@ struct sound_driver *select_sound_driver(char *pref, int *rate, int *format)
list_for_each(head, &sound_driver_list) {
sd = list_entry(head, struct sound_driver, list);
if (strcmp(sd->id, pref) == 0) {
- if (sd->init(rate, format) == 0) {
+ if (sd->init(rate, format, parm) == 0) {
return sd;
}
}
@@ -56,7 +56,7 @@ struct sound_driver *select_sound_driver(char *pref, int *rate, int *format)
list_for_each(head, &sound_driver_list) {
sd = list_entry(head, struct sound_driver, list);
/* Probing */
- if (sd->init(rate, format) == 0) {
+ if (sd->init(rate, format, parm) == 0) {
/* found */
return sd;
}
diff --git a/src/sound.h b/src/sound.h
index 0f72744..4f35350 100644
--- a/src/sound.h
+++ b/src/sound.h
@@ -2,13 +2,14 @@
#define __SOUND_H
#include
+#include
#include "list.h"
struct sound_driver {
char *id;
char *description;
char **help;
- int (*init)(int *, int *);
+ int (*init)(int *, int *, char **);
void (*deinit)(void);
void (*play)(void *, int);
void (*flush)(void);
@@ -17,7 +18,23 @@ struct sound_driver {
struct list_head list;
};
+#define parm_init() { char *token; for (; *parm; parm++) { \
+ char s[80]; strncpy(s, *parm, 80); \
+ token = strtok(s, ":="); token = strtok(NULL, "");
+#define parm_end() } }
+#define parm_error() do { \
+ fprintf(stderr, "xmp: incorrect parameters in -D %s\n", s); \
+ exit(-4); } while (0)
+#define chkparm0(x,y) { \
+ if (!strcmp(s, x)) { \
+ if (token != NULL) parm_error(); else { y; } } }
+#define chkparm1(x,y) { \
+ if (!strcmp(s, x)) { \
+ if (token == NULL) parm_error(); else { y; } } }
+#define chkparm2(x,y,z,w) { if (!strcmp(s, x)) { \
+ if (2 > sscanf(token, y, z, w)) parm_error(); } }
+
void init_sound_drivers(void);
-struct sound_driver *select_sound_driver(char *, int *, int *);
+struct sound_driver *select_sound_driver(char *, int *, int *, char **);
#endif
diff --git a/src/sound_alsa.c b/src/sound_alsa.c
index af8b7c4..6ebc957 100644
--- a/src/sound_alsa.c
+++ b/src/sound_alsa.c
@@ -5,8 +5,7 @@
static snd_pcm_t *pcm_handle;
-
-static int init(int *rate, int *format)
+static int init(int *rate, int *format, char **parm)
{
snd_pcm_hw_params_t *hwparams;
int ret;
@@ -15,6 +14,12 @@ static int init(int *rate, int *format)
unsigned int ptime = 50000; /* 50ms */
char *card_name = "default";
+ parm_init();
+ chkparm1("buffer", btime = 1000 * strtoul(token, NULL, 0));
+ chkparm1("period", btime = 1000 * strtoul(token, NULL, 0));
+ chkparm1("card", card_name = token);
+ parm_end();
+
if ((ret = snd_pcm_open(&pcm_handle, card_name,
SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
fprintf(stderr, "Unable to initialize ALSA pcm device: %s\n",
diff --git a/src/sound_bsd.c b/src/sound_bsd.c
index 95781f3..e55fbb3 100644
--- a/src/sound_bsd.c
+++ b/src/sound_bsd.c
@@ -19,13 +19,7 @@
static int audio_fd;
-static char *help[] = {
- "gain=val", "Audio output gain (0 to 255)",
- "buffer=val", "Audio buffer size (default is 32768)",
- NULL
-};
-
-static int init(int *rate, int *format)
+static int init(int *rate, int *format, char **parm)
{
audio_info_t ainfo;
int gain = 128;
@@ -100,6 +94,12 @@ static void onresume()
{
}
+static char *help[] = {
+ "gain=val", "Audio output gain (0 to 255)",
+ "buffer=val", "Audio buffer size (default is 32768)",
+ NULL
+};
+
struct sound_driver sound_bsd = {
"bsd",
"BSD PCM audio",
diff --git a/src/sound_coreaudio.c b/src/sound_coreaudio.c
index 719f13b..138620c 100644
--- a/src/sound_coreaudio.c
+++ b/src/sound_coreaudio.c
@@ -123,14 +123,13 @@ OSStatus render_proc(void *inRefCon,
*/
-static int init(int *sampling_rate, int *format)
+static int init(int *sampling_rate, int *format, char **parm)
{
struct xmp_options *o = &ctx->o;
AudioStreamBasicDescription ad;
Component comp;
ComponentDescription cd;
AURenderCallbackStruct rc;
- //char *token, **parm;
OSStatus err;
UInt32 size, max_frames;
diff --git a/src/sound_null.c b/src/sound_null.c
index 402cfa3..05b1a7a 100644
--- a/src/sound_null.c
+++ b/src/sound_null.c
@@ -2,7 +2,7 @@
#include
#include "sound.h"
-static int init(int *sampling_rate, int *format)
+static int init(int *sampling_rate, int *format, char **parm)
{
return 0;
}
diff --git a/src/sound_oss.c b/src/sound_oss.c
index 1cf2313..553519c 100644
--- a/src/sound_oss.c
+++ b/src/sound_oss.c
@@ -40,14 +40,9 @@
# endif
#endif
-static int audio_fd;
+struct sound_driver sound_oss;
-static char *help[] = {
- "frag=num,size", "Set the number and size of fragments",
- "dev=", "Audio device to use (default /dev/dsp)",
- "nosync", "Don't flush OSS buffers between modules",
- NULL
-};
+static int audio_fd;
static int fragnum, fragsize;
static int do_sync = 1;
@@ -115,24 +110,21 @@ static void setaudio(int *rate, int *format)
}
}
-static int init(int *rate, int *format)
+static int init(int *rate, int *format, char **parm)
{
char *dev_audio[] = { "/dev/dsp", "/dev/sound/dsp" };
audio_buf_info info;
- //static char buf[80];
- //char *token, **parm;
+ static char buf[80];
int i;
fragnum = 16; /* default number of fragments */
i = 1024; /* default size of fragment */
-#if 0
parm_init();
chkparm2("frag", "%d,%d", &fragnum, &i);
chkparm1("dev", dev_audio[0] = token);
chkparm0("nosync", do_sync = 0);
parm_end();
-#endif
for (fragsize = 0; i >>= 1; fragsize++) ;
if (fragsize < 4)
@@ -146,15 +138,12 @@ static int init(int *rate, int *format)
setaudio(rate, format);
-#if 0
if (ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info) == 0) {
snprintf(buf, 80, "%s [%d fragments of %d bytes]",
- drv_oss.description, info.fragstotal,
+ sound_oss.description, info.fragstotal,
info.fragsize);
- drv_oss.description = buf;
+ sound_oss.description = buf;
}
-#endif
- ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info);
return 0;
}
@@ -206,6 +195,13 @@ static void onresume()
#endif
}
+static char *help[] = {
+ "frag=num,size", "Set the number and size of fragments",
+ "dev=", "Audio device to use (default /dev/dsp)",
+ "nosync", "Don't flush OSS buffers between modules",
+ NULL
+};
+
struct sound_driver sound_oss = {
"oss",
"OSS PCM audio",
diff --git a/src/sound_sndio.c b/src/sound_sndio.c
index 7563390..7567f39 100644
--- a/src/sound_sndio.c
+++ b/src/sound_sndio.c
@@ -22,7 +22,7 @@
static struct sio_hdl *hdl;
-static int init(int *rate, int *format)
+static int init(int *rate, int *format, char **parm)
{
struct sio_par par, askpar;
diff --git a/src/sound_win32.c b/src/sound_win32.c
index a9a3aba..3509898 100644
--- a/src/sound_win32.c
+++ b/src/sound_win32.c
@@ -31,11 +31,6 @@ static WORD freebuffer; /* */
static WORD nextbuffer; /* next buffer to be mixed */
static int num_buffers;
-static char *help[] = {
- "buffers=val", "Number of buffers (default 10)",
- NULL
-};
-
static void show_error(int res)
{
char *msg;
@@ -75,18 +70,17 @@ static void CALLBACK wave_callback(HWAVEOUT hwo, UINT uMsg, DWORD dwInstance,
}
}
-static int init(int *sampling_rate, int *format)
+static int init(int *sampling_rate, int *format, char **parm)
{
MMRESULT res;
WAVEFORMATEX wfe;
int i;
- //char *token, **parm;
num_buffers = 10;
- //parm_init();
- //chkparm1("buffers", num_buffers = strtoul(token, NULL, 0));
- //parm_end();
+ parm_init();
+ chkparm1("buffers", num_buffers = strtoul(token, NULL, 0));
+ parm_end();
if (num_buffers > MAXBUFFERS)
num_buffers = MAXBUFFERS;
@@ -171,6 +165,11 @@ static void onresume()
{
}
+static char *help[] = {
+ "buffers=val", "Number of buffers (default 10)",
+ NULL
+};
+
struct sound_driver sound_win32 = {
"win32",
"Windows WinMM",