Change directory layout

Make the layout more appropriate for a library-only package, move front-ends
and other things not library-related out of src/ and into players/.

Signed-off-by: Claudio Matsuoka <cmatsuoka@gmail.com>
master
Claudio Matsuoka 14 years ago
commit 3e1d8617b4
  1. 26
      Makefile
  2. 19
      common.h
  3. 106
      drivers.c
  4. 26
      drivers/Makefile
  5. 153
      drivers/aix.c
  6. 175
      drivers/alsa.c
  7. 234
      drivers/alsa05.c
  8. 90
      drivers/amiga.c
  9. 230
      drivers/beos.c
  10. 123
      drivers/bsd.c
  11. 57
      drivers/debug.c
  12. 127
      drivers/file.c
  13. 164
      drivers/hpux.c
  14. 168
      drivers/netbsd.c
  15. 125
      drivers/openbsd.c
  16. 261
      drivers/os2_dart.c
  17. 217
      drivers/oss.c
  18. 279
      drivers/osx.c
  19. 101
      drivers/pulseaudio.c
  20. 130
      drivers/qnx.c
  21. 221
      drivers/sgi.c
  22. 42
      drivers/smix.c
  23. 110
      drivers/sndio.c
  24. 206
      drivers/solaris.c
  25. 183
      drivers/wav.c
  26. 177
      drivers/win32.c
  27. 1006
      getopt.c
  28. 193
      getopt1.c
  29. 63
      info.c
  30. 637
      main-old.c
  31. 141
      main.c
  32. 325
      options.c
  33. 11
      sound.h
  34. 70
      sound_alsa.c
  35. 41
      terminal.c

@ -0,0 +1,26 @@
#MAIN_OBJS = getopt.o getopt1.o options.o drivers.o main.o
MAIN_OBJS = sound_alsa.o terminal.o info.o options.o main.o
MAIN_DFILES = Makefile $(MAIN_OBJS:.o=.c)
MAIN_PATH = players/xmp
dist-main:
mkdir -p $(DIST)/$(MAIN_PATH)
cp -RPp $(addprefix $(MAIN_PATH)/,$(MAIN_DFILES)) $(DIST)/$(MAIN_PATH)
$(MAIN_PATH)/options.o: Makefile
M_OBJS = $(addprefix $(MAIN_PATH)/,$(MAIN_OBJS))
$(MAIN_PATH)/xmp: $(M_OBJS) $(LIB)
@CMD='$(LD) -o $@ $(LDFLAGS) $(M_OBJS) -Llib -lxmp -lm -lasound'; \
if [ "$(V)" -gt 0 ]; then echo $$CMD; else echo LD $@ ; fi; \
eval $$CMD
$(M_OBJS): $(LIB)
install-xmp: $(MAIN_PATH)/xmp
@echo Installing xmp in $(DESTDIR)$(BINDIR)
@[ -d $(DESTDIR)$(BINDIR) ] || mkdir -p $(DESTDIR)$(BINDIR)
@$(INSTALL_PROGRAM) $+ $(DESTDIR)$(BINDIR)

@ -0,0 +1,19 @@
struct options {
int start; /* start order */
int amplify; /* amplification factor */
int freq; /* sampling rate */
int format; /* sample format */
int time; /* max. replay time */
int mix; /* channel separation */
int loop; /* loop module */
int random; /* play in random order */
int load_only; /* load module and exit */
char *out_file; /* output file name */
char *ins_path; /* instrument path */
char mute[XMP_MAX_CHANNELS];
};
int set_tty(void);
int reset_tty(void);

@ -0,0 +1,106 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "xmp.h"
extern struct xmp_drv_info drv_file;
extern struct xmp_drv_info drv_wav;
extern struct xmp_drv_info drv_osx;
extern struct xmp_drv_info drv_solaris;
extern struct xmp_drv_info drv_hpux;
extern struct xmp_drv_info drv_bsd;
extern struct xmp_drv_info drv_netbsd;
extern struct xmp_drv_info drv_openbsd;
extern struct xmp_drv_info drv_sndio;
extern struct xmp_drv_info drv_sgi;
extern struct xmp_drv_info drv_aix;
extern struct xmp_drv_info drv_oss_seq;
extern struct xmp_drv_info drv_oss;
extern struct xmp_drv_info drv_alsa;
extern struct xmp_drv_info drv_alsa05;
extern struct xmp_drv_info drv_net;
extern struct xmp_drv_info drv_esd;
extern struct xmp_drv_info drv_arts;
extern struct xmp_drv_info drv_nas;
extern struct xmp_drv_info drv_pulseaudio;
extern struct xmp_drv_info drv_os2dart;
extern struct xmp_drv_info drv_qnx;
extern struct xmp_drv_info drv_beos;
extern struct xmp_drv_info drv_amiga;
extern struct xmp_drv_info drv_win32;
void init_drivers()
{
#ifdef DRIVER_OSX
xmp_drv_register(&drv_osx);
#endif
#ifdef DRIVER_WIN32
xmp_drv_register(&drv_win32);
#endif
#ifdef DRIVER_SOLARIS
xmp_drv_register(&drv_solaris);
#endif
#ifdef DRIVER_HPUX
xmp_drv_register(&drv_hpux);
#endif
#ifdef DRIVER_BSD
xmp_drv_register(&drv_bsd);
#endif
#ifdef DRIVER_NETBSD
xmp_drv_register(&drv_netbsd);
#endif
#ifdef DRIVER_SNDIO
xmp_drv_register(&drv_sndio);
#endif
#ifdef DRIVER_OPENBSD
xmp_drv_register(&drv_openbsd);
#endif
#ifdef DRIVER_SGI
xmp_drv_register(&drv_sgi);
#endif
#ifdef DRIVER_OSS_SEQ
xmp_drv_register(&drv_oss_seq);
#endif
#ifdef DRIVER_OSS
xmp_drv_register(&drv_oss);
#endif
#ifdef DRIVER_ALSA
xmp_drv_register(&drv_alsa);
#endif
#ifdef DRIVER_ALSA05
xmp_drv_register(&drv_alsa05);
#endif
#ifdef DRIVER_QNX
xmp_drv_register(&drv_qnx);
#endif
#ifdef DRIVER_BEOS
xmp_drv_register(&drv_beos);
#endif
#ifdef DRIVER_AMIGA
xmp_drv_register(&drv_amiga);
#endif
#ifdef DRIVER_NET
xmp_drv_register(&drv_net);
#endif
#ifdef DRIVER_OS2DART
xmp_drv_register(&drv_os2dart);
#endif
#ifdef DRIVER_PULSEAUDIO
xmp_drv_register(&drv_pulseaudio);
#endif
#ifdef DRIVER_ARTS
xmp_drv_register(&drv_arts);
#endif
#ifdef DRIVER_ESD
xmp_drv_register(&drv_esd);
#endif
#ifdef DRIVER_NAS
xmp_drv_register(&drv_nas);
#endif
xmp_drv_register(&drv_file);
xmp_drv_register(&drv_wav);
}

@ -0,0 +1,26 @@
DRV = file.c oss.c hpux.c bsd.c solaris.c alsa.c alsa05.c \
sgi.c os2_dart.c netbsd.c openbsd.c aix.c qnx.c \
win32.c smix.c wav.c osx.c beos.c pulseaudio.c amiga.c sndio.c
DRIVERS_OBJS = file.o wav.o
DRIVERS_LOBJS = smix.lo
DRIVERS_DFILES = Makefile $(DRV) debug.c
DRIVERS_PATH = src/drivers
# Don't include platform-specific drivers in DRIVERS_OBJS so we can generate
# foreign makefiles from it (such as MSVC .dsp files, etc)
D_OBJS = $(addprefix $(DRIVERS_PATH)/,$(DRIVERS_OBJS) $(DRIVERS))
D_LOBJS = $(addprefix $(DRIVERS_PATH)/,$(DRIVERS_LOBJS))
dist-drivers:
mkdir -p $(DIST)/$(DRIVERS_PATH)
cp -RPp $(addprefix $(DRIVERS_PATH)/,$(DRIVERS_DFILES)) $(DIST)/$(DRIVERS_PATH)
$(DRIVERS_PATH)/beos.o: src/drivers/beos.c
g++ -c $(XCFLAGS) -o $@ $+
$(DRIVERS_PATH)/arts.o: src/drivers/arts.c
$(CC) $(CFLAGS) $(XCFLAGS) `artsc-config --cflags` -o $@ $+

@ -0,0 +1,153 @@
/* Extended Module Player
* Copyright (C) 1996-2012 Claudio Matsuoka and Hipolito Carraro Jr
*
* This file is part of the Extended Module Player and is distributed
* under the terms of the GNU General Public License. See doc/COPYING
* for more information.
*/
/*
* Based on the AIX XMMS output plugin by Peter Alm, Thomas Nilsson
* and Olle Hallnas.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <sys/types.h>
#include <sys/param.h>
#include <sys/audio.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "common.h"
#include "driver.h"
#include "mixer.h"
static int audio_fd;
static audio_control control;
static audio_change change;
static int init(struct context_data *);
static int setaudio(struct xmp_options *);
static void bufdump(struct context_data *, void *, int);
static void shutdown(struct context_data *);
static void dummy()
{
}
static char *help[] = {
"gain=val", "Audio output gain (0 to 255)",
/* "buffer=val", "Audio buffer size (default is 32768)", */
NULL
};
struct xmp_drv_info drv_bsd = {
"aix", /* driver ID */
"AIX PCM audio", /* driver description */
help, /* help */
init, /* init */
shutdown, /* shutdown */
dummy, /* starttimer */
dummy, /* stoptimer */
bufdump, /* bufdump */
NULL
};
#define AUDIO_MIN_GAIN 0
#define AUDIO_MAX_GAIN 100
static int setaudio(struct xmp_options *o)
{
audio_init ainit;
int gain = 128;
int bsize = 32 * 1024;
char *token, **parm;
parm_init();
chkparm1("gain", gain = strtoul(token, NULL, 0));
/* chkparm1 ("buffer", bsize = strtoul(token, NULL, 0)); */
parm_end();
if (gain < AUDIO_MIN_GAIN)
gain = AUDIO_MIN_GAIN;
if (gain > AUDIO_MAX_GAIN)
gain = AUDIO_MAX_GAIN;
init.mode = PCM; /* audio format */
init.srate = o->freq; /* sample rate */
init.operation = PLAY; /* PLAY or RECORD */
init.channels = o->outfmt & XMP_FORMAT_MONO ? 1 : 2;
init.bits_per_sample = o->resol; /* bits per sample */
init.flags = BIG_ENDIAN | TWOS_COMPLEMENT;
if (ioctl(audio_fd, AUDIO_INIT, &init) < 0) {
close(audio_fd);
return XMP_ERR_DINIT;
}
/* full blast; range: 0-0x7fffffff */
change.volume = 0x7fffffff * (1.0 * gain / 200.0);
change.monitor = AUDIO_IGNORE; /* monitor what's recorded ? */
change.input = AUDIO_IGNORE; /* input to record from */
change.output = OUTPUT_1; /* line-out */
change.balance = 0x3FFFFFFF;
control.ioctl_request = AUDIO_CHANGE;
control.request_info = (char *)&change;
if (ioctl(audio_fd, AUDIO_CONTROL, &control) < 0) {
close(audio_fd);
return XMP_ERR_DINIT;
}
/* start playback - won't actually start until write() calls occur */
control.ioctl_request = AUDIO_START;
control.position = 0;
if (ioctl(audio_fd, AUDIO_CONTROL, &control) < 0) {
close(audio_fd);
return XMP_ERR_DINIT;
}
return 0;
}
static int init(struct context_data *ctx)
{
if ((audio_fd = open("/dev/paud0/1", O_WRONLY)) == -1)
return XMP_ERR_DINIT;
if (setaudio(&ctx->o) != 0)
return XMP_ERR_DINIT;
return 0;
}
/* Build and write one tick (one PAL frame or 1/50 s in standard vblank
* timed mods) of audio data to the output device.
*/
static void bufdump(struct context_data *ctx, void *b, int i)
{
int j;
while (i) {
if ((j = write(audio_fd, b, i)) > 0) {
i -= j;
(char *)b += j;
} else
break;
};
}
static void shutdown(struct context_data *ctx)
{
control.ioctl_request = AUDIO_STOP;
ioctl(audio_fd, AUDIO_CONTROL, &control);
close(audio_fd);
}

@ -0,0 +1,175 @@
/* ALSA driver for xmp
* Copyright (C) 2005-2007 Claudio Matsuoka and Hipolito Carraro Jr
* Based on the ALSA 0.5 driver for xmp, Copyright (C) 2000 Tijs
* van Bakel and Rob Adamson.
*
* This file is part of the Extended Module Player and is distributed
* under the terms of the GNU General Public License. See doc/COPYING
* for more information.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <alsa/asoundlib.h>
#include <alsa/pcm.h>
#include "driver.h"
static int init (struct context_data *);
static int prepare_driver (void);
static void dshutdown (struct context_data *);
static int to_fmt (struct xmp_options *);
static void bufdump (struct context_data *, void *, int);
static void flush (void);
static void dummy () { }
static char *help[] = {
"buffer=num", "Set the ALSA buffer time in milliseconds",
"period=num", "Set the ALSA period time in milliseconds",
"card <name>", "Select sound card to use",
NULL
};
struct xmp_drv_info drv_alsa = {
"alsa", /* driver ID */
"ALSA PCM audio", /* driver description */
help, /* help */
init, /* init */
dshutdown, /* shutdown */
dummy, /* starttimer */
flush, /* stoptimer */
bufdump, /* bufdump */
};
static snd_pcm_t *pcm_handle;
static int init(struct context_data *ctx)
{
snd_pcm_hw_params_t *hwparams;
int ret;
char *token, **parm;
unsigned int channels, rate;
unsigned int btime = 250000; /* 250ms */
unsigned int ptime = 50000; /* 50ms */
char *card_name = "default";
struct xmp_options *o = &ctx->o;
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",
snd_strerror(ret));
return XMP_ERR_DINIT;
}
channels = (o->outfmt & XMP_FORMAT_MONO) ? 1 : 2;
rate = o->freq;
snd_pcm_hw_params_alloca(&hwparams);
snd_pcm_hw_params_any(pcm_handle, hwparams);
snd_pcm_hw_params_set_access(pcm_handle, hwparams,
SND_PCM_ACCESS_RW_INTERLEAVED);
snd_pcm_hw_params_set_format(pcm_handle, hwparams, to_fmt(o));
snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &rate, 0);
snd_pcm_hw_params_set_channels_near(pcm_handle, hwparams, &channels);
snd_pcm_hw_params_set_buffer_time_near(pcm_handle, hwparams, &btime, 0);
snd_pcm_hw_params_set_period_time_near(pcm_handle, hwparams, &ptime, 0);
snd_pcm_nonblock(pcm_handle, 0);
if ((ret = snd_pcm_hw_params(pcm_handle, hwparams)) < 0) {
fprintf(stderr, "Unable to set ALSA output parameters: %s\n",
snd_strerror(ret));
return XMP_ERR_DINIT;
}
if (prepare_driver() < 0)
return XMP_ERR_DINIT;
o->freq = rate;
return 0;
}
static int prepare_driver()
{
int ret;
if ((ret = snd_pcm_prepare(pcm_handle)) < 0 ) {
fprintf(stderr, "Unable to prepare ALSA: %s\n",
snd_strerror(ret));
return ret;
}
return 0;
}
static int to_fmt(struct xmp_options *o)
{
int fmt;
switch (o->resol) {
case 0:
return SND_PCM_FORMAT_MU_LAW;
case 8:
fmt = SND_PCM_FORMAT_U8 | SND_PCM_FORMAT_S8;
break;
default:
if (o->big_endian) {
fmt = SND_PCM_FORMAT_S16_BE | SND_PCM_FORMAT_U16_BE;
} else {
fmt = SND_PCM_FORMAT_S16_LE | SND_PCM_FORMAT_U16_LE;
}
}
if (o->outfmt & XMP_FMT_UNS) {
fmt &= SND_PCM_FORMAT_U8 | SND_PCM_FORMAT_U16_LE |
SND_PCM_FORMAT_U16_BE;
} else {
fmt &= SND_PCM_FORMAT_S8 | SND_PCM_FORMAT_S16_LE |
SND_PCM_FORMAT_S16_BE;
}
return fmt;
}
/* Build and write one tick (one PAL frame or 1/50 s in standard vblank
* timed mods) of audio data to the output device.
*/
static void bufdump(struct context_data *ctx, void *b, int i)
{
int frames;
frames = snd_pcm_bytes_to_frames(pcm_handle, i);
if (snd_pcm_writei(pcm_handle, b, frames) < 0) {
snd_pcm_prepare(pcm_handle);
}
}
static void dshutdown(struct context_data *ctx)
{
snd_pcm_close(pcm_handle);
}
static void flush()
{
snd_pcm_drain(pcm_handle);
prepare_driver();
}

