Simulator first commit
This commit is contained in:
213
node_modules/lame/deps/mpg123/src/output/Makefile.am
generated
vendored
Normal file
213
node_modules/lame/deps/mpg123/src/output/Makefile.am
generated
vendored
Normal file
@ -0,0 +1,213 @@
|
||||
## Makefile.am: produce Makefile.in from this
|
||||
|
||||
## copyright by the mpg123 project - free software under the terms of the LGPL 2.1
|
||||
## see COPYING and AUTHORS files in distribution or http://www.mpg123.org
|
||||
## initially written by Nicholas J. Humfrey
|
||||
|
||||
#AM_CPPFLAGS = -I$(top_srcdir)/src/libmpg123 -I$(top_srcdir)/src
|
||||
INCLUDES = $(LTDLINCL) -I$(top_builddir)/src -I$(top_builddir)/src/libmpg123 -I$(top_srcdir)/src -I$(top_srcdir)/src/libmpg123
|
||||
|
||||
#Do not include uneeded headers from mpg123app.h
|
||||
AM_CPPFLAGS = -DBUILDING_OUTPUT_MODULES=1
|
||||
|
||||
if HAVE_MODULES
|
||||
|
||||
pkglib_LTLIBRARIES =
|
||||
|
||||
# These are not tested and _very_ likely need work: aix alib hp os2 sgi mint
|
||||
|
||||
# Use that sh/perl script to generate the module entries:
|
||||
#for i in alsa coreaudio esd jack nas oss portaudio pulse sdl sndio sun win32 aix alib arts hp os2 sgi mint openal dummy; do echo $i; done |
|
||||
#perl -ne 'chomp; $big = uc($_); print <<EOT;
|
||||
#
|
||||
#if HAVE_$big
|
||||
#pkglib_LTLIBRARIES += output_$_.la
|
||||
#output_${_}_la_SOURCES = $_.c
|
||||
#output_${_}_la_LDFLAGS = -module -no-undefined -avoid-version -export-dynamic -export-symbols-regex '"'"'^mpg123_'"'"' \@${big}_LDFLAGS\@
|
||||
#output_${_}_la_CFLAGS = \@${big}_CFLAGS\@
|
||||
#output_${_}_la_LIBADD = \@${big}_LIBS\@
|
||||
#endif
|
||||
#EOT
|
||||
#'
|
||||
|
||||
if HAVE_ALSA
|
||||
pkglib_LTLIBRARIES += output_alsa.la
|
||||
output_alsa_la_SOURCES = alsa.c
|
||||
output_alsa_la_LDFLAGS = -module -no-undefined -avoid-version -export-dynamic -export-symbols-regex '^mpg123_' @ALSA_LDFLAGS@
|
||||
output_alsa_la_CFLAGS = @ALSA_CFLAGS@
|
||||
output_alsa_la_LIBADD = @ALSA_LIBS@
|
||||
endif
|
||||
|
||||
if HAVE_COREAUDIO
|
||||
pkglib_LTLIBRARIES += output_coreaudio.la
|
||||
output_coreaudio_la_SOURCES = coreaudio.c
|
||||
output_coreaudio_la_LDFLAGS = -module -no-undefined -avoid-version -export-dynamic -export-symbols-regex '^mpg123_' @COREAUDIO_LDFLAGS@
|
||||
output_coreaudio_la_CFLAGS = @COREAUDIO_CFLAGS@
|
||||
output_coreaudio_la_LIBADD = @COREAUDIO_LIBS@
|
||||
endif
|
||||
|
||||
if HAVE_ESD
|
||||
pkglib_LTLIBRARIES += output_esd.la
|
||||
output_esd_la_SOURCES = esd.c
|
||||
output_esd_la_LDFLAGS = -module -no-undefined -avoid-version -export-dynamic -export-symbols-regex '^mpg123_' @ESD_LDFLAGS@
|
||||
output_esd_la_CFLAGS = @ESD_CFLAGS@
|
||||
output_esd_la_LIBADD = @ESD_LIBS@
|
||||
endif
|
||||
|
||||
if HAVE_JACK
|
||||
pkglib_LTLIBRARIES += output_jack.la
|
||||
output_jack_la_SOURCES = jack.c
|
||||
output_jack_la_LDFLAGS = -module -no-undefined -avoid-version -export-dynamic -export-symbols-regex '^mpg123_' @JACK_LDFLAGS@
|
||||
output_jack_la_CFLAGS = @JACK_CFLAGS@
|
||||
output_jack_la_LIBADD = @JACK_LIBS@
|
||||
endif
|
||||
|
||||
if HAVE_NAS
|
||||
pkglib_LTLIBRARIES += output_nas.la
|
||||
output_nas_la_SOURCES = nas.c
|
||||
output_nas_la_LDFLAGS = -module -no-undefined -avoid-version -export-dynamic -export-symbols-regex '^mpg123_' @NAS_LDFLAGS@
|
||||
output_nas_la_CFLAGS = @NAS_CFLAGS@
|
||||
output_nas_la_LIBADD = @NAS_LIBS@
|
||||
endif
|
||||
|
||||
if HAVE_OSS
|
||||
pkglib_LTLIBRARIES += output_oss.la
|
||||
output_oss_la_SOURCES = oss.c
|
||||
output_oss_la_LDFLAGS = -module -no-undefined -avoid-version -export-dynamic -export-symbols-regex '^mpg123_' @OSS_LDFLAGS@
|
||||
output_oss_la_CFLAGS = @OSS_CFLAGS@
|
||||
output_oss_la_LIBADD = @OSS_LIBS@
|
||||
endif
|
||||
|
||||
if HAVE_PORTAUDIO
|
||||
pkglib_LTLIBRARIES += output_portaudio.la
|
||||
output_portaudio_la_SOURCES = portaudio.c
|
||||
output_portaudio_la_LDFLAGS = -module -no-undefined -avoid-version -export-dynamic -export-symbols-regex '^mpg123_' @PORTAUDIO_LDFLAGS@
|
||||
output_portaudio_la_CFLAGS = @PORTAUDIO_CFLAGS@
|
||||
output_portaudio_la_LIBADD = @PORTAUDIO_LIBS@
|
||||
endif
|
||||
|
||||
if HAVE_PULSE
|
||||
pkglib_LTLIBRARIES += output_pulse.la
|
||||
output_pulse_la_SOURCES = pulse.c
|
||||
output_pulse_la_LDFLAGS = -module -no-undefined -avoid-version -export-dynamic -export-symbols-regex '^mpg123_' @PULSE_LDFLAGS@
|
||||
output_pulse_la_CFLAGS = @PULSE_CFLAGS@
|
||||
output_pulse_la_LIBADD = @PULSE_LIBS@
|
||||
endif
|
||||
|
||||
if HAVE_SDL
|
||||
pkglib_LTLIBRARIES += output_sdl.la
|
||||
output_sdl_la_SOURCES = sdl.c
|
||||
output_sdl_la_LDFLAGS = -module -no-undefined -avoid-version -export-dynamic -export-symbols-regex '^mpg123_' @SDL_LDFLAGS@
|
||||
output_sdl_la_CFLAGS = @SDL_CFLAGS@
|
||||
output_sdl_la_LIBADD = @SDL_LIBS@
|
||||
endif
|
||||
|
||||
if HAVE_SNDIO
|
||||
pkglib_LTLIBRARIES += output_sndio.la
|
||||
output_sndio_la_SOURCES = sndio.c
|
||||
output_sndio_la_LDFLAGS = -module -no-undefined -avoid-version -export-dynamic -export-symbols-regex '^mpg123_' @SNDIO_LDFLAGS@
|
||||
output_sndio_la_CFLAGS = @SNDIO_CFLAGS@
|
||||
output_sndio_la_LIBADD = @SNDIO_LIBS@
|
||||
endif
|
||||
|
||||
if HAVE_SUN
|
||||
pkglib_LTLIBRARIES += output_sun.la
|
||||
output_sun_la_SOURCES = sun.c
|
||||
output_sun_la_LDFLAGS = -module -no-undefined -avoid-version -export-dynamic -export-symbols-regex '^mpg123_' @SUN_LDFLAGS@
|
||||
output_sun_la_CFLAGS = @SUN_CFLAGS@
|
||||
output_sun_la_LIBADD = @SUN_LIBS@
|
||||
endif
|
||||
|
||||
if HAVE_WIN32
|
||||
pkglib_LTLIBRARIES += output_win32.la
|
||||
output_win32_la_SOURCES = win32.c
|
||||
output_win32_la_LDFLAGS = -module -no-undefined -avoid-version -export-dynamic -export-symbols-regex '^mpg123_' @WIN32_LDFLAGS@
|
||||
output_win32_la_CFLAGS = @WIN32_CFLAGS@
|
||||
output_win32_la_LIBADD = @WIN32_LIBS@
|
||||
endif
|
||||
|
||||
if HAVE_AIX
|
||||
pkglib_LTLIBRARIES += output_aix.la
|
||||
output_aix_la_SOURCES = aix.c
|
||||
output_aix_la_LDFLAGS = -module -no-undefined -avoid-version -export-dynamic -export-symbols-regex '^mpg123_' @AIX_LDFLAGS@
|
||||
output_aix_la_CFLAGS = @AIX_CFLAGS@
|
||||
output_aix_la_LIBADD = @AIX_LIBS@
|
||||
endif
|
||||
|
||||
if HAVE_ALIB
|
||||
pkglib_LTLIBRARIES += output_alib.la
|
||||
output_alib_la_SOURCES = alib.c
|
||||
output_alib_la_LDFLAGS = -module -no-undefined -avoid-version -export-dynamic -export-symbols-regex '^mpg123_' @ALIB_LDFLAGS@
|
||||
output_alib_la_CFLAGS = @ALIB_CFLAGS@
|
||||
output_alib_la_LIBADD = @ALIB_LIBS@
|
||||
endif
|
||||
|
||||
if HAVE_ARTS
|
||||
pkglib_LTLIBRARIES += output_arts.la
|
||||
output_arts_la_SOURCES = arts.c
|
||||
output_arts_la_LDFLAGS = -module -no-undefined -avoid-version -export-dynamic -export-symbols-regex '^mpg123_' @ARTS_LDFLAGS@
|
||||
output_arts_la_CFLAGS = @ARTS_CFLAGS@
|
||||
output_arts_la_LIBADD = @ARTS_LIBS@
|
||||
endif
|
||||
|
||||
if HAVE_HP
|
||||
pkglib_LTLIBRARIES += output_hp.la
|
||||
output_hp_la_SOURCES = hp.c
|
||||
output_hp_la_LDFLAGS = -module -no-undefined -avoid-version -export-dynamic -export-symbols-regex '^mpg123_' @HP_LDFLAGS@
|
||||
output_hp_la_CFLAGS = @HP_CFLAGS@
|
||||
output_hp_la_LIBADD = @HP_LIBS@
|
||||
endif
|
||||
|
||||
if HAVE_OS2
|
||||
pkglib_LTLIBRARIES += output_os2.la
|
||||
output_os2_la_SOURCES = os2.c
|
||||
output_os2_la_LDFLAGS = -module -no-undefined -avoid-version -export-dynamic -export-symbols-regex '^mpg123_' @OS2_LDFLAGS@
|
||||
output_os2_la_CFLAGS = @OS2_CFLAGS@
|
||||
output_os2_la_LIBADD = @OS2_LIBS@
|
||||
endif
|
||||
|
||||
if HAVE_SGI
|
||||
pkglib_LTLIBRARIES += output_sgi.la
|
||||
output_sgi_la_SOURCES = sgi.c
|
||||
output_sgi_la_LDFLAGS = -module -no-undefined -avoid-version -export-dynamic -export-symbols-regex '^mpg123_' @SGI_LDFLAGS@
|
||||
output_sgi_la_CFLAGS = @SGI_CFLAGS@
|
||||
output_sgi_la_LIBADD = @SGI_LIBS@
|
||||
endif
|
||||
|
||||
if HAVE_MINT
|
||||
pkglib_LTLIBRARIES += output_mint.la
|
||||
output_mint_la_SOURCES = mint.c
|
||||
output_mint_la_LDFLAGS = -module -no-undefined -avoid-version -export-dynamic -export-symbols-regex '^mpg123_' @MINT_LDFLAGS@
|
||||
output_mint_la_CFLAGS = @MINT_CFLAGS@
|
||||
output_mint_la_LIBADD = @MINT_LIBS@
|
||||
endif
|
||||
|
||||
if HAVE_OPENAL
|
||||
pkglib_LTLIBRARIES += output_openal.la
|
||||
output_openal_la_SOURCES = openal.c
|
||||
output_openal_la_LDFLAGS = -module -no-undefined -avoid-version -export-dynamic -export-symbols-regex '^mpg123_' @OPENAL_LDFLAGS@
|
||||
output_openal_la_CFLAGS = @OPENAL_CFLAGS@
|
||||
output_openal_la_LIBADD = @OPENAL_LIBS@
|
||||
endif
|
||||
|
||||
if HAVE_DUMMY
|
||||
pkglib_LTLIBRARIES += output_dummy.la
|
||||
output_dummy_la_SOURCES = dummy.c
|
||||
output_dummy_la_LDFLAGS = -module -no-undefined -avoid-version -export-dynamic -export-symbols-regex '^mpg123_' @DUMMY_LDFLAGS@
|
||||
output_dummy_la_CFLAGS = @DUMMY_CFLAGS@
|
||||
output_dummy_la_LIBADD = @DUMMY_LIBS@
|
||||
endif
|
||||
|
||||
else
|
||||
|
||||
# Static build of one module only.
|
||||
|
||||
AM_CFLAGS=@OUTPUT_CFLAGS@
|
||||
|
||||
all: @OUTPUT_MOD@.$(OBJEXT)
|
||||
|
||||
# No installation happening from here
|
||||
install: all
|
||||
|
||||
|
||||
endif
|
1238
node_modules/lame/deps/mpg123/src/output/Makefile.in
generated
vendored
Normal file
1238
node_modules/lame/deps/mpg123/src/output/Makefile.in
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
300
node_modules/lame/deps/mpg123/src/output/aix.c
generated
vendored
Normal file
300
node_modules/lame/deps/mpg123/src/output/aix.c
generated
vendored
Normal file
@ -0,0 +1,300 @@
|
||||
/*
|
||||
aix: Driver for IBM RS/6000 with AIX Ultimedia Services
|
||||
|
||||
copyright ?-2006 by the mpg123 project - free software under the terms of the LGPL 2.1
|
||||
see COPYING and AUTHORS files in distribution or http://mpg123.org
|
||||
initially written by Juergen Schoew and Tomas Oegren
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/audio.h>
|
||||
#include <stropts.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "mpg123app.h"
|
||||
#include "debug.h"
|
||||
|
||||
/* use AUDIO_BSIZE to set the msec for audio buffering in Ultimedia library
|
||||
*/
|
||||
/* #define AUDIO_BSIZE AUDIO_IGNORE */
|
||||
#define AUDIO_BSIZE 200
|
||||
|
||||
static int rate_best_match(audio_output_t *ao)
|
||||
{
|
||||
static long valid [ ] = { 5510, 6620, 8000, 9600, 11025, 16000, 18900,
|
||||
22050, 27420, 32000, 33075, 37800, 44100, 48000, 0 };
|
||||
int i = 0;
|
||||
long best = 8000;
|
||||
|
||||
if(!ai || ao->fn < 0 || ao->rate < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (valid [i]) {
|
||||
if (abs(valid[i] - ao->rate) < abs(best - ao->rate))
|
||||
{
|
||||
best = valid [i];
|
||||
}
|
||||
i = i + 1;
|
||||
}
|
||||
|
||||
ao->rate = best;
|
||||
return best;
|
||||
}
|
||||
|
||||
static int reset_parameters(audio_output_t *ao)
|
||||
{
|
||||
audio_control acontrol;
|
||||
audio_change achange;
|
||||
audio_init ainit;
|
||||
int ret;
|
||||
|
||||
memset ( & achange, '\0', sizeof (achange));
|
||||
memset ( & acontrol, '\0', sizeof (acontrol));
|
||||
|
||||
achange.balance = 0x3fff0000;
|
||||
achange.balance_delay = 0;
|
||||
achange.volume = (long) (0x7fff << 16);
|
||||
achange.volume_delay = 0;
|
||||
achange.input = AUDIO_IGNORE;
|
||||
if (ao->flags == -1) achange.output = INTERNAL_SPEAKER;
|
||||
else achange.output = 0;
|
||||
|
||||
if(ao->flags & AUDIO_OUT_INTERNAL_SPEAKER)
|
||||
achange.output |= INTERNAL_SPEAKER;
|
||||
if(ao->flags & AUDIO_OUT_HEADPHONES)
|
||||
achange.output |= EXTERNAL_SPEAKER;
|
||||
if(ao->flags & AUDIO_OUT_LINE_OUT)
|
||||
achange.output |= OUTPUT_1;
|
||||
if(ao->flags == 0)
|
||||
achange.output = AUDIO_IGNORE;
|
||||
|
||||
achange.treble = AUDIO_IGNORE;
|
||||
achange.bass = AUDIO_IGNORE;
|
||||
achange.pitch = AUDIO_IGNORE;
|
||||
achange.monitor = AUDIO_IGNORE;
|
||||
achange.dev_info = (char *) NULL;
|
||||
|
||||
acontrol.ioctl_request = AUDIO_CHANGE;
|
||||
acontrol.position = 0;
|
||||
acontrol.request_info = (char *) & achange;
|
||||
|
||||
ret = ioctl (ao->fn, AUDIO_CONTROL, & acontrol);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Init Device for new values */
|
||||
if (ao->rate >0) {
|
||||
memset ( & ainit, '\0', sizeof (ainit));
|
||||
ainit.srate = rate_best_match(ai);
|
||||
if (ao->channels > 0)
|
||||
ainit.channels = ao->channels;
|
||||
else
|
||||
ainit.channels = 1;
|
||||
switch (ao->format) {
|
||||
default :
|
||||
ainit.mode = PCM;
|
||||
ainit.bits_per_sample = 8;
|
||||
ainit.flags = BIG_ENDIAN | TWOS_COMPLEMENT;
|
||||
break;
|
||||
case MPG123_ENC_SIGNED_16:
|
||||
ainit.mode = PCM;
|
||||
ainit.bits_per_sample = 16;
|
||||
ainit.flags = BIG_ENDIAN | TWOS_COMPLEMENT;
|
||||
break;
|
||||
case MPG123_ENC_SIGNED_8:
|
||||
ainit.mode = PCM;
|
||||
ainit.bits_per_sample = 8;
|
||||
ainit.flags = BIG_ENDIAN | TWOS_COMPLEMENT;
|
||||
break;
|
||||
case MPG123_ENC_UNSIGNED_16:
|
||||
ainit.mode = PCM;
|
||||
ainit.bits_per_sample = 16;
|
||||
ainit.flags = BIG_ENDIAN | TWOS_COMPLEMENT | SIGNED;
|
||||
break;
|
||||
case MPG123_ENC_UNSIGNED_8:
|
||||
ainit.mode = PCM;
|
||||
ainit.bits_per_sample = 8;
|
||||
ainit.flags = BIG_ENDIAN | TWOS_COMPLEMENT | SIGNED;
|
||||
break;
|
||||
case MPG123_ENC_ULAW_8:
|
||||
ainit.mode = MU_LAW;
|
||||
ainit.bits_per_sample = 8;
|
||||
ainit.flags = BIG_ENDIAN | TWOS_COMPLEMENT;
|
||||
break;
|
||||
case MPG123_ENC_ALAW_8:
|
||||
ainit.mode = A_LAW;
|
||||
ainit.bits_per_sample = 8;
|
||||
ainit.flags = BIG_ENDIAN | TWOS_COMPLEMENT;
|
||||
break;
|
||||
}
|
||||
ainit.operation = PLAY;
|
||||
ainit.bsize = AUDIO_BSIZE;
|
||||
|
||||
ret = ioctl (ao->fn, AUDIO_INIT, & ainit);
|
||||
if (ret < 0) {
|
||||
error("Can't set new audio parameters!");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
acontrol.ioctl_request = AUDIO_START;
|
||||
acontrol.request_info = NULL;
|
||||
acontrol.position = 0;
|
||||
|
||||
ret = ioctl (ao->fn, AUDIO_CONTROL, & acontrol);
|
||||
if (ret < 0) {
|
||||
error("Can't reset audio!");
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int open_aix(audio_output_t *ao)
|
||||
{
|
||||
audio_init ainit;
|
||||
int ret;
|
||||
|
||||
if(!ao->device) {
|
||||
if(getenv("AUDIODEV")) {
|
||||
ao->device = getenv("AUDIODEV");
|
||||
ao->fn = open(ao->device,O_WRONLY);
|
||||
} else {
|
||||
ao->device = "/dev/paud0/1"; /* paud0 for PCI */
|
||||
ao->fn = open(ao->device,O_WRONLY);
|
||||
if ((ao->fn == -1) & (errno == ENOENT)) {
|
||||
ao->device = "/dev/baud0/1"; /* baud0 for MCA */
|
||||
ao->fn = open(ao->device,O_WRONLY);
|
||||
}
|
||||
}
|
||||
} else ao->fn = open(ao->device,O_WRONLY);
|
||||
|
||||
if(ao->fn < 0) {
|
||||
error("Can't open audio device!");
|
||||
return ao->fn;
|
||||
}
|
||||
|
||||
/* Init to default values */
|
||||
memset ( & ainit, '\0', sizeof (ainit));
|
||||
ainit.srate = 44100;
|
||||
ainit.channels = 2;
|
||||
ainit.mode = PCM;
|
||||
ainit.bits_per_sample = 16;
|
||||
ainit.flags = BIG_ENDIAN | TWOS_COMPLEMENT;
|
||||
ainit.operation = PLAY;
|
||||
ainit.bsize = AUDIO_BSIZE;
|
||||
|
||||
ret = ioctl (ao->fn, AUDIO_INIT, & ainit);
|
||||
if (ret < 0) return ret;
|
||||
|
||||
reset_parameters(ai);
|
||||
return ao->fn;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int get_formats_aix(audio_output_t *ao)
|
||||
{
|
||||
/* ULTIMEDIA DOCUMENTATION SAYS:
|
||||
The Ultimedia Audio Adapter supports fourteen sample rates you can use to
|
||||
capture and playback audio data. The rates are (in kHz): 5.51, 6.62, 8.0,
|
||||
9.6, 11.025, 16.0, 18.9, 22.050, 27.42, 32.0, 33.075, 37.8, 44.1, and 48.0.
|
||||
These rates are supported for mono and stereo PCM (8- and 16-bit), mu-law,
|
||||
and A-law.
|
||||
*/
|
||||
|
||||
long rate;
|
||||
|
||||
rate = ao->rate;
|
||||
rate_best_match(ai);
|
||||
if (ao->rate == rate)
|
||||
return (MPG123_ENC_SIGNED_16|MPG123_ENC_UNSIGNED_16|
|
||||
MPG123_ENC_UNSIGNED_8|MPG123_ENC_SIGNED_8|
|
||||
MPG123_ENC_ULAW_8|MPG123_ENC_ALAW_8);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int write_aix(audio_output_t *ao,unsigned char *buf,int len)
|
||||
{
|
||||
return write(ao->fn,buf,len);
|
||||
}
|
||||
|
||||
static int close_aix(audio_output_t *ao)
|
||||
{
|
||||
audio_control acontrol;
|
||||
audio_buffer abuffer;
|
||||
int ret,i;
|
||||
|
||||
/* Don't close the audio-device until it's played all its contents */
|
||||
memset ( & acontrol, '\0', sizeof ( acontrol ) );
|
||||
acontrol.request_info = &abuffer;
|
||||
acontrol.position = 0;
|
||||
i=50; /* Don't do this forever on a bad day :-) */
|
||||
|
||||
while (i-- > 0) {
|
||||
if ((ioctl(ao->fn, AUDIO_BUFFER, &acontrol))< 0) {
|
||||
error1("buffer read failed: %d", errno);
|
||||
break;
|
||||
} else {
|
||||
if (abuffer.flags <= 0) break;
|
||||
}
|
||||
usleep(200000); /* sleep 0.2 sec */
|
||||
}
|
||||
|
||||
memset ( & acontrol, '\0', sizeof ( acontrol ) );
|
||||
acontrol.ioctl_request = AUDIO_STOP;
|
||||
acontrol.request_info = NULL;
|
||||
acontrol.position = 0;
|
||||
|
||||
ret = ioctl ( ao->fn, AUDIO_CONTROL, & acontrol );
|
||||
if (ret < 0) error("Can't close audio!");
|
||||
|
||||
ret = close (ao->fn);
|
||||
if (ret < 0) error("Can't close audio!");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void flush_aix(audio_output_t *ao)
|
||||
{
|
||||
}
|
||||
|
||||
static int init_aix(audio_output_t* ao)
|
||||
{
|
||||
if (ao==NULL) return -1;
|
||||
|
||||
/* Set callbacks */
|
||||
ao->open = open_aix;
|
||||
ao->flush = flush_aix;
|
||||
ao->write = write_aix;
|
||||
ao->get_formats = get_formats_aix;
|
||||
ao->close = close_aix;
|
||||
|
||||
/* Success */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Module information data structure
|
||||
*/
|
||||
mpg123_module_t mpg123_output_module_info = {
|
||||
/* api_version */ MPG123_MODULE_API_VERSION,
|
||||
/* name */ "AIX",
|
||||
/* description */ "Output audio on IBM RS/6000 with AIX Ultimedia Services.",
|
||||
/* revision */ "$Rev: 932 $",
|
||||
/* handle */ NULL,
|
||||
|
||||
/* init_output */ init_aix,
|
||||
};
|
||||
|
209
node_modules/lame/deps/mpg123/src/output/alib.c
generated
vendored
Normal file
209
node_modules/lame/deps/mpg123/src/output/alib.c
generated
vendored
Normal file
@ -0,0 +1,209 @@
|
||||
/*
|
||||
alib: audio output for HP-UX using alib
|
||||
|
||||
copyright ?-2006 by the mpg123 project - free software under the terms of the LGPL 2.1
|
||||
see COPYING and AUTHORS files in distribution or http://mpg123.org
|
||||
initially written by Erwan Ducroquet
|
||||
based on source code from HP (Audio SDK)
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
* for mpg123 :
|
||||
* hpux:
|
||||
* $(MAKE) \
|
||||
* CC=cc \
|
||||
* LDFLAGS=-L/opt/audio/lib \
|
||||
* AUDIO_LIB=-lAlib \
|
||||
* OBJECTS=decode.o dct64.o \
|
||||
* CFLAGS=-Ae +O3 -DREAL_IS_FLOAT -D_HPUX_SOURCE -DHPUX -I/opt/audio/include \
|
||||
* mpg123
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* For the user :
|
||||
* If you launch mpg123 on a XTerm with sound capabilities, it's OK
|
||||
* Else, you have to set the environment variable "AUDIO" to the name of
|
||||
* an HP Xterm with sound card.
|
||||
*/
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
#include "mpg123app.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
#include <Alib.h> /* /opt/audio/include */
|
||||
#include <CUlib.h> /* /opt/audio/include */
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/* FIXME: These globals should be moved into a structure */
|
||||
static Audio *audioServer = (Audio *) NULL;
|
||||
static struct protoent *tcpProtocolEntry;
|
||||
static ATransID xid;
|
||||
|
||||
static void printAudioError(Audio *audio,char *message,int errorCode) {
|
||||
char errorbuff[132];
|
||||
AGetErrorText(audio, errorCode, errorbuff, 131);
|
||||
error2("%s: %s", message, errorbuff);
|
||||
}
|
||||
static long myHandler(Audio *audio,AErrorEvent *err_event) {
|
||||
printAudioError( audio, "Audio error", err_event->error_code );
|
||||
/* we cannot just do random exists, that messes terminal up
|
||||
need proper error propagation in that case for future, setting intflag or such */
|
||||
/* exit(1); */
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
/*
|
||||
* Set the fn element of ai
|
||||
* Use ao->rate and ao->channels
|
||||
* Doesn't set any volume
|
||||
*/
|
||||
|
||||
/* return on error leaves stuff dirty here... */
|
||||
static int open_alib(audio_output_t *ao)
|
||||
{
|
||||
AudioAttributes Attribs;
|
||||
AudioAttrMask AttribsMask;
|
||||
AGainEntry gainEntry[4];
|
||||
SSPlayParams playParams;
|
||||
SStream audioStream;
|
||||
AErrorHandler prevHandler;
|
||||
char server[1];
|
||||
int i;
|
||||
long status;
|
||||
|
||||
if (audioServer) {
|
||||
error("openAudio: audio already open");
|
||||
return -1;
|
||||
}
|
||||
|
||||
prevHandler = ASetErrorHandler(myHandler);
|
||||
|
||||
server[0] = '\0';
|
||||
audioServer = AOpenAudio( server, NULL );
|
||||
if (audioServer==NULL) {
|
||||
error("Error: could not open audio\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ao->fn = socket( AF_INET, SOCK_STREAM, 0 );
|
||||
if(ao->fn<0) {
|
||||
error("Socket creation failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
Attribs.type = ATSampled;
|
||||
Attribs.attr.sampled_attr.sampling_rate = ao->rate;
|
||||
Attribs.attr.sampled_attr.channels = ao->channels;
|
||||
Attribs.attr.sampled_attr.data_format = ADFLin16;
|
||||
AttribsMask = ASSamplingRateMask | ASChannelsMask | ASDataFormatMask;
|
||||
|
||||
gainEntry[0].gain = AUnityGain;
|
||||
gainEntry[0].u.o.out_ch = AOCTMono;
|
||||
gainEntry[0].u.o.out_dst = AODTDefaultOutput;
|
||||
|
||||
playParams.gain_matrix.type = AGMTOutput; /* gain matrix */
|
||||
playParams.gain_matrix.num_entries = 1;
|
||||
playParams.gain_matrix.gain_entries = gainEntry;
|
||||
playParams.play_volume = AUnityGain; /* play volume */
|
||||
playParams.priority = APriorityNormal; /* normal priority */
|
||||
playParams.event_mask = 0; /* don't solicit any events */
|
||||
|
||||
xid=APlaySStream(audioServer,AttribsMask,&Attribs,
|
||||
&playParams,&audioStream,NULL);
|
||||
|
||||
status=connect(ao->fn,
|
||||
(struct sockaddr *) &audioStream.tcp_sockaddr,
|
||||
sizeof(struct sockaddr_in) );
|
||||
if (status<0) {
|
||||
error("Connect failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
i=-1;
|
||||
tcpProtocolEntry=getprotobyname("tcp");
|
||||
setsockopt(ao->fn,tcpProtocolEntry->p_proto,TCP_NODELAY,&i,sizeof(i));
|
||||
|
||||
return ao->fn;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
static int close_alib(audio_output_t *ao)
|
||||
{
|
||||
close(ao->fn);
|
||||
ASetCloseDownMode( audioServer, AKeepTransactions, NULL );
|
||||
ACloseAudio( audioServer, NULL );
|
||||
audioServer = (Audio *) NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
/*
|
||||
* very simple
|
||||
* deserv to be inline
|
||||
*/
|
||||
|
||||
static int write_alib(audio_output_t *ao,unsigned char *buf,int len)
|
||||
{
|
||||
return write(ao->fn,buf,len*2);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
static int get_formats_alib(audio_output_t *ao)
|
||||
{
|
||||
return MPG123_ENC_SIGNED_16;
|
||||
}
|
||||
|
||||
static void flush_alib(audio_output_t *ao)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
static int init_alib(audio_output_t* ao)
|
||||
{
|
||||
if (ao==NULL) return -1;
|
||||
|
||||
/* Set callbacks */
|
||||
ao->open = open_alib;
|
||||
ao->flush = flush_alib;
|
||||
ao->write = write_alib;
|
||||
ao->get_formats = get_formats_alib;
|
||||
ao->close = close_alib;
|
||||
|
||||
/* Success */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Module information data structure
|
||||
*/
|
||||
mpg123_module_t mpg123_output_module_info = {
|
||||
/* api_version */ MPG123_MODULE_API_VERSION,
|
||||
/* name */ "alib",
|
||||
/* description */ "Output audio HP-UX using alib.",
|
||||
/* revision */ "$Rev:$",
|
||||
/* handle */ NULL,
|
||||
|
||||
/* init_output */ init_alib,
|
||||
};
|
||||
|
297
node_modules/lame/deps/mpg123/src/output/alsa.c
generated
vendored
Normal file
297
node_modules/lame/deps/mpg123/src/output/alsa.c
generated
vendored
Normal file
@ -0,0 +1,297 @@
|
||||
/*
|
||||
alsa: sound output with Advanced Linux Sound Architecture 1.x API
|
||||
|
||||
copyright 2006-8 by the mpg123 project - free software under the terms of the LGPL 2.1
|
||||
see COPYING and AUTHORS files in distribution or http://mpg123.org
|
||||
|
||||
initially written by Clemens Ladisch <clemens@ladisch.de>
|
||||
*/
|
||||
|
||||
#include "mpg123app.h"
|
||||
#include "audio.h"
|
||||
#include "module.h"
|
||||
#include <errno.h>
|
||||
|
||||
/* make ALSA 0.9.x compatible to the 1.0.x API */
|
||||
#define ALSA_PCM_NEW_HW_PARAMS_API
|
||||
#define ALSA_PCM_NEW_SW_PARAMS_API
|
||||
|
||||
#include <alsa/asoundlib.h>
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
/* My laptop has probs playing low-sampled files with only 0.5s buffer... this should be a user setting -- ThOr */
|
||||
#define BUFFER_LENGTH 0.5 /* in seconds */
|
||||
|
||||
static const struct {
|
||||
snd_pcm_format_t alsa;
|
||||
int mpg123;
|
||||
} format_map[] = {
|
||||
{ SND_PCM_FORMAT_S16, MPG123_ENC_SIGNED_16 },
|
||||
{ SND_PCM_FORMAT_U16, MPG123_ENC_UNSIGNED_16 },
|
||||
{ SND_PCM_FORMAT_U8, MPG123_ENC_UNSIGNED_8 },
|
||||
{ SND_PCM_FORMAT_S8, MPG123_ENC_SIGNED_8 },
|
||||
{ SND_PCM_FORMAT_A_LAW, MPG123_ENC_ALAW_8 },
|
||||
{ SND_PCM_FORMAT_MU_LAW, MPG123_ENC_ULAW_8 },
|
||||
{ SND_PCM_FORMAT_S32, MPG123_ENC_SIGNED_32 },
|
||||
{ SND_PCM_FORMAT_U32, MPG123_ENC_UNSIGNED_32 },
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
{ SND_PCM_FORMAT_S24_3BE, MPG123_ENC_SIGNED_24 },
|
||||
{ SND_PCM_FORMAT_U24_3BE, MPG123_ENC_UNSIGNED_24 },
|
||||
#else
|
||||
{ SND_PCM_FORMAT_S24_3LE, MPG123_ENC_SIGNED_24 },
|
||||
{ SND_PCM_FORMAT_U24_3LE, MPG123_ENC_UNSIGNED_24 },
|
||||
#endif
|
||||
{ SND_PCM_FORMAT_FLOAT, MPG123_ENC_FLOAT_32 },
|
||||
{ SND_PCM_FORMAT_FLOAT64, MPG123_ENC_FLOAT_64 }
|
||||
};
|
||||
#define NUM_FORMATS (sizeof format_map / sizeof format_map[0])
|
||||
|
||||
|
||||
static int rates_match(long int desired, unsigned int actual)
|
||||
{
|
||||
return actual * 100 > desired * (100 - AUDIO_RATE_TOLERANCE) &&
|
||||
actual * 100 < desired * (100 + AUDIO_RATE_TOLERANCE);
|
||||
}
|
||||
|
||||
static int initialize_device(audio_output_t *ao)
|
||||
{
|
||||
snd_pcm_hw_params_t *hw=NULL;
|
||||
snd_pcm_sw_params_t *sw=NULL;
|
||||
snd_pcm_uframes_t buffer_size;
|
||||
snd_pcm_uframes_t period_size;
|
||||
snd_pcm_format_t format;
|
||||
snd_pcm_t *pcm=(snd_pcm_t*)ao->userptr;
|
||||
unsigned int rate;
|
||||
int i;
|
||||
|
||||
snd_pcm_hw_params_alloca(&hw); /* Ignore GCC warning here... alsa-lib>=1.0.16 doesn't trigger that anymore, too. */
|
||||
if (snd_pcm_hw_params_any(pcm, hw) < 0) {
|
||||
if(!AOQUIET) error("initialize_device(): no configuration available");
|
||||
return -1;
|
||||
}
|
||||
if (snd_pcm_hw_params_set_access(pcm, hw, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) {
|
||||
if(!AOQUIET) error("initialize_device(): device does not support interleaved access");
|
||||
return -1;
|
||||
}
|
||||
format = SND_PCM_FORMAT_UNKNOWN;
|
||||
for (i = 0; i < NUM_FORMATS; ++i) {
|
||||
if (ao->format == format_map[i].mpg123) {
|
||||
format = format_map[i].alsa;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (format == SND_PCM_FORMAT_UNKNOWN) {
|
||||
if(!AOQUIET) error1("initialize_device(): invalid sample format %d", ao->format);
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (snd_pcm_hw_params_set_format(pcm, hw, format) < 0) {
|
||||
if(!AOQUIET) error1("initialize_device(): cannot set format %s", snd_pcm_format_name(format));
|
||||
return -1;
|
||||
}
|
||||
if (snd_pcm_hw_params_set_channels(pcm, hw, ao->channels) < 0) {
|
||||
if(!AOQUIET) error1("initialize_device(): cannot set %d channels", ao->channels);
|
||||
return -1;
|
||||
}
|
||||
rate = ao->rate;
|
||||
if (snd_pcm_hw_params_set_rate_near(pcm, hw, &rate, NULL) < 0) {
|
||||
if(!AOQUIET) error1("initialize_device(): cannot set rate %u", rate);
|
||||
return -1;
|
||||
}
|
||||
if (!rates_match(ao->rate, rate)) {
|
||||
if(!AOQUIET) error2("initialize_device(): rate %ld not available, using %u", ao->rate, rate);
|
||||
/* return -1; */
|
||||
}
|
||||
buffer_size = rate * BUFFER_LENGTH;
|
||||
if (snd_pcm_hw_params_set_buffer_size_near(pcm, hw, &buffer_size) < 0) {
|
||||
if(!AOQUIET) error("initialize_device(): cannot set buffer size");
|
||||
return -1;
|
||||
}
|
||||
period_size = buffer_size / 4;
|
||||
if (snd_pcm_hw_params_set_period_size_near(pcm, hw, &period_size, NULL) < 0) {
|
||||
if(!AOQUIET) error("initialize_device(): cannot set period size");
|
||||
return -1;
|
||||
}
|
||||
if (snd_pcm_hw_params(pcm, hw) < 0) {
|
||||
if(!AOQUIET) error("initialize_device(): cannot set hw params");
|
||||
return -1;
|
||||
}
|
||||
|
||||
snd_pcm_sw_params_alloca(&sw);
|
||||
if (snd_pcm_sw_params_current(pcm, sw) < 0) {
|
||||
if(!AOQUIET) error("initialize_device(): cannot get sw params");
|
||||
return -1;
|
||||
}
|
||||
/* start playing after the first write */
|
||||
if (snd_pcm_sw_params_set_start_threshold(pcm, sw, 1) < 0) {
|
||||
if(!AOQUIET) error("initialize_device(): cannot set start threshold");
|
||||
return -1;
|
||||
}
|
||||
/* wake up on every interrupt */
|
||||
if (snd_pcm_sw_params_set_avail_min(pcm, sw, 1) < 0) {
|
||||
if(!AOQUIET) error("initialize_device(): cannot set min available");
|
||||
return -1;
|
||||
}
|
||||
#if SND_LIB_VERSION < ((1<<16)|16)
|
||||
/* Always write as many frames as possible (deprecated since alsa-lib 1.0.16) */
|
||||
if (snd_pcm_sw_params_set_xfer_align(pcm, sw, 1) < 0) {
|
||||
if(!AOQUIET) error("initialize_device(): cannot set transfer alignment");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
if (snd_pcm_sw_params(pcm, sw) < 0) {
|
||||
if(!AOQUIET) error("initialize_device(): cannot set sw params");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void error_ignorer(const char *file, int line, const char *function, int err, const char *fmt,...)
|
||||
{
|
||||
/* I can make ALSA silent. */
|
||||
}
|
||||
|
||||
static int open_alsa(audio_output_t *ao)
|
||||
{
|
||||
const char *pcm_name;
|
||||
snd_pcm_t *pcm=NULL;
|
||||
debug1("open_alsa with %p", ao->userptr);
|
||||
|
||||
if(AOQUIET) snd_lib_error_set_handler(error_ignorer);
|
||||
|
||||
pcm_name = ao->device ? ao->device : "default";
|
||||
if (snd_pcm_open(&pcm, pcm_name, SND_PCM_STREAM_PLAYBACK, 0) < 0) {
|
||||
if(!AOQUIET) error1("cannot open device %s", pcm_name);
|
||||
return -1;
|
||||
}
|
||||
ao->userptr = pcm;
|
||||
if (ao->format != -1) {
|
||||
/* we're going to play: initalize sample format */
|
||||
return initialize_device(ao);
|
||||
} else {
|
||||
/* query mode; sample format will be set for each query */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int get_formats_alsa(audio_output_t *ao)
|
||||
{
|
||||
snd_pcm_t *pcm=(snd_pcm_t*)ao->userptr;
|
||||
snd_pcm_hw_params_t *hw;
|
||||
unsigned int rate;
|
||||
int supported_formats, i;
|
||||
|
||||
snd_pcm_hw_params_alloca(&hw);
|
||||
if (snd_pcm_hw_params_any(pcm, hw) < 0) {
|
||||
if(!AOQUIET) error("get_formats_alsa(): no configuration available");
|
||||
return -1;
|
||||
}
|
||||
if (snd_pcm_hw_params_set_access(pcm, hw, SND_PCM_ACCESS_RW_INTERLEAVED) < 0)
|
||||
return -1;
|
||||
if (snd_pcm_hw_params_set_channels(pcm, hw, ao->channels) < 0)
|
||||
return 0;
|
||||
rate = ao->rate;
|
||||
if (snd_pcm_hw_params_set_rate_near(pcm, hw, &rate, NULL) < 0)
|
||||
return -1;
|
||||
if (!rates_match(ao->rate, rate))
|
||||
return 0;
|
||||
supported_formats = 0;
|
||||
for (i = 0; i < NUM_FORMATS; ++i) {
|
||||
if (snd_pcm_hw_params_test_format(pcm, hw, format_map[i].alsa) == 0)
|
||||
supported_formats |= format_map[i].mpg123;
|
||||
}
|
||||
return supported_formats;
|
||||
}
|
||||
|
||||
static int write_alsa(audio_output_t *ao, unsigned char *buf, int bytes)
|
||||
{
|
||||
snd_pcm_t *pcm=(snd_pcm_t*)ao->userptr;
|
||||
snd_pcm_uframes_t frames;
|
||||
snd_pcm_sframes_t written;
|
||||
|
||||
frames = snd_pcm_bytes_to_frames(pcm, bytes);
|
||||
written = snd_pcm_writei(pcm, buf, frames);
|
||||
if (written == -EINTR) /* interrupted system call */
|
||||
written = 0;
|
||||
else if (written == -EPIPE) { /* underrun */
|
||||
if (snd_pcm_prepare(pcm) >= 0)
|
||||
written = snd_pcm_writei(pcm, buf, frames);
|
||||
}
|
||||
if (written >= 0)
|
||||
return snd_pcm_frames_to_bytes(pcm, written);
|
||||
else
|
||||
{
|
||||
if(snd_pcm_state(pcm) == SND_PCM_STATE_SUSPENDED)
|
||||
{
|
||||
/* Iamnothappyabouthisnothappyreallynot. */
|
||||
snd_pcm_resume(pcm);
|
||||
if(snd_pcm_state(pcm) == SND_PCM_STATE_SUSPENDED)
|
||||
{
|
||||
error("device still suspended after resume hackery... giving up");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void flush_alsa(audio_output_t *ao)
|
||||
{
|
||||
snd_pcm_t *pcm=(snd_pcm_t*)ao->userptr;
|
||||
|
||||
/* is this the optimal solution? - we should figure out what we really whant from this function */
|
||||
|
||||
debug("alsa drop");
|
||||
snd_pcm_drop(pcm);
|
||||
debug("alsa prepare");
|
||||
snd_pcm_prepare(pcm);
|
||||
debug("alsa flush done");
|
||||
}
|
||||
|
||||
static int close_alsa(audio_output_t *ao)
|
||||
{
|
||||
snd_pcm_t *pcm=(snd_pcm_t*)ao->userptr;
|
||||
debug1("close_alsa with %p", ao->userptr);
|
||||
if(pcm != NULL) /* be really generous for being called without any device opening */
|
||||
{
|
||||
if (snd_pcm_state(pcm) == SND_PCM_STATE_RUNNING)
|
||||
snd_pcm_drain(pcm);
|
||||
ao->userptr = NULL; /* Should alsa do this or the module wrapper? */
|
||||
return snd_pcm_close(pcm);
|
||||
}
|
||||
else return 0;
|
||||
}
|
||||
|
||||
|
||||
static int init_alsa(audio_output_t* ao)
|
||||
{
|
||||
if (ao==NULL) return -1;
|
||||
|
||||
/* Set callbacks */
|
||||
ao->open = open_alsa;
|
||||
ao->flush = flush_alsa;
|
||||
ao->write = write_alsa;
|
||||
ao->get_formats = get_formats_alsa;
|
||||
ao->close = close_alsa;
|
||||
|
||||
/* Success */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Module information data structure
|
||||
*/
|
||||
mpg123_module_t mpg123_output_module_info = {
|
||||
/* api_version */ MPG123_MODULE_API_VERSION,
|
||||
/* name */ "alsa",
|
||||
/* description */ "Output audio using Advanced Linux Sound Architecture (ALSA).",
|
||||
/* revision */ "$Rev:$",
|
||||
/* handle */ NULL,
|
||||
|
||||
/* init_output */ init_alsa,
|
||||
};
|
||||
|
117
node_modules/lame/deps/mpg123/src/output/arts.c
generated
vendored
Normal file
117
node_modules/lame/deps/mpg123/src/output/arts.c
generated
vendored
Normal file
@ -0,0 +1,117 @@
|
||||
/*
|
||||
arts: audio output via aRts Sound Daemon
|
||||
|
||||
copyright 2007-8 by the mpg123 project - free software under the terms of the LGPL 2.1
|
||||
see COPYING and AUTHORS files in distribution or http://mpg123.org
|
||||
|
||||
initially written by Stefan Lenselink (Stefan@lenselink.org)
|
||||
*/
|
||||
|
||||
|
||||
#include "mpg123app.h"
|
||||
#include <artsc.h>
|
||||
#include "debug.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
arts_stream_t arse; /* That's short for ARts StrEam;-) */
|
||||
} mpg123_arts_t;
|
||||
|
||||
static int open_arts(audio_output_t *ao)
|
||||
{
|
||||
short bits = 0;
|
||||
if(!ao) return -1;
|
||||
|
||||
if(ao->format < 0)
|
||||
{
|
||||
ao->format = MPG123_ENC_SIGNED_16;
|
||||
ao->rate = 44100;
|
||||
ao->channels = 2;
|
||||
}
|
||||
/* Trial and error revealed these two formats to work with aRts. */
|
||||
if(ao->format == MPG123_ENC_SIGNED_16) bits = 16;
|
||||
else if(ao->format == MPG123_ENC_UNSIGNED_8) bits = 8;
|
||||
else return -1;
|
||||
|
||||
/* Initialize the aRts lib*/
|
||||
arts_init();
|
||||
/* Open a stream to the aRts server */
|
||||
((mpg123_arts_t*)ao->userptr)->arse = arts_play_stream( ao->rate, bits, ao->channels, "mpg123" );
|
||||
/* Yeah, black box and all... it's still a pointer that is NULL on error. */
|
||||
return (void*)((mpg123_arts_t*)ao->userptr)->arse == NULL ? -1 : 0;
|
||||
}
|
||||
|
||||
static int get_formats_arts(audio_output_t *ao)
|
||||
{
|
||||
/* aRts runs not everything, but any rate. */
|
||||
return MPG123_ENC_SIGNED_16|MPG123_ENC_UNSIGNED_8;
|
||||
}
|
||||
|
||||
static int write_arts(audio_output_t *ao,unsigned char *buf,int len)
|
||||
{
|
||||
/* PIPE the PCM forward to the aRts Sound Daemon */
|
||||
return arts_write( ((mpg123_arts_t*)ao->userptr)->arse , buf, len);
|
||||
}
|
||||
|
||||
static int close_arts(audio_output_t *ao)
|
||||
{
|
||||
/* Close the connection! */
|
||||
arts_close_stream( ((mpg123_arts_t*)ao->userptr)->arse );
|
||||
/* Free the memory allocated*/
|
||||
arts_free();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void flush_arts(audio_output_t *ao)
|
||||
{
|
||||
/* aRts doesn't have a flush statement! */
|
||||
}
|
||||
|
||||
static int deinit_arts(audio_output_t* ao)
|
||||
{
|
||||
if(ao->userptr)
|
||||
{
|
||||
free(ao->userptr);
|
||||
ao->userptr = NULL;
|
||||
}
|
||||
arts_free();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init_arts(audio_output_t* ao)
|
||||
{
|
||||
if (ao==NULL) return -1;
|
||||
|
||||
ao->userptr = malloc(sizeof(mpg123_arts_t));
|
||||
if(ao->userptr == NULL)
|
||||
{
|
||||
error("Out of memory!");
|
||||
return -1;
|
||||
}
|
||||
/* clear it to have a consistent state */
|
||||
memset(ao->userptr, 0, sizeof(mpg123_arts_t));
|
||||
/* Set callbacks */
|
||||
ao->open = open_arts;
|
||||
ao->flush = flush_arts;
|
||||
ao->write = write_arts;
|
||||
ao->get_formats = get_formats_arts;
|
||||
ao->close = close_arts;
|
||||
ao->deinit = deinit_arts;
|
||||
/* Success */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Module information data structure
|
||||
*/
|
||||
mpg123_module_t mpg123_output_module_info = {
|
||||
/* api_version */ MPG123_MODULE_API_VERSION,
|
||||
/* name */ "arts",
|
||||
/* description */ "Output audio using aRts Sound Daemon",
|
||||
/* revision */ "$Rev: $",
|
||||
/* handle */ NULL,
|
||||
|
||||
/* init_output */ init_arts,
|
||||
};
|
||||
|
||||
|
370
node_modules/lame/deps/mpg123/src/output/coreaudio.c
generated
vendored
Normal file
370
node_modules/lame/deps/mpg123/src/output/coreaudio.c
generated
vendored
Normal file
@ -0,0 +1,370 @@
|
||||
/*
|
||||
coreaudio: audio output on MacOS X
|
||||
|
||||
copyright ?-2006 by the mpg123 project - free software under the terms of the GPL 2
|
||||
see COPYING and AUTHORS files in distribution or http://mpg123.org
|
||||
initially written by Guillaume Outters
|
||||
modified by Nicholas J Humfrey to use SFIFO code
|
||||
modified by Taihei Monma to use AudioUnit and AudioConverter APIs
|
||||
*/
|
||||
|
||||
|
||||
#include "mpg123app.h"
|
||||
|
||||
#include <CoreServices/CoreServices.h>
|
||||
#include <AudioUnit/AudioUnit.h>
|
||||
#include <AudioToolbox/AudioToolbox.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* Including the sfifo code locally, to avoid module linkage issues. */
|
||||
#define SFIFO_STATIC
|
||||
#include "sfifo.c"
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#define FIFO_DURATION (0.5f) /* Duration of the ring buffer in seconds */
|
||||
|
||||
|
||||
typedef struct mpg123_coreaudio
|
||||
{
|
||||
AudioConverterRef converter;
|
||||
AudioUnit outputUnit;
|
||||
int open;
|
||||
char play;
|
||||
int channels;
|
||||
int bps;
|
||||
int last_buffer;
|
||||
int play_done;
|
||||
int decode_done;
|
||||
|
||||
/* Convertion buffer */
|
||||
unsigned char * buffer;
|
||||
size_t buffer_size;
|
||||
|
||||
/* Ring buffer */
|
||||
sfifo_t fifo;
|
||||
|
||||
} mpg123_coreaudio_t;
|
||||
|
||||
|
||||
|
||||
static OSStatus playProc(AudioConverterRef inAudioConverter,
|
||||
UInt32 *ioNumberDataPackets,
|
||||
AudioBufferList *outOutputData,
|
||||
AudioStreamPacketDescription **outDataPacketDescription,
|
||||
void* inClientData)
|
||||
{
|
||||
mpg123_coreaudio_t *ca = (mpg123_coreaudio_t *)inClientData;
|
||||
long n;
|
||||
|
||||
|
||||
if(ca->last_buffer) {
|
||||
ca->play_done = 1;
|
||||
return noErr;
|
||||
}
|
||||
|
||||
for(n = 0; n < outOutputData->mNumberBuffers; n++)
|
||||
{
|
||||
unsigned int wanted = *ioNumberDataPackets * ca->channels * ca->bps;
|
||||
unsigned char *dest;
|
||||
unsigned int read;
|
||||
if(ca->buffer_size < wanted) {
|
||||
debug1("Allocating %d byte sample conversion buffer", wanted);
|
||||
ca->buffer = realloc( ca->buffer, wanted);
|
||||
ca->buffer_size = wanted;
|
||||
}
|
||||
dest = ca->buffer;
|
||||
|
||||
/* Only play if we have data left */
|
||||
if ( sfifo_used( &ca->fifo ) < wanted ) {
|
||||
if(!ca->decode_done) {
|
||||
warning("Didn't have any audio data in callback (buffer underflow)");
|
||||
return -1;
|
||||
}
|
||||
wanted = sfifo_used( &ca->fifo );
|
||||
ca->last_buffer = 1;
|
||||
}
|
||||
|
||||
/* Read audio from FIFO to SDL's buffer */
|
||||
read = sfifo_read( &ca->fifo, dest, wanted );
|
||||
|
||||
if (wanted!=read)
|
||||
warning2("Error reading from the ring buffer (wanted=%u, read=%u).\n", wanted, read);
|
||||
|
||||
outOutputData->mBuffers[n].mDataByteSize = read;
|
||||
outOutputData->mBuffers[n].mData = dest;
|
||||
}
|
||||
|
||||
return noErr;
|
||||
}
|
||||
|
||||
static OSStatus convertProc(void *inRefCon, AudioUnitRenderActionFlags *inActionFlags,
|
||||
const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber,
|
||||
UInt32 inNumFrames, AudioBufferList *ioData)
|
||||
{
|
||||
AudioStreamPacketDescription* outPacketDescription = NULL;
|
||||
mpg123_coreaudio_t* ca = (mpg123_coreaudio_t*)inRefCon;
|
||||
OSStatus err= noErr;
|
||||
|
||||
err = AudioConverterFillComplexBuffer(ca->converter, playProc, inRefCon, &inNumFrames, ioData, outPacketDescription);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int open_coreaudio(audio_output_t *ao)
|
||||
{
|
||||
mpg123_coreaudio_t* ca = (mpg123_coreaudio_t*)ao->userptr;
|
||||
UInt32 size;
|
||||
ComponentDescription desc;
|
||||
Component comp;
|
||||
AudioStreamBasicDescription inFormat;
|
||||
AudioStreamBasicDescription outFormat;
|
||||
AURenderCallbackStruct renderCallback;
|
||||
Boolean outWritable;
|
||||
|
||||
/* Initialize our environment */
|
||||
ca->play = 0;
|
||||
ca->buffer = NULL;
|
||||
ca->buffer_size = 0;
|
||||
ca->last_buffer = 0;
|
||||
ca->play_done = 0;
|
||||
ca->decode_done = 0;
|
||||
|
||||
|
||||
/* Get the default audio output unit */
|
||||
desc.componentType = kAudioUnitType_Output;
|
||||
desc.componentSubType = kAudioUnitSubType_DefaultOutput;
|
||||
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
|
||||
desc.componentFlags = 0;
|
||||
desc.componentFlagsMask = 0;
|
||||
comp = FindNextComponent(NULL, &desc);
|
||||
if(comp == NULL) {
|
||||
error("FindNextComponent failed");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
if(OpenAComponent(comp, &(ca->outputUnit))) {
|
||||
error("OpenAComponent failed");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if(AudioUnitInitialize(ca->outputUnit)) {
|
||||
error("AudioUnitInitialize failed");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* Specify the output PCM format */
|
||||
AudioUnitGetPropertyInfo(ca->outputUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &size, &outWritable);
|
||||
if(AudioUnitGetProperty(ca->outputUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &outFormat, &size)) {
|
||||
error("AudioUnitGetProperty(kAudioUnitProperty_StreamFormat) failed");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if(AudioUnitSetProperty(ca->outputUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &outFormat, size)) {
|
||||
error("AudioUnitSetProperty(kAudioUnitProperty_StreamFormat) failed");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* Specify the input PCM format */
|
||||
ca->channels = ao->channels;
|
||||
inFormat.mSampleRate = ao->rate;
|
||||
inFormat.mChannelsPerFrame = ao->channels;
|
||||
inFormat.mFormatID = kAudioFormatLinearPCM;
|
||||
#ifdef _BIG_ENDIAN
|
||||
inFormat.mFormatFlags = kLinearPCMFormatFlagIsPacked | kLinearPCMFormatFlagIsBigEndian;
|
||||
#else
|
||||
inFormat.mFormatFlags = kLinearPCMFormatFlagIsPacked;
|
||||
#endif
|
||||
|
||||
switch(ao->format)
|
||||
{
|
||||
case MPG123_ENC_SIGNED_16:
|
||||
inFormat.mFormatFlags |= kLinearPCMFormatFlagIsSignedInteger;
|
||||
ca->bps = 2;
|
||||
break;
|
||||
case MPG123_ENC_SIGNED_8:
|
||||
inFormat.mFormatFlags |= kLinearPCMFormatFlagIsSignedInteger;
|
||||
ca->bps = 1;
|
||||
break;
|
||||
case MPG123_ENC_UNSIGNED_8:
|
||||
ca->bps = 1;
|
||||
break;
|
||||
case MPG123_ENC_SIGNED_32:
|
||||
inFormat.mFormatFlags |= kLinearPCMFormatFlagIsSignedInteger;
|
||||
ca->bps = 4;
|
||||
break;
|
||||
case MPG123_ENC_FLOAT_32:
|
||||
inFormat.mFormatFlags |= kLinearPCMFormatFlagIsFloat;
|
||||
ca->bps = 4;
|
||||
break;
|
||||
}
|
||||
|
||||
inFormat.mBitsPerChannel = ca->bps << 3;
|
||||
inFormat.mBytesPerPacket = ca->bps*inFormat.mChannelsPerFrame;
|
||||
inFormat.mFramesPerPacket = 1;
|
||||
inFormat.mBytesPerFrame = ca->bps*inFormat.mChannelsPerFrame;
|
||||
|
||||
/* Add our callback - but don't start it yet */
|
||||
memset(&renderCallback, 0, sizeof(AURenderCallbackStruct));
|
||||
renderCallback.inputProc = convertProc;
|
||||
renderCallback.inputProcRefCon = ao->userptr;
|
||||
if(AudioUnitSetProperty(ca->outputUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &renderCallback, sizeof(AURenderCallbackStruct))) {
|
||||
error("AudioUnitSetProperty(kAudioUnitProperty_SetRenderCallback) failed");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
|
||||
/* Open an audio I/O stream and create converter */
|
||||
if (ao->rate > 0 && ao->channels >0 ) {
|
||||
int ringbuffer_len;
|
||||
|
||||
if(AudioConverterNew(&inFormat, &outFormat, &(ca->converter))) {
|
||||
error("AudioConverterNew failed");
|
||||
return(-1);
|
||||
}
|
||||
if(ao->channels == 1) {
|
||||
SInt32 channelMap[2] = { 0, 0 };
|
||||
if(AudioConverterSetProperty(ca->converter, kAudioConverterChannelMap, sizeof(channelMap), channelMap)) {
|
||||
error("AudioConverterSetProperty(kAudioConverterChannelMap) failed");
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialise FIFO */
|
||||
ringbuffer_len = ao->rate * FIFO_DURATION * ca->bps * ao->channels;
|
||||
debug2( "Allocating %d byte ring-buffer (%f seconds)", ringbuffer_len, (float)FIFO_DURATION);
|
||||
sfifo_init( &ca->fifo, ringbuffer_len );
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int get_formats_coreaudio(audio_output_t *ao)
|
||||
{
|
||||
return MPG123_ENC_SIGNED_16|MPG123_ENC_SIGNED_8|MPG123_ENC_UNSIGNED_8|MPG123_ENC_SIGNED_32|MPG123_ENC_FLOAT_32;
|
||||
}
|
||||
|
||||
static int write_coreaudio(audio_output_t *ao, unsigned char *buf, int len)
|
||||
{
|
||||
mpg123_coreaudio_t* ca = (mpg123_coreaudio_t*)ao->userptr;
|
||||
int written;
|
||||
|
||||
/* If there is no room, then sleep for half the length of the FIFO */
|
||||
while (sfifo_space( &ca->fifo ) < len ) {
|
||||
usleep( (FIFO_DURATION/2) * 1000000 );
|
||||
}
|
||||
|
||||
/* Store converted audio in ring buffer */
|
||||
written = sfifo_write( &ca->fifo, (char*)buf, len);
|
||||
if (written != len) {
|
||||
warning( "Failed to write audio to ring buffer" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Start playback now that we have something to play */
|
||||
if(!ca->play)
|
||||
{
|
||||
if(AudioOutputUnitStart(ca->outputUnit)) {
|
||||
error("AudioOutputUnitStart failed");
|
||||
return(-1);
|
||||
}
|
||||
ca->play = 1;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int close_coreaudio(audio_output_t *ao)
|
||||
{
|
||||
mpg123_coreaudio_t* ca = (mpg123_coreaudio_t*)ao->userptr;
|
||||
|
||||
if (ca) {
|
||||
ca->decode_done = 1;
|
||||
while(!ca->play_done && ca->play) usleep(10000);
|
||||
|
||||
/* No matter the error code, we want to close it (by brute force if necessary) */
|
||||
AudioConverterDispose(ca->converter);
|
||||
AudioOutputUnitStop(ca->outputUnit);
|
||||
AudioUnitUninitialize(ca->outputUnit);
|
||||
CloseComponent(ca->outputUnit);
|
||||
|
||||
/* Free the ring buffer */
|
||||
sfifo_close( &ca->fifo );
|
||||
|
||||
/* Free the conversion buffer */
|
||||
if (ca->buffer) {
|
||||
free( ca->buffer );
|
||||
ca->buffer = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void flush_coreaudio(audio_output_t *ao)
|
||||
{
|
||||
mpg123_coreaudio_t* ca = (mpg123_coreaudio_t*)ao->userptr;
|
||||
|
||||
/* Stop playback */
|
||||
if(AudioOutputUnitStop(ca->outputUnit)) {
|
||||
error("AudioOutputUnitStop failed");
|
||||
}
|
||||
ca->play=0;
|
||||
|
||||
/* Empty out the ring buffer */
|
||||
sfifo_flush( &ca->fifo );
|
||||
}
|
||||
|
||||
static int deinit_coreaudio(audio_output_t* ao)
|
||||
{
|
||||
/* Free up memory */
|
||||
if (ao->userptr) {
|
||||
free( ao->userptr );
|
||||
ao->userptr = NULL;
|
||||
}
|
||||
|
||||
/* Success */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init_coreaudio(audio_output_t* ao)
|
||||
{
|
||||
if (ao==NULL) return -1;
|
||||
|
||||
/* Set callbacks */
|
||||
ao->open = open_coreaudio;
|
||||
ao->flush = flush_coreaudio;
|
||||
ao->write = write_coreaudio;
|
||||
ao->get_formats = get_formats_coreaudio;
|
||||
ao->close = close_coreaudio;
|
||||
ao->deinit = deinit_coreaudio;
|
||||
|
||||
/* Allocate memory for data structure */
|
||||
ao->userptr = malloc( sizeof( mpg123_coreaudio_t ) );
|
||||
if (ao->userptr==NULL) {
|
||||
error("failed to malloc memory for 'mpg123_coreaudio_t'");
|
||||
return -1;
|
||||
}
|
||||
memset( ao->userptr, 0, sizeof(mpg123_coreaudio_t) );
|
||||
|
||||
/* Success */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Module information data structure
|
||||
*/
|
||||
mpg123_module_t mpg123_output_module_info = {
|
||||
/* api_version */ MPG123_MODULE_API_VERSION,
|
||||
/* name */ "coreaudio",
|
||||
/* description */ "Output audio using Mac OS X's CoreAudio.",
|
||||
/* revision */ "$Rev:$",
|
||||
/* handle */ NULL,
|
||||
|
||||
/* init_output */ init_coreaudio,
|
||||
};
|
||||
|
||||
|
78
node_modules/lame/deps/mpg123/src/output/dummy.c
generated
vendored
Normal file
78
node_modules/lame/deps/mpg123/src/output/dummy.c
generated
vendored
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
dummy: dummy audio output
|
||||
|
||||
copyright ?-2006 by the mpg123 project - free software under the terms of the LGPL 2.1
|
||||
see COPYING and AUTHORS files in distribution or http://mpg123.org
|
||||
*/
|
||||
|
||||
#include "mpg123app.h"
|
||||
#include "debug.h"
|
||||
|
||||
static int open_dummy(audio_output_t *ao)
|
||||
{
|
||||
debug("open_dummy()");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_formats_dummy(audio_output_t *ao)
|
||||
{
|
||||
debug("get_formats_dummy()");
|
||||
return MPG123_ENC_SIGNED_16;
|
||||
}
|
||||
|
||||
static int write_dummy(audio_output_t *ao,unsigned char *buf,int len)
|
||||
{
|
||||
debug("write_dummy()");
|
||||
return len;
|
||||
}
|
||||
|
||||
static void flush_dummy(audio_output_t *ao)
|
||||
{
|
||||
debug("flush_dummy()");
|
||||
}
|
||||
|
||||
static int close_dummy(audio_output_t *ao)
|
||||
{
|
||||
debug("close_dummy()");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int deinit_dummy(audio_output_t *ao)
|
||||
{
|
||||
debug("deinit_dummy()");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int init_dummy(audio_output_t* ao)
|
||||
{
|
||||
if (ao==NULL) return -1;
|
||||
debug("init_dummy()");
|
||||
|
||||
/* Set callbacks */
|
||||
ao->open = open_dummy;
|
||||
ao->flush = flush_dummy;
|
||||
ao->write = write_dummy;
|
||||
ao->get_formats = get_formats_dummy;
|
||||
ao->close = close_dummy;
|
||||
ao->deinit = deinit_dummy;
|
||||
|
||||
/* Success */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Module information data structure
|
||||
*/
|
||||
mpg123_module_t mpg123_output_module_info = {
|
||||
/* api_version */ MPG123_MODULE_API_VERSION,
|
||||
/* name */ "dummy",
|
||||
/* description */ "Dummy audio output - does not output audio.",
|
||||
/* revision */ "$Rev:$",
|
||||
/* handle */ NULL,
|
||||
|
||||
/* init_output */ init_dummy,
|
||||
};
|
||||
|
167
node_modules/lame/deps/mpg123/src/output/esd.c
generated
vendored
Normal file
167
node_modules/lame/deps/mpg123/src/output/esd.c
generated
vendored
Normal file
@ -0,0 +1,167 @@
|
||||
/*
|
||||
esd: audio output for ESounD (highly untested nowadays (?))
|
||||
|
||||
copyright ?-2006 by the mpg123 project - free software under the terms of the LGPL 2.1
|
||||
see COPYING and AUTHORS files in distribution or http://mpg123.org
|
||||
initially written by Eric B. Mitchell ("esd port" should be this file...)
|
||||
*/
|
||||
|
||||
/* First the common header, including config.h
|
||||
...this is important for stuff like _FILE_OFFSET_BITS */
|
||||
#include "mpg123app.h"
|
||||
|
||||
#include <esd.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef SOLARIS
|
||||
#include <stropts.h>
|
||||
#include <sys/conf.h>
|
||||
#endif
|
||||
#ifdef NETBSD
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/audioio.h>
|
||||
#endif
|
||||
#include "debug.h"
|
||||
|
||||
static unsigned esd_rate = 0, esd_format = 0, esd_channels = 0;
|
||||
|
||||
|
||||
static int open_esound(audio_output_t *ao)
|
||||
{
|
||||
esd_format_t format = ESD_STREAM | ESD_PLAY;
|
||||
|
||||
if (!esd_rate)
|
||||
{
|
||||
int esd;
|
||||
esd_server_info_t *info;
|
||||
esd_format_t fmt;
|
||||
|
||||
if ((esd = esd_open_sound(NULL)) >= 0)
|
||||
{
|
||||
info = esd_get_server_info(esd);
|
||||
esd_rate = info->rate;
|
||||
fmt = info->format;
|
||||
esd_free_server_info(info);
|
||||
esd_close(esd);
|
||||
}
|
||||
else
|
||||
{
|
||||
esd_rate = esd_audio_rate;
|
||||
fmt = esd_audio_format;
|
||||
}
|
||||
esd_format = MPG123_ENC_UNSIGNED_8;
|
||||
|
||||
if ((fmt & ESD_MASK_BITS) == ESD_BITS16)
|
||||
esd_format |= MPG123_ENC_SIGNED_16;
|
||||
esd_channels = fmt & ESD_MASK_CHAN;
|
||||
}
|
||||
|
||||
if (ao->format == -1)
|
||||
ao->format = esd_format;
|
||||
else if (!(ao->format & esd_format))
|
||||
{
|
||||
error1("Unsupported audio format: %d\n", ao->format);
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
if (ao->format & MPG123_ENC_SIGNED_16)
|
||||
format |= ESD_BITS16;
|
||||
else if (ao->format & MPG123_ENC_UNSIGNED_8)
|
||||
format |= ESD_BITS8;
|
||||
else assert(0);
|
||||
|
||||
if (ao->channels == -1) ao->channels = 2;
|
||||
else if (ao->channels <= 0 || ao->channels > esd_channels)
|
||||
{
|
||||
error1("Unsupported no of channels: %d\n", ao->channels);
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (ao->channels == 1)
|
||||
format |= ESD_MONO;
|
||||
else if (ao->channels == 2)
|
||||
format |= ESD_STEREO;
|
||||
else assert(0);
|
||||
|
||||
if (ao->rate == -1) ao->rate = esd_rate;
|
||||
else if (ao->rate > esd_rate)
|
||||
return -1;
|
||||
|
||||
ao->fn = esd_play_stream_fallback(format, ao->rate, ao->device, "mpg123");
|
||||
return (ao->fn);
|
||||
}
|
||||
|
||||
static int get_formats_esound (audio_output_t *ao)
|
||||
{
|
||||
if (0 < ao->channels && ao->channels <= esd_channels
|
||||
&& 0 < ao->rate && ao->rate <= esd_rate)
|
||||
{
|
||||
return esd_format;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int write_esound(audio_output_t *ao,unsigned char *buf,int len)
|
||||
{
|
||||
return write(ao->fn,buf,len);
|
||||
}
|
||||
|
||||
static int close_esound(audio_output_t *ao)
|
||||
{
|
||||
close (ao->fn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef SOLARIS
|
||||
static void flush_esound (audio_output_t *ao)
|
||||
{
|
||||
ioctl (ao->fn, I_FLUSH, FLUSHRW);
|
||||
}
|
||||
#else
|
||||
#ifdef NETBSD
|
||||
static void flush_esound (audio_output_t *ao)
|
||||
{
|
||||
ioctl (ao->fn, AUDIO_FLUSH, 0);
|
||||
}
|
||||
#else
|
||||
/* Dunno what to do on Linux and Cygwin, but the func must be at least defined! */
|
||||
static void flush_esound (audio_output_t *ao)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
static int init_esound(audio_output_t* ao)
|
||||
{
|
||||
if (ao==NULL) return -1;
|
||||
|
||||
/* Set callbacks */
|
||||
ao->open = open_esound;
|
||||
ao->flush = flush_esound;
|
||||
ao->write = write_esound;
|
||||
ao->get_formats = get_formats_esound;
|
||||
ao->close = close_esound;
|
||||
|
||||
/* Success */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Module information data structure
|
||||
*/
|
||||
mpg123_module_t mpg123_output_module_info = {
|
||||
/* api_version */ MPG123_MODULE_API_VERSION,
|
||||
/* name */ "esd",
|
||||
/* description */ "Output audio using ESounD (The Enlightened Sound Daemon).",
|
||||
/* revision */ "$Rev: 1698 $",
|
||||
/* handle */ NULL,
|
||||
|
||||
/* init_output */ init_esound,
|
||||
};
|
184
node_modules/lame/deps/mpg123/src/output/hp.c
generated
vendored
Normal file
184
node_modules/lame/deps/mpg123/src/output/hp.c
generated
vendored
Normal file
@ -0,0 +1,184 @@
|
||||
/*
|
||||
hp: audio output for HP-UX
|
||||
|
||||
copyright ?-2006 by the mpg123 project - free software under the terms of the LGPL 2.1
|
||||
see COPYING and AUTHORS files in distribution or http://mpg123.org
|
||||
initially written by Michael Hipp
|
||||
*/
|
||||
|
||||
#include "mpg123app.h"
|
||||
#include <fcntl.h>
|
||||
#include <sys/audio.h>
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
static int set_rate(audio_output_t *ao)
|
||||
{
|
||||
if(ao->rate >= 0) {
|
||||
return ioctl(ao->fn,AUDIO_SET_SAMPLE_RATE,ao->rate);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int set_channels(audio_output_t *ao)
|
||||
{
|
||||
if(ao->channels<0) return 0;
|
||||
return ioctl(ao->fn,AUDIO_SET_CHANNELS,ao->channels);
|
||||
}
|
||||
|
||||
static int set_format(audio_output_t *ao)
|
||||
{
|
||||
int fmt;
|
||||
|
||||
switch(ao->format) {
|
||||
case -1:
|
||||
case MPG123_ENC_SIGNED_16:
|
||||
default:
|
||||
fmt = MPG123_ENC_LINEAR16BIT;
|
||||
break;
|
||||
case MPG123_ENC_UNSIGNED_8:
|
||||
error("unsigned 8 bit linear not supported");
|
||||
return -1;
|
||||
case MPG123_ENC_SIGNED_8:
|
||||
error("signed 8 bit linear not supported");
|
||||
return -1;
|
||||
case MPG123_ENC_ALAW_8:
|
||||
fmt = MPG123_ENC_ALAW;
|
||||
break;
|
||||
case MPG123_ENC_ULAW_8:
|
||||
fmt = MPG123_ENC_ULAW;
|
||||
break;
|
||||
}
|
||||
return ioctl(ao->fn,AUDIO_SET_DATA_FORMAT,fmt);
|
||||
}
|
||||
|
||||
static int get_formats(audio_output_t *ao)
|
||||
{
|
||||
return MPG123_ENC_SIGNED_16;
|
||||
}
|
||||
|
||||
static int reset_parameters(audio_output_t *ao)
|
||||
{
|
||||
int ret;
|
||||
ret = set_format(ai);
|
||||
if(ret >= 0)
|
||||
ret = set_channels_hp(ai);
|
||||
if(ret >= 0)
|
||||
ret = set_rate_hp(ai);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int open_hp(audio_output_t *ao)
|
||||
{
|
||||
struct audio_describe ades;
|
||||
struct audio_gain again;
|
||||
int i,audio;
|
||||
|
||||
ao->fn = open("/dev/audio",O_RDWR);
|
||||
|
||||
if(ao->fn < 0)
|
||||
return -1;
|
||||
|
||||
|
||||
ioctl(ao->fn,AUDIO_DESCRIBE,&ades);
|
||||
|
||||
if(ao->gain != -1)
|
||||
{
|
||||
if(ao->gain > ades.max_transmit_gain)
|
||||
{
|
||||
error("your gainvalue was to high -> set to maximum.");
|
||||
ao->gain = ades.max_transmit_gain;
|
||||
}
|
||||
if(ao->gain < ades.min_transmit_gain)
|
||||
{
|
||||
error("your gainvalue was to low -> set to minimum.");
|
||||
ao->gain = ades.min_transmit_gain;
|
||||
}
|
||||
again.channel_mask = AUDIO_CHANNEL_0 | AUDIO_CHANNEL_1;
|
||||
ioctl(ao->fn,AUDIO_GET_GAINS,&again);
|
||||
again.cgain[0].transmit_gain = ao->gain;
|
||||
again.cgain[1].transmit_gain = ao->gain;
|
||||
again.channel_mask = AUDIO_CHANNEL_0 | AUDIO_CHANNEL_1;
|
||||
ioctl(ao->fn,AUDIO_SET_GAINS,&again);
|
||||
}
|
||||
|
||||
if(ao->flags != -1)
|
||||
{
|
||||
if(ao->flags & AUDIO_OUT_INTERNAL_SPEAKER)
|
||||
ioctl(ao->fn,AUDIO_SET_OUTPUT,AUDIO_OUT_SPEAKER);
|
||||
else if(ao->flags & AUDIO_OUT_HEADPHONES)
|
||||
ioctl(ao->fn,AUDIO_SET_OUTPUT,AUDIO_OUT_HEADPHONE);
|
||||
else if(ao->flags & AUDIO_OUT_LINE_OUT)
|
||||
ioctl(ao->fn,AUDIO_SET_OUTPUT,AUDIO_OUT_LINE);
|
||||
}
|
||||
|
||||
if(ao->rate == -1)
|
||||
ao->rate = 44100;
|
||||
|
||||
for(i=0;i<ades.nrates;i++)
|
||||
{
|
||||
if(ao->rate == ades.sample_rate[i])
|
||||
break;
|
||||
}
|
||||
if(i == ades.nrates)
|
||||
{
|
||||
error1("Can't set sample-rate to %ld.\n",ao->rate);
|
||||
i = 0;
|
||||
}
|
||||
|
||||
if(reset_parameters(ai) < 0)
|
||||
return -1;
|
||||
|
||||
return ao->fn;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int write_hp(audio_output_t *ao,unsigned char *buf,int len)
|
||||
{
|
||||
return write(ao->fn,buf,len);
|
||||
}
|
||||
|
||||
static int close_hp(audio_output_t *ao)
|
||||
{
|
||||
close (ao->fn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void flush_hp(audio_output_t *ao)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int init_hp(audio_output_t* ao)
|
||||
{
|
||||
if (ao==NULL) return -1;
|
||||
|
||||
/* Set callbacks */
|
||||
ao->open = open_hp;
|
||||
ao->flush = flush_hp;
|
||||
ao->write = write_hp;
|
||||
ao->get_formats = get_formats_hp;
|
||||
ao->close = close_hp;
|
||||
|
||||
/* Success */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Module information data structure
|
||||
*/
|
||||
mpg123_module_t mpg123_output_module_info = {
|
||||
/* api_version */ MPG123_MODULE_API_VERSION,
|
||||
/* name */ "hp",
|
||||
/* description */ "Output audio HP-UX",
|
||||
/* revision */ "$Rev:$",
|
||||
/* handle */ NULL,
|
||||
|
||||
/* init_output */ init_hp,
|
||||
};
|
450
node_modules/lame/deps/mpg123/src/output/jack.c
generated
vendored
Normal file
450
node_modules/lame/deps/mpg123/src/output/jack.c
generated
vendored
Normal file
@ -0,0 +1,450 @@
|
||||
/*
|
||||
jack: audio output via JACK Audio Connection Kit
|
||||
|
||||
copyright 2006 by the mpg123 project - free software under the terms of the LGPL 2.1
|
||||
see COPYING and AUTHORS files in distribution or http://mpg123.org
|
||||
initially written by Nicholas J. Humfrey
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include <jack/jack.h>
|
||||
#include <jack/ringbuffer.h>
|
||||
#include <sys/errno.h>
|
||||
|
||||
#include "mpg123app.h"
|
||||
#include "debug.h"
|
||||
|
||||
#define MAX_CHANNELS (2)
|
||||
|
||||
typedef struct {
|
||||
int channels;
|
||||
jack_port_t *ports[MAX_CHANNELS];
|
||||
jack_ringbuffer_t * rb[MAX_CHANNELS];
|
||||
size_t rb_size;
|
||||
jack_client_t *client;
|
||||
jack_default_audio_sample_t *tmp_buffer;
|
||||
} jack_handle_t, *jack_handle_ptr;
|
||||
|
||||
|
||||
static jack_handle_t* alloc_jack_handle()
|
||||
{
|
||||
jack_handle_t *handle=NULL;
|
||||
|
||||
handle = malloc(sizeof(jack_handle_t));
|
||||
if (!handle) {
|
||||
error("Failed to allocate memory for our handle.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Initialise the handle, and store for later*/
|
||||
handle->rb[0] = NULL;
|
||||
handle->rb[1] = NULL;
|
||||
handle->ports[0] = NULL;
|
||||
handle->ports[1] = NULL;
|
||||
handle->client = NULL;
|
||||
handle->tmp_buffer = NULL;
|
||||
handle->rb_size = 0;
|
||||
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
|
||||
static void free_jack_handle( jack_handle_t* handle )
|
||||
{
|
||||
int i;
|
||||
|
||||
warning("FIXME: One needs to wait or write some silence here to prevent the last bits of audio to vanish out of the ringbuffer.");
|
||||
|
||||
for(i=0; i<MAX_CHANNELS; i++) {
|
||||
/* Close the port for channel*/
|
||||
if ( handle->ports[i] )
|
||||
jack_port_unregister( handle->client, handle->ports[i] );
|
||||
|
||||
/* Free up the ring buffer for channel*/
|
||||
if ( handle->rb[i] )
|
||||
jack_ringbuffer_free( handle->rb[i] );
|
||||
}
|
||||
|
||||
if (handle->client)
|
||||
jack_client_close(handle->client);
|
||||
|
||||
if (handle->tmp_buffer)
|
||||
free(handle->tmp_buffer);
|
||||
|
||||
free(handle);
|
||||
}
|
||||
|
||||
|
||||
static int process_callback( jack_nframes_t nframes, void *arg )
|
||||
{
|
||||
jack_handle_t* handle = (jack_handle_t*)arg;
|
||||
size_t to_read = sizeof (jack_default_audio_sample_t) * nframes;
|
||||
unsigned int c;
|
||||
|
||||
|
||||
/* copy data to ringbuffer; one per channel*/
|
||||
for (c=0; c < handle->channels; c++)
|
||||
{
|
||||
char *buf = (char*)jack_port_get_buffer(handle->ports[c], nframes);
|
||||
size_t len = jack_ringbuffer_read(handle->rb[c], buf, to_read);
|
||||
|
||||
/* If we don't have enough audio, fill it up with silence*/
|
||||
/* (this is to deal with pausing etc.)*/
|
||||
if (to_read > len)
|
||||
bzero( buf+len, to_read - len );
|
||||
|
||||
/*if (len < to_read)*/
|
||||
/* error1("failed to read from ring buffer %d",c);*/
|
||||
}
|
||||
|
||||
/* Success*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void shutdown_callback( void *arg )
|
||||
{
|
||||
/* jack_handle_t* handle = (jack_handle_t*)arg; */
|
||||
|
||||
debug("shutdown_callback()");
|
||||
|
||||
}
|
||||
|
||||
/* connect to jack ports named in the NULL-terminated wishlist */
|
||||
static int real_connect_jack_ports( jack_handle_t* handle, const char** wishlist)
|
||||
{
|
||||
const char **wish = wishlist;
|
||||
int ch, err;
|
||||
|
||||
if(wish != NULL && *wish == NULL) return 1; /* success, nothing connected as wanted */
|
||||
|
||||
for(ch=0; ch<handle->channels; ++ch)
|
||||
{
|
||||
const char* in = jack_port_name( handle->ports[ch] );
|
||||
|
||||
if ((err = jack_connect(handle->client, in, *wish)) != 0 && err != EEXIST) {
|
||||
error1("connect_jack_ports(): failed to jack_connect() ports: %d",err);
|
||||
return 0;
|
||||
}
|
||||
/* Increment wish only if there is another one. Otherwise simply connect to the same port multiple times. */
|
||||
if(*(wish+1) != NULL) ++wish;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* crude way of automatically connecting up jack ports */
|
||||
/* 0 on error */
|
||||
static int autoconnect_jack_ports( jack_handle_t* handle)
|
||||
{
|
||||
const char **all_ports;
|
||||
unsigned int ch=0;
|
||||
int err,i;
|
||||
|
||||
/* Get a list of all the jack ports*/
|
||||
all_ports = jack_get_ports (handle->client, NULL, NULL, JackPortIsInput);
|
||||
if (!all_ports) {
|
||||
error("connect_jack_ports(): jack_get_ports() returned NULL.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Step through each port name*/
|
||||
for (i = 0; all_ports[i]; ++i) {
|
||||
|
||||
const char* in = jack_port_name( handle->ports[ch] );
|
||||
const char* out = all_ports[i];
|
||||
|
||||
if ((err = jack_connect(handle->client, in, out)) != 0 && err != EEXIST) {
|
||||
error1("connect_jack_ports(): failed to jack_connect() ports: %d",err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Found enough ports ?*/
|
||||
if (++ch >= handle->channels) break;
|
||||
}
|
||||
|
||||
free( all_ports );
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int connect_jack_ports( jack_handle_t* handle, const char *dev )
|
||||
{
|
||||
if (dev==NULL || strcmp(dev, "auto")==0) {
|
||||
return autoconnect_jack_ports( handle );
|
||||
}
|
||||
else
|
||||
{
|
||||
const char* wishlist[] = { NULL, NULL, NULL }; /* Two channels and end marker. */
|
||||
char *devcopy;
|
||||
int ret;
|
||||
size_t len = strlen(dev);
|
||||
devcopy = malloc(len+1);
|
||||
if(devcopy == NULL){ error("OOM"); return 0; }
|
||||
|
||||
/* We just look out for a possible second port, comma separated
|
||||
This is really crude cruft, but it's enough. Can be replaced by something sensible later. */
|
||||
memcpy(devcopy, dev, len+1);
|
||||
if( len > 0 && strcmp(dev, "none")!=0 )
|
||||
{
|
||||
size_t i=0;
|
||||
wishlist[0] = devcopy;
|
||||
while(devcopy[i] != 0 && devcopy[i] != ',') ++i;
|
||||
|
||||
if(devcopy[i] == ',')
|
||||
{
|
||||
devcopy[i] = 0;
|
||||
wishlist[1] = devcopy+i+1;
|
||||
}
|
||||
}
|
||||
if(wishlist[0] == NULL) warning("Not connecting up jack ports as requested.");
|
||||
|
||||
ret = real_connect_jack_ports(handle, wishlist);
|
||||
free(devcopy);
|
||||
return ret;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int close_jack(audio_output_t *ao)
|
||||
{
|
||||
jack_handle_t *handle = (jack_handle_t*)ao->userptr;
|
||||
|
||||
debug("close_jack().");
|
||||
|
||||
/* Close and shutdown*/
|
||||
if (handle) {
|
||||
free_jack_handle( handle );
|
||||
ao->userptr = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int open_jack(audio_output_t *ao)
|
||||
{
|
||||
char client_name[255];
|
||||
jack_handle_t *handle=NULL;
|
||||
jack_options_t jopt = JackNullOption;
|
||||
jack_status_t jstat = 0;
|
||||
unsigned int i;
|
||||
|
||||
debug("jack open");
|
||||
if(!ao) return -1;
|
||||
|
||||
/* Return if already open*/
|
||||
if (ao->userptr) {
|
||||
error("audio device is already open.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Create some storage for ourselves*/
|
||||
if((handle = alloc_jack_handle()) == NULL) return -1;
|
||||
|
||||
ao->userptr = (void*)handle;
|
||||
|
||||
/* Register with Jack*/
|
||||
snprintf(client_name, 255, "mpg123-%d", getpid());
|
||||
if ((handle->client = jack_client_open(client_name, jopt, &jstat)) == 0) {
|
||||
error1("Failed to open jack client: 0x%x", jstat);
|
||||
close_jack(ao);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Display the unique client name allocated to us */
|
||||
fprintf(stderr,"Registered as JACK client %s.\n",
|
||||
jack_get_client_name( handle->client ) );
|
||||
|
||||
/* The initial open lets me choose the settings. */
|
||||
if (ao->format==-1)
|
||||
{
|
||||
ao->format = MPG123_ENC_16;
|
||||
ao->rate = jack_get_sample_rate(handle->client);
|
||||
ao->channels = 2;
|
||||
}
|
||||
|
||||
/* Check the sample rate is correct*/
|
||||
if (jack_get_sample_rate( handle->client ) != (jack_nframes_t)ao->rate) {
|
||||
error("JACK Sample Rate is different to sample rate of file.");
|
||||
close_jack(ao);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Register ports with Jack*/
|
||||
handle->channels = ao->channels;
|
||||
if (handle->channels == 1) {
|
||||
if (!(handle->ports[0] = jack_port_register(handle->client, "mono", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0)))
|
||||
{
|
||||
error("Cannot register JACK output port 'mono'.");
|
||||
close_jack(ao);
|
||||
return -1;
|
||||
}
|
||||
} else if (handle->channels == 2) {
|
||||
if (!(handle->ports[0] = jack_port_register(handle->client, "left", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0)))
|
||||
{
|
||||
error("Cannot register JACK output port 'left'.");
|
||||
close_jack(ao);
|
||||
return -1;
|
||||
}
|
||||
if (!(handle->ports[1] = jack_port_register(handle->client, "right", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0)))
|
||||
{
|
||||
error("Cannot register JACK output port 'right'.");
|
||||
close_jack(ao);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
error1("invalid number of output channels (%d).", handle->channels);
|
||||
close_jack(ao);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Create the ring buffers (one seconds audio)*/
|
||||
handle->rb_size = jack_get_sample_rate(handle->client) * sizeof(jack_default_audio_sample_t);
|
||||
for(i=0;i<handle->channels;i++){
|
||||
handle->rb[i]=jack_ringbuffer_create(handle->rb_size);
|
||||
}
|
||||
|
||||
/* Set the callbacks*/
|
||||
jack_set_process_callback(handle->client, process_callback, (void*)handle);
|
||||
jack_on_shutdown(handle->client, shutdown_callback, (void*)handle);
|
||||
|
||||
/* Activate client*/
|
||||
if (jack_activate(handle->client)) {
|
||||
error("Can't activate client.");
|
||||
}
|
||||
|
||||
/* Connect up the portsm, return */
|
||||
if(!connect_jack_ports( handle, ao->device ))
|
||||
{
|
||||
/* deregistering of ports will not work but should just fail, then, and let the rest clean up */
|
||||
close_jack(ao);
|
||||
return -1;
|
||||
}
|
||||
|
||||
debug("Jack open successful.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Jack prefers floats, I actually assume it does _only_ float/double (as it is nowadays)! */
|
||||
static int get_formats_jack(audio_output_t *ao)
|
||||
{
|
||||
if(jack_get_sample_rate( ((jack_handle_t*)(ao->userptr))->client ) != (jack_nframes_t)ao->rate) return 0;
|
||||
else return MPG123_ENC_FLOAT_32|MPG123_ENC_FLOAT_64|MPG123_ENC_SIGNED_16;
|
||||
}
|
||||
|
||||
|
||||
static int write_jack(audio_output_t *ao, unsigned char *buf, int len)
|
||||
{
|
||||
int c,n = 0;
|
||||
jack_handle_t *handle = (jack_handle_t*)ao->userptr;
|
||||
jack_nframes_t samples;
|
||||
size_t tmp_size;
|
||||
/* Only float or double is used.
|
||||
Note: I still need the tmp buffer because of de-interleaving the channels. */
|
||||
samples = len /
|
||||
(ao->format == MPG123_ENC_FLOAT_64 ? 8 : (ao->format == MPG123_ENC_SIGNED_16 ? 2 : 4))
|
||||
/ handle->channels;
|
||||
tmp_size = samples * sizeof( jack_default_audio_sample_t );
|
||||
|
||||
|
||||
/* Sanity check that ring buffer is at least twice the size of the audio we just got*/
|
||||
if (handle->rb_size/2 < len) {
|
||||
error("ring buffer is less than twice the size of audio given.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* Wait until there is space in the ring buffer*/
|
||||
while (jack_ringbuffer_write_space( handle->rb[0] ) < tmp_size) {
|
||||
/* Sleep for a quarter of the ring buffer size (1/4 second)*/
|
||||
usleep(250000);
|
||||
}
|
||||
|
||||
|
||||
/* Ensure the temporary buffer is big enough*/
|
||||
handle->tmp_buffer = (jack_default_audio_sample_t*)realloc( handle->tmp_buffer, tmp_size);
|
||||
if (!handle->tmp_buffer) {
|
||||
error("failed to realloc temporary buffer.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
for(c=0; c<handle->channels; c++) {
|
||||
size_t len = 0;
|
||||
|
||||
/* Hm, is that optimal? Anyhow, deinterleaving float or double ... or short. With/without conversion. */
|
||||
if(ao->format == MPG123_ENC_SIGNED_16)
|
||||
{
|
||||
short* src = (short*)buf;
|
||||
for(n=0; n<samples; n++)
|
||||
handle->tmp_buffer[n] = src[(n*handle->channels)+c] / 32768.0f;
|
||||
}
|
||||
else if(ao->format == MPG123_ENC_FLOAT_32)
|
||||
{
|
||||
float* src = (float*)buf;
|
||||
for(n=0; n<samples; n++)
|
||||
handle->tmp_buffer[n] = src[(n*handle->channels)+c];
|
||||
}
|
||||
else /* MPG123_ENC_FLOAT_64 */
|
||||
{
|
||||
double* src = (double*)buf;
|
||||
for(n=0; n<samples; n++)
|
||||
handle->tmp_buffer[n] = src[(n*handle->channels)+c];
|
||||
}
|
||||
/* Copy temporary buffer into ring buffer*/
|
||||
len = jack_ringbuffer_write(handle->rb[c], (char*)handle->tmp_buffer, tmp_size);
|
||||
if (len < tmp_size)
|
||||
{
|
||||
error("failed to write to ring ruffer.");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static void flush_jack(audio_output_t *ao)
|
||||
{
|
||||
jack_handle_t *handle = (jack_handle_t*)ao->userptr;
|
||||
int c;
|
||||
|
||||
warning("This way, we drop audio on pausing... there must be a better way.");
|
||||
/* Reset the ring buffers*/
|
||||
for(c=0; c<handle->channels; c++) {
|
||||
jack_ringbuffer_reset(handle->rb[c]);
|
||||
}
|
||||
}
|
||||
|
||||
static int init_jack(audio_output_t* ao)
|
||||
{
|
||||
if (ao==NULL) return -1;
|
||||
|
||||
/* Set callbacks */
|
||||
ao->open = open_jack;
|
||||
ao->flush = flush_jack;
|
||||
ao->write = write_jack;
|
||||
ao->get_formats = get_formats_jack;
|
||||
ao->close = close_jack;
|
||||
|
||||
/* Success */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Module information data structure
|
||||
*/
|
||||
mpg123_module_t mpg123_output_module_info = {
|
||||
/* api_version */ MPG123_MODULE_API_VERSION,
|
||||
/* name */ "jack",
|
||||
/* description */ "Output audio using JACK (JACK Audio Connection Kit).",
|
||||
/* revision */ "$Rev:$",
|
||||
/* handle */ NULL,
|
||||
|
||||
/* init_output */ init_jack,
|
||||
};
|
197
node_modules/lame/deps/mpg123/src/output/mint.c
generated
vendored
Normal file
197
node_modules/lame/deps/mpg123/src/output/mint.c
generated
vendored
Normal file
@ -0,0 +1,197 @@
|
||||
/*
|
||||
mint: audio output for MINT
|
||||
|
||||
copyright ?-2006 by the mpg123 project - free software under the terms of the LGPL 2.1
|
||||
see COPYING and AUTHORS files in distribution or http://mpg123.org
|
||||
initially written by Petr Stehlik
|
||||
*/
|
||||
|
||||
/* derived from LINUX, VOXWARE and SUN for MiNT Audio Device by Petr Stehlik */
|
||||
#include <fcntl.h>
|
||||
#include "mpg123app.h"
|
||||
#include <ioctl.h>
|
||||
#include <audios.h>
|
||||
#include "debug.h"
|
||||
|
||||
/* Globals */
|
||||
extern int outburst;
|
||||
int real_rate_printed = 0;
|
||||
|
||||
|
||||
|
||||
static int rate_best_match(audio_output_t *ao)
|
||||
{
|
||||
int ret,dsp_rate;
|
||||
|
||||
if(!ai || ao->fn < 0 || ao->rate < 0)
|
||||
return -1;
|
||||
|
||||
dsp_rate = ao->rate;
|
||||
ret = ioctl(ao->fn,AIOCSSPEED, (void *)dsp_rate);
|
||||
ret = ioctl(ao->fn,AIOCGSPEED,&dsp_rate);
|
||||
if(ret < 0) return ret;
|
||||
ao->rate = dsp_rate;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_rate(audio_output_t *ao)
|
||||
{
|
||||
int dsp_rate = ao->rate;
|
||||
|
||||
if(ao->rate >= 0) {
|
||||
int ret, real_rate;
|
||||
ret = ioctl(ao->fn, AIOCSSPEED, (void *)dsp_rate);
|
||||
if (ret >= 0 && !real_rate_printed) {
|
||||
ioctl(ao->fn,AIOCGSPEED,&real_rate);
|
||||
if (real_rate != dsp_rate) {
|
||||
fprintf(stderr, "Replay rate: %d Hz\n", real_rate);
|
||||
real_rate_printed = 1;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_channels(audio_output_t *ao)
|
||||
{
|
||||
int chan = ao->channels;
|
||||
|
||||
if(ao->channels < 1) return 0;
|
||||
|
||||
return ioctl(ao->fn, AIOCSCHAN, (void *)chan);
|
||||
}
|
||||
|
||||
static int set_format(audio_output_t *ao)
|
||||
{
|
||||
int fmts;
|
||||
|
||||
if(ao->format == -1)
|
||||
return 0;
|
||||
|
||||
switch(ao->format) {
|
||||
case MPG123_ENC_SIGNED_16:
|
||||
default:
|
||||
fmts = AFMT_S16;
|
||||
break;
|
||||
case MPG123_ENC_UNSIGNED_8:
|
||||
fmts = AFMT_U8;
|
||||
break;
|
||||
case MPG123_ENC_SIGNED_8:
|
||||
fmts = AFMT_S8;
|
||||
break;
|
||||
case MPG123_ENC_ULAW_8:
|
||||
fmts = AFMT_ULAW;
|
||||
break;
|
||||
}
|
||||
|
||||
return ioctl(ao->fn, AIOCSFMT, (void *)fmts);
|
||||
}
|
||||
|
||||
static int reset_parameters(audio_output_t *ao)
|
||||
{
|
||||
int ret;
|
||||
ret = ioctl(ao->fn,AIOCRESET,NULL);
|
||||
if(ret >= 0) ret = set_format(ai);
|
||||
if(ret >= 0) ret = set_channels(ai);
|
||||
if(ret >= 0) ret = set_rate(ai);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int open_mint(audio_output_t *ao)
|
||||
{
|
||||
if(!ai) return -1;
|
||||
|
||||
if(!ao->device)
|
||||
ao->device = "/dev/audio";
|
||||
|
||||
ao->fn = open(ao->device,O_WRONLY);
|
||||
|
||||
if(ao->fn < 0)
|
||||
{
|
||||
error1("Can't open %s!",ao->device);
|
||||
return -1;
|
||||
}
|
||||
ioctl(ao->fn, AIOCGBLKSIZE, &outburst);
|
||||
if(outburst > MAXOUTBURST)
|
||||
outburst = MAXOUTBURST;
|
||||
if(audio_reset_parameters(ai) < 0) {
|
||||
close(ao->fn);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ao->fn;
|
||||
}
|
||||
|
||||
static int get_formats_mint(audio_output_t *ao)
|
||||
{
|
||||
int ret = 0;
|
||||
int fmts;
|
||||
|
||||
if(ioctl(ao->fn,AIOCGFMTS,&fmts) < 0)
|
||||
return -1;
|
||||
|
||||
if(fmts & AFMT_ULAW)
|
||||
ret |= MPG123_ENC_ULAW_8;
|
||||
if(fmts & AFMT_S16)
|
||||
ret |= MPG123_ENC_SIGNED_16;
|
||||
if(fmts & AFMT_U8)
|
||||
ret |= MPG123_ENC_UNSIGNED_8;
|
||||
if(fmts & AFMT_S8)
|
||||
ret |= MPG123_ENC_SIGNED_8;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int write_mint(audio_output_t *ao,unsigned char *buf,int len)
|
||||
{
|
||||
return write(ao->fn,buf,len);
|
||||
}
|
||||
|
||||
static int close_mint(audio_output_t *ao)
|
||||
{
|
||||
close (ao->fn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void flush_mint(audio_output_t *ao)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
static int init_mint(audio_output_t* ao)
|
||||
{
|
||||
if (ao==NULL) return -1;
|
||||
|
||||
/* Set callbacks */
|
||||
ao->open = open_mint;
|
||||
ao->flush = flush_mint;
|
||||
ao->write = write_mint;
|
||||
ao->get_formats = get_formats_mint;
|
||||
ao->close = close_mint;
|
||||
|
||||
/* Success */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Module information data structure
|
||||
*/
|
||||
mpg123_module_t mpg123_output_module_info = {
|
||||
/* api_version */ MPG123_MODULE_API_VERSION,
|
||||
/* name */ "mint",
|
||||
/* description */ "Audio output for MINT.",
|
||||
/* revision */ "$Rev:$",
|
||||
/* handle */ NULL,
|
||||
|
||||
/* init_output */ init_mint,
|
||||
};
|
||||
|
||||
|
335
node_modules/lame/deps/mpg123/src/output/nas.c
generated
vendored
Normal file
335
node_modules/lame/deps/mpg123/src/output/nas.c
generated
vendored
Normal file
@ -0,0 +1,335 @@
|
||||
/*
|
||||
nas: audio output via NAS
|
||||
|
||||
copyright ?-2006 by the mpg123 project - free software under the terms of the LGPL 2.1
|
||||
see COPYING and AUTHORS files in distribution or http://mpg123.org
|
||||
initially written by Martin Denn
|
||||
*/
|
||||
|
||||
#include "mpg123app.h"
|
||||
#include <fcntl.h>
|
||||
#include <audio/audiolib.h>
|
||||
#include <audio/soundlib.h>
|
||||
#include "debug.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
AuServer *aud;
|
||||
AuFlowID flow;
|
||||
AuDeviceAttributes *da;
|
||||
int numDevices;
|
||||
char *buf;
|
||||
AuUint32 buf_size;
|
||||
AuUint32 buf_cnt;
|
||||
AuBool data_sent;
|
||||
AuBool finished;
|
||||
} InfoRec, *InfoPtr;
|
||||
|
||||
#define NAS_SOUND_PORT_DURATION 5 /* seconds */
|
||||
#define NAS_SOUND_LOW_WATER_MARK 25 /* percent */
|
||||
#define NAS_MAX_FORMAT 10 /* currently, there are 7 supported formats */
|
||||
|
||||
|
||||
/* FIXME: stick this inside userptr inside audio_output_t instead */
|
||||
static InfoRec info;
|
||||
|
||||
/* NAS specific routines */
|
||||
|
||||
static void nas_sendData(AuServer *aud, InfoPtr i, AuUint32 numBytes)
|
||||
{
|
||||
if (numBytes < i->buf_cnt) {
|
||||
AuWriteElement(aud, i->flow, 0, numBytes, i->buf, AuFalse, NULL);
|
||||
memmove(i->buf, i->buf + numBytes, i->buf_cnt - numBytes);
|
||||
i->buf_cnt = i->buf_cnt - numBytes;
|
||||
}
|
||||
else {
|
||||
AuWriteElement(aud, i->flow, 0, i->buf_cnt, i->buf,
|
||||
(numBytes > i->buf_cnt), NULL);
|
||||
i->buf_cnt = 0;
|
||||
}
|
||||
i->data_sent = AuTrue;
|
||||
}
|
||||
|
||||
static AuBool nas_eventHandler(AuServer *aud, AuEvent *ev, AuEventHandlerRec *handler)
|
||||
{
|
||||
InfoPtr i = (InfoPtr) handler->data;
|
||||
|
||||
switch (ev->type)
|
||||
{
|
||||
case AuEventTypeMonitorNotify:
|
||||
i->finished = AuTrue;
|
||||
break;
|
||||
case AuEventTypeElementNotify:
|
||||
{
|
||||
AuElementNotifyEvent *event = (AuElementNotifyEvent *) ev;
|
||||
|
||||
switch (event->kind)
|
||||
{
|
||||
case AuElementNotifyKindLowWater:
|
||||
nas_sendData(aud, i, event->num_bytes);
|
||||
break;
|
||||
case AuElementNotifyKindState:
|
||||
switch (event->cur_state)
|
||||
{
|
||||
case AuStatePause:
|
||||
if (event->reason != AuReasonUser)
|
||||
nas_sendData(aud, i, event->num_bytes);
|
||||
break;
|
||||
case AuStateStop:
|
||||
i->finished = AuTrue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return AuTrue;
|
||||
}
|
||||
|
||||
/* 0 on error */
|
||||
static int nas_createFlow(audio_output_t *ao)
|
||||
{
|
||||
AuDeviceID device = AuNone;
|
||||
AuElement elements[2];
|
||||
unsigned char format;
|
||||
AuUint32 buf_samples;
|
||||
int i;
|
||||
|
||||
|
||||
switch(ao->format) {
|
||||
case MPG123_ENC_SIGNED_16:
|
||||
default:
|
||||
if (((char) *(short *)"x")=='x') /* ugly, but painless */
|
||||
format = AuFormatLinearSigned16LSB; /* little endian */
|
||||
else
|
||||
format = AuFormatLinearSigned16MSB; /* big endian */
|
||||
break;
|
||||
case MPG123_ENC_UNSIGNED_8:
|
||||
format = AuFormatLinearUnsigned8;
|
||||
break;
|
||||
case MPG123_ENC_SIGNED_8:
|
||||
format = AuFormatLinearSigned8;
|
||||
break;
|
||||
case MPG123_ENC_ULAW_8:
|
||||
format = AuFormatULAW8;
|
||||
break;
|
||||
}
|
||||
/* look for an output device */
|
||||
for (i = 0; i < AuServerNumDevices(info.aud); i++)
|
||||
if (((AuDeviceKind(AuServerDevice(info.aud, i)) ==
|
||||
AuComponentKindPhysicalOutput) &&
|
||||
AuDeviceNumTracks(AuServerDevice(info.aud, i))
|
||||
== ao->channels )) {
|
||||
device = AuDeviceIdentifier(AuServerDevice(info.aud, i));
|
||||
break;
|
||||
}
|
||||
if (device == AuNone) {
|
||||
error1("Couldn't find an output device providing %d channels.", ao->channels);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* set gain */
|
||||
if(ao->gain >= 0) {
|
||||
info.da = AuGetDeviceAttributes(info.aud, device, NULL);
|
||||
if ((info.da)!=NULL) {
|
||||
AuDeviceGain(info.da) = AuFixedPointFromSum(ao->gain, 0);
|
||||
AuSetDeviceAttributes(info.aud, AuDeviceIdentifier(info.da),
|
||||
AuCompDeviceGainMask, info.da, NULL);
|
||||
}
|
||||
else
|
||||
error("audio/gain: setable Volume/PCM-Level not supported");
|
||||
}
|
||||
|
||||
if (!(info.flow = AuCreateFlow(info.aud, NULL))) {
|
||||
error("Couldn't create flow");
|
||||
return 0;
|
||||
}
|
||||
|
||||
buf_samples = ao->rate * NAS_SOUND_PORT_DURATION;
|
||||
|
||||
AuMakeElementImportClient(&elements[0], /* element */
|
||||
(unsigned short) ao->rate,
|
||||
/* rate */
|
||||
format, /* format */
|
||||
ao->channels, /* channels */
|
||||
AuTrue, /* ??? */
|
||||
buf_samples, /* max samples */
|
||||
(AuUint32) (buf_samples / 100
|
||||
* NAS_SOUND_LOW_WATER_MARK),
|
||||
/* low water mark */
|
||||
0, /* num actions */
|
||||
NULL); /* actions */
|
||||
AuMakeElementExportDevice(&elements[1], /* element */
|
||||
0, /* input */
|
||||
device, /* device */
|
||||
(unsigned short) ao->rate,
|
||||
/* rate */
|
||||
AuUnlimitedSamples, /* num samples */
|
||||
0, /* num actions */
|
||||
NULL); /* actions */
|
||||
AuSetElements(info.aud, /* Au server */
|
||||
info.flow, /* flow ID */
|
||||
AuTrue, /* clocked */
|
||||
2, /* num elements */
|
||||
elements, /* elements */
|
||||
NULL); /* return status */
|
||||
|
||||
AuRegisterEventHandler(info.aud, /* Au server */
|
||||
AuEventHandlerIDMask, /* value mask */
|
||||
0, /* type */
|
||||
info.flow, /* id */
|
||||
nas_eventHandler, /* callback */
|
||||
(AuPointer) &info); /* data */
|
||||
|
||||
info.buf_size = buf_samples * ao->channels * AuSizeofFormat(format);
|
||||
info.buf = (char *) malloc(info.buf_size);
|
||||
if (info.buf == NULL) {
|
||||
error1("Unable to allocate input/output buffer of size %ld",
|
||||
(long)info.buf_size);
|
||||
return 0;
|
||||
}
|
||||
info.buf_cnt = 0;
|
||||
info.data_sent = AuFalse;
|
||||
info.finished = AuFalse;
|
||||
|
||||
AuStartFlow(info.aud, /* Au server */
|
||||
info.flow, /* id */
|
||||
NULL); /* status */
|
||||
return 1; /* success */
|
||||
}
|
||||
|
||||
|
||||
static void flush_nas(audio_output_t *ao)
|
||||
{
|
||||
AuEvent ev;
|
||||
|
||||
while ((!info.data_sent) && (!info.finished)) {
|
||||
AuNextEvent(info.aud, AuTrue, &ev);
|
||||
AuDispatchEvent(info.aud, &ev);
|
||||
}
|
||||
info.data_sent = AuFalse;
|
||||
}
|
||||
|
||||
|
||||
/* returning -1 on error, 0 on success... */
|
||||
static int open_nas(audio_output_t *ao)
|
||||
{
|
||||
if(!ao) return -1;
|
||||
|
||||
if (!(info.aud = AuOpenServer(ao->device, 0, NULL, 0, NULL, NULL))) {
|
||||
if (ao->device==NULL) {
|
||||
error("could not open default NAS server");
|
||||
} else {
|
||||
error1("could not open NAS server %s\n", ao->device);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
info.buf_size = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int get_formats_nas(audio_output_t *ao)
|
||||
{
|
||||
int i, j, k, ret;
|
||||
|
||||
ret=0;
|
||||
j = AuServerNumFormats(info.aud);
|
||||
for (i=0; i<j; i++) {
|
||||
k=AuServerFormat(info.aud,i);
|
||||
switch (k)
|
||||
{
|
||||
case AuFormatULAW8:
|
||||
ret |= MPG123_ENC_ULAW_8;
|
||||
break;
|
||||
case AuFormatLinearUnsigned8:
|
||||
ret |= MPG123_ENC_UNSIGNED_8;
|
||||
break;
|
||||
case AuFormatLinearSigned8:
|
||||
ret |= MPG123_ENC_SIGNED_8;
|
||||
break;
|
||||
case AuFormatLinearSigned16LSB:
|
||||
ret |= MPG123_ENC_SIGNED_16;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int write_nas(audio_output_t *ao,unsigned char *buf,int len)
|
||||
{
|
||||
int buf_cnt = 0;
|
||||
|
||||
if (info.buf_size == 0)
|
||||
if(!nas_createFlow(ao)) return -1;
|
||||
|
||||
while ((info.buf_cnt + (len - buf_cnt)) > info.buf_size) {
|
||||
memcpy(info.buf + info.buf_cnt,
|
||||
buf + buf_cnt,
|
||||
(info.buf_size - info.buf_cnt));
|
||||
buf_cnt += (info.buf_size - info.buf_cnt);
|
||||
info.buf_cnt += (info.buf_size - info.buf_cnt);
|
||||
flush_nas(ao);
|
||||
}
|
||||
memcpy(info.buf + info.buf_cnt,
|
||||
buf + buf_cnt,
|
||||
(len - buf_cnt));
|
||||
info.buf_cnt += (len - buf_cnt);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int close_nas(audio_output_t *ao)
|
||||
{
|
||||
if (info.aud == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (info.buf_size == 0) {
|
||||
/* Au server opened, but not yet initialized */
|
||||
AuCloseServer(info.aud);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (!info.finished) {
|
||||
flush_nas(ao);
|
||||
}
|
||||
AuCloseServer(info.aud);
|
||||
free(info.buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int init_nas(audio_output_t* ao)
|
||||
{
|
||||
if (ao==NULL) return -1;
|
||||
|
||||
/* Set callbacks */
|
||||
ao->open = open_nas;
|
||||
ao->flush = flush_nas;
|
||||
ao->write = write_nas;
|
||||
ao->get_formats = get_formats_nas;
|
||||
ao->close = close_nas;
|
||||
|
||||
/* Success */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Module information data structure
|
||||
*/
|
||||
mpg123_module_t mpg123_output_module_info = {
|
||||
/* api_version */ MPG123_MODULE_API_VERSION,
|
||||
/* name */ "nas",
|
||||
/* description */ "Output audio using NAS (Network Audio System)",
|
||||
/* revision */ "$Rev:$",
|
||||
/* handle */ NULL,
|
||||
|
||||
/* init_output */ init_nas,
|
||||
};
|
||||
|
||||
|
197
node_modules/lame/deps/mpg123/src/output/openal.c
generated
vendored
Normal file
197
node_modules/lame/deps/mpg123/src/output/openal.c
generated
vendored
Normal file
@ -0,0 +1,197 @@
|
||||
/*
|
||||
openal.c: audio output on OpenAL
|
||||
|
||||
copyright 1995-2009 by the mpg123 project - free software under the terms of the LGPL 2.1
|
||||
see COPYING and AUTHORS files in distribution or http://mpg123.org
|
||||
initially written by Taihei Monma
|
||||
*/
|
||||
|
||||
|
||||
#include "mpg123app.h"
|
||||
|
||||
#ifdef OPENAL_SUBDIR_OPENAL
|
||||
#include <OpenAL/al.h>
|
||||
#include <OpenAL/alc.h>
|
||||
#elif defined(OPENAL_SUBDIR_AL)
|
||||
#include <AL/al.h>
|
||||
#include <AL/alc.h>
|
||||
#else
|
||||
#include <al.h>
|
||||
#include <alc.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#define NUM_BUFFERS 16
|
||||
|
||||
#ifndef AL_FORMAT_MONO_FLOAT32
|
||||
#define AL_FORMAT_MONO_FLOAT32 0x10010
|
||||
#endif
|
||||
#ifndef AL_FORMAT_STEREO_FLOAT32
|
||||
#define AL_FORMAT_STEREO_FLOAT32 0x10011
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ALCdevice *device;
|
||||
ALCcontext *context;
|
||||
ALuint source, buffer;
|
||||
ALenum format;
|
||||
ALsizei rate;
|
||||
} mpg123_openal_t;
|
||||
|
||||
|
||||
static int open_openal(audio_output_t *ao)
|
||||
{
|
||||
mpg123_openal_t* al = (mpg123_openal_t*)ao->userptr;
|
||||
|
||||
al->device = alcOpenDevice(NULL);
|
||||
al->context = alcCreateContext(al->device, NULL);
|
||||
alcMakeContextCurrent(al->context);
|
||||
alGenSources(1, &al->source);
|
||||
|
||||
al->rate = ao->rate;
|
||||
if(ao->format == MPG123_ENC_SIGNED_16 && ao->channels == 2) al->format = AL_FORMAT_STEREO16;
|
||||
else if(ao->format == MPG123_ENC_SIGNED_16 && ao->channels == 1) al->format = AL_FORMAT_MONO16;
|
||||
else if(ao->format == MPG123_ENC_UNSIGNED_8 && ao->channels == 2) al->format = AL_FORMAT_STEREO8;
|
||||
else if(ao->format == MPG123_ENC_UNSIGNED_8 && ao->channels == 1) al->format = AL_FORMAT_MONO8;
|
||||
else if(ao->format == MPG123_ENC_FLOAT_32 && ao->channels == 2) al->format = AL_FORMAT_STEREO_FLOAT32;
|
||||
else if(ao->format == MPG123_ENC_FLOAT_32 && ao->channels == 1) al->format = AL_FORMAT_MONO_FLOAT32;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_formats_openal(audio_output_t *ao)
|
||||
{
|
||||
return MPG123_ENC_SIGNED_16|MPG123_ENC_UNSIGNED_8|((alIsExtensionPresent((ALubyte*)"AL_EXT_float32") == AL_TRUE) ? MPG123_ENC_FLOAT_32 : 0);
|
||||
}
|
||||
|
||||
static int write_openal(audio_output_t *ao, unsigned char *buf, int len)
|
||||
{
|
||||
ALint state, n;
|
||||
mpg123_openal_t* al = (mpg123_openal_t*)ao->userptr;
|
||||
|
||||
alGetSourcei(al->source, AL_BUFFERS_QUEUED, &n);
|
||||
if(n < NUM_BUFFERS)
|
||||
{
|
||||
alGenBuffers(1, &al->buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
alGetSourcei(al->source, AL_SOURCE_STATE, &state);
|
||||
if(state != AL_PLAYING)
|
||||
{
|
||||
alSourcePlay(al->source);
|
||||
}
|
||||
while(alGetSourcei(al->source, AL_BUFFERS_PROCESSED, &n), n == 0)
|
||||
{
|
||||
usleep(10000);
|
||||
}
|
||||
alSourceUnqueueBuffers(al->source, 1, &al->buffer);
|
||||
}
|
||||
|
||||
alBufferData(al->buffer, al->format, buf, len, al->rate);
|
||||
alSourceQueueBuffers(al->source, 1, &al->buffer);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int close_openal(audio_output_t *ao)
|
||||
{
|
||||
ALint state, n;
|
||||
mpg123_openal_t* al = (mpg123_openal_t*)ao->userptr;
|
||||
|
||||
if (al)
|
||||
{
|
||||
/* wait until all buffers are consumed */
|
||||
while(alGetSourcei(al->source, AL_SOURCE_STATE, &state), state == AL_PLAYING)
|
||||
{
|
||||
usleep(10000);
|
||||
}
|
||||
/* free all processed buffers */
|
||||
while(alGetSourcei(al->source, AL_BUFFERS_PROCESSED, &n), n > 0)
|
||||
{
|
||||
alSourceUnqueueBuffers(al->source, 1, &al->buffer);
|
||||
alDeleteBuffers(1, &al->buffer);
|
||||
}
|
||||
alDeleteSources(1, &al->source);
|
||||
alcMakeContextCurrent(NULL);
|
||||
alcDestroyContext(al->context);
|
||||
alcCloseDevice(al->device);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void flush_openal(audio_output_t *ao)
|
||||
{
|
||||
ALint n;
|
||||
mpg123_openal_t* al = (mpg123_openal_t*)ao->userptr;
|
||||
|
||||
if (al)
|
||||
{
|
||||
/* stop playing and flush all buffers */
|
||||
alSourceStop(al->source);
|
||||
while(alGetSourcei(al->source, AL_BUFFERS_PROCESSED, &n), n > 0)
|
||||
{
|
||||
alSourceUnqueueBuffers(al->source, 1, &al->buffer);
|
||||
alDeleteBuffers(1, &al->buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int deinit_openal(audio_output_t* ao)
|
||||
{
|
||||
/* Free up memory */
|
||||
if(ao->userptr)
|
||||
{
|
||||
free( ao->userptr );
|
||||
ao->userptr = NULL;
|
||||
}
|
||||
|
||||
/* Success */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init_openal(audio_output_t* ao)
|
||||
{
|
||||
if (ao==NULL) return -1;
|
||||
|
||||
/* Set callbacks */
|
||||
ao->open = open_openal;
|
||||
ao->flush = flush_openal;
|
||||
ao->write = write_openal;
|
||||
ao->get_formats = get_formats_openal;
|
||||
ao->close = close_openal;
|
||||
ao->deinit = deinit_openal;
|
||||
|
||||
/* Allocate memory for data structure */
|
||||
ao->userptr = malloc( sizeof( mpg123_openal_t ) );
|
||||
if(ao->userptr==NULL)
|
||||
{
|
||||
error("failed to malloc memory for 'mpg123_openal_t'");
|
||||
return -1;
|
||||
}
|
||||
memset( ao->userptr, 0, sizeof(mpg123_openal_t) );
|
||||
|
||||
/* Success */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Module information data structure
|
||||
*/
|
||||
mpg123_module_t mpg123_output_module_info = {
|
||||
/* api_version */ MPG123_MODULE_API_VERSION,
|
||||
/* name */ "openal",
|
||||
/* description */ "Output audio using OpenAL.",
|
||||
/* revision */ "$Rev:$",
|
||||
/* handle */ NULL,
|
||||
|
||||
/* init_output */ init_openal,
|
||||
};
|
||||
|
||||
|
665
node_modules/lame/deps/mpg123/src/output/os2.c
generated
vendored
Normal file
665
node_modules/lame/deps/mpg123/src/output/os2.c
generated
vendored
Normal file
@ -0,0 +1,665 @@
|
||||
/*
|
||||
os2: OS/2 RealTime DART Engine
|
||||
|
||||
copyright 1998-2006 by the mpg123 project - free software under the terms of the LGPL 2.1
|
||||
see COPYING and AUTHORS files in distribution or http://mpg123.org
|
||||
initially written by Samuel Audet
|
||||
*/
|
||||
|
||||
#define INCL_OS2MM
|
||||
#define INCL_DOS
|
||||
#define INCL_VIO
|
||||
#define INCL_KBD
|
||||
#include <os2.h>
|
||||
#include <os2me.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
/* I guess this #ifndef could be removed now... */
|
||||
#ifndef MPG123_INCLUDED
|
||||
#include "mpg123app.h"
|
||||
#endif
|
||||
#include "debug.h"
|
||||
|
||||
/* complementary audio parameters */
|
||||
int numbuffers = 5; /* total audio buffers, _bare_ minimum = 4 (cuz of prio boost check) */
|
||||
int audiobufsize = 4884;
|
||||
int lockdevice = FALSE;
|
||||
USHORT volume = 100;
|
||||
char *boostprio = NULL;
|
||||
char *normalprio = NULL;
|
||||
unsigned char boostclass = 3, normalclass = 2;
|
||||
signed char boostdelta = 0, normaldelta = 31;
|
||||
unsigned char mmerror[160] = {0};
|
||||
int playingframe;
|
||||
|
||||
/* audio buffers */
|
||||
static ULONG ulMCIBuffers;
|
||||
|
||||
static MCI_AMP_OPEN_PARMS maop = {0};
|
||||
static MCI_MIXSETUP_PARMS mmp = {0};
|
||||
static MCI_BUFFER_PARMS mbp = {0};
|
||||
static MCI_GENERIC_PARMS mgp = {0};
|
||||
static MCI_SET_PARMS msp = {0};
|
||||
static MCI_STATUS_PARMS mstatp = {0};
|
||||
static MCI_MIX_BUFFER *MixBuffers = NULL;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
MCI_MIX_BUFFER *NextBuffer;
|
||||
int frameNum;
|
||||
} BUFFERINFO;
|
||||
|
||||
BUFFERINFO *bufferinfo = NULL;
|
||||
|
||||
|
||||
static HEV dataplayed = 0;
|
||||
static ULONG resetcount;
|
||||
static BOOL paused = FALSE;
|
||||
|
||||
static MCI_MIX_BUFFER *tobefilled, *playingbuffer = NULL, playedbuffer;
|
||||
static void *pBufferplayed;
|
||||
|
||||
static BOOL nomoredata,nobuffermode,justflushed;
|
||||
|
||||
static TIB *mainthread; /* thread info to set thread priority */
|
||||
|
||||
ULONG keyboardtid;
|
||||
|
||||
|
||||
static LONG APIENTRY DARTEvent(ULONG ulStatus, MCI_MIX_BUFFER *PlayedBuffer, ULONG ulFlags)
|
||||
{
|
||||
switch(ulFlags)
|
||||
{
|
||||
case MIX_STREAM_ERROR | MIX_WRITE_COMPLETE: /* error occur in device */
|
||||
|
||||
if ( ulStatus == ERROR_DEVICE_UNDERRUN)
|
||||
/* Write buffers to rekick off the amp mixer. */
|
||||
mmp.pmixWrite( mmp.ulMixHandle, MixBuffers, ulMCIBuffers );
|
||||
break;
|
||||
|
||||
case MIX_WRITE_COMPLETE: /* for playback */
|
||||
|
||||
playingbuffer = ((BUFFERINFO *) PlayedBuffer->ulUserParm)->NextBuffer;
|
||||
|
||||
/* the next three lines are only useful to audio_playing_samples() */
|
||||
playedbuffer = *PlayedBuffer;
|
||||
playedbuffer.pBuffer = pBufferplayed;
|
||||
memcpy(playedbuffer.pBuffer, PlayedBuffer->pBuffer, PlayedBuffer->ulBufferLength);
|
||||
|
||||
/* just too bad, the decoder fell behind... here we just keep the
|
||||
buffer to be filled in front of the playing one so that when the
|
||||
decoder kicks back in, we'll hear it in at the right time */
|
||||
if(tobefilled == playingbuffer)
|
||||
{
|
||||
tobefilled = ((BUFFERINFO *) playingbuffer->ulUserParm)->NextBuffer;
|
||||
nomoredata = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
playingframe = ((BUFFERINFO *) playingbuffer->ulUserParm)->frameNum;
|
||||
|
||||
/* if we're about to be short of decoder's data
|
||||
(2nd ahead buffer not filled), let's boost its priority! */
|
||||
if(tobefilled == ( (BUFFERINFO *) ((BUFFERINFO *) playingbuffer->ulUserParm)->NextBuffer->ulUserParm)->NextBuffer)
|
||||
DosSetPriority(PRTYS_THREAD,boostclass,boostdelta,mainthread->tib_ptib2->tib2_ultid);
|
||||
}
|
||||
|
||||
/* empty the played buffer in case it doesn't get filled back */
|
||||
memset(PlayedBuffer->pBuffer,0,PlayedBuffer->ulBufferLength);
|
||||
|
||||
DosPostEventSem(dataplayed);
|
||||
|
||||
mmp.pmixWrite( mmp.ulMixHandle, PlayedBuffer, 1 );
|
||||
break;
|
||||
|
||||
} /* end switch */
|
||||
|
||||
return( TRUE );
|
||||
|
||||
} /* end DARTEvent */
|
||||
|
||||
|
||||
static void MciError(ULONG ulError)
|
||||
{
|
||||
unsigned char buffer[128];
|
||||
ULONG rc;
|
||||
|
||||
rc = mciGetErrorString(ulError, buffer, sizeof(buffer));
|
||||
|
||||
if (rc == MCIERR_SUCCESS)
|
||||
sprintf(mmerror,"MCI Error %d: %s",ULONG_LOWD(ulError),buffer);
|
||||
else
|
||||
sprintf(mmerror,"MCI Error %d: Cannot query error message.",ULONG_LOWD(rc));
|
||||
|
||||
error1("%s",mmerror);
|
||||
}
|
||||
|
||||
|
||||
static int set_volume(audio_output_t *ao, USHORT setvolume)
|
||||
{
|
||||
if(setvolume > 100) setvolume = 100;
|
||||
volume = setvolume; /* useful when device is closed and reopened */
|
||||
|
||||
if(maop.usDeviceID)
|
||||
{
|
||||
memset(&msp,0,sizeof(msp));
|
||||
msp.ulAudio = MCI_SET_AUDIO_ALL;
|
||||
msp.ulLevel = setvolume;
|
||||
|
||||
mciSendCommand(maop.usDeviceID, MCI_SET,
|
||||
MCI_WAIT | MCI_SET_AUDIO | MCI_SET_VOLUME,
|
||||
&msp, 0);
|
||||
}
|
||||
return setvolume;
|
||||
}
|
||||
|
||||
|
||||
int open_os2(audio_output_t *ao)
|
||||
{
|
||||
ULONG rc,i;
|
||||
char *temp;
|
||||
ULONG openflags;
|
||||
PPIB ppib;
|
||||
USHORT bits;
|
||||
|
||||
if(maop.usDeviceID) return (maop.usDeviceID);
|
||||
|
||||
if(!ao) return -1;
|
||||
|
||||
if(!ao->device) ao->device = "0";
|
||||
|
||||
if(ao->rate < 0) ao->rate = 44100;
|
||||
if(ao->channels < 0) ao->channels = 2;
|
||||
if(ao->format < 0) ao->format = MPG123_ENC_SIGNED_16;
|
||||
|
||||
if(ao->format == MPG123_ENC_SIGNED_16)
|
||||
bits = 16;
|
||||
else if(ao->format == MPG123_ENC_UNSIGNED_8)
|
||||
bits = 8;
|
||||
else return -1;
|
||||
|
||||
/* open the mixer device */
|
||||
memset (&maop, 0, sizeof(maop));
|
||||
maop.usDeviceID = 0;
|
||||
maop.pszDeviceType = (PSZ) MAKEULONG(MCI_DEVTYPE_AUDIO_AMPMIX, atoi(ao->device));
|
||||
|
||||
openflags = MCI_WAIT | MCI_OPEN_TYPE_ID;
|
||||
if(!lockdevice) openflags |= MCI_OPEN_SHAREABLE;
|
||||
|
||||
rc = mciSendCommand(0, MCI_OPEN, openflags, &maop, 0);
|
||||
|
||||
if (ULONG_LOWD(rc) != MCIERR_SUCCESS)
|
||||
{
|
||||
MciError(rc);
|
||||
maop.usDeviceID = 0;
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* volume in ao->gain ?? */
|
||||
|
||||
/* Set the MCI_MIXSETUP_PARMS data structure to match the audio stream. */
|
||||
|
||||
memset(&mmp, 0, sizeof(mmp));
|
||||
|
||||
mmp.ulBitsPerSample = bits;
|
||||
mmp.ulFormatTag = MCI_WAVE_FORMAT_PCM;
|
||||
mmp.ulSamplesPerSec = ao->rate;
|
||||
mmp.ulChannels = ao->channels;
|
||||
|
||||
/* Setup the mixer for playback of wave data */
|
||||
mmp.ulFormatMode = MCI_PLAY;
|
||||
mmp.ulDeviceType = MCI_DEVTYPE_WAVEFORM_AUDIO;
|
||||
mmp.pmixEvent = DARTEvent;
|
||||
|
||||
rc = mciSendCommand( maop.usDeviceID,
|
||||
MCI_MIXSETUP,
|
||||
MCI_WAIT | MCI_MIXSETUP_INIT,
|
||||
&mmp,
|
||||
0 );
|
||||
|
||||
if ( ULONG_LOWD(rc) != MCIERR_SUCCESS )
|
||||
{
|
||||
MciError(rc);
|
||||
maop.usDeviceID = 0;
|
||||
return(-1);
|
||||
}
|
||||
|
||||
volume = set_volume(ao,volume);
|
||||
|
||||
/* Set up the BufferParms data structure and allocate
|
||||
* device buffers from the Amp-Mixer */
|
||||
|
||||
memset(&mbp, 0, sizeof(mbp));
|
||||
free(MixBuffers);
|
||||
free(bufferinfo);
|
||||
if(numbuffers < 5) numbuffers = 5;
|
||||
if(numbuffers > 200) numbuffers = 200;
|
||||
MixBuffers = calloc(numbuffers, sizeof(*MixBuffers));
|
||||
bufferinfo = calloc(numbuffers, sizeof(*bufferinfo));
|
||||
|
||||
ulMCIBuffers = numbuffers;
|
||||
mbp.ulNumBuffers = ulMCIBuffers;
|
||||
/* mbp.ulBufferSize = mmp.ulBufferSize; */
|
||||
/* I don't like this... they must be smaller than 64KB or else the
|
||||
engine needs major rewrite */
|
||||
mbp.ulBufferSize = audiobufsize;
|
||||
mbp.pBufList = MixBuffers;
|
||||
|
||||
rc = mciSendCommand( maop.usDeviceID,
|
||||
MCI_BUFFER,
|
||||
MCI_WAIT | MCI_ALLOCATE_MEMORY,
|
||||
(PVOID) &mbp,
|
||||
0 );
|
||||
|
||||
if ( ULONG_LOWD(rc) != MCIERR_SUCCESS )
|
||||
{
|
||||
MciError(rc);
|
||||
maop.usDeviceID = 0;
|
||||
return(-1);
|
||||
}
|
||||
|
||||
pBufferplayed = playedbuffer.pBuffer = calloc(1,audiobufsize);
|
||||
|
||||
ulMCIBuffers = mbp.ulNumBuffers; /* never know! */
|
||||
|
||||
/* Fill all device buffers with zeros and set linked list */
|
||||
|
||||
for(i = 0; i < ulMCIBuffers; i++)
|
||||
{
|
||||
MixBuffers[i].ulFlags = 0;
|
||||
MixBuffers[i].ulBufferLength = mbp.ulBufferSize;
|
||||
memset(MixBuffers[i].pBuffer, 0, MixBuffers[i].ulBufferLength);
|
||||
|
||||
MixBuffers[i].ulUserParm = (ULONG) &bufferinfo[i];
|
||||
bufferinfo[i].NextBuffer = &MixBuffers[i+1];
|
||||
}
|
||||
|
||||
bufferinfo[i-1].NextBuffer = &MixBuffers[0];
|
||||
|
||||
/* Create a semaphore to know when data has been played by the DART thread */
|
||||
DosCreateEventSem(NULL,&dataplayed,0,FALSE);
|
||||
|
||||
playingbuffer = &MixBuffers[0];
|
||||
tobefilled = &MixBuffers[1];
|
||||
playingframe = 0;
|
||||
nomoredata = TRUE;
|
||||
nobuffermode = FALSE;
|
||||
justflushed = FALSE;
|
||||
|
||||
if(boostprio)
|
||||
{
|
||||
temp = alloca(strlen(boostprio)+1);
|
||||
strcpy(temp,boostprio);
|
||||
|
||||
boostdelta = atoi(temp+1);
|
||||
*(temp+1) = 0;
|
||||
boostclass = atoi(temp);
|
||||
}
|
||||
if(boostclass > 4) boostdelta = 3;
|
||||
if(boostdelta > 31) boostdelta = 31;
|
||||
if(boostdelta < -31) boostdelta = -31;
|
||||
|
||||
|
||||
if(normalprio)
|
||||
{
|
||||
temp = alloca(strlen(normalprio)+1);
|
||||
strcpy(temp,normalprio);
|
||||
|
||||
normaldelta = atoi(temp+1);
|
||||
*(temp+1) = 0;
|
||||
normalclass = atoi(temp);
|
||||
}
|
||||
if(normalclass > 4) normaldelta = 3;
|
||||
if(normaldelta > 31) normaldelta = 31;
|
||||
if(normaldelta < -31) normaldelta = -31;
|
||||
|
||||
|
||||
DosGetInfoBlocks(&mainthread,&ppib); /* ppib not needed, but makes some DOSCALLS.DLL crash */
|
||||
DosSetPriority(PRTYS_THREAD,boostclass,boostdelta,mainthread->tib_ptib2->tib2_ultid);
|
||||
|
||||
/* Write buffers to kick off the amp mixer. see DARTEvent() */
|
||||
rc = mmp.pmixWrite( mmp.ulMixHandle,
|
||||
MixBuffers,
|
||||
ulMCIBuffers );
|
||||
|
||||
return maop.usDeviceID;
|
||||
}
|
||||
|
||||
|
||||
static int write_os2(audio_output_t *ao,unsigned char *buf,int len)
|
||||
{
|
||||
/* if we're too quick, let's wait */
|
||||
if(nobuffermode)
|
||||
{
|
||||
MCI_MIX_BUFFER *temp = playingbuffer;
|
||||
|
||||
while(
|
||||
(tobefilled != (temp = ((BUFFERINFO *) temp->ulUserParm)->NextBuffer)) &&
|
||||
(tobefilled != (temp = ((BUFFERINFO *) temp->ulUserParm)->NextBuffer)) &&
|
||||
(tobefilled != (temp = ((BUFFERINFO *) temp->ulUserParm)->NextBuffer)) )
|
||||
{
|
||||
DosResetEventSem(dataplayed,&resetcount);
|
||||
DosWaitEventSem(dataplayed, -1);
|
||||
temp = playingbuffer;
|
||||
}
|
||||
|
||||
} else {
|
||||
while(tobefilled == playingbuffer)
|
||||
{
|
||||
DosResetEventSem(dataplayed,&resetcount);
|
||||
DosWaitEventSem(dataplayed, -1);
|
||||
}
|
||||
}
|
||||
|
||||
if (justflushed) {
|
||||
justflushed = FALSE;
|
||||
} else {
|
||||
nomoredata = FALSE;
|
||||
|
||||
memcpy(tobefilled->pBuffer, buf, len);
|
||||
tobefilled->ulBufferLength = len;
|
||||
// ((BUFFERINFO *) tobefilled->ulUserParm)->frameNum = fr->frameNum;
|
||||
|
||||
/* if we're out of the water (3rd ahead buffer filled),
|
||||
let's reduce our priority */
|
||||
if(tobefilled == ( (BUFFERINFO *) ( (BUFFERINFO *) ((BUFFERINFO *) playingbuffer->ulUserParm)->NextBuffer->ulUserParm)->NextBuffer->ulUserParm)->NextBuffer)
|
||||
DosSetPriority(PRTYS_THREAD,normalclass,normaldelta,mainthread->tib_ptib2->tib2_ultid);
|
||||
|
||||
tobefilled = ((BUFFERINFO *) tobefilled->ulUserParm)->NextBuffer;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int write_os2(audio_output_t *ao,unsigned char *buf,int len)
|
||||
{
|
||||
if(len > audiobufsize || !playingbuffer) return -1;
|
||||
|
||||
if(mmp.ulBitsPerSample == 16)
|
||||
ao->format = MPG123_ENC_SIGNED_16;
|
||||
else if(mmp.ulBitsPerSample == 8)
|
||||
ao->format = MPG123_ENC_UNSIGNED_8;
|
||||
else return -1;
|
||||
|
||||
ao->rate = mmp.ulSamplesPerSec;
|
||||
ao->channels = mmp.ulChannels;
|
||||
|
||||
if(buf && len)
|
||||
{
|
||||
ULONG rc;
|
||||
int upto;
|
||||
|
||||
mstatp.ulItem = MCI_STATUS_POSITION;
|
||||
|
||||
rc = mciSendCommand( maop.usDeviceID,
|
||||
MCI_STATUS,
|
||||
MCI_STATUS_ITEM | MCI_WAIT,
|
||||
&mstatp,
|
||||
0 );
|
||||
|
||||
if ( ULONG_LOWD(rc) != MCIERR_SUCCESS )
|
||||
{
|
||||
MciError(rc);
|
||||
maop.usDeviceID = 0;
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* this is hypocrite...
|
||||
DART returns the value in ulReturn instead of ulValue,
|
||||
also it returns in milliseconds and not MMTIME... arg */
|
||||
|
||||
upto = (mstatp.ulReturn-playedbuffer.ulTime) * mmp.ulSamplesPerSec / 1000;
|
||||
upto *= mmp.ulChannels * (mmp.ulBitsPerSample>>3);
|
||||
|
||||
/* if a timing problem occurs, let's at least not crash */
|
||||
if(upto > playingbuffer->ulBufferLength)
|
||||
upto = playingbuffer->ulBufferLength;
|
||||
|
||||
if(len < upto) {
|
||||
memcpy(buf,(char *) (playingbuffer->pBuffer)+upto-len, len);
|
||||
} else {
|
||||
memcpy(buf,(char *) playedbuffer.pBuffer+playedbuffer.ulBufferLength-(len-upto),len-upto);
|
||||
memcpy(buf+(len-upto),playingbuffer->pBuffer,upto);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
static int audio_nobuffermode(audio_output_t *ao, int setnobuffermode)
|
||||
{
|
||||
nobuffermode = setnobuffermode;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int audio_trash_buffers(audio_output_t *ao)
|
||||
{
|
||||
int i;
|
||||
|
||||
justflushed = TRUE;
|
||||
|
||||
// Fill all device buffers with zeros
|
||||
for(i = 0; i < ulMCIBuffers; i++)
|
||||
memset(MixBuffers[i].pBuffer, 0, MixBuffers[i].ulBufferLength);
|
||||
|
||||
tobefilled = ((BUFFERINFO *) playingbuffer->ulUserParm)->NextBuffer;
|
||||
nomoredata = TRUE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
*/
|
||||
|
||||
static int close_os2(audio_output_t *ao)
|
||||
{
|
||||
ULONG rc;
|
||||
|
||||
if(!maop.usDeviceID)
|
||||
return 0;
|
||||
|
||||
while(!nomoredata)
|
||||
{
|
||||
DosResetEventSem(dataplayed,&resetcount);
|
||||
DosWaitEventSem(dataplayed, -1);
|
||||
}
|
||||
|
||||
playingbuffer = NULL;
|
||||
|
||||
DosCloseEventSem(dataplayed);
|
||||
dataplayed = 0;
|
||||
|
||||
free(pBufferplayed);
|
||||
|
||||
rc = mciSendCommand( maop.usDeviceID,
|
||||
MCI_BUFFER,
|
||||
MCI_WAIT | MCI_DEALLOCATE_MEMORY,
|
||||
&mbp,
|
||||
0 );
|
||||
|
||||
if ( ULONG_LOWD(rc) != MCIERR_SUCCESS )
|
||||
{
|
||||
MciError(rc);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
free(bufferinfo);
|
||||
free(MixBuffers);
|
||||
bufferinfo = NULL;
|
||||
MixBuffers = NULL;
|
||||
|
||||
memset(&mbp, 0, sizeof(mbp));
|
||||
|
||||
rc = mciSendCommand( maop.usDeviceID,
|
||||
MCI_CLOSE,
|
||||
MCI_WAIT ,
|
||||
&mgp,
|
||||
0 );
|
||||
|
||||
if ( ULONG_LOWD(rc) != MCIERR_SUCCESS )
|
||||
{
|
||||
MciError(rc);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
memset(&maop, 0, sizeof(maop));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* get formats for specific channel/rate parameters
|
||||
*/
|
||||
int get_formats_os2(audio_output_t *ao)
|
||||
{
|
||||
int fmts = 0;
|
||||
ULONG rc;
|
||||
MCI_MIXSETUP_PARMS mmptemp = {0};
|
||||
|
||||
mmp.ulDeviceType = MCI_DEVTYPE_WAVEFORM_AUDIO;
|
||||
mmp.pmixEvent = DARTEvent;
|
||||
|
||||
mmptemp.ulFormatMode = MCI_PLAY;
|
||||
mmptemp.ulSamplesPerSec = ao->rate;
|
||||
mmptemp.ulChannels = ao->channels;
|
||||
|
||||
mmptemp.ulFormatTag = MCI_WAVE_FORMAT_PCM;
|
||||
mmptemp.ulBitsPerSample = 16;
|
||||
rc = mciSendCommand( maop.usDeviceID,
|
||||
MCI_MIXSETUP,
|
||||
MCI_WAIT | MCI_MIXSETUP_QUERYMODE,
|
||||
&mmptemp,
|
||||
0 );
|
||||
|
||||
if((ULONG_LOWD(rc) == MCIERR_SUCCESS) && (rc != 0x4000)) /* undocumented */
|
||||
fmts = fmts | MPG123_ENC_SIGNED_16;
|
||||
|
||||
mmptemp.ulFormatTag = MCI_WAVE_FORMAT_PCM;
|
||||
mmptemp.ulBitsPerSample = 8;
|
||||
rc = mciSendCommand( maop.usDeviceID,
|
||||
MCI_MIXSETUP,
|
||||
MCI_WAIT | MCI_MIXSETUP_QUERYMODE,
|
||||
&mmptemp,
|
||||
0 );
|
||||
|
||||
if((ULONG_LOWD(rc) == MCIERR_SUCCESS) && (rc != 0x4000)) /* undocumented */
|
||||
fmts = fmts | MPG123_ENC_UNSIGNED_8;
|
||||
|
||||
mmptemp.ulFormatTag = MCI_WAVE_FORMAT_ALAW;
|
||||
mmptemp.ulBitsPerSample = 8;
|
||||
rc = mciSendCommand( maop.usDeviceID,
|
||||
MCI_MIXSETUP,
|
||||
MCI_WAIT | MCI_MIXSETUP_QUERYMODE,
|
||||
&mmptemp,
|
||||
0 );
|
||||
|
||||
if((ULONG_LOWD(rc) == MCIERR_SUCCESS) && (rc != 0x4000)) /* undocumented */
|
||||
fmts = fmts | MPG123_ENC_ALAW_8;
|
||||
|
||||
mmptemp.ulFormatTag = MCI_WAVE_FORMAT_MULAW;
|
||||
mmptemp.ulBitsPerSample = 8;
|
||||
rc = mciSendCommand( maop.usDeviceID,
|
||||
MCI_MIXSETUP,
|
||||
MCI_WAIT | MCI_MIXSETUP_QUERYMODE,
|
||||
&mmptemp,
|
||||
0 );
|
||||
|
||||
if((ULONG_LOWD(rc) == MCIERR_SUCCESS) && (rc != 0x4000)) /* undocumented */
|
||||
fmts = fmts | MPG123_ENC_ULAW_8;
|
||||
|
||||
return fmts;
|
||||
}
|
||||
|
||||
static int get_devices_os2(char *info, int deviceid)
|
||||
{
|
||||
char buffer[128];
|
||||
MCI_SYSINFO_PARMS mip;
|
||||
|
||||
if(deviceid && info)
|
||||
{
|
||||
MCI_SYSINFO_LOGDEVICE mid;
|
||||
|
||||
mip.pszReturn = buffer;
|
||||
mip.ulRetSize = sizeof(buffer);
|
||||
mip.usDeviceType = MCI_DEVTYPE_AUDIO_AMPMIX;
|
||||
mip.ulNumber = deviceid;
|
||||
|
||||
mciSendCommand(0,
|
||||
MCI_SYSINFO,
|
||||
MCI_WAIT | MCI_SYSINFO_INSTALLNAME,
|
||||
&mip,
|
||||
0);
|
||||
|
||||
mip.ulItem = MCI_SYSINFO_QUERY_DRIVER;
|
||||
mip.pSysInfoParm = ∣
|
||||
strcpy(mid.szInstallName,buffer);
|
||||
|
||||
mciSendCommand(0,
|
||||
MCI_SYSINFO,
|
||||
MCI_WAIT | MCI_SYSINFO_ITEM,
|
||||
&mip,
|
||||
0);
|
||||
|
||||
strcpy(info,mid.szProductInfo);
|
||||
return deviceid;
|
||||
|
||||
} else {
|
||||
int number;
|
||||
|
||||
mip.pszReturn = buffer;
|
||||
mip.ulRetSize = sizeof(buffer);
|
||||
mip.usDeviceType = MCI_DEVTYPE_AUDIO_AMPMIX;
|
||||
|
||||
mciSendCommand(0,
|
||||
MCI_SYSINFO,
|
||||
MCI_WAIT | MCI_SYSINFO_QUANTITY,
|
||||
&mip,
|
||||
0);
|
||||
|
||||
number = atoi(mip.pszReturn);
|
||||
return number;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void flush_os2(audio_output_t *ao)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
static int init_os2(audio_output_t* ao)
|
||||
{
|
||||
if (ao==NULL) return -1;
|
||||
|
||||
/* Set callbacks */
|
||||
ao->open = open_os2;
|
||||
ao->flush = flush_os2;
|
||||
ao->write = write_os2;
|
||||
ao->get_formats = get_formats_os2;
|
||||
ao->close = close_os2;
|
||||
|
||||
/* Success */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Module information data structure
|
||||
*/
|
||||
mpg123_module_t mpg123_output_module_info = {
|
||||
/* api_version */ MPG123_MODULE_API_VERSION,
|
||||
/* name */ "os2",
|
||||
/* description */ "Audio output for OS2.",
|
||||
/* revision */ "$Rev:$",
|
||||
/* handle */ NULL,
|
||||
|
||||
/* init_output */ init_os2,
|
||||
};
|
||||
|
||||
|
319
node_modules/lame/deps/mpg123/src/output/oss.c
generated
vendored
Normal file
319
node_modules/lame/deps/mpg123/src/output/oss.c
generated
vendored
Normal file
@ -0,0 +1,319 @@
|
||||
/*
|
||||
oss: audio output via Open Sound System
|
||||
|
||||
copyright ?-2006 by the mpg123 project - free software under the terms of the LGPL 2.1
|
||||
see COPYING and AUTHORS files in distribution or http://mpg123.org
|
||||
initially written by Michael Hipp
|
||||
*/
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "mpg123app.h"
|
||||
|
||||
#ifdef HAVE_LINUX_SOUNDCARD_H
|
||||
#include <linux/soundcard.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_SOUNDCARD_H
|
||||
#include <sys/soundcard.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MACHINE_SOUNDCARD_H
|
||||
#include <machine/soundcard.h>
|
||||
#endif
|
||||
|
||||
#ifndef AFMT_S16_NE
|
||||
# ifdef OSS_BIG_ENDIAN
|
||||
# define AFMT_S16_NE AFMT_S16_BE
|
||||
# else
|
||||
# define AFMT_S16_NE AFMT_S16_LE
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef AFMT_U16_NE
|
||||
# ifdef OSS_BIG_ENDIAN
|
||||
# define AFMT_U16_NE AFMT_U16_BE
|
||||
# else
|
||||
# define AFMT_U16_NE AFMT_U16_LE
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
struct oss_stuff
|
||||
{
|
||||
int fragment; /* size of one fragment */
|
||||
int nfrag; /* number of fragments */
|
||||
};
|
||||
|
||||
static int rate_best_match_oss(audio_output_t *ao)
|
||||
{
|
||||
int ret,dsp_rate;
|
||||
|
||||
if(!ao || ao->fn < 0 || ao->rate < 0) return -1;
|
||||
dsp_rate = ao->rate;
|
||||
|
||||
ret = ioctl(ao->fn, SNDCTL_DSP_SPEED,&dsp_rate);
|
||||
if(ret < 0) return ret;
|
||||
ao->rate = dsp_rate;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_rate_oss(audio_output_t *ao)
|
||||
{
|
||||
int dsp_rate;
|
||||
int ret = 0;
|
||||
|
||||
if(ao->rate >= 0) {
|
||||
dsp_rate = ao->rate;
|
||||
ret = ioctl(ao->fn, SNDCTL_DSP_SPEED,&dsp_rate);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int set_channels_oss(audio_output_t *ao)
|
||||
{
|
||||
int chan = ao->channels - 1;
|
||||
int ret;
|
||||
|
||||
if(ao->channels < 0) return 0;
|
||||
|
||||
ret = ioctl(ao->fn, SNDCTL_DSP_STEREO, &chan);
|
||||
if(chan != (ao->channels-1)) return -1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int set_format_oss(audio_output_t *ao)
|
||||
{
|
||||
int fmts;
|
||||
int sf,ret;
|
||||
|
||||
if(ao->format == -1) return 0;
|
||||
|
||||
switch(ao->format) {
|
||||
case MPG123_ENC_SIGNED_16:
|
||||
default:
|
||||
fmts = AFMT_S16_NE;
|
||||
break;
|
||||
case MPG123_ENC_UNSIGNED_8:
|
||||
fmts = AFMT_U8;
|
||||
break;
|
||||
case MPG123_ENC_SIGNED_8:
|
||||
fmts = AFMT_S8;
|
||||
break;
|
||||
case MPG123_ENC_ULAW_8:
|
||||
fmts = AFMT_MU_LAW;
|
||||
break;
|
||||
case MPG123_ENC_ALAW_8:
|
||||
fmts = AFMT_A_LAW;
|
||||
break;
|
||||
case MPG123_ENC_UNSIGNED_16:
|
||||
fmts = AFMT_U16_NE;
|
||||
break;
|
||||
}
|
||||
|
||||
sf = fmts;
|
||||
ret = ioctl(ao->fn, SNDCTL_DSP_SETFMT, &fmts);
|
||||
if(sf != fmts) return -1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int reset_parameters_oss(audio_output_t *ao)
|
||||
{
|
||||
int ret;
|
||||
ret = ioctl(ao->fn, SNDCTL_DSP_RESET, NULL);
|
||||
if(ret < 0 && !AOQUIET) error("Can't reset audio!");
|
||||
ret = set_format_oss(ao);
|
||||
if (ret == -1) goto err;
|
||||
ret = set_channels_oss(ao);
|
||||
if (ret == -1) goto err;
|
||||
ret = set_rate_oss(ao);
|
||||
if (ret == -1) goto err;
|
||||
|
||||
/* Careful here. As per OSS v1.1, the next ioctl() commits the format
|
||||
* set above, so we must issue SNDCTL_DSP_RESET before we're allowed to
|
||||
* change it again. [dk]
|
||||
*/
|
||||
|
||||
/* FIXME: this needs re-enabled (but not using global variables this time):
|
||||
if (ioctl(ao->fn, SNDCTL_DSP_GETBLKSIZE, &outburst) == -1 ||
|
||||
outburst > MAXOUTBURST)
|
||||
outburst = MAXOUTBURST;
|
||||
*/
|
||||
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int open_oss(audio_output_t *ao)
|
||||
{
|
||||
char usingdefdev = 0;
|
||||
|
||||
if(!ao) return -1;
|
||||
|
||||
if(!ao->device) {
|
||||
ao->device = "/dev/dsp";
|
||||
usingdefdev = 1;
|
||||
}
|
||||
|
||||
ao->fn = open(ao->device,O_WRONLY);
|
||||
|
||||
if(ao->fn < 0)
|
||||
{
|
||||
if(usingdefdev) {
|
||||
ao->device = "/dev/sound/dsp";
|
||||
ao->fn = open(ao->device,O_WRONLY);
|
||||
if(ao->fn < 0) {
|
||||
if(!AOQUIET) error("Can't open default sound device!");
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if(!AOQUIET) error1("Can't open %s!",ao->device);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if(reset_parameters_oss(ao) < 0) {
|
||||
close(ao->fn);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(ao->gain >= 0) {
|
||||
int e,mask;
|
||||
e = ioctl(ao->fn , SOUND_MIXER_READ_DEVMASK ,&mask);
|
||||
if(e < 0) {
|
||||
if(!AOQUIET) error("audio/gain: Can't get audio device features list.");
|
||||
}
|
||||
else if(mask & SOUND_MASK_PCM) {
|
||||
int gain = (ao->gain<<8)|(ao->gain);
|
||||
e = ioctl(ao->fn, SOUND_MIXER_WRITE_PCM , &gain);
|
||||
}
|
||||
else if(!(mask & SOUND_MASK_VOLUME)) {
|
||||
if(!AOQUIET) error1("audio/gain: setable Volume/PCM-Level not supported by your audio device: %#04x",mask);
|
||||
}
|
||||
else {
|
||||
int gain = (ao->gain<<8)|(ao->gain);
|
||||
e = ioctl(ao->fn, SOUND_MIXER_WRITE_VOLUME , &gain);
|
||||
}
|
||||
}
|
||||
|
||||
return ao->fn;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* get formats for specific channel/rate parameters
|
||||
*/
|
||||
static int get_formats_oss(audio_output_t *ao)
|
||||
{
|
||||
int fmt = 0;
|
||||
int r = ao->rate;
|
||||
int c = ao->channels;
|
||||
int i;
|
||||
|
||||
static int fmts[] = {
|
||||
MPG123_ENC_ULAW_8 , MPG123_ENC_SIGNED_16 ,
|
||||
MPG123_ENC_UNSIGNED_8 , MPG123_ENC_SIGNED_8 ,
|
||||
MPG123_ENC_UNSIGNED_16 , MPG123_ENC_ALAW_8
|
||||
};
|
||||
|
||||
/* Reset is required before we're allowed to set the new formats. [dk] */
|
||||
ioctl(ao->fn, SNDCTL_DSP_RESET, NULL);
|
||||
|
||||
for(i=0;i<6;i++) {
|
||||
ao->format = fmts[i];
|
||||
if(set_format_oss(ao) < 0) {
|
||||
continue;
|
||||
}
|
||||
ao->channels = c;
|
||||
if(set_channels_oss(ao) < 0) {
|
||||
continue;
|
||||
}
|
||||
ao->rate = r;
|
||||
if(rate_best_match_oss(ao) < 0) {
|
||||
continue;
|
||||
}
|
||||
if( (ao->rate*100 > r*(100-AUDIO_RATE_TOLERANCE)) && (ao->rate*100 < r*(100+AUDIO_RATE_TOLERANCE)) ) {
|
||||
fmt |= fmts[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
if(ioctl(ao->fn,SNDCTL_DSP_GETFMTS,&fmts) < 0) {
|
||||
if(!AOQUIET) error("Failed to get SNDCTL_DSP_GETFMTS");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(fmts & AFMT_MU_LAW)
|
||||
ret |= MPG123_ENC_ULAW_8;
|
||||
if(fmts & AFMT_S16_NE)
|
||||
ret |= MPG123_ENC_SIGNED_16;
|
||||
if(fmts & AFMT_U8)
|
||||
ret |= MPG123_ENC_UNSIGNED_8;
|
||||
if(fmts & AFMT_S8)
|
||||
ret |= MPG123_ENC_SIGNED_8;
|
||||
if(fmts & AFMT_U16_NE)
|
||||
ret |= MPG123_ENC_UNSIGNED_16;
|
||||
if(fmts & AFMT_A_LAW)
|
||||
ret |= MPG123_ENC_ALAW_8;
|
||||
#endif
|
||||
|
||||
return fmt;
|
||||
}
|
||||
|
||||
static int write_oss(audio_output_t *ao,unsigned char *buf,int len)
|
||||
{
|
||||
return write(ao->fn,buf,len);
|
||||
}
|
||||
|
||||
static int close_oss(audio_output_t *ao)
|
||||
{
|
||||
close(ao->fn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void flush_oss(audio_output_t *ao)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static int init_oss(audio_output_t* ao)
|
||||
{
|
||||
if (ao==NULL) return -1;
|
||||
|
||||
/* Set callbacks */
|
||||
ao->open = open_oss;
|
||||
ao->flush = flush_oss;
|
||||
ao->write = write_oss;
|
||||
ao->get_formats = get_formats_oss;
|
||||
ao->close = close_oss;
|
||||
|
||||
/* Success */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Module information data structure
|
||||
*/
|
||||
mpg123_module_t mpg123_output_module_info = {
|
||||
/* api_version */ MPG123_MODULE_API_VERSION,
|
||||
/* name */ "oss",
|
||||
/* description */ "Output audio using OSS",
|
||||
/* revision */ "$Rev: 2927 $",
|
||||
/* handle */ NULL,
|
||||
|
||||
/* init_output */ init_oss,
|
||||
};
|
||||
|
||||
|
13
node_modules/lame/deps/mpg123/src/output/output.h
generated
vendored
Executable file
13
node_modules/lame/deps/mpg123/src/output/output.h
generated
vendored
Executable file
@ -0,0 +1,13 @@
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "mpg123.h"
|
||||
#include "module.h"
|
||||
#include "audio.h"
|
||||
|
||||
extern mpg123_module_t mpg123_output_module_info;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
255
node_modules/lame/deps/mpg123/src/output/portaudio.c
generated
vendored
Normal file
255
node_modules/lame/deps/mpg123/src/output/portaudio.c
generated
vendored
Normal file
@ -0,0 +1,255 @@
|
||||
/*
|
||||
portaudio: audio output via PortAudio cross-platform audio API
|
||||
|
||||
copyright 2006-9 by the mpg123 project - free software under the terms of the LGPL 2.1
|
||||
see COPYING and AUTHORS files in distribution or http://mpg123.org
|
||||
initially written by Nicholas J. Humfrey
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include <portaudio.h>
|
||||
|
||||
#include "audio.h"
|
||||
#include "mpg123app.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
/* Including the sfifo code locally, to avoid module linkage issues. */
|
||||
#define SFIFO_STATIC
|
||||
#include "sfifo.c"
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#define SAMPLE_SIZE (2)
|
||||
#define FRAMES_PER_BUFFER (256)
|
||||
#define FIFO_DURATION (0.5f)
|
||||
|
||||
|
||||
typedef struct {
|
||||
PaStream *stream;
|
||||
sfifo_t fifo;
|
||||
} mpg123_portaudio_t;
|
||||
|
||||
#ifdef PORTAUDIO18
|
||||
#define PaTime PaTimestamp
|
||||
#define Pa_IsStreamActive Pa_StreamActive
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef PORTAUDIO18
|
||||
static int paCallback( void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
PaTime outTime, void *userData )
|
||||
#else
|
||||
static int paCallback(
|
||||
const void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
const PaStreamCallbackTimeInfo* timeInfo,
|
||||
PaStreamCallbackFlags statusFlags,
|
||||
void *userData )
|
||||
#endif
|
||||
{
|
||||
audio_output_t *ao = userData;
|
||||
mpg123_portaudio_t *pa = (mpg123_portaudio_t*)ao->userptr;
|
||||
unsigned long bytes = framesPerBuffer * SAMPLE_SIZE * ao->channels;
|
||||
|
||||
if (sfifo_used(&pa->fifo)<bytes) {
|
||||
error("ringbuffer for PortAudio is empty");
|
||||
return 1;
|
||||
} else {
|
||||
sfifo_read( &pa->fifo, outputBuffer, bytes );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int open_portaudio(audio_output_t *ao)
|
||||
{
|
||||
mpg123_portaudio_t *pa = (mpg123_portaudio_t*)ao->userptr;
|
||||
PaError err;
|
||||
|
||||
/* Open an audio I/O stream. */
|
||||
if (ao->rate > 0 && ao->channels >0 ) {
|
||||
|
||||
err = Pa_OpenDefaultStream(
|
||||
&pa->stream,
|
||||
0, /* no input channels */
|
||||
ao->channels, /* number of output channels */
|
||||
paInt16, /* signed 16-bit samples */
|
||||
ao->rate, /* sample rate */
|
||||
FRAMES_PER_BUFFER, /* frames per buffer */
|
||||
#ifdef PORTAUDIO18
|
||||
0, /* number of buffers, if zero then use default minimum */
|
||||
#endif
|
||||
paCallback, /* no callback - use blocking IO */
|
||||
ao );
|
||||
|
||||
if( err != paNoError ) {
|
||||
error1("Failed to open PortAudio default stream: %s", Pa_GetErrorText( err ));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Initialise FIFO */
|
||||
sfifo_init( &pa->fifo, ao->rate * FIFO_DURATION * SAMPLE_SIZE *ao->channels );
|
||||
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
static int get_formats_portaudio(audio_output_t *ao)
|
||||
{
|
||||
/* Only implemented Signed 16-bit audio for now */
|
||||
return MPG123_ENC_SIGNED_16;
|
||||
}
|
||||
|
||||
|
||||
static int write_portaudio(audio_output_t *ao, unsigned char *buf, int len)
|
||||
{
|
||||
mpg123_portaudio_t *pa = (mpg123_portaudio_t*)ao->userptr;
|
||||
PaError err;
|
||||
int written;
|
||||
|
||||
/* Sleep for half the length of the FIFO */
|
||||
while (sfifo_space( &pa->fifo ) < len ) {
|
||||
#ifdef WIN32
|
||||
Sleep( (FIFO_DURATION/2) * 1000);
|
||||
#else
|
||||
usleep( (FIFO_DURATION/2) * 1000000 );
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Write the audio to the ring buffer */
|
||||
written = sfifo_write( &pa->fifo, buf, len );
|
||||
|
||||
/* Start stream if not ative */
|
||||
err = Pa_IsStreamActive( pa->stream );
|
||||
if (err == 0) {
|
||||
err = Pa_StartStream( pa->stream );
|
||||
if( err != paNoError ) {
|
||||
error1("Failed to start PortAudio stream: %s", Pa_GetErrorText( err ));
|
||||
return -1; /* triggering exit here is not good, better handle that somehow... */
|
||||
}
|
||||
} else if (err < 0) {
|
||||
error1("Failed to check state of PortAudio stream: %s", Pa_GetErrorText( err ));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return written;
|
||||
}
|
||||
|
||||
|
||||
static int close_portaudio(audio_output_t *ao)
|
||||
{
|
||||
mpg123_portaudio_t *pa = (mpg123_portaudio_t*)ao->userptr;
|
||||
PaError err;
|
||||
|
||||
if (pa->stream) {
|
||||
/* stop the stream if it is active */
|
||||
if (Pa_IsStreamActive( pa->stream ) == 1) {
|
||||
err = Pa_StopStream( pa->stream );
|
||||
if( err != paNoError ) {
|
||||
error1("Failed to stop PortAudio stream: %s", Pa_GetErrorText( err ));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* and then close the stream */
|
||||
err = Pa_CloseStream( pa->stream );
|
||||
if( err != paNoError ) {
|
||||
error1("Failed to close PortAudio stream: %s", Pa_GetErrorText( err ));
|
||||
return -1;
|
||||
}
|
||||
|
||||
pa->stream = NULL;
|
||||
}
|
||||
|
||||
/* and free memory used by fifo */
|
||||
sfifo_close( &pa->fifo );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void flush_portaudio(audio_output_t *ao)
|
||||
{
|
||||
mpg123_portaudio_t *pa = (mpg123_portaudio_t*)ao->userptr;
|
||||
PaError err;
|
||||
|
||||
/* throw away contents of FIFO */
|
||||
sfifo_flush( &pa->fifo );
|
||||
|
||||
/* and empty out PortAudio buffers */
|
||||
err = Pa_AbortStream( pa->stream );
|
||||
|
||||
}
|
||||
|
||||
|
||||
static int deinit_portaudio(audio_output_t* ao)
|
||||
{
|
||||
/* Free up memory */
|
||||
if (ao->userptr) {
|
||||
free( ao->userptr );
|
||||
ao->userptr = NULL;
|
||||
}
|
||||
|
||||
/* Shut down PortAudio */
|
||||
Pa_Terminate();
|
||||
|
||||
/* Success */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int init_portaudio(audio_output_t* ao)
|
||||
{
|
||||
int err = paNoError;
|
||||
|
||||
if (ao==NULL) return -1;
|
||||
|
||||
/* Set callbacks */
|
||||
ao->open = open_portaudio;
|
||||
ao->flush = flush_portaudio;
|
||||
ao->write = write_portaudio;
|
||||
ao->get_formats = get_formats_portaudio;
|
||||
ao->close = close_portaudio;
|
||||
ao->deinit = deinit_portaudio;
|
||||
|
||||
/* Allocate memory for handle */
|
||||
ao->userptr = malloc( sizeof(mpg123_portaudio_t) );
|
||||
if (ao->userptr==NULL) {
|
||||
error( "Failed to allocated memory for driver structure" );
|
||||
return -1;
|
||||
}
|
||||
memset( ao->userptr, 0, sizeof(mpg123_portaudio_t) );
|
||||
|
||||
/* Initialise PortAudio */
|
||||
err = Pa_Initialize();
|
||||
if( err != paNoError ) {
|
||||
error1("Failed to initialise PortAudio: %s", Pa_GetErrorText( err ));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Success */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Module information data structure
|
||||
*/
|
||||
mpg123_module_t mpg123_output_module_info = {
|
||||
/* api_version */ MPG123_MODULE_API_VERSION,
|
||||
/* name */ "portaudio",
|
||||
/* description */ "Output audio using PortAudio",
|
||||
/* revision */ "$Rev:$",
|
||||
/* handle */ NULL,
|
||||
|
||||
/* init_output */ init_portaudio,
|
||||
};
|
||||
|
164
node_modules/lame/deps/mpg123/src/output/pulse.c
generated
vendored
Normal file
164
node_modules/lame/deps/mpg123/src/output/pulse.c
generated
vendored
Normal file
@ -0,0 +1,164 @@
|
||||
/*
|
||||
pulse: audio output using PulseAudio server
|
||||
|
||||
copyright 2006-9 by the mpg123 project - free software under the terms of the LGPL 2.1
|
||||
see COPYING and AUTHORS files in distribution or http://mpg123.org
|
||||
initially written by Nicholas J. Humfrey
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <pulse/simple.h>
|
||||
#include <pulse/error.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "mpg123app.h"
|
||||
#include "audio.h"
|
||||
#include "module.h"
|
||||
#include "debug.h"
|
||||
|
||||
static int open_pulse(audio_output_t *ao)
|
||||
{
|
||||
int err;
|
||||
pa_simple* pas = NULL;
|
||||
pa_sample_spec ss;
|
||||
/* Check if already open ? */
|
||||
if (ao->userptr) {
|
||||
error("Pulse audio output is already open.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Open an audio I/O stream. */
|
||||
/* When they are < 0, I shall set some default. */
|
||||
if(ao->rate < 0 || ao->format < 0 || ao->channels < 0)
|
||||
{
|
||||
ao->rate = 44100;
|
||||
ao->channels = 2;
|
||||
ao->format = MPG123_ENC_SIGNED_16;
|
||||
}
|
||||
|
||||
/* Fill out pulse audio's data structure */
|
||||
ss.channels = ao->channels;
|
||||
ss.rate = ao->rate;
|
||||
|
||||
switch(ao->format) {
|
||||
case MPG123_ENC_SIGNED_16:
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
ss.format=PA_SAMPLE_S16BE;
|
||||
#else
|
||||
ss.format=PA_SAMPLE_S16LE;
|
||||
#endif
|
||||
break;
|
||||
case MPG123_ENC_ALAW_8:
|
||||
ss.format=PA_SAMPLE_ALAW;
|
||||
break;
|
||||
case MPG123_ENC_ULAW_8:
|
||||
ss.format=PA_SAMPLE_ULAW;
|
||||
break;
|
||||
case MPG123_ENC_UNSIGNED_8:
|
||||
ss.format=PA_SAMPLE_U8;
|
||||
break;
|
||||
default:
|
||||
error1("Unsupported audio format: 0x%x", ao->format);
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/* Perform the open */
|
||||
pas = pa_simple_new(
|
||||
NULL, /* Use the default server */
|
||||
"mpg123", /* Our application's name */
|
||||
PA_STREAM_PLAYBACK,
|
||||
ao->device, /* Use the default device if NULL */
|
||||
"MPEG Audio", /* Description of our stream */
|
||||
&ss, /* Our sample format */
|
||||
NULL, /* Use default channel map */
|
||||
NULL, /* Use default buffering attributes */
|
||||
&err /* Error result code */
|
||||
);
|
||||
|
||||
if( pas == NULL ) {
|
||||
error1("Failed to open pulse audio output: %s", pa_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Store the pointer */
|
||||
ao->userptr = (void*)pas;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int get_formats_pulse(audio_output_t *ao)
|
||||
{
|
||||
/* Only implemented Signed 16-bit audio for now */
|
||||
return MPG123_ENC_SIGNED_16;
|
||||
}
|
||||
|
||||
|
||||
static int write_pulse(audio_output_t *ao, unsigned char *buf, int len)
|
||||
{
|
||||
pa_simple *pas = (pa_simple*)ao->userptr;
|
||||
int ret, err;
|
||||
/* Doesn't return number of bytes but just success or not. */
|
||||
ret = pa_simple_write( pas, buf, len, &err );
|
||||
if(ret<0){ error1("Failed to write audio: %s", pa_strerror(err)); return -1; }
|
||||
|
||||
return len; /* If successful, everything has been written. */
|
||||
}
|
||||
|
||||
static int close_pulse(audio_output_t *ao)
|
||||
{
|
||||
pa_simple *pas = (pa_simple*)ao->userptr;
|
||||
|
||||
if (pas) {
|
||||
pa_simple_free( pas );
|
||||
ao->userptr = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void flush_pulse(audio_output_t *ao)
|
||||
{
|
||||
pa_simple *pas = (pa_simple*)ao->userptr;
|
||||
|
||||
if (pas) {
|
||||
int err;
|
||||
pa_simple_flush( pas, &err );
|
||||
if (err) error1("Failed to flush audio: %s", pa_strerror(err));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int init_pulse(audio_output_t* ao)
|
||||
{
|
||||
if (ao==NULL) return -1;
|
||||
|
||||
/* Set callbacks */
|
||||
ao->open = open_pulse;
|
||||
ao->flush = flush_pulse;
|
||||
ao->write = write_pulse;
|
||||
ao->get_formats = get_formats_pulse;
|
||||
ao->close = close_pulse;
|
||||
|
||||
/* Success */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Module information data structure
|
||||
*/
|
||||
mpg123_module_t mpg123_output_module_info = {
|
||||
/* api_version */ MPG123_MODULE_API_VERSION,
|
||||
/* name */ "pulse",
|
||||
/* description */ "Output audio using PulseAudio Server",
|
||||
/* revision */ "$Rev:$",
|
||||
/* handle */ NULL,
|
||||
|
||||
/* init_output */ init_pulse,
|
||||
};
|
||||
|
206
node_modules/lame/deps/mpg123/src/output/sdl.c
generated
vendored
Normal file
206
node_modules/lame/deps/mpg123/src/output/sdl.c
generated
vendored
Normal file
@ -0,0 +1,206 @@
|
||||
/*
|
||||
sdl: audio output via SDL cross-platform API
|
||||
|
||||
copyright 2006-9 by the mpg123 project - free software under the terms of the LGPL 2.1
|
||||
see COPYING and AUTHORS files in distribution or http://mpg123.org
|
||||
initially written by Nicholas J. Humfrey
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
#include "audio.h"
|
||||
#include "mpg123app.h"
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
/* Including the sfifo code locally, to avoid module linkage issues. */
|
||||
#define SFIFO_STATIC
|
||||
#include "sfifo.c"
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
#define SAMPLE_SIZE (2)
|
||||
#define FRAMES_PER_BUFFER (256)
|
||||
#define FIFO_DURATION (0.5f)
|
||||
|
||||
|
||||
|
||||
|
||||
/* The audio function callback takes the following parameters:
|
||||
stream: A pointer to the audio buffer to be filled
|
||||
len: The length (in bytes) of the audio buffer
|
||||
*/
|
||||
static void audio_callback_sdl(void *udata, Uint8 *stream, int len)
|
||||
{
|
||||
audio_output_t *ao = (audio_output_t*)udata;
|
||||
sfifo_t *fifo = (sfifo_t*)ao->userptr;
|
||||
int bytes_read;
|
||||
|
||||
/* Only play if we have data left */
|
||||
if ( sfifo_used( fifo ) < len ) {
|
||||
warning("Didn't have any audio data for SDL (buffer underflow)");
|
||||
SDL_PauseAudio(1);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Read audio from FIFO to SDL's buffer */
|
||||
bytes_read = sfifo_read( fifo, stream, len );
|
||||
|
||||
if (len!=bytes_read)
|
||||
warning2("Error reading from the FIFO (wanted=%u, bytes_read=%u).\n", len, bytes_read);
|
||||
|
||||
}
|
||||
|
||||
static int open_sdl(audio_output_t *ao)
|
||||
{
|
||||
sfifo_t *fifo = (sfifo_t*)ao->userptr;
|
||||
|
||||
/* Open an audio I/O stream. */
|
||||
if (ao->rate > 0 && ao->channels >0 ) {
|
||||
size_t ringbuffer_len;
|
||||
SDL_AudioSpec wanted;
|
||||
|
||||
/* L16 uncompressed audio data, using 16-bit signed representation in twos
|
||||
complement notation - system endian-ness. */
|
||||
wanted.format = AUDIO_S16SYS;
|
||||
wanted.samples = 1024; /* Good low-latency value for callback */
|
||||
wanted.callback = audio_callback_sdl;
|
||||
wanted.userdata = ao;
|
||||
wanted.channels = ao->channels;
|
||||
wanted.freq = ao->rate;
|
||||
|
||||
/* Open the audio device, forcing the desired format */
|
||||
if ( SDL_OpenAudio(&wanted, NULL) ) {
|
||||
error1("Couldn't open SDL audio: %s\n", SDL_GetError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Initialise FIFO */
|
||||
ringbuffer_len = ao->rate * FIFO_DURATION * SAMPLE_SIZE *ao->channels;
|
||||
debug2( "Allocating %d byte ring-buffer (%f seconds)", (int)ringbuffer_len, (float)FIFO_DURATION);
|
||||
if (sfifo_init( fifo, ringbuffer_len )) error1( "Failed to initialise FIFO of size %d bytes", (int)ringbuffer_len );
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
static int get_formats_sdl(audio_output_t *ao)
|
||||
{
|
||||
/* Only implemented Signed 16-bit audio for now */
|
||||
return MPG123_ENC_SIGNED_16;
|
||||
}
|
||||
|
||||
|
||||
static int write_sdl(audio_output_t *ao, unsigned char *buf, int len)
|
||||
{
|
||||
sfifo_t *fifo = (sfifo_t*)ao->userptr;
|
||||
|
||||
/* Sleep for half the length of the FIFO */
|
||||
while (sfifo_space( fifo ) < len )
|
||||
#ifdef WIN32
|
||||
Sleep( (FIFO_DURATION/2) * 1000);
|
||||
#else
|
||||
usleep( (FIFO_DURATION/2) * 1000000 );
|
||||
#endif
|
||||
|
||||
/* Bung decoded audio into the FIFO
|
||||
SDL Audio locking probably isn't actually needed
|
||||
as SFIFO claims to be thread safe...
|
||||
*/
|
||||
SDL_LockAudio();
|
||||
sfifo_write( fifo, buf, len);
|
||||
SDL_UnlockAudio();
|
||||
|
||||
|
||||
/* Unpause once the buffer is 50% full */
|
||||
if (sfifo_used(fifo) > (sfifo_size(fifo)*0.5) ) SDL_PauseAudio(0);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int close_sdl(audio_output_t *ao)
|
||||
{
|
||||
sfifo_t *fifo = (sfifo_t*)ao->userptr;
|
||||
|
||||
SDL_CloseAudio();
|
||||
|
||||
/* Free up the memory used by the FIFO */
|
||||
sfifo_close( fifo );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void flush_sdl(audio_output_t *ao)
|
||||
{
|
||||
sfifo_t *fifo = (sfifo_t*)ao->userptr;
|
||||
|
||||
SDL_PauseAudio(1);
|
||||
|
||||
sfifo_flush( fifo );
|
||||
}
|
||||
|
||||
|
||||
static int deinit_sdl(audio_output_t* ao)
|
||||
{
|
||||
/* Free up memory */
|
||||
if (ao->userptr) {
|
||||
free( ao->userptr );
|
||||
ao->userptr = NULL;
|
||||
}
|
||||
|
||||
/* Shut down SDL */
|
||||
SDL_Quit();
|
||||
|
||||
/* Success */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int init_sdl(audio_output_t* ao)
|
||||
{
|
||||
if (ao==NULL) return -1;
|
||||
|
||||
/* Set callbacks */
|
||||
ao->open = open_sdl;
|
||||
ao->flush = flush_sdl;
|
||||
ao->write = write_sdl;
|
||||
ao->get_formats = get_formats_sdl;
|
||||
ao->close = close_sdl;
|
||||
ao->deinit = deinit_sdl;
|
||||
|
||||
/* Allocate memory */
|
||||
ao->userptr = malloc( sizeof(sfifo_t) );
|
||||
if (ao->userptr==NULL) {
|
||||
error( "Failed to allocated memory for FIFO structure" );
|
||||
return -1;
|
||||
}
|
||||
memset( ao->userptr, 0, sizeof(sfifo_t) );
|
||||
|
||||
/* Initialise SDL */
|
||||
if (SDL_Init( SDL_INIT_AUDIO ) ) {
|
||||
error1("Failed to initialise SDL: %s\n", SDL_GetError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Success */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Module information data structure
|
||||
*/
|
||||
mpg123_module_t mpg123_output_module_info = {
|
||||
/* api_version */ MPG123_MODULE_API_VERSION,
|
||||
/* name */ "sdl",
|
||||
/* description */ "Output audio using SDL (Simple DirectMedia Layer).",
|
||||
/* revision */ "$Rev:$",
|
||||
/* handle */ NULL,
|
||||
|
||||
/* init_output */ init_sdl,
|
||||
};
|
213
node_modules/lame/deps/mpg123/src/output/sgi.c
generated
vendored
Normal file
213
node_modules/lame/deps/mpg123/src/output/sgi.c
generated
vendored
Normal file
@ -0,0 +1,213 @@
|
||||
/*
|
||||
sgi: audio output on SGI boxen
|
||||
|
||||
copyright ?-2006 by the mpg123 project - free software under the terms of the LGPL 2.1
|
||||
see COPYING and AUTHORS files in distribution or http://mpg123.org
|
||||
initially written (as it seems) by Thomas Woerner
|
||||
*/
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
/* #include <audio.h> */
|
||||
#include <dmedia/audio.h>
|
||||
|
||||
#include "mpg123app.h"
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
/* Analog output constant */
|
||||
static const char analog_output_res_name[] = ".AnalogOut";
|
||||
|
||||
|
||||
static int set_rate(audio_output_t *ao, ALconfig config)
|
||||
{
|
||||
int dev = alGetDevice(config);
|
||||
ALpv params[1];
|
||||
|
||||
/* Make sure the device is OK */
|
||||
if (dev < 0)
|
||||
{
|
||||
error1("set_rate: %s",alGetErrorString(oserror()));
|
||||
return 1;
|
||||
}
|
||||
|
||||
params[0].param = AL_OUTPUT_RATE;
|
||||
params[0].value.ll = alDoubleToFixed(ao->rate);
|
||||
|
||||
if (alSetParams(dev, params,1) < 0)
|
||||
error1("set_rate: %s",alGetErrorString(oserror()));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int set_channels(audio_output_t *ao, ALconfig config)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if(ao->channels == 2)
|
||||
ret = alSetChannels(config, AL_STEREO);
|
||||
else
|
||||
ret = alSetChannels(config, AL_MONO);
|
||||
|
||||
if (ret < 0)
|
||||
error1("set_channels : %s",alGetErrorString(oserror()));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_format(audio_output_t *ao, ALconfig config)
|
||||
{
|
||||
if (alSetSampFmt(config,AL_SAMPFMT_TWOSCOMP) < 0)
|
||||
error1("set_format : %s",alGetErrorString(oserror()));
|
||||
|
||||
if (alSetWidth(config,AL_SAMPLE_16) < 0)
|
||||
error1("set_format : %s",alGetErrorString(oserror()));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int open_sgi(audio_output_t *ao)
|
||||
{
|
||||
int dev = AL_DEFAULT_OUTPUT;
|
||||
ALconfig config = alNewConfig();
|
||||
ALport port = NULL;
|
||||
|
||||
/* Test for correct completion */
|
||||
if (config == 0) {
|
||||
error1("open_sgi: %s",alGetErrorString(oserror()));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Set port parameters */
|
||||
if(ao->channels == 2)
|
||||
alSetChannels(config, AL_STEREO);
|
||||
else
|
||||
alSetChannels(config, AL_MONO);
|
||||
|
||||
alSetWidth(config, AL_SAMPLE_16);
|
||||
alSetSampFmt(config,AL_SAMPFMT_TWOSCOMP);
|
||||
alSetQueueSize(config, 131069);
|
||||
|
||||
/* Setup output device to specified module. If there is no module
|
||||
specified in ao structure, use the default four output */
|
||||
if ((ao->device) != NULL) {
|
||||
char *dev_name;
|
||||
|
||||
dev_name=malloc((strlen(ao->device) + strlen(analog_output_res_name) + 1) *
|
||||
sizeof(char));
|
||||
|
||||
strcpy(dev_name,ao->device);
|
||||
strcat(dev_name,analog_output_res_name);
|
||||
|
||||
/* Find the asked device resource */
|
||||
dev=alGetResourceByName(AL_SYSTEM,dev_name,AL_DEVICE_TYPE);
|
||||
|
||||
/* Free allocated space */
|
||||
free(dev_name);
|
||||
|
||||
if (!dev) {
|
||||
error2("Invalid audio resource: %s (%s)",dev_name, alGetErrorString(oserror()));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the device */
|
||||
if (alSetDevice(config,dev) < 0)
|
||||
{
|
||||
error1("open_sgi: %s",alGetErrorString(oserror()));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Open the audio port */
|
||||
port = alOpenPort("mpg123-VSC", "w", config);
|
||||
if(port == NULL) {
|
||||
error1("Unable to open audio channel: %s", alGetErrorString(oserror()));
|
||||
return -1;
|
||||
}
|
||||
|
||||
ao->userptr = (void*)port;
|
||||
|
||||
|
||||
set_format(ao, config);
|
||||
set_channels(ao, config);
|
||||
set_rate(ao, config);
|
||||
|
||||
|
||||
alFreeConfig(config);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int get_formats_sgi(audio_output_t *ao)
|
||||
{
|
||||
return MPG123_ENC_SIGNED_16;
|
||||
}
|
||||
|
||||
|
||||
static int write_sgi(audio_output_t *ao,unsigned char *buf,int len)
|
||||
{
|
||||
ALport port = (ALport)ao->userptr;
|
||||
|
||||
if(ao->format == MPG123_ENC_SIGNED_8)
|
||||
alWriteFrames(port, buf, len>>1);
|
||||
else
|
||||
alWriteFrames(port, buf, len>>2);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
static int close_sgi(audio_output_t *ao)
|
||||
{
|
||||
ALport port = (ALport)ao->userptr;
|
||||
|
||||
if (port) {
|
||||
while(alGetFilled(port) > 0) sginap(1);
|
||||
alClosePort(port);
|
||||
ao->userptr=NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void flush_sgi(audio_output_t *ao)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
static int init_sgi(audio_output_t* ao)
|
||||
{
|
||||
if (ao==NULL) return -1;
|
||||
|
||||
/* Set callbacks */
|
||||
ao->open = open_sgi;
|
||||
ao->flush = flush_sgi;
|
||||
ao->write = write_sgi;
|
||||
ao->get_formats = get_formats_sgi;
|
||||
ao->close = close_sgi;
|
||||
|
||||
/* Success */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Module information data structure
|
||||
*/
|
||||
mpg123_module_t mpg123_output_module_info = {
|
||||
/* api_version */ MPG123_MODULE_API_VERSION,
|
||||
/* name */ "sgi",
|
||||
/* description */ "Audio output for SGI.",
|
||||
/* revision */ "$Rev:$",
|
||||
/* handle */ NULL,
|
||||
|
||||
/* init_output */ init_sgi,
|
||||
};
|
||||
|
||||
|
161
node_modules/lame/deps/mpg123/src/output/sndio.c
generated
vendored
Normal file
161
node_modules/lame/deps/mpg123/src/output/sndio.c
generated
vendored
Normal file
@ -0,0 +1,161 @@
|
||||
/*
|
||||
* sndio: sndio audio output
|
||||
*
|
||||
* Copyright (c) 2008 Christian Weisgerber <naddy@openbsd.org>,
|
||||
* Alexandre Ratchov <alex@caoua.org>
|
||||
*
|
||||
* 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 "mpg123app.h"
|
||||
|
||||
#include <sndio.h>
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
static int open_sndio(audio_output_t *ao)
|
||||
{
|
||||
struct sio_hdl *hdl;
|
||||
struct sio_par par;
|
||||
|
||||
hdl = sio_open(ao->device /* NULL is fine */, SIO_PLAY, 0);
|
||||
if (hdl == NULL)
|
||||
return -1;
|
||||
|
||||
sio_initpar(&par);
|
||||
par.rate = ao->rate;
|
||||
par.pchan = ao->channels;
|
||||
par.le = SIO_LE_NATIVE;
|
||||
switch(ao->format) {
|
||||
case MPG123_ENC_SIGNED_32:
|
||||
par.sig = 1;
|
||||
par.bits = 32;
|
||||
break;
|
||||
case MPG123_ENC_UNSIGNED_32:
|
||||
par.sig = 0;
|
||||
par.bits = 32;
|
||||
break;
|
||||
case MPG123_ENC_SIGNED_16:
|
||||
case -1: /* query mode */
|
||||
par.sig = 1;
|
||||
par.bits = 16;
|
||||
break;
|
||||
case MPG123_ENC_UNSIGNED_16:
|
||||
par.sig = 0;
|
||||
par.bits = 16;
|
||||
break;
|
||||
case MPG123_ENC_UNSIGNED_8:
|
||||
par.sig = 0;
|
||||
par.bits = 8;
|
||||
break;
|
||||
case MPG123_ENC_SIGNED_8:
|
||||
par.sig = 1;
|
||||
par.bits = 8;
|
||||
break;
|
||||
default:
|
||||
if (!AOQUIET)
|
||||
error1("open_sndio: invalid sample format %d",
|
||||
ao->format);
|
||||
sio_close(hdl);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!sio_setpar(hdl, &par) || !sio_getpar(hdl, &par) ||
|
||||
!sio_start(hdl)) {
|
||||
sio_close(hdl);
|
||||
return -1;
|
||||
}
|
||||
if ((par.bits != 8 && par.bits != 16 && par.bits != 32) ||
|
||||
par.le != SIO_LE_NATIVE) {
|
||||
sio_close(hdl);
|
||||
return -1;
|
||||
}
|
||||
ao->rate = par.rate;
|
||||
ao->channels = par.pchan;
|
||||
switch (par.bits) {
|
||||
case 8:
|
||||
ao->format = par.sig ? MPG123_ENC_SIGNED_8 :
|
||||
MPG123_ENC_UNSIGNED_8;
|
||||
break;
|
||||
case 16:
|
||||
ao->format = par.sig ? MPG123_ENC_SIGNED_16 :
|
||||
MPG123_ENC_UNSIGNED_16;
|
||||
break;
|
||||
case 32:
|
||||
ao->format = par.sig ? MPG123_ENC_SIGNED_32 :
|
||||
MPG123_ENC_UNSIGNED_32;
|
||||
break;
|
||||
}
|
||||
ao->userptr = hdl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_formats_sndio(audio_output_t *ao)
|
||||
{
|
||||
return (MPG123_ENC_SIGNED_32|MPG123_ENC_UNSIGNED_32|
|
||||
MPG123_ENC_SIGNED_16|MPG123_ENC_UNSIGNED_16|
|
||||
MPG123_ENC_UNSIGNED_8|MPG123_ENC_SIGNED_8);
|
||||
}
|
||||
|
||||
static int write_sndio(audio_output_t *ao, unsigned char *buf, int len)
|
||||
{
|
||||
struct sio_hdl *hdl = (struct sio_hdl *)ao->userptr;
|
||||
int count;
|
||||
|
||||
count = (int)sio_write(hdl, buf, len);
|
||||
if (count == 0 && sio_eof(hdl))
|
||||
return -1;
|
||||
return count;
|
||||
}
|
||||
|
||||
static void flush_sndio(audio_output_t *ao)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static int close_sndio(audio_output_t *ao)
|
||||
{
|
||||
struct sio_hdl *hdl = (struct sio_hdl *)ao->userptr;
|
||||
|
||||
sio_close(hdl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init_sndio(audio_output_t* ao)
|
||||
{
|
||||
if (ao == NULL)
|
||||
return -1;
|
||||
|
||||
/* Set callbacks */
|
||||
ao->open = open_sndio;
|
||||
ao->flush = flush_sndio; /* required */
|
||||
ao->write = write_sndio;
|
||||
ao->get_formats = get_formats_sndio;
|
||||
ao->close = close_sndio;
|
||||
|
||||
/* Success */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Module information data structure
|
||||
*/
|
||||
mpg123_module_t mpg123_output_module_info = {
|
||||
/* api_version */ MPG123_MODULE_API_VERSION,
|
||||
/* name */ "sndio",
|
||||
/* description */ "Output audio using sndio library",
|
||||
/* revision */ "$Rev:$",
|
||||
/* handle */ NULL,
|
||||
|
||||
/* init_output */ init_sndio,
|
||||
};
|
281
node_modules/lame/deps/mpg123/src/output/sun.c
generated
vendored
Normal file
281
node_modules/lame/deps/mpg123/src/output/sun.c
generated
vendored
Normal file
@ -0,0 +1,281 @@
|
||||
/*
|
||||
sun: audio output for Sun systems
|
||||
|
||||
copyright ?-2006 by the mpg123 project - free software under the terms of the LGPL 2.1
|
||||
see COPYING and AUTHORS files in distribution or http://mpg123.org
|
||||
initially written by Michael Hipp
|
||||
*/
|
||||
|
||||
#include "mpg123app.h"
|
||||
|
||||
#ifdef HAVE_SYS_IOCTL_H
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SUN_AUDIOIO_H
|
||||
#include <sun/audioio.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_AUDIOIO_H
|
||||
#include <sys/audioio.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_AUDIO_H
|
||||
#include <sys/audio.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ASM_AUDIOIO_H
|
||||
#include <asm/audioio.h>
|
||||
#endif
|
||||
|
||||
#include <fcntl.h>
|
||||
#include "debug.h"
|
||||
|
||||
static void set_format_helper(audio_output_t *ao, audio_info_t *ainfo)
|
||||
{
|
||||
|
||||
switch(ao->format) {
|
||||
case -1:
|
||||
case MPG123_ENC_SIGNED_16:
|
||||
default:
|
||||
#ifndef AUDIO_ENCODING_LINEAR /* not supported */
|
||||
#define AUDIO_ENCODING_LINEAR 3
|
||||
#endif
|
||||
ainfo->play.encoding = AUDIO_ENCODING_LINEAR;
|
||||
ainfo->play.precision = 16;
|
||||
break;
|
||||
case MPG123_ENC_UNSIGNED_8:
|
||||
#if defined(SOLARIS) || defined(SPARCLINUX)
|
||||
ainfo->play.encoding = AUDIO_ENCODING_LINEAR8;
|
||||
ainfo->play.precision = 8;
|
||||
break;
|
||||
#endif
|
||||
case MPG123_ENC_SIGNED_8:
|
||||
error("Linear signed 8 bit not supported!");
|
||||
return;
|
||||
case MPG123_ENC_ULAW_8:
|
||||
ainfo->play.encoding = AUDIO_ENCODING_ULAW;
|
||||
ainfo->play.precision = 8;
|
||||
break;
|
||||
case MPG123_ENC_ALAW_8:
|
||||
ainfo->play.encoding = AUDIO_ENCODING_ALAW;
|
||||
ainfo->play.precision = 8;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
static int reset_parameters_sun(audio_output_t *ao)
|
||||
{
|
||||
audio_info_t ainfo;
|
||||
|
||||
AUDIO_INITINFO(&ainfo);
|
||||
if(ao->rate != -1) ainfo.play.sample_rate = ao->rate;
|
||||
|
||||
if(ao->channels >= 0) ainfo.play.channels = ao->channels;
|
||||
|
||||
set_format_helper(ao,&ainfo);
|
||||
if(ioctl(ao->fn, AUDIO_SETINFO, &ainfo) == -1) return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rate_best_match(audio_output_t *ao)
|
||||
{
|
||||
audio_info_t ainfo;
|
||||
AUDIO_INITINFO(&ainfo);
|
||||
|
||||
ainfo.play.sample_rate = ao->rate;
|
||||
if(ioctl(ao->fn, AUDIO_SETINFO, &ainfo) < 0) {
|
||||
ao->rate = 0;
|
||||
return 0;
|
||||
}
|
||||
if(ioctl(ao->fn, AUDIO_GETINFO, &ainfo) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ao->rate = ainfo.play.sample_rate;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_rate(audio_output_t *ao)
|
||||
{
|
||||
audio_info_t ainfo;
|
||||
|
||||
if(ao->rate != -1) {
|
||||
AUDIO_INITINFO(&ainfo);
|
||||
ainfo.play.sample_rate = ao->rate;
|
||||
if(ioctl(ao->fn, AUDIO_SETINFO, &ainfo) == -1) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int set_channels(audio_output_t *ao)
|
||||
{
|
||||
audio_info_t ainfo;
|
||||
|
||||
AUDIO_INITINFO(&ainfo);
|
||||
ainfo.play.channels = ao->channels;
|
||||
if(ioctl(ao->fn, AUDIO_SETINFO, &ainfo) == -1)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_format(audio_output_t *ao)
|
||||
{
|
||||
audio_info_t ainfo;
|
||||
|
||||
AUDIO_INITINFO(&ainfo);
|
||||
set_format_helper(ao,&ainfo);
|
||||
if(ioctl(ao->fn, AUDIO_SETINFO, &ainfo) == -1)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int open_sun(audio_output_t *ao)
|
||||
{
|
||||
audio_info_t ainfo;
|
||||
|
||||
if(!ao->device) {
|
||||
if(getenv("AUDIODEV")) {
|
||||
ao->device = getenv("AUDIODEV");
|
||||
} else {
|
||||
ao->device = "/dev/audio";
|
||||
}
|
||||
}
|
||||
|
||||
ao->fn = open(ao->device,O_WRONLY);
|
||||
if(ao->fn < 0) return ao->fn;
|
||||
|
||||
#if defined(SUNOS) && defined(AUDIO_GETDEV)
|
||||
{
|
||||
int type;
|
||||
if(ioctl(ao->fn, AUDIO_GETDEV, &type) == -1) return -1;
|
||||
if(type == AUDIO_DEV_UNKNOWN || type == AUDIO_DEV_AMD)
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
#if defined(SOLARIS) || defined(SPARCLINUX)
|
||||
{
|
||||
struct audio_device ad;
|
||||
if(ioctl(ao->fn, AUDIO_GETDEV, &ad) == -1)
|
||||
return -1;
|
||||
if(!strstr(ad.name,"dbri") && !strstr(ad.name,"CS4231"))
|
||||
warning1("Unknown sound system %s. But we try it.",ad.name);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if(reset_parameters_sun(ao) < 0) return -1;
|
||||
|
||||
AUDIO_INITINFO(&ainfo);
|
||||
|
||||
if(ao->flags > 0)
|
||||
ainfo.play.port = 0;
|
||||
if(ao->flags & AUDIO_OUT_INTERNAL_SPEAKER)
|
||||
ainfo.play.port |= AUDIO_SPEAKER;
|
||||
if(ao->flags & AUDIO_OUT_HEADPHONES)
|
||||
ainfo.play.port |= AUDIO_HEADPHONE;
|
||||
#ifdef AUDIO_LINE_OUT
|
||||
if(ao->flags & AUDIO_OUT_LINE_OUT)
|
||||
ainfo.play.port |= AUDIO_LINE_OUT;
|
||||
#endif
|
||||
|
||||
if(ao->gain != -1)
|
||||
ainfo.play.gain = ao->gain;
|
||||
|
||||
if(ioctl(ao->fn, AUDIO_SETINFO, &ainfo) == -1)
|
||||
return -1;
|
||||
|
||||
return ao->fn;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static int get_formats_sun(audio_output_t *ao)
|
||||
{
|
||||
static int tab[][3] = {
|
||||
{ AUDIO_ENCODING_ULAW , 8, MPG123_ENC_ULAW_8 } ,
|
||||
{ AUDIO_ENCODING_ALAW , 8, MPG123_ENC_ALAW_8 } ,
|
||||
{ AUDIO_ENCODING_LINEAR , 16, MPG123_ENC_SIGNED_16 } ,
|
||||
#if 0
|
||||
#if defined(SOLARIS) || defined(SPARCLINUX)
|
||||
{ AUDIO_ENCODING_LINEAR8 , 8, MPG123_ENC_UNSIGNED_8 } ,
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
audio_info_t ainfo;
|
||||
int i,fmts=0;
|
||||
|
||||
for(i=0;i<sizeof(tab)/sizeof(tab[0]);i++) {
|
||||
AUDIO_INITINFO(&ainfo);
|
||||
ainfo.play.encoding = tab[i][0];
|
||||
ainfo.play.precision = tab[i][1];
|
||||
#if 1
|
||||
ainfo.play.sample_rate = ao->rate;
|
||||
ainfo.play.channels = ao->channels;
|
||||
#endif
|
||||
if(ioctl(ao->fn, AUDIO_SETINFO, &ainfo) >= 0) {
|
||||
fmts |= tab[i][2];
|
||||
}
|
||||
}
|
||||
return fmts;
|
||||
}
|
||||
|
||||
static int write_sun(audio_output_t *ao,unsigned char *buf,int len)
|
||||
{
|
||||
return write(ao->fn,buf,len);
|
||||
}
|
||||
|
||||
static int close_sun(audio_output_t *ao)
|
||||
{
|
||||
close (ao->fn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void flush_sun(audio_output_t *ao)
|
||||
{
|
||||
/*ioctl (ao->fn, I_FLUSH, FLUSHRW);*/
|
||||
}
|
||||
|
||||
|
||||
static int init_sun(audio_output_t* ao)
|
||||
{
|
||||
if (ao==NULL) return -1;
|
||||
|
||||
/* Set callbacks */
|
||||
ao->open = open_sun;
|
||||
ao->flush = flush_sun;
|
||||
ao->write = write_sun;
|
||||
ao->get_formats = get_formats_sun;
|
||||
ao->close = close_sun;
|
||||
|
||||
/* Success */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Module information data structure
|
||||
*/
|
||||
mpg123_module_t mpg123_output_module_info = {
|
||||
/* api_version */ MPG123_MODULE_API_VERSION,
|
||||
/* name */ "sun",
|
||||
/* description */ "Audio output for Sun Audio.",
|
||||
/* revision */ "$Rev: 1872 $",
|
||||
/* handle */ NULL,
|
||||
|
||||
/* init_output */ init_sun,
|
||||
};
|
||||
|
||||
|
229
node_modules/lame/deps/mpg123/src/output/win32.c
generated
vendored
Normal file
229
node_modules/lame/deps/mpg123/src/output/win32.c
generated
vendored
Normal file
@ -0,0 +1,229 @@
|
||||
/*
|
||||
win32: audio output for Windows 32bit
|
||||
|
||||
copyright ?-2007 by the mpg123 project - free software under the terms of the LGPL 2.1
|
||||
see COPYING and AUTHORS files in distribution or http://mpg123.org
|
||||
|
||||
initially written (as it seems) by Tony Million
|
||||
rewrite of basic functionality for callback-less and properly ringbuffered operation by ravenexp
|
||||
*/
|
||||
|
||||
#include "mpg123app.h"
|
||||
#include <windows.h>
|
||||
#include "debug.h"
|
||||
|
||||
/*
|
||||
Buffer size and number of buffers in the playback ring
|
||||
NOTE: This particular num/size combination performs best under heavy
|
||||
loads for my system, however this may not be true for any hardware/OS out there.
|
||||
Generally, BUFFER_SIZE < 8k || NUM_BUFFERS > 16 || NUM_BUFFERS < 4 are not recommended.
|
||||
*/
|
||||
#define BUFFER_SIZE 0x10000
|
||||
#define NUM_BUFFERS 8 /* total 512k roughly 2.5 sec of CD quality sound */
|
||||
|
||||
/* Buffer ring queue state */
|
||||
struct queue_state
|
||||
{
|
||||
WAVEHDR buffer_headers[NUM_BUFFERS];
|
||||
/* The next buffer to be filled and put in playback */
|
||||
int next_buffer;
|
||||
/* Buffer playback completion event */
|
||||
HANDLE play_done_event;
|
||||
HWAVEOUT waveout;
|
||||
};
|
||||
|
||||
static int open_win32(struct audio_output_struct *ao)
|
||||
{
|
||||
struct queue_state* state;
|
||||
int i;
|
||||
MMRESULT res;
|
||||
WAVEFORMATEX out_fmt;
|
||||
UINT dev_id;
|
||||
|
||||
if(!ao) return -1;
|
||||
if(ao->rate == -1) return 0;
|
||||
|
||||
/* Allocate queue state struct for this device */
|
||||
state = calloc(1, sizeof(struct queue_state));
|
||||
if(!state) return -1;
|
||||
|
||||
ao->userptr = state;
|
||||
/* Allocate playback buffers */
|
||||
for(i = 0; i < NUM_BUFFERS; i++)
|
||||
if(!(state->buffer_headers[i].lpData = malloc(BUFFER_SIZE)))
|
||||
ereturn(-1, "Out of memory for playback buffers.");
|
||||
|
||||
state->play_done_event = CreateEvent(0,FALSE,FALSE,0);
|
||||
if(state->play_done_event == INVALID_HANDLE_VALUE) return -1;
|
||||
|
||||
/* FIXME: real device enumeration by capabilities? */
|
||||
dev_id = WAVE_MAPPER; /* probably does the same thing */
|
||||
ao->device = "WaveMapper";
|
||||
/* FIXME: support for smth besides MPG123_ENC_SIGNED_16? */
|
||||
out_fmt.wFormatTag = WAVE_FORMAT_PCM;
|
||||
out_fmt.wBitsPerSample = 16;
|
||||
out_fmt.nChannels = ao->channels;
|
||||
out_fmt.nSamplesPerSec = ao->rate;
|
||||
out_fmt.nBlockAlign = out_fmt.nChannels*out_fmt.wBitsPerSample/8;
|
||||
out_fmt.nAvgBytesPerSec = out_fmt.nBlockAlign*out_fmt.nSamplesPerSec;
|
||||
out_fmt.cbSize = 0;
|
||||
|
||||
res = waveOutOpen(&state->waveout, dev_id, &out_fmt,
|
||||
(DWORD_PTR)state->play_done_event, 0, CALLBACK_EVENT);
|
||||
|
||||
switch(res)
|
||||
{
|
||||
case MMSYSERR_NOERROR:
|
||||
break;
|
||||
case MMSYSERR_ALLOCATED:
|
||||
ereturn(-1, "Audio output device is already allocated.");
|
||||
case MMSYSERR_NODRIVER:
|
||||
ereturn(-1, "No device driver is present.");
|
||||
case MMSYSERR_NOMEM:
|
||||
ereturn(-1, "Unable to allocate or lock memory.");
|
||||
case WAVERR_BADFORMAT:
|
||||
ereturn(-1, "Unsupported waveform-audio format.");
|
||||
default:
|
||||
ereturn(-1, "Unable to open wave output device.");
|
||||
}
|
||||
|
||||
/* Reset event from the "device open" message */
|
||||
ResetEvent(state->play_done_event);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_formats_win32(struct audio_output_struct *ao)
|
||||
{
|
||||
/* FIXME: support for smth besides MPG123_ENC_SIGNED_16? */
|
||||
return MPG123_ENC_SIGNED_16;
|
||||
}
|
||||
|
||||
/* Stores audio data to the fixed size buffers and pushes them into the playback queue.
|
||||
I have one grief with that: The last piece of a track may not reach the output,
|
||||
only full buffers sent... But we don't get smooth audio otherwise. */
|
||||
static int write_win32(struct audio_output_struct *ao, unsigned char *buf, int len)
|
||||
{
|
||||
struct queue_state* state;
|
||||
MMRESULT res;
|
||||
WAVEHDR* hdr;
|
||||
|
||||
int rest_len; /* Input data bytes left for next recursion. */
|
||||
int bufill; /* Bytes we stuff into buffer now. */
|
||||
|
||||
if(!ao || !ao->userptr) return -1;
|
||||
if(!buf || len <= 0) return 0;
|
||||
|
||||
state = (struct queue_state*)ao->userptr;
|
||||
hdr = &state->buffer_headers[state->next_buffer];
|
||||
|
||||
/* Check buffer header and wait if it's being played.
|
||||
Skip waiting if the buffer is not full yet */
|
||||
while(hdr->dwBufferLength == BUFFER_SIZE && !(hdr->dwFlags & WHDR_DONE))
|
||||
{
|
||||
/* debug1("waiting for buffer %i...", state->next_buffer); */
|
||||
WaitForSingleObject(state->play_done_event, INFINITE);
|
||||
}
|
||||
|
||||
/* If it was a full buffer being played, clean up. */
|
||||
if(hdr->dwFlags & WHDR_DONE)
|
||||
{
|
||||
waveOutUnprepareHeader(state->waveout, hdr, sizeof(WAVEHDR));
|
||||
hdr->dwFlags = 0;
|
||||
hdr->dwBufferLength = 0;
|
||||
}
|
||||
|
||||
/* Now see how much we want to stuff in and then stuff it in. */
|
||||
bufill = BUFFER_SIZE - hdr->dwBufferLength;
|
||||
if(len < bufill) bufill = len;
|
||||
|
||||
rest_len = len - bufill;
|
||||
memcpy(hdr->lpData + hdr->dwBufferLength, buf, bufill);
|
||||
hdr->dwBufferLength += bufill;
|
||||
if(hdr->dwBufferLength == BUFFER_SIZE)
|
||||
{ /* Send the buffer out when it's full. */
|
||||
res = waveOutPrepareHeader(state->waveout, hdr, sizeof(WAVEHDR));
|
||||
if(res != MMSYSERR_NOERROR) ereturn(-1, "Can't write to audio output device (prepare).");
|
||||
|
||||
res = waveOutWrite(state->waveout, hdr, sizeof(WAVEHDR));
|
||||
if(res != MMSYSERR_NOERROR) ereturn(-1, "Can't write to audio output device.");
|
||||
|
||||
/* Cycle to the next buffer in the ring queue */
|
||||
state->next_buffer = (state->next_buffer + 1) % NUM_BUFFERS;
|
||||
}
|
||||
/* I'd like to propagate error codes or something... but there are no catchable surprises left.
|
||||
Anyhow: Here is the recursion that makes ravenexp happy;-) */
|
||||
if(rest_len && write_win32(ao, buf + bufill, rest_len) < 0) /* Write the rest. */
|
||||
return -1;
|
||||
else
|
||||
return len;
|
||||
}
|
||||
|
||||
static void flush_win32(struct audio_output_struct *ao)
|
||||
{
|
||||
int i, z;
|
||||
struct queue_state* state;
|
||||
|
||||
if(!ao || !ao->userptr) return;
|
||||
state = (struct queue_state*)ao->userptr;
|
||||
|
||||
/* FIXME: The very last output buffer is not played. This could be a problem on the feeding side. */
|
||||
i = 0;
|
||||
z = state->next_buffer - 1;
|
||||
for(i = 0; i < NUM_BUFFERS; i++)
|
||||
{
|
||||
if(!state->buffer_headers[i].dwFlags & WHDR_DONE)
|
||||
WaitForSingleObject(state->play_done_event, INFINITE);
|
||||
|
||||
waveOutUnprepareHeader(state->waveout, &state->buffer_headers[i], sizeof(WAVEHDR));
|
||||
state->buffer_headers[i].dwFlags = 0;
|
||||
state->buffer_headers[i].dwBufferLength = 0;
|
||||
z = (z + 1) % NUM_BUFFERS;
|
||||
}
|
||||
}
|
||||
|
||||
static int close_win32(struct audio_output_struct *ao)
|
||||
{
|
||||
int i;
|
||||
struct queue_state* state;
|
||||
|
||||
if(!ao || !ao->userptr) return -1;
|
||||
state = (struct queue_state*)ao->userptr;
|
||||
|
||||
flush_win32(ao);
|
||||
waveOutClose(state->waveout);
|
||||
CloseHandle(state->play_done_event);
|
||||
|
||||
for(i = 0; i < NUM_BUFFERS; i++) free(state->buffer_headers[i].lpData);
|
||||
|
||||
free(ao->userptr);
|
||||
ao->userptr = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init_win32(audio_output_t* ao)
|
||||
{
|
||||
if(!ao) return -1;
|
||||
|
||||
/* Set callbacks */
|
||||
ao->open = open_win32;
|
||||
ao->flush = flush_win32;
|
||||
ao->write = write_win32;
|
||||
ao->get_formats = get_formats_win32;
|
||||
ao->close = close_win32;
|
||||
|
||||
/* Success */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Module information data structure
|
||||
*/
|
||||
mpg123_module_t mpg123_output_module_info = {
|
||||
/* api_version */ MPG123_MODULE_API_VERSION,
|
||||
/* name */ "win32",
|
||||
/* description */ "Audio output for Windows (winmm).",
|
||||
/* revision */ "$Rev:$",
|
||||
/* handle */ NULL,
|
||||
|
||||
/* init_output */ init_win32,
|
||||
};
|
Reference in New Issue
Block a user