@ -0,0 +1,234 @@
/* ALSA 0.5 driver for xmp
* Copyright (C) 2000 Tijs van Bakel and Rob Adamson
*
* This file is part of the Extended Module Player and is distributed
* under the terms of the GNU General Public License. See doc/COPYING
* for more information.
*
* Fixed for ALSA 0.5 by Rob Adamson <R.Adamson@fitz.cam.ac.uk>
* Sat, 29 Apr 2000 17:10:46 +0100 (BST)
*/
/* preliminary alsa 0.5 support, Tijs van Bakel, 02-03-2000.
* only default values are supported and music sounds chunky
*/
/* Better ALSA 0.5 support, Rob Adamson, 16 Mar 2000.
* Again, hard-wired fragment size & number and sample rate,
* but it plays smoothly now.
*/
/* Now uses specified options - Rob Adamson, 20 Mar 2000 */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/asoundlib.h>
#include "driver.h"
#include "mixer.h"
static int init (struct context_data *ctx);
static void dshutdown (struct context_data *);
static void bufdump (struct context_data *, void *, int);
static void bufwipe (void);
static void flush (void);
static void dummy()
{
}
static char *help[] = {
"frag=num,size", "Set the number and size (bytes) of fragments",
"card <name>", "Select sound card to use",
NULL
};
struct xmp_drv_info drv_alsa05 = {
"alsa05", /* driver ID */
"ALSA 0.5 PCM audio", /* driver description */
help, /* help */
init, /* init */
dshutdown, /* shutdown */
dummy, /* starttimer */
flush, /* stoptimer */
bufdump, /* bufdump */
NULL
};
static snd_pcm_t *pcm_handle;
static int frag_num = 4;
static size_t frag_size = 4096;
static char *mybuffer = NULL;
static char *mybuffer_nextfree = NULL;
static char *card_name;
static int prepare_driver(void)
{
int rc;
rc = snd_pcm_plugin_prepare(pcm_handle, SND_PCM_CHANNEL_PLAYBACK);
if (rc < 0) {
printf("Unable to prepare plugin: %s\n", snd_strerror(rc));
return rc;
}
return 0;
}
static int to_fmt(struct xmp_options *o)
{
int fmt;
if (o->resol == 0)
return SND_PCM_SFMT_MU_LAW;
if (o->resol == 8) {
fmt = SND_PCM_SFMT_U8 | SND_PCM_SFMT_S8;
} else {
fmt = SND_PCM_SFMT_S16_LE | SND_PCM_SFMT_S16_BE |
SND_PCM_SFMT_U16_LE | SND_PCM_SFMT_U16_BE;
if (o->big_endian) {
fmt &= SND_PCM_SFMT_S16_BE | SND_PCM_SFMT_U16_BE;
} else {
fmt &= SND_PCM_SFMT_S16_LE | SND_PCM_SFMT_U16_LE;
}
}
if (o->outfmt & XMP_FMT_UNS) {
fmt &= SND_PCM_SFMT_U8|SND_PCM_SFMT_U16_LE|SND_PCM_SFMT_U16_BE;
} else {
fmt &= SND_PCM_SFMT_S8|SND_PCM_SFMT_S16_LE|SND_PCM_SFMT_S16_BE;
}
return fmt;
}
static int init(struct context_data *ctx)
{
struct xmp_options *o = &ctx->o;
snd_pcm_channel_params_t params;
snd_pcm_channel_setup_t setup;
int card = 0;
int dev = 0;
int rc;
char *token, **parm;
parm_init();
chkparm2("frag", "%d,%d", &frag_num, &frag_size);
if (frag_num > 8)
frag_num = 8;
if (frag_num < 4)
frag_num = 4;
if (frag_size > 65536)
frag_size = 65536;
if (frag_size < 16)
frag_size = 16;
chkparm1("card", card_name = token);
// card = snd_card_name(card_name); /* ? */
// dev = snd_defaults_pcm_device(); /* ? */
parm_end();
mybuffer = malloc(frag_size);
if (mybuffer) {
mybuffer_nextfree = mybuffer;
} else {
printf("Unable to allocate memory for mixer buffer\n");
return XMP_ERR_DINIT;
}
if ((rc =
snd_pcm_open(&pcm_handle, card, dev, SND_PCM_OPEN_PLAYBACK)) < 0) {
printf("Unable to initialize pcm device: %s\n",
snd_strerror(rc));
return XMP_ERR_DINIT;
}
memset(&params, 0, sizeof(snd_pcm_channel_params_t));
params.mode = SND_PCM_MODE_BLOCK;
params.buf.block.frag_size = frag_size;
params.buf.block.frags_min = 1;
params.buf.block.frags_max = frag_num;
//params.mode = SND_PCM_MODE_STREAM;
//params.buf.stream.queue_size = 16384;
//params.buf.stream.fill = SND_PCM_FILL_NONE;
//params.buf.stream.max_fill = 0;
params.channel = SND_PCM_CHANNEL_PLAYBACK;
params.start_mode = SND_PCM_START_FULL;
params.stop_mode = SND_PCM_STOP_ROLLOVER;
params.format.interleave = 1;
params.format.format = to_fmt(o);
params.format.rate = o->freq;
params.format.voices = (o->outfmt & XMP_FORMAT_MONO) ? 1 : 2;
if ((rc = snd_pcm_plugin_params(pcm_handle, &params)) < 0) {
printf("Unable to set output parameters: %s\n",
snd_strerror(rc));
return XMP_ERR_DINIT;
}
if (prepare_driver() < 0)
return XMP_ERR_DINIT;
memset(&setup, 0, sizeof(setup));
setup.mode = SND_PCM_MODE_STREAM;
setup.channel = SND_PCM_CHANNEL_PLAYBACK;
if ((rc = snd_pcm_channel_setup(pcm_handle, &setup)) < 0) {
printf("Unable to setup channel: %s\n", snd_strerror(rc));
return XMP_ERR_DINIT;
}
return 0;
}
/* Build and write one tick (one PAL frame or 1/50 s in standard vblank
* timed mods) of audio data to the output device.
*/
static void bufdump(struct context_data *ctx, void *b, int i)
{
/* Note this assumes a fragment size of (frag_size) */
while (i > 0) {
size_t f = (frag_size) - (mybuffer_nextfree - mybuffer);
size_t to_copy = (f < i) ? f : i;
memcpy(mybuffer_nextfree, b, to_copy);
b += to_copy;
mybuffer_nextfree += to_copy;
f -= to_copy;
i -= to_copy;
if (f == 0) {
snd_pcm_plugin_write(pcm_handle, mybuffer, frag_size);
mybuffer_nextfree = mybuffer;
}
}
}
static void dshutdown(struct context_data *ctx)
{
snd_pcm_close(pcm_handle);
free(mybuffer);
}
static void flush()
{
snd_pcm_plugin_flush(pcm_handle, SND_PCM_CHANNEL_PLAYBACK);
prepare_driver();
}

@ -0,0 +1,90 @@
/* Amiga AHI driver for Extended Module Player
* Copyright (C) 2007 Lorence Lombardo
*
* This file is part of the Extended Module Player and is distributed
* under the terms of the GNU General Public License. See doc/COPYING
* for more information.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include "common.h"
#include "driver.h"
#include "mixer.h"
#include "convert.h"
static int fd;
static int init(struct context_data *);
static void bufdump(struct context_data *, void *, int);
static void shutdown(struct context_data *);
static void dummy()
{
}
static char *help[] = {
"buffer=val", "Audio buffer size",
NULL
};
struct xmp_drv_info drv_amiga = {
"ahi", /* driver ID */
"Amiga AHI audio", /* driver description */
help, /* help */
init, /* init */
shutdown, /* shutdown */
dummy, /* starttimer */
dummy, /* stoptimer */
dummy, /* resetvoices */
bufdump, /* bufdump */
NULL
};
static int init(struct context_data *ctx)
{
struct xmp_options *o = &ctx->o;
char outfile[256];
int nch = o->outfmt & XMP_FORMAT_MONO ? 1 : 2;
int bsize = o->freq * nch * o->resol / 4;
char *token, **parm;
parm_init();
chkparm1("buffer", bsize = strtoul(token, NULL, 0));
parm_end();
sprintf(outfile, "AUDIO:B/%d/F/%d/C/%d/BUFFER/%d",
o->resol, o->freq, nch, bsize);
fd = open(outfile, O_WRONLY);
return 0;
}
static void bufdump(struct context_data *ctx, void *b, int i)
{
int j;
while (i) {
if ((j = write(fd, b, i)) > 0) {
i -= j;
b = (char *)b + j;
} else
break;
}
}
static void shutdown(struct context_data *ctx)
{
if (fd)
close(fd);
}

@ -0,0 +1,230 @@
/* Extended Module Player
* Copyright (C) 1996-2012 Claudio Matsuoka and Hipolito Carraro Jr
*
* This file is part of the Extended Module Player and is distributed
* under the terms of the GNU General Public License. See doc/COPYING
* for more information.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <Application.h>
#include <SoundPlayer.h>
#define B_AUDIO_CHAR 1
#define B_AUDIO_SHORT 2
extern "C" {
#include <string.h>
#include <stdlib.h>
#include "xmp.h"
/* g++ doesn't like typedef xmp_context and struct context_data */
#define xmp_context _xmp_context
#include "common.h"
#include "driver.h"
#include "mixer.h"
}
static int init (struct context_data *ctx);
static void bufdump (struct context_data *, void *, int);
static void myshutdown (struct context_data *);
static void dummy()
{
}
static char *help[] = {
"buffer=num,size", "set the number and size of buffer fragments",
NULL
};
struct xmp_drv_info drv_beos = {
"beos", /* driver ID */
"BeOS PCM audio", /* driver description */
NULL, /* help */
(int (*)())init, /* init */
(void (*)())myshutdown, /* shutdown */
dummy, /* starttimer */
dummy, /* flush */
(void (*)())bufdump, /* bufdump */
};
static media_raw_audio_format fmt;
static BSoundPlayer *player;
/*
* CoreAudio helpers from mplayer/libao
* The player fills a ring buffer, BSP retrieves data from the buffer
*/
static int paused;
static uint8 *buffer;
static int buffer_len;
static int buf_write_pos;
static int buf_read_pos;
static int chunk_size;
static int chunk_num;
static int packet_size;
/* return minimum number of free bytes in buffer, value may change between
* two immediately following calls, and the real number of free bytes
* might actually be larger! */
static int buf_free()
{
int free = buf_read_pos - buf_write_pos - chunk_size;
if (free < 0)
free += buffer_len;
return free;
}
/* return minimum number of buffered bytes, value may change between
* two immediately following calls, and the real number of buffered bytes
* might actually be larger! */
static int buf_used()
{
int used = buf_write_pos - buf_read_pos;
if (used < 0)
used += buffer_len;
return used;
}
/* add data to ringbuffer */
static int write_buffer(unsigned char *data, int len)
{
int first_len = buffer_len - buf_write_pos;
int free = buf_free();
if (len > free)
len = free;
if (first_len > len)
first_len = len;
/* till end of buffer */
memcpy(buffer + buf_write_pos, data, first_len);
if (len > first_len) { /* we have to wrap around */
/* remaining part from beginning of buffer */
memcpy(buffer, data + first_len, len - first_len);
}
buf_write_pos = (buf_write_pos + len) % buffer_len;
return len;
}
/* remove data from ringbuffer */
static int read_buffer(unsigned char *data, int len)
{
int first_len = buffer_len - buf_read_pos;
int buffered = buf_used();
if (len > buffered)
len = buffered;
if (first_len > len)
first_len = len;
/* till end of buffer */
memcpy(data, buffer + buf_read_pos, first_len);
if (len > first_len) { /* we have to wrap around */
/* remaining part from beginning of buffer */
memcpy(data + first_len, buffer, len - first_len);
}
buf_read_pos = (buf_read_pos + len) % buffer_len;
return len;
}
/*
* end of CoreAudio helpers
*/
void render_proc(void *theCookie, void *buffer, size_t req,
const media_raw_audio_format &format)
{
int amt;
while ((amt = buf_used()) < req)
snooze(100000);
read_buffer((unsigned char *)buffer, req);
}
static int init(struct context_data *ctx)
{
struct xmp_options *o = &ctx->o;
char *dev;
char *token, **parm;
static char desc[80];
be_app = new BApplication("application/x-vnd.cm-xmp");
chunk_size = 4096;
chunk_num = 20;
parm_init();
chkparm2("buffer", "%d,%d", &chunk_num, &chunk_size);
parm_end();
snprintf(desc, 80, "%s [%d fragments of %d bytes]",
drv_beos.description, chunk_num, chunk_size);
drv_beos.description = desc;
fmt.frame_rate = o->freq;
fmt.channel_count = o->outfmt & XMP_FORMAT_MONO ? 1 : 2;
fmt.format = o->resol > 8 ? B_AUDIO_SHORT : B_AUDIO_CHAR;
fmt.byte_order = B_HOST_IS_LENDIAN ?
B_MEDIA_LITTLE_ENDIAN : B_MEDIA_BIG_ENDIAN;
fmt.buffer_size = chunk_size * chunk_num;
buffer_len = chunk_size * chunk_num;
buffer = (uint8 *)calloc(1, buffer_len);
buf_read_pos = 0;
buf_write_pos = 0;
paused = 1;
player = new BSoundPlayer(&fmt, "xmp output", render_proc);
return 0;
}
/* Build and write one tick (one PAL frame or 1/50 s in standard vblank
* timed mods) of audio data to the output device.
*/
static void bufdump(struct context_data *ctx, void *b, int i)
{
int j = 0;
/* block until we have enough free space in the buffer */
while (buf_free() < i)
snooze(100000);
while (i) {
if ((j = write_buffer((uint8 *)b, i)) > 0) {
i -= j;
b += j;
} else
break;
}
if (paused) {
player->Start();
player->SetHasData(true);
paused = 0;
}
}
static void myshutdown(struct context_data *ctx)
{
player->Stop();
be_app->Lock();
be_app->Quit();
}

@ -0,0 +1,123 @@
/* Extended Module Player
* Copyright (C) 1996-2012 Claudio Matsuoka and Hipolito Carraro Jr
*
* This file is part of the Extended Module Player and is distributed
* under the terms of the GNU General Public License. See doc/COPYING
* for more information.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <sys/types.h>
#include <sys/param.h>
#include <sys/audioio.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "common.h"
#include "driver.h"
#include "mixer.h"
static int audio_fd;
static int init(struct context_data *);
static int setaudio(struct xmp_option *);
static void bufdump(struct context_data *, void *, int);
static void shutdown(struct context_data *);
static void dummy()
{
}
static char *help[] = {
"gain=val", "Audio output gain (0 to 255)",
"buffer=val", "Audio buffer size (default is 32768)",
NULL
};
struct xmp_drv_info drv_bsd = {
"bsd", /* driver ID */
"BSD PCM audio", /* driver description */
help, /* help */
init, /* init */
shutdown, /* shutdown */
dummy, /* starttimer */
dummy, /* flush */
bufdump, /* bufdump */
};
static int setaudio(struct xmp_options *o)
{
audio_info_t ainfo;
int gain = 128;
int bsize = 32 * 1024;
char *token, **parm;
parm_init();
chkparm1("gain", gain = strtoul(token, NULL, 0));
chkparm1("buffer", bsize = strtoul(token, NULL, 0));
parm_end();
if (gain < AUDIO_MIN_GAIN)
gain = AUDIO_MIN_GAIN;
if (gain > AUDIO_MAX_GAIN)
gain = AUDIO_MAX_GAIN;
AUDIO_INITINFO(&ainfo);
ainfo.play.sample_rate = o->freq;
ainfo.play.channels = o->outfmt & XMP_FORMAT_MONO ? 1 : 2;
ainfo.play.precision = o->resol;
ainfo.play.encoding = o->resol > 8 ?
AUDIO_ENCODING_SLINEAR : AUDIO_ENCODING_ULINEAR;
ainfo.play.gain = gain;
ainfo.play.buffer_size = bsize;
if (ioctl(audio_fd, AUDIO_SETINFO, &ainfo) == -1) {
close(audio_fd);
return XMP_ERR_DINIT;
}
drv_bsd.description = "BSD PCM audio";
return 0;
}
static int init(struct context_data *ctx)
{
if ((audio_fd = open("/dev/sound", O_WRONLY)) == -1)
return XMP_ERR_DINIT;
if (setaudio(o) != 0)
return XMP_ERR_DINIT;
return 0;
}
/* Build and write one tick (one PAL frame or 1/50 s in standard vblank
* timed mods) of audio data to the output device.
*/
static void bufdump(struct context_data *ctx, void *b, int i)
{
int j;
while (i) {
if ((j = write(audio_fd, b, i)) > 0) {
i -= j;
(char *)b += j;
} else
break;
};
}
static void shutdown(struct context_data *ctx)
{
close(audio_fd);
}

@ -0,0 +1,57 @@
/* Extended Module Player
* Copyright (C) 1996-2012 Claudio Matsuoka and Hipolito Carraro Jr
*
* This file is part of the Extended Module Player and is distributed
* under the terms of the GNU General Public License. See doc/COPYING
* for more information.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <string.h>
#include <stdlib.h>
#include "common.h"
#include "driver.h"
static void starttimer(void);
static void stoptimer(void);
static void bufdump(void);
static int init(struct context_data *ctx);
static void shutdown(struct context_data *);
struct xmp_drv_info drv_debug = {
"debug", /* driver ID */
"Driver debugger", /* driver description */
NULL, /* help */
init, /* init */
shutdown, /* shutdown */
starttimer, /* settimer */
stoptimer, /* stoptimer */
bufdump, /* bufdump */
};
static void starttimer()
{
printf("** starttimer\n");
}
static void stoptimer()
{
printf("** stoptimer\n");
}
static void bufdump()
{
}
static int init(struct context_data *ctx)
{
return 0;
}
static void shutdown(struct context_data *ctx)
{
printf("** shutdown\n");
}

@ -0,0 +1,127 @@
/* Extended Module Player
* Copyright (C) 1996-2012 Claudio Matsuoka and Hipolito Carraro Jr
*
* This file is part of the Extended Module Player and is distributed
* under the terms of the GNU General Public License. See doc/COPYING
* for more information.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include "common.h"
#include "driver.h"
#include "convert.h"
#ifndef O_BINARY
#define O_BINARY 0
#endif
#define DATA(x) (((struct data *)drv_file.data)->x)
struct data {
int fd;
int endian;
};
static int init(struct context_data *);
static void bufdump(struct context_data *, void *, int);
static void shutdown(struct context_data *);
static void dummy()
{
}
static char *help[] = {
"big-endian", "Generate big-endian 16-bit samples",
"little-endian", "Generate little-endian 16-bit samples",
NULL
};
struct xmp_drv_info drv_file = {
"file", /* driver ID */
"file", /* driver description */
help, /* help */
init, /* init */
shutdown, /* shutdown */
dummy, /* starttimer */
dummy, /* stoptimer */
bufdump, /* bufdump */
};
static int init(struct context_data *ctx)
{
struct xmp_options *o = &ctx->o;
char *buf;
int bsize;
char *token, **parm;
drv_file.data = malloc(sizeof (struct data));
if (drv_file.data == NULL)
return -1;
DATA(endian) = 0;
parm_init();
chkparm0("big-endian", DATA(endian) = 1);
chkparm0("little-endian", DATA(endian) = -1);
parm_end();
if (!o->outfile)
o->outfile = "xmp.out";
if (strcmp(o->outfile, "-")) {
DATA(fd) = open(o->outfile, O_WRONLY | O_CREAT | O_TRUNC
| O_BINARY, 0644);
if (DATA(fd) < 0)
return -1;
} else {
DATA(fd) = 1;
}
if (strcmp(o->outfile, "-")) {
bsize = strlen(drv_file.description) + strlen(o->outfile) + 8;
buf = malloc(bsize);
snprintf(buf, bsize, "%s: %s", drv_file.description,
o->outfile);
drv_file.description = buf;
} else {
drv_file.description = strdup("Output to stdout");
}
return 0;
}
static void bufdump(struct context_data *ctx, void *b, int i)
{
struct xmp_options *o = &ctx->o;
int j;
if ((o->big_endian && DATA(endian) == -1) ||
(!o->big_endian && DATA(endian) == 1)) {
xmp_cvt_sex(i, b);
}
while (i) {
if ((j = write(DATA(fd), b, i)) > 0) {
i -= j;
b = (char *)b + j;
} else
break;
}
}
static void shutdown(struct context_data *ctx)
{
if (DATA(fd) > 0)
close(DATA(fd));
free(drv_file.description);
free(drv_file.data);
}

@ -0,0 +1,164 @@
/* Extended Module Player
* Copyright (C) 1996-2012 Claudio Matsuoka and Hipolito Carraro Jr
*
* This file is part of the Extended Module Player and is distributed
* under the terms of the GNU General Public License. See doc/COPYING
* for more information.
*/
/* This code was tested on a 9000/710 running HP-UX 9.05 with 8 kHz,
* 16 bit mono output.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/audio.h>
#include <fcntl.h>
#include "common.h"
#include "driver.h"
#include "mixer.h"
static int audio_fd;
static int init(struct context_data *);
static int setaudio(struct xmp_options *);
static void bufdump(struct context_data *, void *, int);
static void shutdown(struct context_data *);
static void dummy()
{
}
/* Standard sampling rates */
static int srate[] = {
44100, 32000, 22050, 16000, 11025, 8000, 0
};
static char *help[] = {
"gain=val", "Audio output gain (0 to 255)",
"port={s|h|l}", "Audio port (s[peaker], h[eadphones], l[ineout])",
"buffer=val", "Audio buffer size",
NULL
};
struct xmp_drv_info drv_hpux = {
"hpux", /* driver ID */
"HP-UX PCM audio", /* driver description */
help, /* help */
init, /* init */
shutdown, /* shutdown */
dummy, /* starttimer */
dummy, /* flush */
bufdump, /* bufdump */
};
static int setaudio(struct xmp_options *o)
{
int flags;
int gain = 128;
int bsize = 32 * 1024;
int port = AUDIO_OUT_SPEAKER;
struct audio_gains agains;
struct audio_describe adescribe;
char *token, **parm;
int i;
parm_init();
chkparm1("gain", gain = strtoul(token, NULL, 0));
chkparm1("buffer", bsize = strtoul(token, NULL, 0));
chkparm1("port", port = (int)*token)
parm_end();
switch (port) {
case 'h':
port = AUDIO_OUT_HEADPHONE;
break;
case 'l':
port = AUDIO_OUT_LINE;
break;
default:
port = AUDIO_OUT_SPEAKER;
}
if ((flags = fcntl(audio_fd, F_GETFL, 0)) < 0)
return XMP_ERR_DINIT;
flags |= O_NDELAY;
if ((flags = fcntl(audio_fd, F_SETFL, flags)) < 0)
return XMP_ERR_DINIT;
if (ioctl(audio_fd, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_LINEAR16BIT) ==
-1)
return XMP_ERR_DINIT;
if (ioctl(audio_fd, AUDIO_SET_CHANNELS,
o->outfmt & XMP_FORMAT_MONO ? 1 : 2) == -1) {
o->outfmt ^= XMP_FORMAT_MONO;
if (ioctl(audio_fd, AUDIO_SET_CHANNELS,
o->outfmt & XMP_FORMAT_MONO ? 1 : 2) == -1)
return XMP_ERR_DINIT;
}
ioctl(audio_fd, AUDIO_SET_OUTPUT, port);
for (i = 0; ioctl(audio_fd, AUDIO_SET_SAMPLE_RATE, o->freq) == -1; i++)
if ((o->freq = srate[i]) == 0)
return XMP_ERR_DINIT;
if (ioctl(audio_fd, AUDIO_DESCRIBE, &adescribe) == -1)
return XMP_ERR_DINIT;
if (ioctl(audio_fd, AUDIO_GET_GAINS, &agains) == -1)
return XMP_ERR_DINIT;
agains.transmit_gain = adescribe.min_transmit_gain +
(adescribe.max_transmit_gain - adescribe.min_transmit_gain) *
gain / 256;
if (ioctl(audio_fd, AUDIO_SET_GAINS, &agains) == -1)
return XMP_ERR_DINIT;
ioctl(audio_fd, AUDIO_SET_TXBUFSIZE, bsize);
return 0;
}
static int init(struct context_data *ctx)
{
if ((audio_fd = open("/dev/audio", O_WRONLY)) == -1)
return XMP_ERR_DINIT;
if (setaudio(ctl) != 0)
return XMP_ERR_DINIT;
return 0;
}
/* Build and write one tick (one PAL frame or 1/50 s in standard vblank
* timed mods) of audio data to the output device.
*/
static void bufdump(struct context_data *ctx, void *b, int i)
{
int j;
while (i) {
if ((j = write(audio_fd, b, i)) > 0) {
i -= j;
(char *)b += j;
} else
break;
}
}
static void shutdown(struct context_data *ctx)
{
close(audio_fd);
}

@ -0,0 +1,168 @@
/* Extended Module Player
* Copyright (C) 1996-2012 Claudio Matsuoka and Hipolito Carraro Jr
*
* This file is part of the Extended Module Player and is distributed
* under the terms of the GNU General Public License. See doc/COPYING
* for more information.
*/
/* Based on bsd.c and solaris.c */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <sys/types.h>
#include <sys/param.h>
#include <sys/audioio.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "common.h"
#include "driver.h"
#include "mixer.h"
static int audio_fd;
static int audioctl_fd;
static int init(struct context_data *);
static int setaudio(struct xmp_options *);
static void bufdump(struct context_data *, void *, int);
static void shutdown(struct context_data *);
static void dummy()
{
}
static char *help[] = {
"gain=val", "Audio output gain (0 to 255)",
/* XXX "port={s|h|l}", "Audio port (s[peaker], h[eadphones], l[ineout])", XXX */
"buffer=val", "Audio buffer size (default is 32768)",
NULL
};
struct xmp_drv_info drv_netbsd = {
"netbsd", /* driver ID */
"NetBSD PCM audio", /* driver description */
help, /* help */
init, /* init */
shutdown, /* shutdown */
dummy, /* starttimer */
dummy, /* flush */
bufdump, /* bufdump */
};
static int setaudio(struct xmp_options *o)
{
audio_info_t ainfo;
int gain = 128;
int bsize = 32 * 1024;
char *token, **parm;
/* try to open audioctldevice */
if ((audioctl_fd = open("/dev/audioctl", O_RDWR)) < 0) {
fprintf(stderr, "couldn't open audioctldevice\n");
close(audio_fd);
return -1;
}
/* empty buffers before change config */
ioctl(audio_fd, AUDIO_DRAIN, 0); /* drain everything out */
ioctl(audio_fd, AUDIO_FLUSH); /* flush audio */
ioctl(audioctl_fd, AUDIO_FLUSH); /* flush audioctl */
/* get audio parameters. */
if (ioctl(audioctl_fd, AUDIO_GETINFO, &ainfo) < 0) {
fprintf(stderr, "AUDIO_GETINFO failed!\n");
close(audio_fd);
close(audioctl_fd);
return -1;
}
close(audioctl_fd);
parm_init();
chkparm1("gain", gain = strtoul(token, NULL, 0));
chkparm1("buffer", bsize = strtoul(token, NULL, 0));
/* chkparm1 ("port", port = (int)*token) */
parm_end();
#if 0
switch (port) {
case 'h':
port = AUDIO_HEADPHONE;
break;
case 'l':
port = AUDIO_LINE_OUT;
break;
case 's':
port = AUDIO_SPEAKER;
}
#endif
if (gain < AUDIO_MIN_GAIN)
gain = AUDIO_MIN_GAIN;
if (gain > AUDIO_MAX_GAIN)
gain = AUDIO_MAX_GAIN;
AUDIO_INITINFO(&ainfo);
ainfo.play.sample_rate = o->freq;
ainfo.play.channels = o->outfmt & XMP_FORMAT_MONO ? 1 : 2;
ainfo.play.precision = o->resol;
/* ainfo.play.precision = AUDIO_ENCODING_ULINEAR; */
ainfo.play.encoding = o->resol > 8 ?
AUDIO_ENCODING_SLINEAR : AUDIO_ENCODING_ULINEAR;
ainfo.play.gain = gain;
/* ainfo.play.port = port; */
ainfo.play.buffer_size = bsize;
if (ioctl(audio_fd, AUDIO_SETINFO, &ainfo) == -1) {
close(audio_fd);
return XMP_ERR_DINIT;
}
/* o->resol = 0; */
/* o->freq = 8000; */
/* o->outfmt |=XMP_FORMAT_MONO; */
o->freq = 44000;
drv_netbsd.description = "NetBSD PCM audio";
return 0;
}
static int init(struct context_data *ctx)
{
if ((audio_fd = open("/dev/sound", O_WRONLY)) == -1)
return XMP_ERR_DINIT;
if (setaudio(&ctx->o) != 0)
return XMP_ERR_DINIT;
return 0;
}
/* Build and write one tick (one PAL frame or 1/50 s in standard vblank
* timed mods) of audio data to the output device.
*/
static void bufdump(struct context_data *ctx, void *b, int i)
{
int j;
while (i) {
if ((j = write(audio_fd, b, i)) > 0) {
i -= j;
(char *)b += j;
} else
break;
}
}
static void shutdown(struct context_data *ctx)
{
close(audio_fd);
}

@ -0,0 +1,125 @@
/* Extended Module Player
* Copyright (C) 1996-2012 Claudio Matsuoka and Hipolito Carraro Jr
*
* This file is part of the Extended Module Player and is distributed
* under the terms of the GNU General Public License. See doc/COPYING
* for more information.
*/
/* This should work for OpenBSD */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <sys/types.h>
#include <sys/param.h>
#include <sys/audioio.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "common.h"
#include "driver.h"
#include "mixer.h"
static int audio_fd;
static int init(struct context_data *);
static int setaudio(struct xmp_options *);
static void bufdump(struct context_data *, void *, int);
static void shutdown(struct context_data *);
static void dummy()
{
}
static char *help[] = {
"gain=val", "Audio output gain (0 to 255)",
"buffer=val", "Audio buffer size (default is 32768)",
NULL
};
struct xmp_drv_info drv_openbsd = {
"openbsd", /* driver ID */
"OpenBSD PCM audio", /* driver description */
help, /* help */
init, /* init */
shutdown, /* shutdown */
dummy, /* starttimer */
dummy, /* flush */
bufdump, /* bufdump */
};
static int setaudio(struct xmp_options *o)
{
audio_info_t ainfo;
int gain = 128;
int bsize = 32 * 1024;
char *token, **parm;
parm_init();
chkparm1("gain", gain = strtoul(token, NULL, 0));
chkparm1("buffer", bsize = strtoul(token, NULL, 0));
parm_end();
if (gain < AUDIO_MIN_GAIN)
gain = AUDIO_MIN_GAIN;
if (gain > AUDIO_MAX_GAIN)
gain = AUDIO_MAX_GAIN;
AUDIO_INITINFO(&ainfo);
ainfo.play.sample_rate = o->freq;
ainfo.play.channels = o->outfmt & XMP_FORMAT_MONO ? 1 : 2;
ainfo.play.precision = o->resol;
ainfo.play.encoding = o->resol > 8 ?
AUDIO_ENCODING_SLINEAR : AUDIO_ENCODING_ULINEAR;
ainfo.play.gain = gain;
ainfo.play.buffer_size = bsize;
if (ioctl(audio_fd, AUDIO_SETINFO, &ainfo) == -1) {
close(audio_fd);
return XMP_ERR_DINIT;
}
drv_openbsd.description = "OpenBSD PCM audio";
return 0;
}
static int init(struct context_data *ctx)
{
if ((audio_fd = open("/dev/sound", O_WRONLY)) == -1)
return XMP_ERR_DINIT;
if (setaudio(&ctx->o) != 0)
return XMP_ERR_DINIT;
return 0;
}
/* Build and write one tick (one PAL frame or 1/50 s in standard vblank
* timed mods) of audio data to the output device.
*/
static void bufdump(struct context_data *ctx, void *b, int i)
{
int j;
while (i) {
if ((j = write(audio_fd, b, i)) > 0) {
i -= j;
b = (char *)b + j;
} else
break;
}
}
static void shutdown(struct context_data *ctx)
{
close(audio_fd);
}

@ -0,0 +1,261 @@
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
/*
This should work for OS/2 Dart
History:
1.0 - By Kevin Langman
*/
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define INCL_DOS
#include <os2.h>
#include <mcios2.h>
#include <meerror.h>
#include <os2medef.h>
#include "common.h"
#include "driver.h"
#include "mixer.h"
#define BUFFERCOUNT 4
#define BUF_MIN 8
#define BUF_MAX 32
static int init(struct context_data *);
static int setaudio(struct xmp_options *);
static void bufdump(struct context_data *, void *, int);
static void shutdown(struct context_data *);
static MCI_MIX_BUFFER MixBuffers[BUFFERCOUNT];
static MCI_MIXSETUP_PARMS MixSetupParms;
static MCI_BUFFER_PARMS BufferParms;
static MCI_GENERIC_PARMS GenericParms;
static ULONG DeviceID = 0;
static int bsize = 16;
static short next = 2;
static short ready = 1;
static HMTX mutex;
static void dummy()
{
}
static char *help[] = {
"sharing={Y,N}", "Device Sharing (default is N)",
"device=val", "OS/2 Audio Device (default is 0 auto-detect)",
"buffer=val", "Audio buffer size (default is 16)",
NULL
};
struct xmp_drv_info drv_os2dart = {
"dart", /* driver ID */
"OS/2 Direct Audio Realtime", /* driver description */
help, /* help */
init, /* init */
shutdown, /* shutdown */
dummy, /* starttimer */
dummy, /* flush */
bufdump, /* bufdump */
};
// Buffer update thread (created and called by DART)
static LONG APIENTRY OS2_Dart_UpdateBuffers
(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer, ULONG ulFlags) {
if ((ulFlags == MIX_WRITE_COMPLETE) ||
((ulFlags == (MIX_WRITE_COMPLETE | MIX_STREAM_ERROR)) &&
(ulStatus == ERROR_DEVICE_UNDERRUN))) {
DosRequestMutexSem(mutex, SEM_INDEFINITE_WAIT);
ready++;
DosReleaseMutexSem(mutex);
}
return (TRUE);
}
static int setaudio(struct xmp_options *o)
{
char sharing = 0;
int device = 0;
int flags;
int i;
MCI_AMP_OPEN_PARMS AmpOpenParms;
char *token, **parm;
//printf( "In SetAudio...\n" );
parm_init();
chkparm1("sharing", sharing = *token);
chkparm1("device", device = atoi(token));
chkparm1("buffer", bsize = strtoul(token, NULL, 0));
parm_end();
if ((bsize < BUF_MIN || bsize > BUF_MAX) && bsize != 0) {
bsize = 16 * 1024;
} else {
bsize *= 1024;
}
//if( sharing < 1 || sharing > 0 ){
// sharing = 0;
//}
MixBuffers[0].pBuffer = NULL; /* marker */
memset(&GenericParms, 0, sizeof(MCI_GENERIC_PARMS));
/* open AMP device */
memset(&AmpOpenParms, 0, sizeof(MCI_AMP_OPEN_PARMS));
AmpOpenParms.usDeviceID = 0;
AmpOpenParms.pszDeviceType =
(PSZ) MAKEULONG(MCI_DEVTYPE_AUDIO_AMPMIX, (USHORT) device);
flags = MCI_WAIT | MCI_OPEN_TYPE_ID;
if (sharing == 'Y' || sharing == 'y') {
flags = flags | MCI_OPEN_SHAREABLE;
}
if (mciSendCommand(0, MCI_OPEN, flags,
(PVOID) & AmpOpenParms, 0) != MCIERR_SUCCESS) {
return -1;
}
DeviceID = AmpOpenParms.usDeviceID;
/* setup playback parameters */
memset(&MixSetupParms, 0, sizeof(MCI_MIXSETUP_PARMS));
MixSetupParms.ulBitsPerSample = o->resol;
MixSetupParms.ulFormatTag = MCI_WAVE_FORMAT_PCM;
MixSetupParms.ulSamplesPerSec = o->freq;
MixSetupParms.ulChannels = o->outfmt & XMP_FORMAT_MONO ? 1 : 2;
MixSetupParms.ulFormatMode = MCI_PLAY;
MixSetupParms.ulDeviceType = MCI_DEVTYPE_WAVEFORM_AUDIO;
MixSetupParms.pmixEvent = OS2_Dart_UpdateBuffers;
if (mciSendCommand(DeviceID, MCI_MIXSETUP,
MCI_WAIT | MCI_MIXSETUP_INIT,
(PVOID) & MixSetupParms, 0) != MCIERR_SUCCESS) {
mciSendCommand(DeviceID, MCI_CLOSE, MCI_WAIT,
(PVOID) & GenericParms, 0);
return -1;
}
/* take in account the DART suggested buffer size... */
if (bsize == 0) {
bsize = MixSetupParms.ulBufferSize;
}
//printf( "Dart Buffer Size = %d\n", bsize );
BufferParms.ulNumBuffers = BUFFERCOUNT;
BufferParms.ulBufferSize = bsize;
BufferParms.pBufList = MixBuffers;
if (mciSendCommand(DeviceID, MCI_BUFFER,
MCI_WAIT | MCI_ALLOCATE_MEMORY,
(PVOID) & BufferParms, 0) != MCIERR_SUCCESS) {
mciSendCommand(DeviceID, MCI_CLOSE, MCI_WAIT,
(PVOID) & GenericParms, 0);
return -1;
}
for (i = 0; i < BUFFERCOUNT; i++) {
MixBuffers[i].ulBufferLength = bsize;
}
//MixBuffers[0].ulBufferLength = bsize;
//MixBuffers[1].ulBufferLength = bsize;
//MixBuffers[2].ulBufferLength = bsize;
//MixBuffers[3].ulBufferLength = bsize;
return 0;
}
static int init(struct context_data *ctx)
{
//printf( "In Init...\n" );
if (setaudio(ctl) != 0)
return XMP_ERR_DINIT;
/* Start Playback */
//printf("Starting Playback!!\n");
memset(MixBuffers[0].pBuffer, /*32767 */ 0, bsize);
memset(MixBuffers[1].pBuffer, /*32767 */ 0, bsize);
MixSetupParms.pmixWrite(MixSetupParms.ulMixHandle, MixBuffers, 2);
return 0;
}
/* Build and write one tick (one PAL frame or 1/50 s in standard vblank
* timed mods) of audio data to the output device.
*/
static void bufdump(struct context_data *ctx, void *b, int i)
{
static int index = 0;
//printf( "In BufDump...\n" );
if (index + i > bsize) {
//printf("Next = %d, ready = %d\n", next, ready);
do {
DosRequestMutexSem(mutex, SEM_INDEFINITE_WAIT);
if (ready != 0) {
DosReleaseMutexSem(mutex);
break;
}
DosReleaseMutexSem(mutex);
DosSleep(20);
} while (TRUE);
MixBuffers[next].ulBufferLength = index;
MixSetupParms.pmixWrite(MixSetupParms.ulMixHandle,
&(MixBuffers[next]), 1);
ready--;
next++;
index = 0;
if (next == BUFFERCOUNT) {
next = 0;
}
}
memcpy(&((char *)MixBuffers[next].pBuffer)[index], b, i);
index += i;
}
static void shutdown(struct context_data *ctx)
{
//printf( "In ShutDown...\n" );
if (MixBuffers[0].pBuffer) {
mciSendCommand(DeviceID, MCI_BUFFER,
MCI_WAIT | MCI_DEALLOCATE_MEMORY, &BufferParms,
0);
MixBuffers[0].pBuffer = NULL;
}
if (DeviceID) {
mciSendCommand(DeviceID, MCI_CLOSE, MCI_WAIT,
(PVOID) & GenericParms, 0);
DeviceID = 0;
}
}

@ -0,0 +1,217 @@
/* Extended Module Player
* Copyright (C) 1996-2012 Claudio Matsuoka and Hipolito Carraro Jr
*
* This file is part of the Extended Module Player and is distributed
* under the terms of the GNU General Public License. See doc/COPYING
* for more information.
*/
/*
* devfs /dev/sound/dsp support by Dirk Jagdmann
* resume/onpause by Test Rat <ttsestt@gmail.com>
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <string.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#if defined(HAVE_SYS_SOUNDCARD_H)
#include <sys/soundcard.h>
#elif defined(HAVE_MACHINE_SOUNDCARD_H)
#include <machine/soundcard.h>
#endif
#include "driver.h"
static int audio_fd;
static void from_fmt(struct xmp_options *, int);
static int to_fmt(struct xmp_options *);
static void setaudio(struct xmp_options *);
static int init(struct context_data *);
static void shutdown(struct context_data *);
static void bufdump(struct context_data *, void *, int);
static void resume(void);
static void onpause(void);
static char *help[] = {
"frag=num,size", "Set the number and size of fragments",
"dev=<device_name>", "Audio device to use (default /dev/dsp)",
"nosync", "Don't flush OSS buffers between modules",
NULL
};
struct xmp_drv_info drv_oss = {
"oss", /* driver ID */
"OSS PCM audio", /* driver description */
help, /* help */
init, /* init */
shutdown, /* shutdown */
resume, /* starttimer */
onpause, /* stoptimer */
bufdump, /* bufdump */
};
static int fragnum, fragsize;
static int do_sync = 1;
static int to_fmt(struct xmp_options *o)
{
int fmt;
if (!o->resol)
return AFMT_MU_LAW;
if (o->resol == 8)
fmt = AFMT_U8 | AFMT_S8;
else {
fmt = o->big_endian ? AFMT_S16_BE | AFMT_U16_BE :
AFMT_S16_LE | AFMT_U16_LE;
}
if (o->outfmt & XMP_FMT_UNS)
fmt &= AFMT_U8 | AFMT_U16_LE | AFMT_U16_BE;
else
fmt &= AFMT_S8 | AFMT_S16_LE | AFMT_S16_BE;
return fmt;
}
static void from_fmt(struct xmp_options *o, int outfmt)
{
if (outfmt & AFMT_MU_LAW) {
o->resol = 0;
return;
}
if (outfmt & (AFMT_S16_LE | AFMT_S16_BE | AFMT_U16_LE | AFMT_U16_BE))
o->resol = 16;
else
o->resol = 8;
if (outfmt & (AFMT_U8 | AFMT_U16_LE | AFMT_U16_BE))
o->outfmt |= XMP_FMT_UNS;
else
o->outfmt &= ~XMP_FMT_UNS;
}
static void setaudio(struct xmp_options *o)
{
static int fragset = 0;
int frag = 0;
int fmt;
frag = (fragnum << 16) + fragsize;
fmt = to_fmt(o);
ioctl(audio_fd, SNDCTL_DSP_SETFMT, &fmt);
from_fmt(o, fmt);
fmt = !(o->outfmt & XMP_FORMAT_MONO);
ioctl(audio_fd, SNDCTL_DSP_STEREO, &fmt);
if (fmt)
o->outfmt &= ~XMP_FORMAT_MONO;
else
o->outfmt |= XMP_FORMAT_MONO;
ioctl(audio_fd, SNDCTL_DSP_SPEED, &o->freq);
/* Set the fragments only once */
if (!fragset) {
if (fragnum && fragsize)
ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &frag);
fragset++;
}
}
static int init(struct context_data *ctx)
{
char *dev_audio[] = { "/dev/dsp", "/dev/sound/dsp" };
struct xmp_options *o = &ctx->o;
audio_buf_info info;
static char buf[80];
char *token, **parm;
int i;
fragnum = 16; /* default number of fragments */
i = 1024; /* default size of fragment */
parm_init();
chkparm2("frag", "%d,%d", &fragnum, &i);
chkparm1("dev", dev_audio[0] = token);
chkparm0("nosync", do_sync = 0);
parm_end();
for (fragsize = 0; i >>= 1; fragsize++) ;
if (fragsize < 4)
fragsize = 4;
for (i = 0; i < sizeof(dev_audio) / sizeof(dev_audio[0]); i++)
if ((audio_fd = open(dev_audio[i], O_WRONLY)) >= 0)
break;
if (audio_fd < 0)
return XMP_ERR_DINIT;
setaudio(o);
if (ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info) == 0) {
snprintf(buf, 80, "%s [%d fragments of %d bytes]",
drv_oss.description, info.fragstotal,
info.fragsize);
drv_oss.description = buf;
}
return 0;
}
/* Build and write one tick (one PAL frame or 1/50 s in standard vblank
* timed mods) of audio data to the output device.
*/
static void bufdump(struct context_data *ctx, void *b, int i)
{
int j;
while (i) {
if ((j = write(audio_fd, b, i)) > 0) {
i -= j;
b = (char *)b + j;
} else
break;
};
}
static void shutdown(struct context_data *ctx)
{
ioctl(audio_fd, SNDCTL_DSP_RESET, NULL);
close(audio_fd);
}
static void resume()
{
#ifdef SNDCTL_DSP_SETTRIGGER
int trig = PCM_ENABLE_OUTPUT;
ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &trig);
#endif
}
static void onpause()
{
#ifdef SNDCTL_DSP_SETTRIGGER
int trig = 0;
ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &trig);
#else
ioctl(audio_fd, SNDCTL_DSP_RESET, NULL);
#endif
if (do_sync)
ioctl(audio_fd, SNDCTL_DSP_SYNC, NULL);
}

@ -0,0 +1,279 @@
/* Extended Module Player
* Copyright (C) 1996-2012 Claudio Matsuoka and Hipolito Carraro Jr
* CoreAudio helpers (C) 2000 Timothy J. Wood
*
* This file is part of the Extended Module Player and is distributed
* under the terms of the GNU General Public License. See doc/COPYING
* for more information.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <CoreAudio/CoreAudio.h>
#include <AudioUnit/AudioUnit.h>
#include <AudioToolbox/AudioToolbox.h>
#include <CoreServices/CoreServices.h>
#include <unistd.h>
#include "common.h"
#include "driver.h"
#include "mixer.h"
static int init (struct context_data *ctx);
static void bufdump (struct context_data *, void *, int);
static void shutdown (struct context_data *);
static void dummy () { }
struct xmp_drv_info drv_osx = {
"osx", /* driver ID */
"OSX CoreAudio", /* driver description */
NULL, /* help */
init, /* init */
shutdown, /* shutdown */
dummy, /* starttimer */
dummy, /* flush */
bufdump, /* bufdump */
};
static AudioUnit au;
/*
* CoreAudio helpers from mplayer/libao
* The player fills a ring buffer, OSX retrieves data from the buffer
*/
static int paused;
static uint8 *buffer;
static int buffer_len;
static int buf_write_pos;
static int buf_read_pos;
static int num_chunks;
static int chunk_size;
static int packet_size;
/* return minimum number of free bytes in buffer, value may change between
* two immediately following calls, and the real number of free bytes
* might actually be larger! */
static int buf_free()
{
int free = buf_read_pos - buf_write_pos - chunk_size;
if (free < 0)
free += buffer_len;
return free;
}
/* return minimum number of buffered bytes, value may change between
* two immediately following calls, and the real number of buffered bytes
* might actually be larger! */
static int buf_used()
{
int used = buf_write_pos - buf_read_pos;
if (used < 0)
used += buffer_len;
return used;
}
/* add data to ringbuffer */
static int write_buffer(unsigned char *data, int len)
{
int first_len = buffer_len - buf_write_pos;
int free = buf_free();
if (len > free)
len = free;
if (first_len > len)
first_len = len;
/* till end of buffer */
memcpy(buffer + buf_write_pos, data, first_len);
if (len > first_len) { /* we have to wrap around */
/* remaining part from beginning of buffer */
memcpy(buffer, data + first_len, len - first_len);
}
buf_write_pos = (buf_write_pos + len) % buffer_len;
return len;
}
/* remove data from ringbuffer */
static int read_buffer(unsigned char *data, int len)
{
int first_len = buffer_len - buf_read_pos;
int buffered = buf_used();
if (len > buffered)
len = buffered;
if (first_len > len)
first_len = len;
/* till end of buffer */
memcpy(data, buffer + buf_read_pos, first_len);
if (len > first_len) { /* we have to wrap around */
/* remaining part from beginning of buffer */
memcpy(data + first_len, buffer, len - first_len);
}
buf_read_pos = (buf_read_pos + len) % buffer_len;
return len;
}
OSStatus render_proc(void *inRefCon,
AudioUnitRenderActionFlags *inActionFlags,
const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber,
UInt32 inNumFrames, AudioBufferList *ioData)
{
int amt = buf_used();
int req = inNumFrames * packet_size;
if (amt > req)
amt = req;
read_buffer((unsigned char *)ioData->mBuffers[0].mData, amt);
ioData->mBuffers[0].mDataByteSize = amt;
return noErr;
}
/*
* end of CoreAudio helpers
*/
static int init(struct context_data *ctx)
{
struct xmp_options *o = &ctx->o;
AudioStreamBasicDescription ad;
Component comp;
ComponentDescription cd;
AURenderCallbackStruct rc;
//char *token, **parm;
OSStatus err;
UInt32 size, max_frames;
//parm_init();
//parm_end();
ad.mSampleRate = o->freq;
ad.mFormatID = kAudioFormatLinearPCM;
ad.mFormatFlags = kAudioFormatFlagIsPacked |
kAudioFormatFlagIsSignedInteger;
if (o->big_endian)
ad.mFormatFlags |= kAudioFormatFlagIsBigEndian;
else
ad.mFormatFlags &= ~kAudioFormatFlagIsBigEndian;
ad.mChannelsPerFrame = o->outfmt & XMP_FORMAT_MONO ? 1 : 2;
ad.mBitsPerChannel = o->resol;
ad.mBytesPerFrame = o->resol / 8 * ad.mChannelsPerFrame;
ad.mBytesPerPacket = ad.mBytesPerFrame;
ad.mFramesPerPacket = 1;
packet_size = ad.mFramesPerPacket * ad.mChannelsPerFrame *
(ad.mBitsPerChannel / 8);
cd.componentType = kAudioUnitType_Output;
cd.componentSubType = kAudioUnitSubType_DefaultOutput;
cd.componentManufacturer = kAudioUnitManufacturer_Apple;
cd.componentFlags = 0;
cd.componentFlagsMask = 0;
if ((comp = FindNextComponent(NULL, &cd)) == NULL) {
fprintf(stderr, "error: FindNextComponent\n");
return XMP_ERR_DINIT;
}
if ((err = OpenAComponent(comp, &au))) {
fprintf(stderr, "error: OpenAComponent (%d)\n", (int)err);
return XMP_ERR_DINIT;
}
if ((err = AudioUnitInitialize(au))) {
fprintf(stderr, "error: AudioUnitInitialize (%d)\n", (int)err);
return XMP_ERR_DINIT;
}
if ((err = AudioUnitSetProperty(au, kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input, 0, &ad, sizeof(ad)))) {
fprintf(stderr, "error: AudioUnitSetProperty: StreamFormat (%d)\n", (int)err);
fprintf(stderr, "mSampleRate = %lf\n", ad.mSampleRate);
fprintf(stderr, "mFormatID = 0x%x\n", (unsigned)ad.mFormatID);
fprintf(stderr, "mFormatFlags = 0x%x\n", (unsigned)ad.mFormatFlags);
fprintf(stderr, "mChannelsPerFrame = %d\n", (int)ad.mChannelsPerFrame);
fprintf(stderr, "mBitsPerChannel = %d\n", (int)ad.mBitsPerChannel);
fprintf(stderr, "mBytesPerFrame = %d\n", (int)ad.mBytesPerFrame);
fprintf(stderr, "mBytesPerPacket = %d\n", (int)ad.mBytesPerPacket);
fprintf(stderr, "mFramesPerPacket = %d\n", (int)ad.mFramesPerPacket);
return XMP_ERR_DINIT;
}
size = sizeof(UInt32);
if ((err = AudioUnitGetProperty(au, kAudioDevicePropertyBufferSize,
kAudioUnitScope_Input, 0, &max_frames, &size))) {
fprintf(stderr, "error: AudioUnitGetProperty: BufferSize (%d)\n", (int)err);
return XMP_ERR_DINIT;
}
chunk_size = max_frames;
num_chunks = (o->freq * ad.mBytesPerFrame + chunk_size - 1) /
chunk_size;
buffer_len = (num_chunks + 1) * chunk_size;
buffer = calloc(num_chunks + 1, chunk_size);
rc.inputProc = render_proc;
rc.inputProcRefCon = 0;
buf_read_pos = 0;
buf_write_pos = 0;
paused = 1;
if ((err = AudioUnitSetProperty(au, kAudioUnitProperty_SetRenderCallback,
kAudioUnitScope_Input, 0, &rc, sizeof(rc)))) {
fprintf(stderr, "error: AudioUnitSetProperty: SetRenderCallback (%d)\n", (int)err);
return XMP_ERR_DINIT;
}
return 0;
}
/* Build and write one tick (one PAL frame or 1/50 s in standard vblank
* timed mods) of audio data to the output device.
*/
static void bufdump(struct context_data *ctx, void *b, int i)
{
int j = 0;
/* block until we have enough free space in the buffer */
while (buf_free() < i)
usleep(100000);
while (i) {
if ((j = write_buffer(b, i)) > 0) {
i -= j;
b += j;
} else
break;
}
if (paused) {
AudioOutputUnitStart(au);
paused = 0;
}
}
static void shutdown(struct context_data *ctx)
{
AudioOutputUnitStop(au);
AudioUnitUninitialize(au);
CloseComponent(au);
free(buffer);
}

@ -0,0 +1,101 @@
/* Extended Module Player
* Copyright (C) 1996-2012 Claudio Matsuoka and Hipolito Carraro Jr
*
* This file is part of the Extended Module Player and is distributed
* under the terms of the GNU General Public License. See doc/COPYING
* for more information.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <unistd.h>
#include <pulse/simple.h>
#include <pulse/error.h>
#include "common.h"
#include "driver.h"
#include "mixer.h"
static pa_simple *s;
static int init(struct context_data *);
static void bufdump(struct context_data *, void *, int);
static void myshutdown(struct context_data *);
static void flush();
static void dummy()
{
}
struct xmp_drv_info drv_pulseaudio = {
"pulseaudio", /* driver ID */
"PulseAudio", /* driver description */
NULL, /* help */
init, /* init */
myshutdown, /* shutdown */
dummy, /* starttimer */
flush, /* flush */
bufdump, /* bufdump */
};
static int init(struct context_data *ctx)
{
struct xmp_options *o = &ctx->o;
pa_sample_spec ss;
int error;
ss.format = PA_SAMPLE_S16NE;
ss.channels = o->outfmt & XMP_FORMAT_MONO ? 1 : 2;
ss.rate = o->freq;
s = pa_simple_new(NULL, /* Use the default server */
"xmp", /* Our application's name */
PA_STREAM_PLAYBACK,
NULL, /* Use the default device */
"Music", /* Description of our stream */
&ss, /* Our sample format */
NULL, /* Use default channel map */
NULL, /* Use default buffering attributes */
&error); /* Ignore error code */
if (s == 0) {
fprintf(stderr, "pulseaudio error: %s\n", pa_strerror(error));
return XMP_ERR_DINIT;
}
return 0;
}
static void flush()
{
int error;
if (pa_simple_drain(s, &error) < 0) {
fprintf(stderr, "pulseaudio error: %s\n", pa_strerror(error));
}
}
static void bufdump(struct context_data *ctx, void *b, int i)
{
int j, error;
do {
if ((j = pa_simple_write(s, b, i, &error)) > 0) {
i -= j;
b += j;
} else
break;
} while (i);
if (j < 0) {
fprintf(stderr, "pulseaudio error: %s\n", pa_strerror(error));
}
}
static void myshutdown(struct context_data *ctx)
{
if (s)
pa_simple_free(s);
}

@ -0,0 +1,130 @@
/* Extended Module Player
* Copyright (C) 1996-2012 Claudio Matsuoka and Hipolito Carraro Jr
*
* This file is part of the Extended Module Player and is distributed
* under the terms of the GNU General Public License. See doc/COPYING
* for more information.
*/
/*
* Based on the QNX4 port of nspmod by Mike Gorchak <malva@selena.kherson.ua>
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <sys/audio.h>
#include <sys/ioctl.h>
#include "common.h"
#include "driver.h"
#include "mixer.h"
static int fd_audio;
static int init(struct context_data *);
static void bufdump(struct context_data *, void *, int);
static void myshutdown(struct context_data *);
static void mysync();
static void dummy()
{
}
static char *help[] = {
"dev=<device_name>", "Audio device name (default is /dev/dsp)",
"buffer=val", "Audio buffer size (default is 32768)",
NULL
};
struct xmp_drv_info drv_qnx = {
"QNX", /* driver ID */
"QNX PCM audio", /* driver description */
NULL, /* help */
init, /* init */
myshutdown, /* shutdown */
dummy, /* starttimer */
dummy, /* flush */
bufdump, /* bufdump */
};
static int init(struct context_data *ctx)
{
struct xmp_options *o = &ctx->o;
int rc, rate, bits, stereo, bsize;
char *dev;
char *token, **parm;
parm_init();
chkparm1("dev", dev = token);
chkparm1("buffer", bsize = strtoul(token, NULL, 0));
parm_end();
rate = o->freq;
bits = o->resol;
stereo = 1;
bufsize = 32 * 1024;
fd_audio = open(dev, O_WRONLY);
if (fd_audio < 0) {
fprintf(stderr, "can't open audio device\n");
return XMP_ERR_DINIT;
}
if (o->outfmt & XMP_FORMAT_MONO)
stereo = 0;
if (ioctl(fd_audio, SOUND_PCM_WRITE_BITS, &bits) < 0) {
perror("can't set resolution");
goto error;
}
if (ioctl(fd, SNDCTL_DSP_STEREO, &stereo) < 0) {
perror("can't set channels");
goto error;
}
if (ioctl(fd, SNDCTL_DSP_SPEED, &rate) < 0) {
perror("can't set rate");
goto error;
}
if (ioctl(fd, SNDCTL_DSP_GETBLKSIZE, &buf.size) < 0) {
perror("can't set rate");
goto error;
}
if (ioctl(fd, SNDCTL_DSP_GETBLKSIZE, &bufsize) < 0) {
perror("can't set buffer");
goto error;
}
return 0;
error:
close(fd_audio);
return XMP_ERR_DINIT;
}
static void bufdump(struct context_data *ctx, void *b, int i)
{
int j;
do {
if ((j = write(fd_audio, b, i)) > 0) {
i -= j;
b += j;
} else
break;
} while (i);
}
static void myshutdown(struct context_data *ctx)
{
close(fd_audio);
}
static void mysync()
{
ioctl(fd, SNDCTL_DSP_SYNC, NULL);
}

@ -0,0 +1,221 @@
/* Extended Module Player
* Copyright (C) 1996-2012 Claudio Matsuoka and Hipolito Carraro Jr
*
* This file is part of the Extended Module Player and is distributed
* under the terms of the GNU General Public License. See doc/COPYING
* for more information.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <dmedia/audio.h>
#include <fcntl.h>
#include "common.h"
#include "driver.h"
#include "mixer.h"
static ALport audio_port;
/* Hack to get 16 bit sound working - 19990706 bdowning */
static int al_sample_16;
static int init(struct context_data *);
static int setaudio(struct xmp_options *);
static void bufdump(struct context_data *, void *, int);
static void shutdown(struct context_data *);
static void dummy()
{
}
/*
* audio port sample rates (these are the only ones supported by the library)
*/
static int srate[] = {
48000,
44100,
32000,
22050,
16000,
11025,
8000,
0
};
static char *help[] = {
"buffer=val", "Audio buffer size",
NULL
};
struct xmp_drv_info drv_sgi = {
"sgi", /* driver ID */
"SGI PCM audio", /* driver description */
help, /* help */
init, /* init */
shutdown, /* shutdown */
dummy, /* starttimer */
dummy, /* flush */
bufdump, /* bufdump */
};
static int setaudio(struct xmp_options *o)
{
int bsize = 32 * 1024;
ALconfig config;
long pvbuffer[2];
char *token, **parm;
int i;
parm_init();
chkparm1("buffer", bsize = strtoul(token, NULL, 0));
parm_end();
if ((config = ALnewconfig()) == 0)
return XMP_ERR_DINIT;
/*
* Set sampling rate
*/
pvbuffer[0] = AL_OUTPUT_RATE;
#if 0 /* DOESN'T WORK */
for (i = 0; srate[i]; i++) {
if (srate[i] <= o->freq)
pvbuffer[1] = o->freq = srate[i];
}
#endif /* DOESN'T WORK */
/*
* This was flawed as far as I can tell - it just progressively lowered
* the sample rate to the lowest possible!
*
* o->freq = 44100
*
* i = 0 / if (48000 <= 44100)
* i = 1 / if (44100 <= 44100)
* then pvbuffer[1] = o->freq = 44100
* i = 2 / if (32000 <= 44100)
* then pvbuffer[1] = o->freq = 32000
* i = 3 / if (22050 <= 32000)
* then pvbuffer[1] = o->freq = 22050
* etc...
*
* Below is my attempt to write a new one. It picks the next highest
* rate available up to the maximum. This seems a lot more reasonable.
*
* - 19990706 bdowning
*/
for (i = 0; srate[i]; i++) ; /* find the end of the array */
while (i-- > 0) {
if (srate[i] >= o->freq) {
pvbuffer[1] = o->freq = srate[i];
break;
}
}
if (i == 0)
pvbuffer[1] = o->freq = srate[0]; /* 48 kHz. Wow! */
if (ALsetparams(AL_DEFAULT_DEVICE, pvbuffer, 2) < 0)
return XMP_ERR_DINIT;
/*
* Set sample format to signed integer
*/
if (ALsetsampfmt(config, AL_SAMPFMT_TWOSCOMP) < 0)
return XMP_ERR_DINIT;
/*
* Set sample width; 24 bit samples are not currently supported by xmp
*/
if (o->resol > 8) {
if (ALsetwidth(config, AL_SAMPLE_16) < 0) {
if (ALsetwidth(config, AL_SAMPLE_8) < 0)
return XMP_ERR_DINIT;
o->resol = 8;
} else
al_sample_16 = 1;
} else {
if (ALsetwidth(config, AL_SAMPLE_8) < 0) {
if (ALsetwidth(config, AL_SAMPLE_16) < 0)
return XMP_ERR_DINIT;
o->resol = 16;
} else
al_sample_16 = 0;
}
/*
* Set number of channels; 4 channel output is not currently supported
*/
if (o->outfmt & XMP_FORMAT_MONO) {
if (ALsetchannels(config, AL_MONO) < 0) {
if (ALsetchannels(config, AL_STEREO) < 0)
return XMP_ERR_DINIT;
o->outfmt &= ~XMP_FORMAT_MONO;
}
} else {
if (ALsetchannels(config, AL_STEREO) < 0) {
if (ALsetchannels(config, AL_MONO) < 0)
return XMP_ERR_DINIT;
o->outfmt |= XMP_FORMAT_MONO;
}
}
/*
* Set buffer size
*/
if (ALsetqueuesize(config, bsize) < 0)
return XMP_ERR_DINIT;
/*
* Open the audio port
*/
if ((audio_port = ALopenport("xmp", "w", config)) == 0)
return XMP_ERR_DINIT;
return 0;
}
static int init(struct context_data *ctx)
{
if (setaudio(&ctx->o) != 0)
return XMP_ERR_DINIT;
return 0;
}
/* Build and write one tick (one PAL frame or 1/50 s in standard vblank
* timed mods) of audio data to the output device.
*
* Apparently ALwritesamps requires the number of samples instead of
* the number of bytes, which is what I assume i is. This was a
* trial-and-error fix, but it appears to work. - 19990706 bdowning
*/
static void bufdump(struct context_data *ctx, void *b, int i)
{
if (al_sample_16)
i /= 2;
ALwritesamps(audio_port, b, i);
}
static void shutdown(struct context_data *ctx)
{
ALcloseport(audio_port);
}

@ -0,0 +1,42 @@
/* Extended Module Player
* Copyright (C) 1996-2012 Claudio Matsuoka and Hipolito Carraro Jr
*
* This file is part of the Extended Module Player and is distributed
* under the terms of the GNU General Public License. See doc/COPYING
* for more information.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "common.h"
#include "driver.h"
#include "mixer.h"
static int init(struct context_data *);
static void shutdown(struct context_data *);
static void dummy()
{
}
struct xmp_drv_info drv_smix = {
"smix", /* driver ID */
"nil softmixer", /* driver description */
NULL, /* help */
init, /* init */
shutdown, /* shutdown */
dummy, /* starttimer */
dummy, /* stoptimer */
dummy, /* bufdump */
NULL
};
static int init(struct context_data *ctx)
{
}
static void shutdown(struct context_data *ctx)
{
}

@ -0,0 +1,110 @@
/*
* Copyright (c) 2009 Thomas Pfaff <tpfaff@tp76.info>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <stdlib.h>
#include <string.h>
#include <sndio.h>
#include "driver.h"
#include "mixer.h"
#include "common.h"
static struct sio_hdl *hdl;
static int init (struct context_data *);
static void bufdump (struct context_data *, void *, int);
static void shutdown (struct context_data *);
static void dummy (void);
struct xmp_drv_info drv_sndio = {
"sndio", /* driver ID */
"OpenBSD sndio", /* driver description */
NULL, /* help */
init, /* init */
shutdown, /* shutdown */
dummy, /* starttimer */
dummy, /* stoptimer */
bufdump, /* bufdump */
};
static void
dummy (void)
{
}
static int
init (struct context_data *ctx)
{
struct sio_par par, askpar;
struct xmp_options *opt = &ctx->o;
hdl = sio_open (NULL, SIO_PLAY, 0);
if (hdl == NULL) {
fprintf (stderr, "%s: failed to open audio device\n",
__func__);
return XMP_ERR_DINIT;
}
sio_initpar (&par);
par.pchan = opt->outfmt & XMP_FORMAT_MONO ? 1 : 2;
par.rate = opt->freq;
par.bits = opt->resol;
par.sig = opt->resol > 8 ? 1 : 0;
par.le = SIO_LE_NATIVE;
par.appbufsz = par.rate / 4;
askpar = par;
if (!sio_setpar (hdl, &par) || !sio_getpar (hdl, &par)) {
fprintf (stderr, "%s: failed to set parameters\n", __func__);
goto error;
}
if ((par.bits == 16 && par.le != askpar.le) ||
par.bits != askpar.bits ||
par.sig != askpar.sig ||
par.pchan != askpar.pchan ||
((par.rate * 1000 < askpar.rate * 995) ||
(par.rate * 1000 > askpar.rate * 1005))) {
fprintf (stderr, "%s: parameters not supported\n", __func__);
goto error;
}
if (!sio_start (hdl)) {
fprintf (stderr, "%s: failed to start audio device\n",
__func__);
goto error;
}
return 0;
error:
sio_close (hdl);
return XMP_ERR_DINIT;
}
static void
bufdump (struct context_data *ctx, void *b, int len)
{
if (b != NULL)
sio_write (hdl, buf, len);
}
static void
shutdown (struct context_data *ctx)
{
sio_close (hdl);
hdl = NULL;
}

@ -0,0 +1,206 @@
/* Extended Module Player
* Copyright (C) 1996-2012 Claudio Matsuoka and Hipolito Carraro Jr
*
* This file is part of the Extended Module Player and is distributed
* under the terms of the GNU General Public License. See doc/COPYING
* for more information.
*/
/* CS4231 code tested on Sparc 20 and Ultra 1 running Solaris 2.5.1
* with mono/stereo, 16 bit, 22.05 kHz and 44.1 kHz using the internal
* speaker and headphones.
*
* AMD 7930 code tested on Axil 240 running Solaris 2.5.1 and an Axil
* 220 running Linux 2.0.33.
*/
/* Fixed and improved by Keith Hargrove <Keith.Hargrove@Eng.Sun.COM>
* Wed, 30 Jun 1999 14:23:52 -0700 (PDT)
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#if defined(HAVE_SYS_AUDIOIO_H)
#include <sys/audioio.h>
#elif defined(HAVE_SYS_AUDIO_IO_H)
#include <sys/audio.io.h>
#elif defined(HAVE_SUN_AUDIOIO_H)
#include <sun/audioio.h>
#endif
#include <sys/stropts.h>
/* This is for Linux on Sparc */
#if defined(HAVE_SBUS_AUDIO_AUDIO_H)
#include <sbus/audio/audio.h>
#endif
#include "common.h"
#include "driver.h"
#include "mixer.h"
static int audio_fd;
static int audioctl_fd;
static int init(struct context_data *);
static int setaudio(struct xmp_options *);
static void bufdump(struct context_data *, void *, int);
static void shutdown(struct context_data *);
static void dummy()
{
}
static char *help[] = {
"gain=val", "Audio output gain (0 to 255)",
"port={s|h|l}", "Audio port (s[peaker], h[eadphones], l[ineout])",
"buffer=val", "Audio buffer size (default is 32768)",
NULL
};
struct xmp_drv_info drv_solaris = {
"solaris", /* driver ID */
"Solaris PCM audio", /* driver description */
help, /* help */
init, /* init */
shutdown, /* shutdown */
dummy, /* starttimer */
dummy, /* flush */
bufdump, /* bufdump */
};
static int setaudio(struct xmp_options *o)
{
audio_info_t ainfo, ainfo2;
int gain;
int bsize = 32 * 1024;
int port;
char *token, **parm;
AUDIO_INITINFO(&ainfo);
/* try to open audioctl device */
if ((audioctl_fd = open("/dev/audioctl", O_RDWR)) < 0) {
fprintf(stderr, "couldn't open audioctl device\n");
close(audio_fd);
return -1;
}
/* sleep(2); -- Really needed? */
/* empty buffers before change config */
ioctl(audio_fd, AUDIO_DRAIN, 0); /* drain everything out */
ioctl(audio_fd, I_FLUSH, FLUSHRW); /* flush everything */
ioctl(audioctl_fd, I_FLUSH, FLUSHRW); /* flush everything */
/* get audio parameters. */
if (ioctl(audioctl_fd, AUDIO_GETINFO, &ainfo) < 0) {
fprintf(stderr, "AUDIO_GETINFO failed!\n");
close(audio_fd);
close(audioctl_fd);
return -1;
}
close(audioctl_fd);
/* KH: Sun Dbri doesn't support 8bits linear. I dont muck with the gain
* or the port setting. I hate when a program does that. There is
* nothing more frustrating then having a program change your volume
* and change from external speakers to the tiny one
*/
gain = ainfo.play.gain;
port = ainfo.play.port;
parm_init();
chkparm1("gain", gain = strtoul(token, NULL, 0));
chkparm1("buffer", bsize = strtoul(token, NULL, 0));
chkparm1("port", port = (int)*token)
parm_end();
switch (port) {
case 'h':
port = AUDIO_HEADPHONE;
break;
case 'l':
port = AUDIO_LINE_OUT;
break;
case 's':
port = AUDIO_SPEAKER;
}
if (gain < AUDIO_MIN_GAIN)
gain = AUDIO_MIN_GAIN;
if (gain > AUDIO_MAX_GAIN)
gain = AUDIO_MAX_GAIN;
AUDIO_INITINFO(&ainfo); /* For CS4231 */
AUDIO_INITINFO(&ainfo2); /* For AMD 7930 if needed */
ainfo.play.sample_rate = o->freq;
ainfo.play.channels = o->outfmt & XMP_FORMAT_MONO ? 1 : 2;
ainfo.play.precision = o->resol;
ainfo.play.encoding = AUDIO_ENCODING_LINEAR;
ainfo2.play.gain = ainfo.play.gain = gain;
ainfo2.play.port = ainfo.play.port = port;
ainfo2.play.buffer_size = ainfo.play.buffer_size = bsize;
if (ioctl(audio_fd, AUDIO_SETINFO, &ainfo) == -1) {
/* CS4231 initialization Failed, perhaps we have an AMD 7930 */
if (ioctl(audio_fd, AUDIO_SETINFO, &ainfo2) == -1) {
close(audio_fd);
return XMP_ERR_DINIT;
}
o->resol = 0;
o->freq = 8000;
o->outfmt |= XMP_FORMAT_MONO;
drv_solaris.description = "Solaris AMD7930 PCM audio";
} else {
drv_solaris.description = "Solaris CS4231 PCM audio";
}
return 0;
}
static int init(struct context_data *ctx)
{
struct xmp_options *o = &ctx->o;
if ((audio_fd = open("/dev/audio", O_WRONLY)) == -1)
return XMP_ERR_DINIT;
if (setaudio(o) != 0)
return XMP_ERR_DINIT;
return 0;
}
/* Build and write one tick (one PAL frame or 1/50 s in standard vblank
* timed mods) of audio data to the output device.
*/
static void bufdump(struct context_data *ctx, void *b, int i)
{
int j;
while (i) {
if ((j = write(audio_fd, b, i)) > 0) {
i -= j;
b = (char *)b + j;
} else
break;
}
}
static void shutdown(struct context_data *ctx)
{
close(audio_fd);
}

@ -0,0 +1,183 @@
/* Extended Module Player
* Copyright (C) 1996-2012 Claudio Matsuoka and Hipolito Carraro Jr
*
* This file is part of the Extended Module Player and is distributed
* under the terms of the GNU General Public License. See doc/COPYING
* for more information.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include "common.h"
#include "driver.h"
#include "convert.h"
#ifndef O_BINARY
#define O_BINARY 0
#endif
#define DATA(x) (((struct data *)drv_wav.data)->x)
struct data {
int fd;
uint32 size;
};
static int init(struct context_data *);
static void bufdump(struct context_data *, void *, int);
static void shutdown(struct context_data *);
static void dummy()
{
}
struct xmp_drv_info drv_wav = {
"wav", /* driver ID */
"WAV writer", /* driver description */
NULL, /* help */
init, /* init */
shutdown, /* shutdown */
dummy, /* starttimer */
dummy, /* stoptimer */
bufdump, /* bufdump */
};
static void writeval_16l(int fd, uint16 v)
{
uint8 x;
x = v & 0xff;
write(DATA(fd), &x, 1);
x = v >> 8;
write(DATA(fd), &x, 1);
}
static void writeval_32l(int fd, uint32 v)
{
uint8 x;
x = v & 0xff;
write(DATA(fd), &x, 1);
x = (v >> 8) & 0xff;
write(DATA(fd), &x, 1);
x = (v >> 16) & 0xff;
write(DATA(fd), &x, 1);
x = (v >> 24) & 0xff;
write(DATA(fd), &x, 1);
}
static int init(struct context_data *ctx)
{
char *buf;
uint32 len = 0;
uint16 chan;
uint32 sampling_rate, bytes_per_second;
uint16 bytes_per_frame, bits_per_sample;
char *f, filename[PATH_MAX];
struct xmp_options *o = &ctx->o;
drv_wav.data = malloc(sizeof (struct data));
if (drv_wav.data == NULL)
return -1;
if (!o->outfile) {
if (global_filename) {
if ((f = strrchr(global_filename, '/')) != NULL)
strncpy(filename, f + 1, PATH_MAX);
else
strncpy(filename, global_filename, PATH_MAX);
} else {
strcpy(filename, "xmp");
}
strncat(filename, ".wav", PATH_MAX);
o->outfile = filename;
}
if (strcmp(o->outfile, "-")) {
DATA(fd) = open(o->outfile, O_WRONLY | O_CREAT | O_TRUNC
| O_BINARY, 0644);
if (DATA(fd) < 0)
return -1;
} else {
DATA(fd) = 1;
}
if (strcmp(o->outfile, "-")) {
int len = strlen(drv_wav.description) + strlen(o->outfile) + 8;
if ((buf = malloc(len)) == NULL)
return -1;
snprintf(buf, len, "%s: %s", drv_wav.description, o->outfile);
drv_wav.description = buf;
} else {
drv_wav.description = strdup("WAV writer: stdout");
len = -1;
}
write(DATA(fd), "RIFF", 4);
writeval_32l(DATA(fd), len);
write(DATA(fd), "WAVE", 4);
chan = o->outfmt & XMP_FORMAT_MONO ? 1 : 2;
sampling_rate = o->freq;
bits_per_sample = o->resol;
if (bits_per_sample == 8)
o->outfmt |= XMP_FMT_UNS;
bytes_per_frame = chan * bits_per_sample / 8;
bytes_per_second = sampling_rate * bytes_per_frame;
write(DATA(fd), "fmt ", 4);
writeval_32l(DATA(fd), 16);
writeval_16l(DATA(fd), 1);
writeval_16l(DATA(fd), chan);
writeval_32l(DATA(fd), sampling_rate);
writeval_32l(DATA(fd), bytes_per_second);
writeval_16l(DATA(fd), bytes_per_frame);
writeval_16l(DATA(fd), bits_per_sample);
write(DATA(fd), "data", 4);
writeval_32l(DATA(fd), len);
DATA(size) = 0;
return 0;
}
static void bufdump(struct context_data *ctx, void *b, int i)
{
struct xmp_options *o = &ctx->o;
if (o->big_endian)
xmp_cvt_sex(i, b);
write(DATA(fd), b, i);
DATA(size) += i;
}
static void shutdown(struct context_data *ctx)
{
lseek(DATA(fd), 40, SEEK_SET);
writeval_32l(DATA(fd), DATA(size));
lseek(DATA(fd), 4, SEEK_SET);
writeval_32l(DATA(fd), DATA(size) + 40);
if (DATA(fd) > 0)
close(DATA(fd));
free(drv_wav.description);
free(drv_wav.data);
}

@ -0,0 +1,177 @@
/* Extended Module Player
* Copyright (C) 1996-2012 Claudio Matsuoka and Hipolito Carraro Jr
*
* This file is part of the Extended Module Player and is distributed
* under the terms of the GNU General Public License. See doc/COPYING
* for more information.
*/
/*
* Based on Bjornar Henden's driver for Mikmod
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <windows.h>
#include "common.h"
#include "driver.h"
#include "mixer.h"
#define MAXBUFFERS 32 /* max number of buffers */
#define BUFFERSIZE 120 /* buffer size in ms */
static HWAVEOUT hwaveout;
static WAVEHDR header[MAXBUFFERS];
static LPSTR buffer[MAXBUFFERS]; /* pointers to buffers */
static WORD freebuffer; /* */
static WORD nextbuffer; /* next buffer to be mixed */
static int num_buffers;
static int init(struct context_data *);
static void bufdump(struct context_data *, void *, int);
static void deinit(struct context_data *);
static void dummy()
{
}
static char *help[] = {
"buffers=val", "Number of buffers (default 10)",
NULL
};
struct xmp_drv_info drv_win32 = {
"win32", /* driver ID */
"Windows WinMM driver", /* driver description */
help, /* help */
init, /* init */
deinit, /* shutdown */
dummy, /* starttimer */
dummy, /* flush */
bufdump, /* bufdump */
};
static void show_error(int res)
{
char *msg;
switch (res) {
case MMSYSERR_ALLOCATED:
msg = "Device is already open";
break;
case MMSYSERR_BADDEVICEID:
msg = "Device is out of range";
break;
case MMSYSERR_NODRIVER:
msg = "No audio driver in this system";
break;
case MMSYSERR_NOMEM:
msg = "Unable to allocate sound memory";
break;
case WAVERR_BADFORMAT:
msg = "Audio format not supported";
break;
case WAVERR_SYNC:
msg = "The device is synchronous";
break;
default:
msg = "Unknown media error";
}
fprintf(stderr, "Error: %s", msg);
}
static void CALLBACK wave_callback(HWAVEOUT hwo, UINT uMsg, DWORD dwInstance,
DWORD dwParam1, DWORD dwParam2)
{
if (uMsg == WOM_DONE) {
freebuffer++;
freebuffer %= num_buffers;
}
}
static int init(struct context_data *ctx)
{
struct xmp_options *o = &ctx->o;
MMRESULT res;
WAVEFORMATEX wfe;
int i;
char *token, **parm;
num_buffers = 10;
parm_init();
chkparm1("buffers", num_buffers = strtoul(token, NULL, 0));
parm_end();
if (num_buffers > MAXBUFFERS)
num_buffers = MAXBUFFERS;
if (!waveOutGetNumDevs())
return XMP_ERR_DINIT;
wfe.wFormatTag = WAVE_FORMAT_PCM;
wfe.wBitsPerSample = o->resol;
wfe.nChannels = o->flags & XMP_FORMAT_MONO ? 1 : 2;
wfe.nSamplesPerSec = o->freq;
wfe.nAvgBytesPerSec = wfe.nSamplesPerSec * wfe.nChannels *
wfe.wBitsPerSample / 8;
wfe.nBlockAlign = wfe.nChannels * wfe.wBitsPerSample / 8;
res = waveOutOpen(&hwaveout, WAVE_MAPPER, &wfe, (DWORD) wave_callback,
0, CALLBACK_FUNCTION);
if (res != MMSYSERR_NOERROR) {
show_error(res);
return XMP_ERR_DINIT;
}
waveOutReset(hwaveout);
for (i = 0; i < num_buffers; i++) {
buffer[i] = malloc(OUT_MAXLEN);
header[i].lpData = buffer[i];
if (!buffer[i] || res != MMSYSERR_NOERROR) {
show_error(res);
return XMP_ERR_DINIT;
}
}
freebuffer = nextbuffer = 0;
return 0;
}
static void bufdump(struct context_data *ctx, void *b, int len)
{
memcpy(buffer[nextbuffer], b, len);
while ((nextbuffer + 1) % num_buffers == freebuffer)
Sleep(10);
header[nextbuffer].dwBufferLength = len;
waveOutPrepareHeader(hwaveout, &header[nextbuffer], sizeof(WAVEHDR));
waveOutWrite(hwaveout, &header[nextbuffer], sizeof(WAVEHDR));
nextbuffer++;
nextbuffer %= num_buffers;
}
static void deinit(struct context_data *ctx)
{
int i;
if (hwaveout) {
for (i = 0; i < num_buffers; i++) {
if (header[i].dwFlags & WHDR_PREPARED)
waveOutUnprepareHeader(hwaveout, &header[i],
sizeof(WAVEHDR));
free(buffer[i]);
}
while (waveOutClose(hwaveout) == WAVERR_STILLPLAYING)
Sleep(10);
hwaveout = NULL;
}
}

1006
getopt.c

File diff suppressed because it is too large Load Diff

@ -0,0 +1,193 @@
/* getopt_long and getopt_long_only entry points for GNU getopt.
Copyright (C) 1987,88,89,90,91,92,93,94,96,97 Free Software Foundation, Inc.
This file is part of the GNU C Library. Its master source is NOT part of
the C library, however. The master source lives in /gd/gnu/lib.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifndef HAVE_GETOPT_LONG
#include "getopt.h"
#if !defined (__STDC__) || !__STDC__
/* This is a separate conditional since some stdc systems
reject `defined (const)'. */
#ifndef const
#define const
#endif
#endif
#include <stdio.h>
/* Comment out all this code if we are using the GNU C Library, and are not
actually compiling the library itself. This code is part of the GNU C
Library, but also included in many other GNU distributions. Compiling
and linking in this code is a waste when using the GNU C library
(especially if it is a shared library). Rather than having every GNU
program understand `configure --with-gnu-libc' and omit the object files,
it is simpler to just do this in the source for each such file. */
#define GETOPT_INTERFACE_VERSION 2
#if !defined (_LIBC) && defined (__GLIBC__) && __GLIBC__ >= 2
#include <gnu-versions.h>
#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
#define ELIDE_CODE
#endif
#endif
#ifndef ELIDE_CODE
/* This needs to come after some library #include
to get __GNU_LIBRARY__ defined. */
#ifdef __GNU_LIBRARY__
#include <stdlib.h>
#endif
#ifndef NULL
#define NULL 0
#endif
int
getopt_long (argc, argv, options, long_options, opt_index)
int argc;
char *const *argv;
const char *options;
const struct option *long_options;
int *opt_index;
{
return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
}
/* Like getopt_long, but '-' as well as '--' can indicate a long option.
If an option that starts with '-' (not '--') doesn't match a long option,
but does match a short option, it is parsed as a short option
instead. */
int
getopt_long_only (argc, argv, options, long_options, opt_index)
int argc;
char *const *argv;
const char *options;
const struct option *long_options;
int *opt_index;
{
return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
}
#endif /* Not ELIDE_CODE. */
#ifdef TEST
#include <stdio.h>
int
main (argc, argv)
int argc;
char **argv;
{
int c;
int digit_optind = 0;
while (1)
{
int this_option_optind = optind ? optind : 1;
int option_index = 0;
static struct option long_options[] =
{
{"add", 1, 0, 0},
{"append", 0, 0, 0},
{"delete", 1, 0, 0},
{"verbose", 0, 0, 0},
{"create", 0, 0, 0},
{"file", 1, 0, 0},
{0, 0, 0, 0}
};
c = getopt_long (argc, argv, "abc:d:0123456789",
long_options, &option_index);
if (c == -1)
break;
switch (c)
{
case 0:
printf ("option %s", long_options[option_index].name);
if (optarg)
printf (" with arg %s", optarg);
printf ("\n");
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (digit_optind != 0 && digit_optind != this_option_optind)
printf ("digits occur in two different argv-elements.\n");
digit_optind = this_option_optind;
printf ("option %c\n", c);
break;
case 'a':
printf ("option a\n");
break;
case 'b':
printf ("option b\n");
break;
case 'c':
printf ("option c with value `%s'\n", optarg);
break;
case 'd':
printf ("option d with value `%s'\n", optarg);
break;
case '?':
break;
default:
printf ("?? getopt returned character code 0%o ??\n", c);
}
}
if (optind < argc)
{
printf ("non-option ARGV-elements: ");
while (optind < argc)
printf ("%s ", argv[optind++]);
printf ("\n");
}
exit (0);
}
#endif /* TEST */
#endif /* HAVE_GETOPT_LONG */

@ -0,0 +1,63 @@
#include <stdio.h>
#include <xmp.h>
void info_mod(struct xmp_module_info *mi)
{
int i;
printf("Module name : %s\n", mi->mod->name);
printf("Module type : %s\n", mi->mod->type);
printf("Module length : %d patterns\n", mi->mod->len);
printf("Stored patterns: %d\n", mi->mod->pat);
printf("Instruments : %d\n", mi->mod->ins);
printf("Samples : %d\n", mi->mod->smp);
printf("Channels : %d [ ", mi->mod->chn);
for (i = 0; i < mi->mod->chn; i++) {
printf("%x ", mi->mod->xxc[i].pan >> 4);
}
printf("]\n");
printf("Estimated time : %dmin%ds\n", (mi->total_time + 500) / 60000,
((mi->total_time + 500) / 1000) % 60);
}
void info_frame(struct xmp_module_info *mi, int reset)
{
static int ord = -1, tpo = -1, bpm = -1;
static int max_channels = -1;
int time;
if (reset) {
ord = -1;
max_channels = -1;
}
if (mi->virt_used > max_channels)
max_channels = mi->virt_used;
if (mi->frame != 0)
return;
time = mi->current_time / 100;
if (mi->order != ord || mi->bpm != bpm || mi->tempo != tpo) {
printf("\rTempo[%02X] BPM[%02X] Pos[%02X/%02X] "
"Pat[%02X/%02X] Row[ / ] Chn[ / ] 0:00:00.0",
mi->tempo, mi->bpm,
mi->order, mi->mod->len - 1,
mi->pattern, mi->mod->pat - 1);
ord = mi->order;
bpm = mi->bpm;
tpo = mi->tempo;
}
printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"
"%02X/%02X] Chn[%02X/%02X] %3d:%02d:%02d.%d",
mi->row, mi->num_rows - 1, mi->virt_used, max_channels,
(int)(time / (60 * 600)), (int)((time / 600) % 60),
(int)((time / 10) % 60), (int)(time % 10));
fflush(stdout);
}

@ -0,0 +1,637 @@
/* Extended Module Player
* Copyright (C) 1996-2012 Claudio Matsuoka and Hipolito Carraro Jr
*
* This file is part of the Extended Module Player and is distributed
* under the terms of the GNU General Public License. See doc/COPYING
* for more information.
*/
/*
* Fri, 05 Jun 1998 16:46:13 -0700 "Mark R. Boyns" <boyns@sdsu.edu>
* I needed to use xmp as a filter and was able to use /dev/fd/0 as an
* input source but ran into problems with xmp trying to read interactive
* commands. So, I added a few lines of code to disable command reading
* with the --nocmd option.
*/
/*
* Wed, 10 Jun 1998 15:42:25 -0500 Douglas Carmichael <dcarmich@dcarmichael.net>
* Support for real-time priority in FreeBSD.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#ifdef __CYGWIN__
#include <sys/select.h>
#endif
#ifdef HAVE_SIGNAL_H
#include <signal.h>
#endif
#include <unistd.h>
#ifdef __AROS__
#define __AMIGA__
#endif
#ifdef __AMIGA__
#undef HAVE_TERMIOS_H
#define __USE_INLINE__
#include <proto/dos.h>
#endif
#ifdef HAVE_TERMIOS_H
#include <termios.h>
#endif
#ifdef HAVE_SYS_RTPRIO_H
#include <sys/resource.h>
#include <sys/rtprio.h>
#endif
#ifdef __EMX__
#define INCL_BASE
#include <os2.h>
#endif
#ifdef WIN32
#include <windows.h>
#include "conio.h"
#endif
#include "xmp.h"
extern int optind;
/* Options not belonging to libxmp */
int probeonly = 0;
int randomize = 0;
int loadonly = 0;
int nocmd = 0;
int showtime = 0;
#ifdef HAVE_SYS_RTPRIO_H
int rt = 0;
#endif
static struct xmp_options *opt;
static int verbosity;
#ifdef HAVE_TERMIOS_H
static struct termios term;
#endif
static int background = 0;
#ifdef SIGTSTP
static int stopped = 0;
#endif
static int refresh_status = 0;
static int max_nch = 0;
static double rows, tot_nch;
int skip = 0;
#ifdef HAVE_SIGNAL_H
static int sigusr = 0;
#endif
void get_options (int, char **, struct xmp_options *, xmp_context);
void init_drivers (void);
static xmp_context ctx;
static int paused;
static int set_tty()
{
#ifdef HAVE_TERMIOS_H
struct termios t;
if (background)
return -1;
if (tcgetattr (0, &term) < 0)
return -1;
t = term;
t.c_lflag &= ~(ECHO | ICANON | TOSTOP);
t.c_cc[VMIN] = t.c_cc[VTIME] = 0;
if (tcsetattr (0, TCSAFLUSH, &t) < 0)
return -1;
#endif
return 0;
}
static int reset_tty()
{
#ifdef HAVE_TERMIOS_H
if (background)
return -1;
if (tcsetattr(0, TCSAFLUSH, &term) < 0) {
fprintf(stderr, "can't reset terminal!\n");
return -1;
}
#endif
return 0;
}
#ifdef HAVE_SIGNAL_H
#ifdef SIGTSTP
static void sigtstp_handler(int n)
{
if (!stopped) {
if (showtime)
fprintf(stderr, "\n");
else if (verbosity)
fprintf(stderr, "] - STOPPED\n");
xmp_timer_stop(ctx);
stopped = 1;
}
signal (SIGTSTP, SIG_DFL);
kill (getpid (), SIGTSTP);
}
static void sigcont_handler(int n)
{
#ifndef __AMIGA__
background = (tcgetpgrp(0) == getppid());
#endif
if (background)
reset_tty();
else
set_tty();
if (stopped)
xmp_timer_restart(ctx);
stopped = 0;
refresh_status = 1;
/* Unlike BSD systems, signals under Linux are reset to their
* default behavior when raised.
*/
signal(SIGCONT, sigcont_handler);
signal(SIGTSTP, sigtstp_handler);
}
#endif
static void sigusr_handler(int n)
{
signal(sigusr = n, sigusr_handler);
}
static void cleanup(int s)
{
signal(SIGTERM, SIG_DFL);
signal(SIGINT, SIG_DFL);
#ifdef SIGQUIT
signal(SIGQUIT, SIG_DFL);
#endif
signal(SIGFPE, SIG_DFL);
signal(SIGSEGV, SIG_DFL);
fprintf(stderr, "\n*** Interrupted: signal %d caught\n", s);
xmp_stop_module(ctx);
xmp_close_audio(ctx);
reset_tty ();
exit (-2);
}
#endif /* HAVE_SIGNAL_H */
#ifdef __CYGWIN__
/*
* from daniel åkerud <daniel.akerud@gmail.com>
* date Tue, Jul 28, 2009 at 9:59 AM
*
* Under Cygwin, the read() in process_echoback blocks because VTIME = 0
* is not handled correctly. To fix this you can either:
*
* 1. Enable "tty emulation" in Cygwin using an environment variable.
* http://www.mail-archive.com/cygwin@cygwin.com/msg99417.html
* For me this is _very_ slow and I can see the characters as they are
* typed out when running xmp. I have not investigated why this is
* happening, but there is of course a reason why this mode is not
* enabled by default.
*
* 2. Do a select() before read()ing if the platform is Cygwin.
* This makes Cygwin builds work out of the box with no fiddling around,
* but does impose a neglectible cpu overhead (for Cygwin builds only).
*/
static int stdin_ready_for_reading()
{
fd_set fds;
struct timeval tv;
int ret;
tv.tv_sec = 0;
tv.tv_usec = 0;
FD_ZERO(&fds);
FD_SET(STDIN_FILENO, &fds);
ret = select(STDIN_FILENO + 1, &fds, NULL, NULL, &tv);
if (ret > 0 && FD_ISSET(STDIN_FILENO, &fds))
return 1;
return 0;
}
#endif
void read_keyboard()
{
unsigned char cmd;
int k;
/* Interactive commands */
if (nocmd || background)
return;
#if defined HAVE_TERMIOS_H && !defined WIN32
#ifdef __CYGWIN__
k = 0;
if (stdin_ready_for_reading())
#endif
k = read(0, &cmd, 1);
#elif defined WIN32
k = cmd = kbhit() ? getch() : 0;
#elif defined __AMIGA__
/* Amiga CLI */
{
BPTR in = Input();
k = cmd = 0;
if (WaitForChar(in, 1)) {
char c;
Read(in, &c, 1);
cmd = k = c;
}
}
#else
k = cmd = 0;
#endif
if (k > 0) {
switch (cmd) {
case 'q': /* quit */
skip = -2;
xmp_mod_stop(ctx);
paused = 0;
break;
case 'f': /* jump to next order */
xmp_ord_next(ctx);
paused = 0;
break;
case 'b': /* jump to previous order */
xmp_ord_prev(ctx);
paused = 0;
break;
case 'n': /* skip to next module */
skip = 1;
xmp_mod_stop(ctx);
paused = 0;
break;
case 'p': /* skip to previous module */
skip = -1;
xmp_mod_stop(ctx);
paused = 0;
break;
case 'l':
if (xmp_test_flag(ctx, XMP_CTL_LOOP))
xmp_reset_flag(ctx, XMP_CTL_LOOP);
else
xmp_set_flag(ctx, XMP_CTL_LOOP);
break;
case ' ': /* paused module */
paused ^= 1;
if (verbosity) {
fprintf (stderr, "%s", paused ?
"] - PAUSED\b\b\b\b\b\b\b\b\b\b" :
"] \b\b\b\b\b\b\b\b\b\b");
}
if (paused)
xmp_timer_stop(ctx);
else
xmp_timer_restart(ctx);
break;
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
xmp_channel_mute(ctx, cmd - '1', 1, -1);
break;
case '0':
xmp_channel_mute(ctx, 9, 1, -1);
break;
case '!':
xmp_channel_mute(ctx, 0, 8, 0);
break;
}
}
}
static void shuffle (int argc, char **argv)
{
int i, j;
char *x;
for (i = 1; i < argc; i++) {
j = 1 + rand () % (argc - 1);
x = argv[i];
argv[i] = argv[j];
argv[j] = x;
}
}
int main(int argc, char **argv)
{
int i, t, lf_flag, first, num_mod;
time_t t0, t1, t2, t3;
#ifndef WIN32
struct timeval tv;
struct timezone tz;
#endif
#ifdef HAVE_SYS_RTPRIO_H
struct rtprio rtp;
#endif
int getprevious = 0, skipprev = 0;
#ifdef __EMX__
long rc;
#endif
struct xmp_module_info mi;
init_drivers();
ctx = xmp_create_context();
xmp_init(ctx, argc, argv);
opt = xmp_get_options(ctx);
//opt->verbosity = 1;
get_options(argc, argv, opt, ctx);
//verbosity = opt->verbosity;
if (!(probeonly || argv[optind])) {
fprintf (stderr, "%s: no modules to play\n"
"Use `%s --help' for more information.\n", argv[0], argv[0]);
exit (-1);
}
#ifndef WIN32
gettimeofday(&tv, &tz);
srand(tv.tv_usec);
#else
srand(GetTickCount());
#endif
if (randomize)
shuffle(argc - optind + 1, &argv[optind - 1]);
if (opt->outfile && (!opt->drv_id || strcmp(opt->drv_id, "wav")))
opt->drv_id = "file";
global_filename = argv[optind];
#ifdef HAVE_TERMIOS_H
if ((background = (tcgetpgrp (0) == getppid ()))) {
//verb = opt->verbosity;
//opt->verbosity = 0;
i = xmp_open_audio(ctx);
//xmp_verbosity_level(ctx, opt->verbosity = verb);
} else
#endif
{
i = xmp_open_audio(ctx);
}
if (i < 0) {
fprintf (stderr, "%s: ", argv[0]);
switch (i) {
case XMP_ERR_DINIT:
fprintf (stderr, "can't initialize driver\n");
return -1;
case XMP_ERR_NODRV:
fprintf (stderr, "driver does not exist\n");
return -2;
case XMP_ERR_DSPEC:
fprintf (stderr, "driver not specified\n");
return -3;
default:
fprintf (stderr, "unknown error\n");
return -128;
}
}
fprintf(stderr, "Extended Module Player " VERSION "\n"
"Copyright (C) 1996-2012 Claudio Matsuoka and Hipolito Carraro Jr\n");
if (1) {
int srate, res, chn, itpt;
xmp_get_driver_cfg(ctx, &srate, &res, &chn, &itpt);
fprintf(stderr, "Using %s\n", (char*)xmp_get_driver_description(ctx));
if (srate) {
fprintf(stderr, "Mixer set to %dbit, %d Hz, %s%s\n", res, srate,
itpt ? "interpolated " : "", chn > 1 ? "stereo" : "mono");
}
}
if (probeonly)
exit(0);
/*
* Support for real-time priority by Douglas Carmichael <dcarmich@mcs.com>
*/
#ifdef HAVE_SYS_RTPRIO_H
if (rt) {
rtp.type = RTP_PRIO_REALTIME;
rtp.prio = 0;
if (rtprio (RTP_SET, 0, &rtp) == -1) {
fprintf (stderr, "%s: Can't get realtime priority.\n", argv[0]);
exit(1);
}
}
#endif
#ifdef __EMX__
rc = DosSetPriority (PRTYS_THREAD, PRTYC_TIMECRITICAL, PRTYD_MINIMUM, 0);
if (rc != 0) {
printf ("Error setting Priority. Priority defaulting to the System Default.\n" );
}
#endif
#ifdef HAVE_SIGNAL_H
signal(SIGTERM, cleanup);
signal(SIGINT, cleanup);
signal(SIGFPE, cleanup);
signal(SIGSEGV, cleanup);
#ifdef SIGQUIT
signal(SIGQUIT, cleanup);
#endif
#ifdef SIGTSTP
signal(SIGTSTP, sigtstp_handler);
#endif
#ifdef SIGCONT
signal(SIGCONT, sigcont_handler);
#endif
#ifdef SIGUSR1
signal(SIGUSR1, sigusr_handler);
signal(SIGUSR2, sigusr_handler);
#endif
#endif
set_tty ();
paused = 0;
time (&t0);
num_mod = lf_flag = 0;
for (first = optind; optind < argc; optind++) {
if (getprevious) {
optind -= 2;
if (optind < first) {
optind += 2;
}
}
if (!background) {
if (lf_flag)
fprintf (stderr, "\n");
lf_flag = fprintf (stderr, "Loading %s... (%d of %d)\n",
argv[optind], optind - first + 1, argc - first);
}
if (background) {
//verb = xmp_verbosity_level(ctx, 0);
t = xmp_load_module(ctx, argv[optind]);
//xmp_verbosity_level(ctx, verb);
} else {
t = xmp_load_module(ctx, argv[optind]);
}
if (t < 0) {
switch (t) {
case -1:
fprintf (stderr, "%s: %s: unrecognized file format\n",
argv[0], argv[optind]);
getprevious = skipprev;
continue;
case -2:
fprintf (stderr, "%s: %s: possibly corrupted file\n",
argv[0], argv[optind]);
getprevious = skipprev;
continue;
case -3: {
char line[1024];
snprintf(line, 1024, "%s: %s", *argv, argv[optind]);
perror(line);
getprevious = skipprev;
continue; }
}
}
rows = tot_nch = max_nch = getprevious = skipprev = 0;
num_mod++;
//xmp_get_module_info(ctx, &mi);
if (loadonly)
goto skip_play;
/* Play the module */
time(&t2);
xmp_player_start(ctx);
for (;;) {
read_keyboard();
if (paused) {
usleep(100000);
} else {
if (xmp_player_frame(ctx) != 0)
break;
xmp_play_buffer(ctx);
xmp_player_get_info(ctx, &mi);
printf("%2d %2d %2d\r", mi.order, mi.pattern, mi.row);
fflush(stdout);
}
}
xmp_player_end(ctx);
time(&t3);
t = difftime(t3, t2);
xmp_release_module(ctx);
if (showtime) {
fprintf(stderr, "\r \r");
}
if (!background) {
fprintf (stderr,
"\rElapsed time : %dmin%02ds %s \n",
t / 60, t % 60, skip ? "(SKIPPED)" : " ");
#if 0
fprintf (stderr, "Channels used : %d/%d", max_nch, mi.chn);
if (max_nch)
fprintf (stderr, ", avg %.2f (%.1f%%)\n",
tot_nch / rows, 100.0 * tot_nch / rows / mi.chn);
else
fprintf (stderr, "\n");
#endif
}
skip_play:
if (skip == -1) {
optind -= optind > first ? 2 : 1;
skipprev = 1;
}
if (skip == -2)
break;
skip = 0;
}
time (&t1);
if (!loadonly && !background && num_mod > 1) {
t = difftime (t1, t0);
fprintf (stderr, "\n\t%d modules played, total time %dh%02dmin%02ds\n",
num_mod, t / 3600, (t % 3600) / 60, t % 60);
}
xmp_close_audio(ctx);
xmp_deinit(ctx);
xmp_free_context(ctx);
reset_tty();
return 0;
}

141
main.c

@ -0,0 +1,141 @@
/* A simple frontend for xmp */
#define HAVE_TERMIOS_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/time.h>
#include <xmp.h>
//#include "sound.h"
#include "common.h"
extern int optind;
static void cleanup()
{
signal(SIGTERM, SIG_DFL);
signal(SIGINT, SIG_DFL);
signal(SIGQUIT, SIG_DFL);
signal(SIGFPE, SIG_DFL);
signal(SIGSEGV, SIG_DFL);
sound_deinit();
reset_tty();
printf("\n");
exit(EXIT_FAILURE);
}
static void shuffle(int argc, char **argv)
{
int i, j;
char *x;
for (i = 1; i < argc; i++) {
j = 1 + rand() % (argc - 1);
x = argv[i];
argv[i] = argv[j];
argv[j] = x;
}
}
int main(int argc, char **argv)
{
xmp_context ctx;
struct xmp_module_info mi;
struct options options;
int i;
int silent = 0;
int first;
#ifndef WIN32
struct timeval tv;
struct timezone tz;
gettimeofday(&tv, &tz);
srand(tv.tv_usec);
#else
srand(GetTickCount());
#endif
memset(&options, 0, sizeof (struct options));
get_options(argc, argv, &options);
if (options.random) {
shuffle(argc - optind + 1, &argv[optind - 1]);
}
if (!silent && sound_init(44100, 2) < 0) {
fprintf(stderr, "%s: can't initialize sound\n", argv[0]);
exit(EXIT_FAILURE);
}
signal(SIGTERM, cleanup);
signal(SIGINT, cleanup);
signal(SIGFPE, cleanup);
signal(SIGSEGV, cleanup);
signal(SIGQUIT, cleanup);
set_tty();
ctx = xmp_create_context();
for (first = optind; optind < argc; optind++) {
printf("\nLoading %s... (%d of %d)\n",
argv[optind], optind - first + 1, argc - first);
if (xmp_load_module(ctx, argv[optind]) < 0) {
fprintf(stderr, "%s: error loading %s\n", argv[0],
argv[i]);
continue;
}
if (xmp_player_start(ctx, options.start, 44100, 0) == 0) {
int new_mod = 1;
/* Mute channels */
for (i = 0; i < XMP_MAX_CHANNELS; i++) {
xmp_channel_mute(ctx, i, options.mute[i]);
}
/* Show module data */
xmp_player_get_info(ctx, &mi);
info_mod(&mi);
/* Play module */
while (xmp_player_frame(ctx) == 0) {
xmp_player_get_info(ctx, &mi);
if (mi.loop_count > 0)
break;
info_frame(&mi, new_mod);
if (!silent) {
sound_play(mi.buffer, mi.buffer_size);
}
new_mod = 0;
options.start = 0;
}
xmp_player_end(ctx);
}
xmp_release_module(ctx);
printf("\n");
}
xmp_free_context(ctx);
reset_tty();
if (!silent) {
sound_deinit();
}
exit(EXIT_SUCCESS);
}

@ -0,0 +1,325 @@
/* Extended Module Player
* Copyright (C) 1996-2012 Claudio Matsuoka and Hipolito Carraro Jr
*
* This file is part of the Extended Module Player and is distributed
* under the terms of the GNU General Public License. See doc/COPYING
* for more information.
*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
#include <xmp.h>
#include "common.h"
extern char *optarg;
static int o, i;
static char *token;
extern int probeonly;
extern int loadonly;
extern int randomize;
extern int nocmd;
#ifdef HAVE_SYS_RTPRIO_H
extern int rt;
#endif
#define OPT_LOADONLY 0x103
#define OPT_FX9BUG 0x105
#define OPT_PROBEONLY 0x106
#define OPT_STDOUT 0x109
#define OPT_STEREO 0x10a
#define OPT_NOCMD 0x10b
#define OPT_REALTIME 0x10c
#define OPT_FIXLOOP 0x10d
#define OPT_CRUNCH 0x10e
#define OPT_NOFILTER 0x10f
#define OPT_VBLANK 0x110
#define OPT_SHOWTIME 0x111
#define OPT_DUMP 0x112
static void exclude_formats(char *list)
{
char *tok;
tok = strtok(list, ", ");
while (tok) {
xmp_enable_format(tok, 0);
tok = strtok(NULL, ", ");
}
}
static void list_wrap(char *s, int l, int r, int v)
{
int i;
static int c = 0;
static int m = 0;
char *t;
if (s == NULL) {
for (i = 0; i < l; i++)
printf(" ");
c = l;
m = r;
return;
} else if (c > l) {
c++;
printf(v ? "," : " ");
}
t = strtok(s, " ");
while (t) {
if ((c + strlen(t) + 1) > m) {
c = l;
printf("\n");
for (i = 0; i < l; i++) {
printf(" ");
}
} else if (c > l) {
printf(" ");
}
c += strlen(t) + 1;
printf("%s", t);
t = strtok(NULL, " ");
}
}
static void usage(char *s)
{
struct xmp_fmt_info *f, *fmt;
struct xmp_drv_info *d, *drv;
char **hlp, buf[80];
int i;
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");
printf("\nAvailable drivers:\n");
xmp_get_drv_info(&drv);
list_wrap(NULL, 3, 78, 1);
for (d = drv; d; d = d->next) {
snprintf(buf, 80, "%s (%s)", d->id, d->description);
list_wrap(buf, 3, 0, 1);
}
printf("\n");
for (d = drv; d; d = d->next) {
if (d->help)
printf("\n%s options:\n", d->description);
for (hlp = d->help; hlp && *hlp; hlp += 2)
printf(" -D%-20.20s %s\n", hlp[0], hlp[1]);
}
#endif
printf("\nPlayer control options:\n"
" -D parameter[=val] Pass configuration parameter to the output driver\n"
" -d --driver name Force output to the specified device\n"
" --fix-sample-loops Use sample loop start /2 in MOD/UNIC/NP3\n"
" --offset-bug-emulation Emulate Protracker 2.x bug in effect 9\n"
" -l --loop Enable module looping\n"
" -M --mute ch-list Mute the specified channels\n"
" --nocmd Disable interactive commands\n"
" --norc Don't read configuration files\n"
" -R --random Random order playing\n"
#ifdef HAVE_SYS_RTPRIO_H
" --realtime Run in real-time priority\n"
#endif
" -S --solo ch-list Set channels to solo mode\n"
" -s --start num Start from the specified order\n"
" -T --tempo num Initial tempo (default 6)\n"
" -t --time num Maximum playing time in seconds\n"
" --vblank Force vblank timing in Amiga modules (no CIA)\n"
"\nPlayer sound options:\n"
" -8 --8bit Convert 16 bit samples to 8 bit\n"
" -m --mono Mono output\n"
" -P --pan pan Percentual pan amplitude\n"
" -r --reverse Reverse left/right stereo channels\n"
" --stereo Stereo output\n"
"\nSoftware mixer options:\n"
" -a --amplify {0|1|2|3} Amplification factor: 0=Normal, 1=x2, 2=x4, 3=x8\n"
" -b --bits {8|16} Software mixer resolution (8 or 16 bits)\n"
" -c --stdout Mix the module to stdout\n"
" -F --click-filter Apply low pass filter to reduce clicks\n"
" -f --frequency rate Sampling rate in hertz (default 44100)\n"
" -n --nearest Use nearest neighbor interpolation\n"
" -o --output-file name Mix the module to file ('-' for stdout)\n"
" -u --unsigned Set the mixer to use unsigned samples\n"
"\nEnvironment options:\n"
" -I --instrument-path Set pathname to external samples\n"
"\nInformation options:\n"
" -h --help Print a summary of the command line options\n"
" --load-only Load module and exit\n"
" --probe-only Probe audio device and exit\n"
" -q --quiet Quiet mode (verbosity level = 0)\n"
" --show-time Display elapsed and remaining time\n"
" -V --version Print version information\n"
" -v --verbose Verbose mode (incremental)\n");
}
void get_options(int argc, char **argv, struct options *options)
{
int optidx = 0;
#define OPTIONS "a:b:cD:d:f:hI:lM:mo:qRS:s:T:t:uVv"
static struct option lopt[] = {
{"amplify", 1, 0, 'a'},
{"bits", 1, 0, 'b'},
{"driver", 1, 0, 'd'},
{"frequency", 1, 0, 'f'},
{"offset-bug-emulation", 0, 0, OPT_FX9BUG},
{"help", 0, 0, 'h'},
{"instrument-path", 1, 0, 'I'},
{"load-only", 0, 0, OPT_LOADONLY},
{"loop", 0, 0, 'l'},
{"mono", 0, 0, 'm'},
{"mute", 1, 0, 'M'},
{"nocmd", 0, 0, OPT_NOCMD},
{"output-file", 1, 0, 'o'},
{"pan", 1, 0, 'P'},
{"quiet", 0, 0, 'q'},
{"random", 0, 0, 'R'},
{"solo", 1, 0, 'S'},
{"start", 1, 0, 's'},
{"stdout", 0, 0, 'c'},
{"tempo", 1, 0, 'T'},
{"time", 1, 0, 't'},
{"unsigned", 0, 0, 'u'},
{"version", 0, 0, 'V'},
{"verbose", 0, 0, 'v'},
{NULL, 0, 0, 0}
};
i = 0;
while ((o = getopt_long(argc, argv, OPTIONS, lopt, &optidx)) != -1) {
switch (o) {
case 'a':
options->amplify = atoi(optarg);
break;
case 'b':
if (atoi(optarg) == 8) {
options->format |= XMP_FORMAT_8BIT;
}
break;
case 'c':
options->out_file = "-";
break;
#if 0
case 'D':
xmp_set_driver_parameter(opt, optarg);
break;
case 'd':
options->drv_id = optarg;
break;
case OPT_FX9BUG:
options->quirk |= XMP_QRK_FX9BUG;
break;
#endif
case 'f':
options->freq = strtoul(optarg, NULL, 0);
break;
case 'I':
options->ins_path = optarg;
break;
case 'l':
options->loop = 1;
break;
case OPT_LOADONLY:
options->load_only = 1;
break;
case 'm':
options->format |= XMP_FORMAT_MONO;
break;
case 'o':
options->out_file = optarg;
if (strlen(optarg) >= 4 &&
!strcasecmp(optarg + strlen(optarg) - 4, ".wav")) {
//options->drv_id = "wav";
}
break;
case 'P':
options->mix = strtoul(optarg, NULL, 0);
if (options->mix < 0)
options->mix = 0;
if (options->mix > 100)
options->mix = 100;
break;
case 'q':
//options->verbosity = 0;
break;
case 'R':
options->random = 1;
break;
case 'M':
case 'S':
if (o == 'S') {
memset(options->mute, 1, XMP_MAX_CHANNELS);
}
token = strtok(optarg, ",");
while (token) {
int a, b;
char buf[40];
memset(buf, 0, 40);
if (strchr(token, '-')) {
b = strcspn(token, "-");
strncpy(buf, token, b);
a = atoi(buf);
strncpy(buf, token + b + 1,
strlen(token) - b - 1);
b = atoi(buf);
} else {
a = b = atoi(token);
}
for (; b >= a; b--) {
if (b < XMP_MAX_CHANNELS)
options->mute[b] = (o == 'M');
}
token = strtok(NULL, ",");
}
break;
case 's':
options->start = strtoul(optarg, NULL, 0);
break;
case 't':
options->time = strtoul(optarg, NULL, 0);
break;
case 'u':
options->format |= XMP_FORMAT_UNSIGNED;
break;
case 'V':
puts("Extended Module Player " VERSION);
exit(0);
case 'v':
//options->verbosity++;
break;
case 'h':
usage(argv[0]);
default:
exit(-1);
}
}
/* Set limits */
if (options->freq < 1000)
options->freq = 1000; /* Min. rate 1 kHz */
if (options->freq > 48000)
options->freq = 48000; /* Max. rate 48 kHz */
}

@ -0,0 +1,11 @@
struct sound_driver {
char *id;
char *description;
char **help;
int (*init) ();
void (*deinit) ();
void (*pause) ();
void (*resume) ();
struct list_head *next;
};

@ -0,0 +1,70 @@
#include <alsa/asoundlib.h>
#include <alsa/pcm.h>
#include "sound.h"
static snd_pcm_t *pcm_handle;
int sound_init(int sampling_rate, int channels)
{
snd_pcm_hw_params_t *hwparams;
int ret;
unsigned int chan, rate;
unsigned int btime = 250000; /* 250ms */
unsigned int ptime = 50000; /* 50ms */
char *card_name = "default";
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",
snd_strerror(ret));
return -1;
}
chan = channels;
rate = sampling_rate;
snd_pcm_hw_params_alloca(&hwparams);
snd_pcm_hw_params_any(pcm_handle, hwparams);
snd_pcm_hw_params_set_access(pcm_handle, hwparams,
SND_PCM_ACCESS_RW_INTERLEAVED);
snd_pcm_hw_params_set_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16);
snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &rate, 0);
snd_pcm_hw_params_set_channels_near(pcm_handle, hwparams, &chan);
snd_pcm_hw_params_set_buffer_time_near(pcm_handle, hwparams, &btime, 0);
snd_pcm_hw_params_set_period_time_near(pcm_handle, hwparams, &ptime, 0);
snd_pcm_nonblock(pcm_handle, 0);
if ((ret = snd_pcm_hw_params(pcm_handle, hwparams)) < 0) {
fprintf(stderr, "Unable to set ALSA output parameters: %s\n",
snd_strerror(ret));
return -1;
}
if ((ret = snd_pcm_prepare(pcm_handle)) < 0) {
fprintf(stderr, "Unable to prepare ALSA: %s\n",
snd_strerror(ret));
return -1;
}
return 0;
}
void sound_play(void *b, int i)
{
int frames;
frames = snd_pcm_bytes_to_frames(pcm_handle, i);
if (snd_pcm_writei(pcm_handle, b, frames) < 0) {
snd_pcm_prepare(pcm_handle);
}
}
void sound_deinit()
{
/* snd_pcm_drain(pcm_handle); */
snd_pcm_close(pcm_handle);
}

@ -0,0 +1,41 @@
#include <stdio.h>
#include <termios.h>
#include <xmp.h>
#include "common.h"
static int background = 0;
static struct termios term;
int set_tty()
{
struct termios t;
if (background)
return -1;
if (tcgetattr(0, &term) < 0)
return -1;
t = term;
t.c_lflag &= ~(ECHO | ICANON | TOSTOP);
t.c_cc[VMIN] = t.c_cc[VTIME] = 0;
if (tcsetattr(0, TCSAFLUSH, &t) < 0)
return -1;
return 0;
}
int reset_tty()
{
if (background)
return -1;
if (tcsetattr(0, TCSAFLUSH, &term) < 0) {
fprintf(stderr, "can't reset terminal!\n");
return -1;
}
return 0;
}
Loading…
Cancel
Save