Commit a8b2361b authored by Led's avatar Led

0.12.0.20041101

parent 9496158b
0.12
----
*) Abstract audio stuff into a plugin oriented thing
*) audio_ao & audio_oss & audio_shout
*) allow for sending to multiple audio devices
*) AudioOutput
*) have "format" as a default config option for all audioOutputs
*) don't automatically close audioOutput devices on openDevice(),
instead, let the plugins determine if they should be closed
or not, so that they can just leave the device open,
like if they are using a constant audioFormat
*) Fix id3v1 encoding
*) Cleanup Config File Code
*) Steal resampling code from ices (i think this code works only for 16-bit)
*) Rewrite replaygain stuff:
*) Replay gain struct with album and track gain's and peak's
......@@ -19,11 +28,6 @@
*) Add libshout && vorbis encoding support
*) clean up code to make more robust (only works for 16-bits)
*) check for memory leaks and such
*) add option for keeping audio devices alive (i.e. send silence even
when stopped/paused), this should also force a consistant
audio format
*) need some way to send metadata through shout plugin
*) cleanup configure script stuff (shout needs vorbisenc)
*) add command
......@@ -35,18 +39,20 @@
*) command for displaying playlist contents
*) command for appending to playlist
*) have listallinfo return directories
*) allow find/search commands take arbitrary search pairs
*) max http buffering configurable
*) abstract out input buffering from inputStream_http to inputStream
*) use getaddrinfo instead of gethostbyname (check libshout)
Post-1.0
--------
1) crosslink "list" stuff, for example, artists are crosslinked to alubms and
*) crosslink "list" stuff, for example, artists are crosslinked to alubms and
vice versa, this way you can do list album artists or list artist albums, this
will make life easier when we add genre and other metadata
2) rewrite linked list impelmentation to be more flexible
a) remove "key" stuff
b) allow assigning a compare function for a list
*) rewrite linked list impelmentation to be more flexible
*) remove "key" stuff
*) allow assigning a compare function for a list
*) allow find/search commands take arbitrary search pairs
*) add configurable metadata, and add newmetadata items
......@@ -76,6 +76,9 @@
/* Define for ogg vorbis support */
#undef HAVE_OGG
/* Define to enable OSS */
#undef HAVE_OSS
/* Define to enable libshout support */
#undef HAVE_SHOUT
......@@ -106,9 +109,6 @@
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define to disable OSS mixer support */
#undef NO_OSS_MIXER
/* Name of package */
#undef PACKAGE
......
......@@ -35,6 +35,7 @@ AC_ARG_ENABLE(audio,[ --disable-audio disable support for playing],,enable_a
AC_ARG_ENABLE(shout,[ --disable-shout disable support for streaming through shout],,enable_shout=yes)
AC_ARG_ENABLE(iconv,[ --disable-iconv disable iconv support],,enable_iconv=yes)
AC_ARG_ENABLE(ipv6,[ --disable-ipv6 disable IPv6 support],,enable_ipv6=yes)
AC_ARG_ENABLE(alsa,[ --disable-oss disable OSS support],,enable_oss=yes)
AC_ARG_ENABLE(alsa,[ --disable-alsa disable ALSA Mixer support],,enable_alsa=yes)
AC_ARG_ENABLE(ogg,[ --disable-ogg disable ogg support],,enable_ogg=yes)
AC_ARG_ENABLE(flac,[ --disable-flac disable flac support],,enable_flac=yes)
......@@ -109,7 +110,7 @@ if test x$enable_shout = xyes; then
XIPH_PATH_SHOUT([AC_DEFINE(HAVE_SHOUT, 1, [Define to enable libshout support]) MPD_LIBS="$MPD_LIBS $SHOUT_LIBS" MPD_CFLAGS="$MPD_CFLAGS $SHOUT_CFLAGS"], enable_shout=no)
fi
AC_CHECK_HEADER(sys/soundcard.h,enable_oss=yes,[AC_MSG_WARN(Soundcard headers not found -- disabling OSS mixer);enable_oss=no;AC_DEFINE(NO_OSS_MIXER,1,[Define to disable OSS mixer support])])
AC_CHECK_HEADER(sys/soundcard.h,[enable_oss=yes;AC_DEFINE(HAVE_OSS,1,[Define to enable OSS])],[AC_MSG_WARN(Soundcard headers not found -- disabling OSS support);enable_oss=no])
if test x$enable_alsa = xyes; then
AC_MSG_CHECKING(for alsa)
......
......@@ -14,37 +14,35 @@ error_file "~/.mpd/mpd.error"
# EVERYTHING ELSE IS OPTIONAL
##########################################################
################# FILESYSTEM SETTINGS ####################
#
# If the names of files or directories are
# not correctly displayed then set the
# following to the filesystem coding.
#
# Usually this is either:
# ISO-8859-1 or UTF-8
#
# After changing the filesystem_charset
# you will need to recreate the db:
# mpd --create-db
################## AUDIO OUTPUT ##########################
#
#filesystem_charset "ISO-8859-1"
# libao (ao_driver) supports any of the following:
# Refer to libao documentation for more information
#
##########################################################
#################### OPTIONAL FILES ######################
audio_output {
# Use default settings
type "ao"
name "default ao output"
#
# Location of DB file
# use this if you want to use OSS audio output
# type "ao"
# name "my OSS sound card"
# driver "oss"
# options "dsp=/dev/dsp"
#
#db_file "~/.mpd/mpd.db"
# use this if you want to use ALSA audio output
# type "ao"
# name "my ALSA device"
# driver "alsa09"
# options "dev=hw:0,0"
} # end of audio_output "ao"
#
# The state file (if set) will be a file
# for storing all current information
# (playlist, playing/paused, etc...) from
# the last MPD session. This will be used
# to recreate your last MPD session after
# restart.
# Set this if you have problems
# playing audio files.
# This will resample your music so
# that it comes out at the set rate.
#
#state_file "~/.mpd/mpdstate"
#audio_output_format "44100:16:2"
#
##########################################################
......@@ -68,31 +66,61 @@ error_file "~/.mpd/mpd.error"
##########################################################
################## AUDIO OUTPUT ##########################
################# SHOUT STREAMING ########################
#
# OSS Audio Output
#ao_driver "oss"
#ao_driver_options "dsp=/dev/dsp"
# Set this to allow mpd to stream its output to icecast2
# (i.e. mpd is a icecast2 source)
#
# ALSA Audio Output
#ao_driver "alsa09"
#ao_driver_options "dev=hw:0,0"
#audio_output {
# type "shout"
# name "my cool stream"
# host "hostname"
# port "8000"
# user "source"
# password "hackme"
# quality "5.0"
# format "44100:16:1"
#} # end of audio_output
#
# Set this if you have problems
# playing audio files.
# This will resample your music so
# that it comes out at the set rate.
##########################################################
################# FILESYSTEM SETTINGS ####################
#
#audio_output_format "44100:16:2"
# If the names of files or directories are
# not correctly displayed then set the
# following to the filesystem coding.
#
# You should not need mess with
# this value unless you know
# what you're doing.
# Usually this is either:
# ISO-8859-1 or UTF-8
#
#audio_write_size "1024"
# After changing the filesystem_charset
# you will need to recreate the db:
# mpd --create-db
#
#filesystem_charset "ISO-8859-1"
#
##########################################################
#################### OPTIONAL FILES ######################
#
# Location of DB file
#
#db_file "~/.mpd/mpd.db"
#
# The state file (if set) will be a file
# for storing all current information
# (playlist, playing/paused, etc...) from
# the last MPD session. This will be used
# to recreate your last MPD session after
# restart.
#
#state_file "~/.mpd/mpdstate"
#
##########################################################
################# REPLAYGAIN #############################
#
# Use Replay Gain (album or title)
......@@ -163,20 +191,6 @@ error_file "~/.mpd/mpd.error"
##########################################
################ SHOUT OPTIONS #####################
#
#shout_host "host"
#shout_port "8000"
#shout_user "source"
#shout_password "hackme"
#shout_name "My MPD!"
#shout_mount "/mpd.ogg"
#shout_quality "0.5"
#shout_format "44100:16:1"
#
####################################################
################ MISCELLANEOUS OPTIONS ###################
#
# This setting exists as precaution against attacks.
......
......@@ -58,6 +58,7 @@ mpd_SOURCES = \
audio.c \
audioOutput.c \
audioOutput_ao.c \
audioOutput_oss.c \
audioOutput_shout.c \
buffer2array.c \
charConv.c \
......
......@@ -180,6 +180,7 @@ mpd_SOURCES = \
audio.c \
audioOutput.c \
audioOutput_ao.c \
audioOutput_oss.c \
audioOutput_shout.c \
buffer2array.c \
charConv.c \
......@@ -236,22 +237,22 @@ am__objects_2 = mpd-aac_plugin.$(OBJEXT) mpd-audiofile_plugin.$(OBJEXT) \
mpd-ogg_plugin.$(OBJEXT)
am_mpd_OBJECTS = $(am__objects_1) $(am__objects_2) mpd-audio.$(OBJEXT) \
mpd-audioOutput.$(OBJEXT) mpd-audioOutput_ao.$(OBJEXT) \
mpd-audioOutput_shout.$(OBJEXT) mpd-buffer2array.$(OBJEXT) \
mpd-charConv.$(OBJEXT) mpd-command.$(OBJEXT) mpd-conf.$(OBJEXT) \
mpd-decode.$(OBJEXT) mpd-directory.$(OBJEXT) \
mpd-inputPlugin.$(OBJEXT) mpd-inputStream.$(OBJEXT) \
mpd-inputStream_file.$(OBJEXT) mpd-inputStream_http.$(OBJEXT) \
mpd-interface.$(OBJEXT) mpd-list.$(OBJEXT) mpd-listen.$(OBJEXT) \
mpd-log.$(OBJEXT) mpd-ls.$(OBJEXT) mpd-main.$(OBJEXT) \
mpd-metadataChunk.$(OBJEXT) mpd-myfprintf.$(OBJEXT) \
mpd-outputBuffer.$(OBJEXT) mpd-path.$(OBJEXT) \
mpd-pcm_utils.$(OBJEXT) mpd-permission.$(OBJEXT) \
mpd-player.$(OBJEXT) mpd-playerData.$(OBJEXT) \
mpd-playlist.$(OBJEXT) mpd-replayGain.$(OBJEXT) \
mpd-sig_handlers.$(OBJEXT) mpd-signal_check.$(OBJEXT) \
mpd-song.$(OBJEXT) mpd-stats.$(OBJEXT) mpd-tables.$(OBJEXT) \
mpd-tag.$(OBJEXT) mpd-utils.$(OBJEXT) mpd-volume.$(OBJEXT) \
mpd-utf8.$(OBJEXT)
mpd-audioOutput_oss.$(OBJEXT) mpd-audioOutput_shout.$(OBJEXT) \
mpd-buffer2array.$(OBJEXT) mpd-charConv.$(OBJEXT) \
mpd-command.$(OBJEXT) mpd-conf.$(OBJEXT) mpd-decode.$(OBJEXT) \
mpd-directory.$(OBJEXT) mpd-inputPlugin.$(OBJEXT) \
mpd-inputStream.$(OBJEXT) mpd-inputStream_file.$(OBJEXT) \
mpd-inputStream_http.$(OBJEXT) mpd-interface.$(OBJEXT) \
mpd-list.$(OBJEXT) mpd-listen.$(OBJEXT) mpd-log.$(OBJEXT) \
mpd-ls.$(OBJEXT) mpd-main.$(OBJEXT) mpd-metadataChunk.$(OBJEXT) \
mpd-myfprintf.$(OBJEXT) mpd-outputBuffer.$(OBJEXT) \
mpd-path.$(OBJEXT) mpd-pcm_utils.$(OBJEXT) \
mpd-permission.$(OBJEXT) mpd-player.$(OBJEXT) \
mpd-playerData.$(OBJEXT) mpd-playlist.$(OBJEXT) \
mpd-replayGain.$(OBJEXT) mpd-sig_handlers.$(OBJEXT) \
mpd-signal_check.$(OBJEXT) mpd-song.$(OBJEXT) \
mpd-stats.$(OBJEXT) mpd-tables.$(OBJEXT) mpd-tag.$(OBJEXT) \
mpd-utils.$(OBJEXT) mpd-volume.$(OBJEXT) mpd-utf8.$(OBJEXT)
mpd_OBJECTS = $(am_mpd_OBJECTS)
mpd_DEPENDENCIES =
mpd_LDFLAGS =
......@@ -267,6 +268,7 @@ am__depfiles_maybe = depfiles
@AMDEP_TRUE@ ./$(DEPDIR)/mpd-audio.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/mpd-audioOutput.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/mpd-audioOutput_ao.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/mpd-audioOutput_oss.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/mpd-audioOutput_shout.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/mpd-audiofile_plugin.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/mpd-buffer2array.Po \
......@@ -368,6 +370,7 @@ mpd-ogg_plugin.$(OBJEXT): inputPlugins/ogg_plugin.c
mpd-audio.$(OBJEXT): audio.c
mpd-audioOutput.$(OBJEXT): audioOutput.c
mpd-audioOutput_ao.$(OBJEXT): audioOutput_ao.c
mpd-audioOutput_oss.$(OBJEXT): audioOutput_oss.c
mpd-audioOutput_shout.$(OBJEXT): audioOutput_shout.c
mpd-buffer2array.$(OBJEXT): buffer2array.c
mpd-charConv.$(OBJEXT): charConv.c
......@@ -418,6 +421,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-audio.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-audioOutput.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-audioOutput_ao.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-audioOutput_oss.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-audioOutput_shout.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-audiofile_plugin.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpd-buffer2array.Po@am__quote@
......@@ -662,6 +666,24 @@ mpd-audioOutput_ao.lo: audioOutput_ao.c
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mpd_CFLAGS) $(CFLAGS) -c -o mpd-audioOutput_ao.lo `test -f 'audioOutput_ao.c' || echo '$(srcdir)/'`audioOutput_ao.c
mpd-audioOutput_oss.o: audioOutput_oss.c
@AMDEP_TRUE@ source='audioOutput_oss.c' object='mpd-audioOutput_oss.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/mpd-audioOutput_oss.Po' tmpdepfile='$(DEPDIR)/mpd-audioOutput_oss.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mpd_CFLAGS) $(CFLAGS) -c -o mpd-audioOutput_oss.o `test -f 'audioOutput_oss.c' || echo '$(srcdir)/'`audioOutput_oss.c
mpd-audioOutput_oss.obj: audioOutput_oss.c
@AMDEP_TRUE@ source='audioOutput_oss.c' object='mpd-audioOutput_oss.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/mpd-audioOutput_oss.Po' tmpdepfile='$(DEPDIR)/mpd-audioOutput_oss.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mpd_CFLAGS) $(CFLAGS) -c -o mpd-audioOutput_oss.obj `cygpath -w audioOutput_oss.c`
mpd-audioOutput_oss.lo: audioOutput_oss.c
@AMDEP_TRUE@ source='audioOutput_oss.c' object='mpd-audioOutput_oss.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/mpd-audioOutput_oss.Plo' tmpdepfile='$(DEPDIR)/mpd-audioOutput_oss.TPlo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mpd_CFLAGS) $(CFLAGS) -c -o mpd-audioOutput_oss.lo `test -f 'audioOutput_oss.c' || echo '$(srcdir)/'`audioOutput_oss.c
mpd-audioOutput_shout.o: audioOutput_shout.c
@AMDEP_TRUE@ source='audioOutput_shout.c' object='mpd-audioOutput_shout.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/mpd-audioOutput_shout.Po' tmpdepfile='$(DEPDIR)/mpd-audioOutput_shout.TPo' @AMDEPBACKSLASH@
......
......@@ -31,9 +31,6 @@ static AudioFormat audio_format;
static AudioFormat * audio_configFormat = NULL;
static AudioOutput * aoOutput = NULL;
static AudioOutput * shoutOutput = NULL;
void copyAudioFormat(AudioFormat * dest, AudioFormat * src) {
if(!src) return;
......@@ -42,17 +39,34 @@ void copyAudioFormat(AudioFormat * dest, AudioFormat * src) {
dest->channels = src->channels;
}
static AudioOutput ** audioOutputArray = NULL;
static int audioOutputArraySize = 0;
extern AudioOutputPlugin aoPlugin;
extern AudioOutputPlugin shoutPlugin;
void initAudioDriver() {
ConfigParam * param = NULL;
int i;
initAudioOutputPlugins();
loadAudioOutputPlugin(&aoPlugin);
loadAudioOutputPlugin(&shoutPlugin);
aoOutput = newAudioOutput("ao");
assert(aoOutput);
shoutOutput = newAudioOutput("shout");
while((param = getNextConfigParam(CONF_AUDIO_OUTPUT, param))) {
i = audioOutputArraySize++;
audioOutputArray = realloc(audioOutputArray,
audioOutputArraySize*sizeof(AudioOutput *));
audioOutputArray[i] = newAudioOutput(param);
if(!audioOutputArray[i]) {
ERROR("problems configuring output device defined at "
"line %i\n", param->line);
exit(EXIT_FAILURE);
}
}
}
void getOutputAudioFormat(AudioFormat * inAudioFormat,
......@@ -65,13 +79,17 @@ void getOutputAudioFormat(AudioFormat * inAudioFormat,
}
void initAudioConfig() {
char * conf = getConf()[CONF_AUDIO_OUTPUT_FORMAT];
ConfigParam * param = getConfigParam(CONF_AUDIO_OUTPUT_FORMAT);
if(NULL == conf) return;
if(NULL == param || NULL == param->value) return;
audio_configFormat = malloc(sizeof(AudioFormat));
if(0 != parseAudioConfig(audio_configFormat, conf)) exit(EXIT_FAILURE);
if(0 != parseAudioConfig(audio_configFormat, param->value)) {
ERROR("error parsing \"%s\" at line %i\n",
CONF_AUDIO_OUTPUT_FORMAT, param->line);
exit(EXIT_FAILURE);
}
}
int parseAudioConfig(AudioFormat * audioFormat, char * conf) {
......@@ -145,14 +163,19 @@ void finishAudioConfig() {
}
void finishAudioDriver() {
finishAudioOutput(aoOutput);
if(shoutOutput) finishAudioOutput(shoutOutput);
shoutOutput = NULL;
aoOutput = NULL;
int i;
for(i = 0; i < audioOutputArraySize; i++) {
finishAudioOutput(audioOutputArray[i]);
}
free(audioOutputArray);
audioOutputArray = NULL;
audioOutputArraySize = 0;
}
int isCurrentAudioFormat(AudioFormat * audioFormat) {
if(!audioFormat) return 0;
if(!audioFormat) return 1;
if(memcmp(audioFormat,&audio_format,sizeof(AudioFormat)) != 0) return 0;
......@@ -160,29 +183,62 @@ int isCurrentAudioFormat(AudioFormat * audioFormat) {
}
int openAudioDevice(AudioFormat * audioFormat) {
if(!aoOutput->open || !isCurrentAudioFormat(audioFormat)) {
if(audioFormat) copyAudioFormat(&audio_format, audioFormat);
if(shoutOutput) openAudioOutput(shoutOutput, &audio_format);
return openAudioOutput(aoOutput, &audio_format);
int isCurrentFormat = isCurrentAudioFormat(audioFormat);
int ret = -1;
int i;
if(!audioOutputArray) return -1;
if(!isCurrentFormat) {
copyAudioFormat(&audio_format, audioFormat);
}
return 0;
for(i = 0; i < audioOutputArraySize; i++) {
if(!audioOutputArray[i]->open || !isCurrentFormat) {
openAudioOutput(audioOutputArray[i], &audio_format);
}
if(audioOutputArray[i]->open) ret = 0;
}
return ret;
}
int playAudio(char * playChunk, int size) {
if(shoutOutput) playAudioOutput(shoutOutput, playChunk, size);
return playAudioOutput(aoOutput, playChunk, size);
int ret = -1;
int i;
for(i = 0; i < audioOutputArraySize; i++) {
if(0 == playAudioOutput(audioOutputArray[i], playChunk, size)) {
ret = 0;
}
}
return ret;
}
int isAudioDeviceOpen() {
return aoOutput->open;
int ret = 0;
int i;
for(i = 0; i < audioOutputArraySize; i++) {
ret |= audioOutputArray[i]->open;
}
return ret;
}
void closeAudioDevice() {
if(shoutOutput) closeAudioOutput(shoutOutput);
closeAudioOutput(aoOutput);
int i;
for(i = 0; i < audioOutputArraySize; i++) {
closeAudioOutput(audioOutputArray[i]);
}
}
void sendMetadataToAudioDevice(MpdTag * tag) {
if(shoutOutput) sendMetadataToAudioOutput(shoutOutput, tag);
int i;
for(i = 0; i < audioOutputArraySize; i++) {
sendMetadataToAudioOutput(audioOutputArray[i], tag);
}
}
#include <audioOutput.h>
#include "audioOutput.h"
#include <list.h>
#include "list.h"
#include "log.h"
#include <string.h>
#define AUDIO_OUTPUT_TYPE "type"
#define AUDIO_OUTPUT_NAME "name"
static List * audioOutputPluginList;
void loadAudioOutputPlugin(AudioOutputPlugin * audioOutputPlugin) {
if(!audioOutputPlugin->name) return;
insertInList(audioOutputPluginList, audioOutputPlugin->name,
audioOutputPlugin);
}
void unloadAudioOutputPlugin(AudioOutputPlugin * audioOutputPlugin) {
if(!audioOutputPlugin->name) return;
deleteFromList(audioOutputPluginList, audioOutputPlugin->name);
}
......@@ -21,13 +29,32 @@ void finishAudioOutputPlugins() {
freeList(audioOutputPluginList);
}
AudioOutput * newAudioOutput(char * name) {
#define getBlockParam(name, str) { \
BlockParam * bp; \
bp = getBlockParam(param, name); \
if(bp == NULL) { \
ERROR("couldn't find parameter \"%s\" in audio output " \
"definition begining at %i\n", \
name, param->line); \
exit(EXIT_FAILURE); \
} \
str = bp->value; \
}
AudioOutput * newAudioOutput(ConfigParam * param) {
AudioOutput * ret = NULL;
void * data = NULL;
char * name = NULL;
char * type = NULL;
getBlockParam(AUDIO_OUTPUT_NAME, name);
getBlockParam(AUDIO_OUTPUT_TYPE, type);
if(findInList(audioOutputPluginList, name, &data)) {
if(findInList(audioOutputPluginList, type, &data)) {
AudioOutputPlugin * plugin = (AudioOutputPlugin *) data;
ret = malloc(sizeof(AudioOutput));
ret->name = strdup(name);
ret->type = strdup(type);
ret->finishDriverFunc = plugin->finishDriverFunc;
ret->openDeviceFunc = plugin->openDeviceFunc;
ret->playFunc = plugin->playFunc;
......@@ -35,11 +62,16 @@ AudioOutput * newAudioOutput(char * name) {
ret->sendMetdataFunc = plugin->sendMetdataFunc;
ret->open = 0;
if(plugin->initDriverFunc(ret) != 0) {
if(plugin->initDriverFunc(ret, param) != 0) {
free(ret);
ret = NULL;
}
}
else {
ERROR("couldn't find audio output plugin for type \"%s\" at "
"line %i", type, param->line);
exit(EXIT_FAILURE);
}
return ret;
}
......@@ -61,6 +93,8 @@ void closeAudioOutput(AudioOutput * audioOutput) {
void finishAudioOutput(AudioOutput * audioOutput) {
closeAudioOutput(audioOutput);
audioOutput->finishDriverFunc(audioOutput);
free(audioOutput->type);
free(audioOutput->name);
free(audioOutput);
}
......
......@@ -24,12 +24,14 @@
#include "mpd_types.h"
#include "audio.h"
#include "tag.h"
#include "conf.h"
#define AUDIO_AO_DRIVER_DEFAULT "default"
typedef struct _AudioOutput AudioOutput;
typedef int (* AudioOutputInitDriverFunc) (AudioOutput * audioOutput);
typedef int (* AudioOutputInitDriverFunc) (AudioOutput * audioOutput,
ConfigParam * param);
typedef void (* AudioOutputFinishDriverFunc) (AudioOutput * audioOutput);
......@@ -46,6 +48,8 @@ typedef void (* AudioOutputSendMetadataFunc) (AudioOutput * audioOutput,
struct _AudioOutput {
int open;
char * name;
char * type;
AudioOutputFinishDriverFunc finishDriverFunc;
AudioOutputOpenDeviceFunc openDeviceFunc;
......@@ -73,7 +77,7 @@ void finishAudioOutputPlugins();
void loadAudioOutputPlugin(AudioOutputPlugin * audioOutputPlugin);
void unloadAudioOutputPlugin(AudioOutputPlugin * audioOutputPlugin);
AudioOutput * newAudioOutput(char * name);
AudioOutput * newAudioOutput(ConfigParam * param);
int openAudioOutput(AudioOutput * audioOutput, AudioFormat * audioFormat);
int playAudioOutput(AudioOutput * audioOutput, char * playChunk, int size);
void closeAudioOutput(AudioOutput * audioOutput);
......
......@@ -56,7 +56,9 @@ static void audioOutputAo_error() {
}
}
static int audioOutputAo_initDriver(AudioOutput * audioOutput) {
static int audioOutputAo_initDriver(AudioOutput * audioOutput,
ConfigParam * param)
{
ao_info * ai;
char * dup;
char * stk1;
......@@ -66,38 +68,51 @@ static int audioOutputAo_initDriver(AudioOutput * audioOutput) {
char * value;
char * test;
AoData * ad = newAoData();
BlockParam * blockParam;
audioOutput->data = ad;
ad->writeSize = strtol((getConf())[CONF_AUDIO_WRITE_SIZE],&test,10);
if (*test!='\0') {
ERROR("\"%s\" is not a valid write size\n",
(getConf())[CONF_AUDIO_WRITE_SIZE]);
exit(EXIT_FAILURE);
if((blockParam = getBlockParam(param, "write_size"))) {
ad->writeSize = strtol(blockParam->value, &test, 10);
if (*test!='\0') {
ERROR("\"%s\" is not a valid write size at line %i\n",
blockParam->value, blockParam->line);
exit(EXIT_FAILURE);
}
}
else ad->writeSize = 1024;
if(driverInitCount == 0) {
ao_initialize();
}
driverInitCount++;
if(strcmp(AUDIO_AO_DRIVER_DEFAULT,(getConf())[CONF_AO_DRIVER])==0) {
blockParam = getBlockParam(param, "driver");
if(!blockParam || 0 == strcmp(blockParam->value,"default")) {
ad->driverId = ao_default_driver_id();
}
else if((ad->driverId =
ao_driver_id((getConf())[CONF_AO_DRIVER]))<0) {
ERROR("\"%s\" is not a valid ao driver\n",
(getConf())[CONF_AO_DRIVER]);
ao_driver_id(blockParam->value))<0) {
ERROR("\"%s\" is not a valid ao driver at line %i\n",
blockParam->value, blockParam->line);
exit(EXIT_FAILURE);
}
if((ai = ao_driver_info(ad->driverId))==NULL) {
ERROR("problems getting ao_driver_info\n");
ERROR("problems getting driver info for device defined at "
"line %i\n", param->line);
ERROR("you may not have permission to the audio device\n");
exit(EXIT_FAILURE);
}
dup = strdup((getConf())[CONF_AO_DRIVER_OPTIONS]);
blockParam = getBlockParam(param, "options");
if(blockParam) {
dup = strdup(blockParam->value);
}
else dup = strdup("");
if(strlen(dup)) {
stk1 = NULL;
n1 = strtok_r(dup,";",&stk1);
......@@ -157,10 +172,11 @@ static void audioOutputAo_closeDevice(AudioOutput * audioOutput) {
if(ad->device) {
blockSignals();
ao_close(ad->device);
audioOutput->open = 0;
ad->device = NULL;
unblockSignals();
}
audioOutput->open = 0;
}
static int audioOutputAo_openDevice(AudioOutput * audioOutput,
......@@ -196,10 +212,7 @@ static int audioOutputAo_play(AudioOutput * audioOutput, char * playChunk,
int send;
AoData * ad = (AoData *)audioOutput->data;
if(ad->device==NULL) {
ERROR("trying to play w/o the ao device being open!\n");
return -1;
}
if(ad->device==NULL) return -1;
while(size>0) {
send = ad->writeSize > size ? size : ad->writeSize;
......
/* the Music Player Daemon (MPD)
* (c)2003-2004 by Warren Dukes (shank@mercury.chem.pitt.edu)
* This project's homepage is: http://www.musicpd.org
*
* OSS audio output (c) 2004 by Eric Wong <eric@petta-tech.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../config.h"
#include "audioOutput.h"
#include <stdlib.h>
#ifdef HAVE_OSS
#include "conf.h"
#include "log.h"
#include "sig_handlers.h"
#include <string.h>
#include <assert.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#if defined(__OpenBSD__) || defined(__NetBSD__)
# include <soundcard.h>
#else /* !(defined(__OpenBSD__) || defined(__NetBSD__) */
# include <sys/soundcard.h>
#endif /* !(defined(__OpenBSD__) || defined(__NetBSD__) */
typedef struct _OssData {
int fd;
char * device;
} OssData;
static OssData * newOssData() {
OssData * ret = malloc(sizeof(OssData));
ret->device = NULL;
ret->fd = -1;
return ret;
}
static void freeOssData(OssData * od) {
if(od->device) free(od->device);
free(od);
}
static int oss_initDriver(AudioOutput * audioOutput, ConfigParam * param) {
BlockParam * bp = getBlockParam(param, "device");
OssData * od = newOssData();
audioOutput->data = od;
if(!bp) {
int fd;
if(0 <= (fd = open("/dev/sound/dsp", O_WRONLY | O_NONBLOCK))) {
od->device = strdup("/dev/sound/dsp");
}
else if(0 <= (fd = open("/dev/dsp", O_WRONLY | O_NONBLOCK))) {
od->device = strdup("/dev/dsp");
}
else {
ERROR("Error trying to open default OSS device "
"specified at line %i\n", param->line);
ERROR("Specify a OSS device and/or check your "
"permissions\n");
exit(EXIT_FAILURE);
}
close(od->fd);
od->fd = -1;
return 0;
}
od->device = strdup(bp->value);
return 0;
}
static void oss_finishDriver(AudioOutput * audioOutput) {
OssData * od = audioOutput->data;
freeOssData(od);
}
static int oss_openDevice(AudioOutput * audioOutput, AudioFormat * audioFormat)
{
OssData * od = audioOutput->data;
#ifdef WORDS_BIGENDIAN
int i = AFMT_S16_BE;
#else
int i = AFMT_S16_LE;
#endif
if((od->fd = open(od->device, O_WRONLY)) < 0)
goto fail;
if(ioctl(od->fd, SNDCTL_DSP_SETFMT, &i))
goto fail;
if(ioctl(od->fd, SNDCTL_DSP_CHANNELS, &audioFormat->channels))
goto fail;
if(ioctl(od->fd, SNDCTL_DSP_SPEED, &audioFormat->sampleRate))
goto fail;
if(ioctl(od->fd, SNDCTL_DSP_SAMPLESIZE, &audioFormat->bits))
goto fail;
/*i = 1; if (ioctl(od->fd,SNDCTL_DSP_STEREO,&i)) err != 32; */
audioOutput->open = 1;
return 0;
fail:
if(od->fd >= 0) close(od->fd);
audioOutput->open = 0;
ERROR("Error opening OSS device \"%s\": %s\n", od->device,
strerror(errno));
return -1;
}
static void oss_closeDevice(AudioOutput * audioOutput) {
OssData * od = audioOutput->data;
if(od->fd >= 0) {
close(od->fd);
od->fd = -1;
}
audioOutput->open = 0;
}
static int oss_playAudio(AudioOutput * audioOutput, char * playChunk,
int size)
{
OssData * od = audioOutput->data;
int ret;
while (size > 0) {
ret = write(od->fd, playChunk, size);
if(ret<0) {
ERROR("closing audio device due to write error\n");
oss_closeDevice(audioOutput);
return -1;
}
playChunk += ret;
size -= ret;
}
return 0;
}
AudioOutputPlugin ossPlugin =
{
"oss",
oss_initDriver,
oss_finishDriver,
oss_openDevice,
oss_playAudio,
oss_closeDevice,
NULL /* sendMetadataFunc */
};
#else /* HAVE OSS */
AudioOutputPlugin ossPlugin =
{
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL /* sendMetadataFunc */
};
#endif /* HAVE_OSS */
......@@ -21,59 +21,72 @@
#include "../config.h"
#define CONF_PORT 0
#define CONF_MUSIC_DIRECTORY 1
#define CONF_PLAYLIST_DIRECTORY 2
#define CONF_LOG_FILE 3
#define CONF_ERROR_FILE 4
#define CONF_CONNECTION_TIMEOUT 5
#define CONF_MIXER_DEVICE 6
#define CONF_MAX_CONNECTIONS 7
#define CONF_MAX_PLAYLIST_LENGTH 8
#define CONF_BUFFER_BEFORE_PLAY 9
#define CONF_MAX_COMMAND_LIST_SIZE 10
#define CONF_MAX_OUTPUT_BUFFER_SIZE 11
#define CONF_AO_DRIVER 12
#define CONF_AO_DRIVER_OPTIONS 13
#define CONF_SAVE_ABSOLUTE_PATHS_IN_PLAYLISTS 14
#define CONF_BIND_TO_ADDRESS 15
#define CONF_MIXER_TYPE 16
#define CONF_STATE_FILE 17
#define CONF_USER 18
#define CONF_DB_FILE 19
#define CONF_LOG_LEVEL 20
#define CONF_MIXER_CONTROL 21
#define CONF_AUDIO_WRITE_SIZE 22
#define CONF_FS_CHARSET 23
#define CONF_PASSWORD 24
#define CONF_DEFAULT_PERMISSIONS 25
#define CONF_BUFFER_SIZE 26
#define CONF_REPLAYGAIN 27
#define CONF_AUDIO_OUTPUT_FORMAT 28
#define CONF_HTTP_PROXY_HOST 29
#define CONF_HTTP_PROXY_PORT 30
#define CONF_HTTP_PROXY_USER 31
#define CONF_HTTP_PROXY_PASSWORD 32
#define CONF_REPLAYGAIN_PREAMP 33
#define CONF_SHOUT_HOST 34
#define CONF_SHOUT_PORT 35
#define CONF_SHOUT_PASSWD 36
#define CONF_SHOUT_MOUNT 37
#define CONF_SHOUT_NAME 38
#define CONF_SHOUT_USER 39
#define CONF_SHOUT_QUALITY 40
#define CONF_ID3V1_ENCODING 41
#define CONF_SHOUT_FORMAT 42
#define CONF_PORT "port"
#define CONF_MUSIC_DIR "music_directory"
#define CONF_PLAYLIST_DIR "playlist_directory"
#define CONF_LOG_FILE "log_file"
#define CONF_ERROR_FILE "error_file"
#define CONF_CONN_TIMEOUT "connection_timeout"
#define CONF_MIXER_DEVICE "mixer_device"
#define CONF_MAX_CONN "max_connections"
#define CONF_MAX_PLAYLIST_LENGTH "max_playlist_length"
#define CONF_BUFFER_BEFORE_PLAY "buffer_before_play"
#define CONF_MAX_COMMAND_LIST_SIZE "max_command_list_size"
#define CONF_MAX_OUTPUT_BUFFER_SIZE "max_output_buffer_size"
#define CONF_AUDIO_OUTPUT "audio_output"
#define CONF_SAVE_ABSOLUTE_PATHS "save_absolute_paths_in_playlists"
#define CONF_BIND_TO_ADDRESS "bind_to_address"
#define CONF_MIXER_TYPE "mixer_type"
#define CONF_STATE_FILE "state_file"
#define CONF_USER "user"
#define CONF_DB_FILE "db_file"
#define CONF_LOG_LEVEL "log_level"
#define CONF_MIXER_CONTROL "mixer_control"
#define CONF_AUDIO_WRITE_SIZE "audio_write_size"
#define CONF_FS_CHARSET "filesystem_charset"
#define CONF_PASSWORD "password"
#define CONF_DEFAULT_PERMS "default_permissions"
#define CONF_AUDIO_BUFFER_SIZE "audio_buffer_size"
#define CONF_REPLAYGAIN "replaygain"
#define CONF_AUDIO_OUTPUT_FORMAT "audio_output_format"
#define CONF_HTTP_PROXY_HOST "http_proxy_host"
#define CONF_HTTP_PROXY_PORT "http_proxy_port"
#define CONF_HTTP_PROXY_USER "http_proxy_user"
#define CONF_HTTP_PROXY_PASSWORD "http_proxy_password"
#define CONF_REPLAYGAIN_PREAMP "replaygain_preamp"
#define CONF_ID3V1_ENCODING "id3v1_encoding"
#define CONF_CAT_CHAR "\n"
typedef struct _BlockParam {
char * name;
char * value;
int line;
} BlockParam;
/* do not free the return value, it is a static variable */
char ** readConf(char * file);
char ** getConf();
typedef struct _ConfigParam {
char * value;
unsigned int line;
BlockParam * blockParams;
int numberOfBlockParams;
} ConfigParam;
void initConf();
void writeConf(char * file);
void readConf(char * file);
/* don't free the returned value
set _last_ to NULL to get first entry */
ConfigParam * getNextConfigParam(char * name, ConfigParam * last);
#define getConfigParam(name) getNextConfigParam(name, NULL)
char * getConfigParamValue(char * name);
char * forceAndGetConfigParamValue(char * name);
void registerConfigParam(char * name, int repeats, int block);
BlockParam * getBlockParam(ConfigParam * param, char * name);
char * parseConfigFilePath(char * name, int force);
#endif
......@@ -158,6 +158,10 @@ int waitOnDecode(PlayerControl * pc, DecoderControl * dc, OutputBuffer * cb,
}
if((tag = metadataChunkToMpdTagDup(&(pc->fileMetadataChunk)))) {
/* lets put the filename in the title if no tag info */
if(!tag->title && !tag->artist && !tag->album) {
tag->title = strdup(pc->currentUrl);
}
sendMetadataToAudioDevice(tag);
freeMpdTag(tag);
}
......
......@@ -1053,7 +1053,8 @@ int readDirectoryDB() {
fsCharset = &(buffer[strlen(
DIRECTORY_FS_CHARSET)]);
if((tempCharset =
getConf()[CONF_FS_CHARSET]) &&
getConfigParamValue(
CONF_FS_CHARSET)) &&
strcmp(fsCharset,tempCharset))
{
WARNING("Using \"%s\" for the "
......@@ -1308,7 +1309,7 @@ int sumSongTime(FILE * fp, Song * song, void * data) {
}
int printInfoForAllIn(FILE * fp, char * name) {
return traverseAllIn(fp,name,directoryPrintSongInfo,NULL,NULL);
return traverseAllIn(fp,name,directoryPrintSongInfo,printDirectoryInDirectory,NULL);
}
int countSongsIn(FILE * fp, char * name) {
......
......@@ -47,6 +47,11 @@
#define HTTP_REDIRECT_MAX 10
static char * proxyHost = NULL;
static int proxyPort = 0;
static char * proxyUser = NULL;
static char * proxyPassword = NULL;
typedef struct _InputStreemHTTPData {
char * host;
char * path;
......@@ -59,57 +64,73 @@ typedef struct _InputStreemHTTPData {
int icyMetaint;
int prebuffer;
int icyOffset;
char * proxyHost;
int proxyPort;
char * proxyAuth;
char * httpAuth;
} InputStreamHTTPData;
void inputStream_initHttp() {
if(getConf()[CONF_HTTP_PROXY_HOST]) {
char * portStr = getConf()[CONF_HTTP_PROXY_PORT];
int port = 0;
char * test;
if(!portStr) {
ERROR("http_proxy_host specified but not the http_"
"proxy_port\n");
ConfigParam * param = getConfigParam(CONF_HTTP_PROXY_HOST);
char * test;
if(param) {
proxyHost = param->value;
param = getConfigParam(CONF_HTTP_PROXY_PORT);
if(!param) {
ERROR("%s specified but not %s", CONF_HTTP_PROXY_HOST,
CONF_HTTP_PROXY_PORT);
exit(EXIT_FAILURE);
}
port = strtol(portStr, &test, 10);
if(port <= 0 || *test != '\0') {
ERROR("http_proxy_port \"%s\" is not a positive integer"
"\n", portStr);
proxyPort = strtol(param->value, &test, 10);
if(proxyPort <= 0 || *test != '\0') {
ERROR("%s \"%s\" is not a positive integer, line %i\n"
CONF_HTTP_PROXY_PORT, param->value,
param->line);
}
if(getConf()[CONF_HTTP_PROXY_USER] &&
!getConf()[CONF_HTTP_PROXY_PASSWORD])
{
ERROR("http_proxy_user specified, but not http_proxy_"
"password\n");
exit(EXIT_FAILURE);
param = getConfigParam(CONF_HTTP_PROXY_USER);
if(param) {
proxyUser = param->value;
param = getConfigParam(CONF_HTTP_PROXY_PASSWORD);
if(!param) {
ERROR("%s specifid but not %s\n",
CONF_HTTP_PROXY_USER,
CONF_HTTP_PROXY_PASSWORD);
exit(EXIT_FAILURE);
}
proxyPassword = param->value;
}
if(getConf()[CONF_HTTP_PROXY_PASSWORD] &&
!getConf()[CONF_HTTP_PROXY_USER])
{
ERROR("http proxy password specified, but not http "
"proxy user\n");
param = getConfigParam(CONF_HTTP_PROXY_PASSWORD);
if(param) {
ERROR("%s specifid but not %s\n",
CONF_HTTP_PROXY_PASSWORD, CONF_HTTP_PROXY_USER);
exit(EXIT_FAILURE);
}
}
else if(getConf()[CONF_HTTP_PROXY_PORT]) {
ERROR("http_proxy_port specified but not http_proxy_host\n");
else if((param = getConfigParam(CONF_HTTP_PROXY_PORT))) {
ERROR("%s specified but not %s, line %i\n",
CONF_HTTP_PROXY_PORT, CONF_HTTP_PROXY_HOST,
param->line);
exit(EXIT_FAILURE);
}
else if(getConf()[CONF_HTTP_PROXY_USER]) {
ERROR("http_proxy_user specified but not http_proxy_host\n");
else if((param = getConfigParam(CONF_HTTP_PROXY_USER))) {
ERROR("%s specified but not %s, line %i\n",
CONF_HTTP_PROXY_USER, CONF_HTTP_PROXY_HOST,
param->line);
exit(EXIT_FAILURE);
}
else if(getConf()[CONF_HTTP_PROXY_PASSWORD]) {
ERROR("http_proxy_password specified but not http_proxy_host"
"\n");
else if((param = getConfigParam(CONF_HTTP_PROXY_PASSWORD))) {
ERROR("%s specified but not %s, line %i\n",
CONF_HTTP_PROXY_PASSWORD, CONF_HTTP_PROXY_HOST,
param->line);
exit(EXIT_FAILURE);
}
}
......@@ -188,19 +209,10 @@ static char * authString(char * header, char * user, char * password) {
static InputStreamHTTPData * newInputStreamHTTPData() {
InputStreamHTTPData * ret = malloc(sizeof(InputStreamHTTPData));
if(getConf()[CONF_HTTP_PROXY_HOST]) {
ret->proxyHost = getConf()[CONF_HTTP_PROXY_HOST];
DEBUG(__FILE__ ": Proxy host %s\n", ret->proxyHost);
ret->proxyPort = atoi(getConf()[CONF_HTTP_PROXY_PORT]);
DEBUG(__FILE__ ": Proxy port %i\n", ret->proxyPort);
ret->proxyAuth = proxyAuthString(
getConf()[CONF_HTTP_PROXY_USER],
getConf()[CONF_HTTP_PROXY_PASSWORD]);
}
else {
ret->proxyHost = NULL;
ret->proxyAuth = NULL;
if(proxyHost) {
ret->proxyAuth = proxyAuthString(proxyUser, proxyPassword);
}
else ret->proxyAuth = NULL;
ret->httpAuth = NULL;
ret->host = NULL;
......@@ -299,7 +311,7 @@ static int parseUrl(InputStreamHTTPData * data, char * url) {
}
/* fetch the path */
if(data->proxyHost) data->path = strdup(url);
if(proxyHost) data->path = strdup(url);
else data->path = strdup(slash ? slash : "/");
return 0;
......@@ -319,9 +331,9 @@ static int initHTTPConnection(InputStream * inStream) {
struct sockaddr_in6 sin6;
#endif
if(data->proxyHost) {
connHost = data->proxyHost;
connPort = data->proxyPort;
if(proxyHost) {
connHost = proxyHost;
connPort = proxyPort;
}
else {
connHost = data->host;
......
......@@ -47,12 +47,19 @@
#define INTERFACE_LIST_MODE_BEGIN "command_list_begin"
#define INTERFACE_LIST_OK_MODE_BEGIN "command_list_ok_begin"
#define INTERFACE_LIST_MODE_END "command_list_end"
#define INTERFACE_DEFAULT_OUT_BUFFER_SIZE 4096
int interface_max_connections = 0;
int interface_timeout;
unsigned long long interface_max_command_list_size;
unsigned long long interface_max_output_buffer_size;
#define INTERFACE_DEFAULT_OUT_BUFFER_SIZE 4096
#define INTERFACE_TIMEOUT_DEFAULT 60
#define INTERFACE_MAX_CONNECTIONS_DEFAULT 10
#define INTERFACE_MAX_COMMAND_LIST_DEFAULT (2048*1024)
#define INTERFACE_MAX_OUTPUT_BUFFER_SIZE_DEFAULT (2048*1024)
/* set this to zero to indicate we have no possible interfaces */
static int interface_max_connections = 0; /*INTERFACE_MAX_CONNECTIONS_DEFAULT;*/
static int interface_timeout = INTERFACE_TIMEOUT_DEFAULT;
static size_t interface_max_command_list_size =
INTERFACE_MAX_COMMAND_LIST_DEFAULT;
static size_t interface_max_output_buffer_size =
INTERFACE_MAX_OUTPUT_BUFFER_SIZE_DEFAULT;
typedef struct _Interface {
char buffer[INTERFACE_MAX_BUFFER_LENGTH+2];
......@@ -420,33 +427,59 @@ int doIOForInterfaces() {
void initInterfaces() {
int i;
char * test;
ConfigParam * param;
interface_timeout = strtol((getConf())[CONF_CONNECTION_TIMEOUT],&test,10);
if(*test!='\0' || interface_timeout<=0) {
ERROR("connection timeout \"%s\" is not a positive integer\n",(getConf())[CONF_CONNECTION_TIMEOUT]);
exit(EXIT_FAILURE);
}
param = getConfigParam(CONF_CONN_TIMEOUT);
interface_max_connections = strtol((getConf())[CONF_MAX_CONNECTIONS],&test,10);
if(*test!='\0' || interface_max_connections<=0) {
ERROR("max connections \"%s\" is not a positive integer\n",(getConf())[CONF_MAX_CONNECTIONS]);
exit(EXIT_FAILURE);
if(param) {
interface_timeout = strtol(param->value,&test,10);
if(*test!='\0' || interface_timeout<=0) {
ERROR("connection timeout \"%s\" is not a positive "
"integer, line %i\n", CONF_CONN_TIMEOUT,
param->line);
exit(EXIT_FAILURE);
}
}
interface_max_command_list_size = strtoll((getConf())[CONF_MAX_COMMAND_LIST_SIZE],&test,10);
if(*test!='\0' || interface_max_command_list_size<=0) {
ERROR("max command list size \"%s\" is not a positive integer\n",(getConf())[CONF_MAX_COMMAND_LIST_SIZE]);
exit(EXIT_FAILURE);
}
param = getConfigParam(CONF_MAX_CONN);
interface_max_output_buffer_size = strtoll((getConf())[CONF_MAX_OUTPUT_BUFFER_SIZE],&test,10);
if(*test!='\0' || interface_max_output_buffer_size<=0) {
ERROR("max output buffer size \"%s\" is not a positive integer\n",(getConf())[CONF_MAX_OUTPUT_BUFFER_SIZE]);
exit(EXIT_FAILURE);
if(param) {
interface_max_connections = strtol(param->value, &test, 10);
if(*test!='\0' || interface_max_connections<=0) {
ERROR("max connections \"%s\" is not a positive integer"
", line %i\n", param->value, param->line);
exit(EXIT_FAILURE);
}
}
else interface_max_connections = INTERFACE_MAX_CONNECTIONS_DEFAULT;
param = getConfigParam(CONF_MAX_COMMAND_LIST_SIZE);
if(param) {
interface_max_command_list_size = strtoll(param->value,
&test, 10);
if(*test!='\0' || interface_max_command_list_size<=0) {
ERROR("max command list size \"%s\" is not a positive "
"integer, line %i\n", param->value,
param->line);
exit(EXIT_FAILURE);
}
interface_max_command_list_size*=1024;
}
param = getConfigParam(CONF_MAX_OUTPUT_BUFFER_SIZE);
interface_max_command_list_size*=1024;
interface_max_output_buffer_size*=1024;
if(param) {
interface_max_output_buffer_size = strtoll(param->value, &test,
10);
if(*test!='\0' || interface_max_output_buffer_size<=0) {
ERROR("max output buffer size \"%s\" is not a positive "
"integer, line %i\n", param->value,
param->line);
exit(EXIT_FAILURE);
}
interface_max_output_buffer_size*=1024;
}
interfaces = malloc(sizeof(Interface)*interface_max_connections);
......
......@@ -192,7 +192,7 @@ int findInList(List * list,char * key,void ** data) {
tmpNode = list->nodesArray[cur];
cmp = strcmp(tmpNode->key,key);
if(cmp==0) {
(*data) = tmpNode->data;
if(data) *data = tmpNode->data;
return 1;
}
else if(cmp>0) high = cur;
......
......@@ -88,6 +88,7 @@ void deleteNodeFromList(List * list,ListNode * node);
* _key_ -> which node is being searched for
* _data_ -> a pointer to where data will be placed,
* _data_ memory should not by allocated or freed
* _data_ can be NULL
* returns 1 if successful, 0 otherwise
*/
int findInList(List * list, char * key, void ** data);
......
......@@ -44,6 +44,7 @@
int listenSocket;
int establish(unsigned short port) {
ConfigParam * param;
int allowReuse = ALLOW_REUSE;
int sock;
struct sockaddr * addrp;
......@@ -60,8 +61,10 @@ int establish(unsigned short port) {
memset(&sin, 0, sizeof(struct sockaddr_in));
sin.sin_port = htons(port);
sin.sin_family = AF_INET;
param = getConfigParam(CONF_BIND_TO_ADDRESS);
if(strcmp((getConf())[CONF_BIND_TO_ADDRESS],"any")==0) {
if(!param || 0==strcmp(param->value, "any")==0) {
#ifdef HAVE_IPV6
if(ipv6Supported()) {
sin6.sin6_addr = in6addr_any;
......@@ -78,9 +81,9 @@ int establish(unsigned short port) {
}
else {
struct hostent * he;
if(!(he = gethostbyname((getConf())[CONF_BIND_TO_ADDRESS]))) {
ERROR("can't lookup host \"%s\"\n",
(getConf())[CONF_BIND_TO_ADDRESS]);
if(!(he = gethostbyname(param->value))) {
ERROR("can't lookup host \"%s\" at line %i\n",
param->value, param->line);
exit(EXIT_FAILURE);
}
switch(he->h_addrtype) {
......@@ -88,8 +91,8 @@ int establish(unsigned short port) {
case AF_INET6:
if(!ipv6Supported()) {
ERROR("no IPv6 support, but a IPv6 address "
"found for \"%s\"\n",
(getConf())[CONF_BIND_TO_ADDRESS]);
"found for \"%s\" at line %i\n",
param->value, param->line);
exit(EXIT_FAILURE);
}
bcopy((char *)he->h_addr,(char *)
......@@ -105,8 +108,9 @@ int establish(unsigned short port) {
addrlen = sizeof(struct sockaddr_in);
break;
default:
ERROR("address type for \"%s\" is not IPv4 or IPv6\n",
(getConf())[CONF_BIND_TO_ADDRESS]);
ERROR("address type for \"%s\" is not IPv4 or IPv6 "
"at line %i\n",
param->value, param->line);
exit(EXIT_FAILURE);
}
}
......
......@@ -32,16 +32,24 @@ short warningFlushed = 0;
static char * warningBuffer = NULL;
void initLog() {
if(strcmp(getConf()[CONF_LOG_LEVEL],"default")==0) {
ConfigParam * param = getConfigParam(CONF_LOG_LEVEL);
if(!param) return;
if(0 == strcmp(param->value, "default")) {
if(logLevel<LOG_LEVEL_LOW) logLevel = LOG_LEVEL_LOW;
}
else if(strcmp(getConf()[CONF_LOG_LEVEL],"secure")==0) {
else if(0 == strcmp(param->value, "secure")) {
if(logLevel<LOG_LEVEL_SECURE) logLevel = LOG_LEVEL_SECURE;
}
else if(strcmp(getConf()[CONF_LOG_LEVEL],"verbose")==0) {
else if(0 == strcmp(param->value, "verbose")) {
if(logLevel<LOG_LEVEL_DEBUG) logLevel = LOG_LEVEL_DEBUG;
}
else ERROR("unknown log level \"%s\"\n",getConf()[CONF_LOG_LEVEL]);
else {
ERROR("unknown log level \"%s\" at line %i\n",
param->value, param->line);
exit(EXIT_FAILURE);
}
}
#define BUFFER_LENGTH 4096
......
......@@ -165,9 +165,12 @@ void parseOptions(int argc, char ** argv, Options * options) {
return;
}
else if(argcLeft<=2) {
char ** conf = NULL;
if(argcLeft==2) conf = readConf(argv[argc-1]);
if(argcLeft==1) {
int conf = 0;
if(argcLeft==2) {
readConf(argv[argc-1]);
conf = 1;
}
else if(argcLeft==1) {
FILE * fp;
char * homedir = getenv("HOME");
char userfile[MAXPATHLEN+1] = "";
......@@ -179,23 +182,27 @@ void parseOptions(int argc, char ** argv, Options * options) {
}
if(strlen(userfile) && (fp=fopen(userfile,"r"))) {
fclose(fp);
conf = readConf(userfile);
readConf(userfile);
conf = 1;
}
else if((fp=fopen(SYSTEM_CONFIG_FILE_LOCATION,"r"))) {
fclose(fp);
conf = readConf(SYSTEM_CONFIG_FILE_LOCATION);
readConf(SYSTEM_CONFIG_FILE_LOCATION);
conf = 1;
}
}
if(conf) {
options->portStr = conf[CONF_PORT];
options->musicDirArg = conf[CONF_MUSIC_DIRECTORY];
options->playlistDirArg = conf[CONF_PLAYLIST_DIRECTORY];
options->logFile = conf[CONF_LOG_FILE];
options->errorFile = conf[CONF_ERROR_FILE];
options->usr = conf[CONF_USER];
if(conf[CONF_DB_FILE]) {
options->dbFile = conf[CONF_DB_FILE];
}
options->portStr = forceAndGetConfigParamValue(
CONF_PORT);
options->musicDirArg =
parseConfigFilePath(CONF_MUSIC_DIR, 1);
options->playlistDirArg =
parseConfigFilePath(CONF_PLAYLIST_DIR, 1);
options->logFile = parseConfigFilePath(CONF_LOG_FILE,1);
options->errorFile =
parseConfigFilePath(CONF_ERROR_FILE, 1);
options->usr = getConfigParamValue(CONF_USER);
options->dbFile = parseConfigFilePath(CONF_DB_FILE, 0);
return;
}
}
......@@ -261,6 +268,9 @@ void changeToUser(Options * options) {
exit(EXIT_FAILURE);
}
if(userpwd->pw_dir) {
setenv("HOME", userpwd->pw_dir, 1);
}
}
}
......
......@@ -114,6 +114,7 @@ void initPaths(char * playlistDirArg, char * musicDirArg) {
char * charset = NULL;
char * originalLocale;
struct stat st;
ConfigParam * param;
playlistDir = prependCwdToPathDup(playlistDirArg);
if((stat(playlistDir,&st))<0) {
......@@ -135,8 +136,10 @@ void initPaths(char * playlistDirArg, char * musicDirArg) {
exit(EXIT_FAILURE);
}
if(getConf()[CONF_FS_CHARSET]) {
charset = strdup(getConf()[CONF_FS_CHARSET]);
param = getConfigParam(CONF_FS_CHARSET);
if(param) {
charset = strdup(param->value);
}
#ifdef HAVE_LOCALE
#ifdef HAVE_LANGINFO_CODESET
......@@ -296,5 +299,3 @@ char * prependCwdToPathDup(char * path) {
return realloc(ret,len+1);
}
/* vim:set shiftwidth=4 tabstop=8 expandtab: */
......@@ -69,56 +69,53 @@ unsigned int parsePermissions(char * string) {
}
void initPermissions() {
char * passwordSets;
char * nextSet;
char * temp;
char * cp1;
char * cp2;
char * password;
unsigned int * permission;
ConfigParam * param;
permission_passwords = makeList(free);
permission_default = PERMISSION_READ | PERMISSION_ADD |
PERMISSION_CONTROL | PERMISSION_ADMIN;
if(getConf()[CONF_DEFAULT_PERMISSIONS]) {
permission_default = parsePermissions(
getConf()[CONF_DEFAULT_PERMISSIONS]);
}
if(!getConf()[CONF_PASSWORD]) return;
if(!getConf()[CONF_DEFAULT_PERMISSIONS]) permission_default = 0;
param = getNextConfigParam(CONF_PASSWORD, NULL);
passwordSets = strdup(getConf()[CONF_PASSWORD]);
if(param) {
permission_default = 0;
nextSet = strtok_r(passwordSets,CONF_CAT_CHAR,&cp1);
while(nextSet && strlen(nextSet)) {
if(!strstr(nextSet,PERMISSION_PASSWORD_CHAR)) {
ERROR("\"%s\" not found in password string \"%s\"\n",
do {
if(!strstr(param->value, PERMISSION_PASSWORD_CHAR)) {
ERROR("\"%s\" not found in password string "
"\"%s\", line %i\n",
PERMISSION_PASSWORD_CHAR,
nextSet);
exit(EXIT_FAILURE);
}
param->value,
param->line);
exit(EXIT_FAILURE);
}
if(!(temp = strtok_r(nextSet,PERMISSION_PASSWORD_CHAR,&cp2))) {
ERROR("something weird just happend in permission.c\n");
exit(EXIT_FAILURE);
}
password = temp;
if(!(temp = strtok_r(param->value,
PERMISSION_PASSWORD_CHAR,&cp2))) {
ERROR("something weird just happend in permission.c\n");
exit(EXIT_FAILURE);
}
permission = malloc(sizeof(unsigned int));
*permission = parsePermissions(strtok_r(NULL,"",&cp2));
password = temp;
insertInList(permission_passwords,password,permission);
permission = malloc(sizeof(unsigned int));
*permission = parsePermissions(strtok_r(NULL,"",&cp2));
nextSet = strtok_r(NULL,CONF_CAT_CHAR,&cp1);
insertInList(permission_passwords,password,permission);
} while((param = getNextConfigParam(CONF_PASSWORD, param)));
}
sortList(permission_passwords);
param = getConfigParam(CONF_DEFAULT_PERMS);
free(passwordSets);
if(param) permission_default = parsePermissions(param->value);
sortList(permission_passwords);
}
int getPermissionFromPassword(char * password, unsigned int * permission) {
......
......@@ -30,23 +30,32 @@
int buffered_before_play;
int buffered_chunks;
#define DEFAULT_BUFFER_SIZE 2048
#define DEFAULT_BUFFER_BEFORE_PLAY 25
PlayerData * playerData_pd;
void initPlayerData() {
float perc;
float perc = DEFAULT_BUFFER_BEFORE_PLAY;
char * test;
int shmid;
int crossfade = 0;
size_t bufferSize;
size_t bufferSize = DEFAULT_BUFFER_SIZE;
size_t allocationSize;
OutputBuffer * buffer;
ConfigParam * param;
bufferSize = strtol(getConf()[CONF_BUFFER_SIZE],&test,10);
if(*test!='\0' || bufferSize<=0) {
ERROR("buffer size \"%s\" is not a positive integer\n",
getConf()[CONF_BUFFER_SIZE]);
exit(EXIT_FAILURE);
param = getConfigParam(CONF_AUDIO_BUFFER_SIZE);
if(param) {
bufferSize = strtol(param->value, &test, 10);
if(*test!='\0' || bufferSize<=0) {
ERROR("buffer size \"%s\" is not a positive integer, "
"line %i\n", param->value, param->line);
exit(EXIT_FAILURE);
}
}
bufferSize*=1024;
buffered_chunks = bufferSize/CHUNK_SIZE;
......@@ -56,13 +65,18 @@ void initPlayerData() {
exit(EXIT_FAILURE);
}
perc = strtod((getConf())[CONF_BUFFER_BEFORE_PLAY],&test);
if(*test!='%' || perc<0 || perc>100) {
ERROR("buffered before play \"%s\" is not a positive "
"percentage and less than 100 percent\n",
(getConf())[CONF_BUFFER_BEFORE_PLAY]);
exit(EXIT_FAILURE);
param = getConfigParam(CONF_BUFFER_BEFORE_PLAY);
if(param) {
perc = strtod(param->value, &test);
if(*test!='%' || perc<0 || perc>100) {
ERROR("buffered before play \"%s\" is not a positive "
"percentage and less than 100 percent, line %i"
"\n", param->value, param->line);
exit(EXIT_FAILURE);
}
}
buffered_before_play = (perc/100)*buffered_chunks;
if(buffered_before_play>buffered_chunks) {
buffered_before_play = buffered_chunks;
......
......@@ -60,6 +60,9 @@
#define PLAYLIST_HASH_MULT 4
#define DEFAULT_PLAYLIST_MAX_LENGTH (1024*16)
#define DEFAULT_PLAYLIST_SAVE_ABSOLUTE_PATHS 0
typedef struct _Playlist {
Song ** songs;
/* holds version a song was modified on */
......@@ -77,13 +80,13 @@ typedef struct _Playlist {
static Playlist playlist;
static int playlist_state = PLAYLIST_STATE_STOP;
static int playlist_max_length;
static int playlist_max_length = DEFAULT_PLAYLIST_MAX_LENGTH;
static int playlist_stopOnError;
static int playlist_errorCount = 0;
static int playlist_queueError;
static int playlist_noGoToNext = 0;
static int playlist_saveAbsolutePaths;
static int playlist_saveAbsolutePaths = DEFAULT_PLAYLIST_SAVE_ABSOLUTE_PATHS;
static char * playlist_stateFile = NULL;
......@@ -128,6 +131,7 @@ static void incrPlaylistCurrent() {
void initPlaylist() {
char * test;
int i;
ConfigParam * param;
playlist.length = 0;
playlist.repeat = 0;
......@@ -136,26 +140,32 @@ void initPlaylist() {
playlist.queued = -1;
playlist.current = -1;
playlist_max_length = strtol((getConf())[CONF_MAX_PLAYLIST_LENGTH],&test,10);
if(*test!='\0') {
ERROR("max playlist length \"%s\" is not an integer\n",
(getConf())[CONF_MAX_PLAYLIST_LENGTH]);
exit(EXIT_FAILURE);
}
param = getConfigParam(CONF_MAX_PLAYLIST_LENGTH);
if(strcmp("yes",(getConf())[CONF_SAVE_ABSOLUTE_PATHS_IN_PLAYLISTS])
==0) {
playlist_saveAbsolutePaths = 1;
}
else if(strcmp("no",(getConf())[CONF_SAVE_ABSOLUTE_PATHS_IN_PLAYLISTS])
==0) {
playlist_saveAbsolutePaths = 0;
if(param) {
playlist_max_length = strtol(param->value, &test, 10);
if(*test!='\0') {
ERROR("max playlist length \"%s\" is not an integer, "
"line %i\n", param->value, param->line);
exit(EXIT_FAILURE);
}
}
else {
ERROR("save_absolute_paths_in_playlist \"%s\" is not yes or "
"no\n",
(getConf())[CONF_SAVE_ABSOLUTE_PATHS_IN_PLAYLISTS]);
exit(EXIT_FAILURE);
param = getConfigParam(CONF_SAVE_ABSOLUTE_PATHS);
if(param) {
if(0 == strcmp("yes", param->value) ) {
playlist_saveAbsolutePaths = 1;
}
else if(0 == strcmp("no", param->value) ) {
playlist_saveAbsolutePaths = 0;
}
else {
ERROR("%s \"%s\" is not yes or no, line %i"
CONF_SAVE_ABSOLUTE_PATHS,
param->value, param->line);
exit(EXIT_FAILURE);
}
}
playlist.songs = malloc(sizeof(Song *)*playlist_max_length);
......@@ -167,11 +177,9 @@ void initPlaylist() {
memset(playlist.songs,0,sizeof(char *)*playlist_max_length);
srand(time(NULL));
srandom(time(NULL));
if(getConf()[CONF_STATE_FILE]) {
playlist_stateFile = getConf()[CONF_STATE_FILE];
}
playlist_stateFile = parseConfigFilePath(CONF_STATE_FILE, 0);
for(i=0; i<playlist_max_length*PLAYLIST_HASH_MULT; i++) {
playlist.idToPosition[i] = -1;
......@@ -635,7 +643,7 @@ int addSongToPlaylist(FILE * fp, Song * song) {
else */if(playlist.queued>=0) start = playlist.queued+1;
else start = playlist.current+1;
if(start < playlist.length) {
swap = rand()%(playlist.length-start);
swap = random()%(playlist.length-start);
swap+=start;
swapOrder(playlist.length-1,swap);
}
......@@ -1129,7 +1137,7 @@ void randomizeOrder(int start,int end) {
}
for(i=start;i<=end;i++) {
ri = rand()%(end-start+1)+start;
ri = random()%(end-start+1)+start;
if(ri==playlist.current) playlist.current = i;
else if(i==playlist.current) playlist.current = ri;
swapOrder(i,ri);
......@@ -1220,7 +1228,7 @@ int shufflePlaylist(FILE * fp) {
}
/* shuffle the rest of the list */
for(;i<playlist.length;i++) {
ri = rand()%(playlist.length-1)+1;
ri = random()%(playlist.length-1)+1;
swapSongs(i,ri);
}
......
......@@ -32,34 +32,38 @@ static int replayGainState = REPLAYGAIN_OFF;
static float replayGainPreamp = 1.0;
void initReplayGainState() {
if(!getConf()[CONF_REPLAYGAIN]) return;
ConfigParam * param = getConfigParam(CONF_REPLAYGAIN);
if(strcmp(getConf()[CONF_REPLAYGAIN],"track")==0) {
if(!param) return;
if(strcmp(param->value, "track") == 0) {
replayGainState = REPLAYGAIN_TRACK;
}
else if(strcmp(getConf()[CONF_REPLAYGAIN],"album")==0) {
else if(strcmp(param->value, "album") == 0) {
replayGainState = REPLAYGAIN_ALBUM;
}
else {
ERROR("replaygain value \"%s\" is invalid\n",
getConf()[CONF_REPLAYGAIN]);
ERROR("replaygain value \"%s\" at line %i is invalid\n",
param->value, param->line);
exit(EXIT_FAILURE);
}
if(getConf()[CONF_REPLAYGAIN_PREAMP]) {
param = getConfigParam(CONF_REPLAYGAIN_PREAMP);
if(param) {
char * test;
float f = strtod(getConf()[CONF_REPLAYGAIN_PREAMP], &test);
float f = strtod(param->value, &test);
if(*test != '\0') {
ERROR("Replaygain preamp \"%s\" is not a number\n",
getConf()[CONF_REPLAYGAIN_PREAMP]);
ERROR("Replaygain preamp \"%s\" is not a number at "
"line %i\n", param->value, param->line);
exit(EXIT_FAILURE);
}
if(f < -15 || f > 15) {
ERROR("Replaygain preamp \"%s\" is not between -15 and"
"15\n",
getConf()[CONF_REPLAYGAIN_PREAMP]);
"15 at line %i\n",
param->value, param->line);
exit(EXIT_FAILURE);
}
......
......@@ -93,18 +93,6 @@ char * getID3Info(struct id3_tag * tag, char * id) {
utf8 = id3_ucs4_utf8duplicate(ucs4);
if(!utf8) return NULL;
if(getConf()[CONF_ID3V1_ENCODING]
&& (id3_tag_options(tag, 0, 0) & ID3_TAG_OPTION_ID3V1)) {
char* isostr;
setCharSetConversion("ISO-8859-1", "UTF-8");
isostr = convStrDup(utf8);
free(utf8);
setCharSetConversion("UTF-8", getConf()[CONF_ID3V1_ENCODING]);
utf8 = convStrDup(isostr);
free(isostr);
}
return utf8;
}
#endif
......
......@@ -29,7 +29,7 @@
#include <sys/ioctl.h>
#include <fcntl.h>
#include <errno.h>
#ifndef NO_OSS_MIXER
#ifdef HAVE_OSS
#include <sys/soundcard.h>
#endif
#ifdef HAVE_ALSA
......@@ -45,12 +45,25 @@
#define VOLUME_MIXER_ALSA_DEFAULT "default"
#define VOLUME_MIXER_ALSA_CONTROL_DEFAULT "Master"
int volume_mixerType = VOLUME_MIXER_TYPE_SOFTWARE;
char * volume_mixerDevice;
#ifdef HAVE_OSS
#define VOLUME_MIXER_TYPE_DEFAULT VOLUME_MIXER_TYPE_OSS
#define VOLUME_MIXER_DEVICE_DEFAULT VOLUME_MIXER_OSS_DEFAULT
#else
#ifdef HAVE_ALSA
#define VOLUME_MIXER_TYPE_DEFAULT VOLUME_MIXER_TYPE_ALSA
#define VOLUME_MIXER_DEVICE_DEFAULT VOLUME_MIXER_ALSA_DEFAULT
#else
#define VOLUME_MIXER_TYPE_DEFAULT VOLUME_MIXER_TYPE_SOFTWARE
#define VOLUME_MIXER_DEVICE_DEFAULT VOLUME_MIXER_SOFTWARE_DEFAULT
#endif
#endif
int volume_mixerType = VOLUME_MIXER_TYPE_DEFAULT;
char * volume_mixerDevice = VOLUME_MIXER_DEVICE_DEFAULT;
int volume_softwareSet = 100;
#ifndef NO_OSS_MIXER
#ifdef HAVE_OSS
int volume_ossFd;
int volume_ossControl = SOUND_MIXER_VOLUME;
#endif
......@@ -63,16 +76,19 @@ long volume_alsaMax;
int volume_alsaSet = -1;
#endif
#ifndef NO_OSS_MIXER
#ifdef HAVE_OSS
int prepOssMixer(char * device) {
int devmask = 0;
ConfigParam * param;
if((volume_ossFd = open(device,O_RDONLY))<0) {
WARNING("unable to open oss mixer \"%s\"\n",device);
return -1;
}
if(getConf()[CONF_MIXER_CONTROL]) {
param = getConfigParam(CONF_MIXER_CONTROL);
if(param) {
char * labels[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_LABELS;
char * dup;
int i,j;
......@@ -88,7 +104,7 @@ int prepOssMixer(char * device) {
/* eliminate spaces at the end */
j = strlen(dup)-1;
while(j>=0 && dup[j]==' ') dup[j--] = '\0';
if(strcasecmp(dup,getConf()[CONF_MIXER_CONTROL])==0) {
if(strcasecmp(dup, param->value)==0) {
free(dup);
break;
}
......@@ -96,14 +112,14 @@ int prepOssMixer(char * device) {
}
if(i>=SOUND_MIXER_NRDEVICES) {
WARNING("mixer control \"%s\" not found\n",
getConf()[CONF_MIXER_CONTROL]);
WARNING("mixer control \"%s\" not found at line %i\n",
param->value, param->line);
close(volume_ossFd);
return -1;
}
else if(!( ( 1 << i ) & devmask )) {
WARNING("mixer control \"%s\" not usable\n",
getConf()[CONF_MIXER_CONTROL]);
WARNING("mixer control \"%s\" not usable at line %i\n",
param->value, param->line);
close(volume_ossFd);
return -1;
}
......@@ -173,6 +189,7 @@ int prepAlsaMixer(char * card) {
int err;
snd_mixer_elem_t * elem;
char * controlName = VOLUME_MIXER_ALSA_CONTROL_DEFAULT;
ConfigParam * param;
if((err = snd_mixer_open(&volume_alsaMixerHandle,0))<0) {
WARNING("problems opening alsa mixer: %s\n",snd_strerror(err));
......@@ -201,8 +218,11 @@ int prepAlsaMixer(char * card) {
}
elem = snd_mixer_first_elem(volume_alsaMixerHandle);
if(getConf()[CONF_MIXER_CONTROL]) {
controlName = getConf()[CONF_MIXER_CONTROL];
param = getConfigParam(CONF_MIXER_CONTROL);
if(param) {
controlName = param->value;
}
while(elem) {
......@@ -315,7 +335,7 @@ int prepMixer(char * device) {
case VOLUME_MIXER_TYPE_ALSA:
return prepAlsaMixer(device);
#endif
#ifndef NO_OSS_MIXER
#ifdef HAVE_OSS
case VOLUME_MIXER_TYPE_OSS:
return prepOssMixer(device);
#endif
......@@ -331,7 +351,7 @@ void finishVolume() {
closeAlsaMixer();
break;
#endif
#ifndef NO_OSS_MIXER
#ifdef HAVE_OSS
case VOLUME_MIXER_TYPE_OSS:
closeOssMixer();
break;
......@@ -340,29 +360,37 @@ void finishVolume() {
}
void initVolume() {
if(0);
ConfigParam * param = getConfigParam(CONF_MIXER_TYPE);
if(param) {
if(0);
#ifdef HAVE_ALSA
else if(strcmp((getConf())[CONF_MIXER_TYPE],VOLUME_MIXER_ALSA)==0) {
volume_mixerType = VOLUME_MIXER_TYPE_ALSA;
volume_mixerDevice = VOLUME_MIXER_ALSA_DEFAULT;
}
else if(strcmp(param->value, VOLUME_MIXER_ALSA)==0) {
volume_mixerType = VOLUME_MIXER_TYPE_ALSA;
volume_mixerDevice = VOLUME_MIXER_ALSA_DEFAULT;
}
#endif
#ifndef NO_OSS_MIXER
else if(strcmp((getConf())[CONF_MIXER_TYPE],VOLUME_MIXER_OSS)==0) {
volume_mixerType = VOLUME_MIXER_TYPE_OSS;
volume_mixerDevice = VOLUME_MIXER_OSS_DEFAULT;
}
#ifdef HAVE_OSS
else if(strcmp(param->value, VOLUME_MIXER_OSS)==0) {
volume_mixerType = VOLUME_MIXER_TYPE_OSS;
volume_mixerDevice = VOLUME_MIXER_OSS_DEFAULT;
}
#endif
else if(strcmp((getConf())[CONF_MIXER_TYPE],VOLUME_MIXER_SOFTWARE)==0) {
volume_mixerType = VOLUME_MIXER_TYPE_SOFTWARE;
volume_mixerDevice = VOLUME_MIXER_SOFTWARE_DEFAULT;
}
else {
ERROR("unknown mixer type: %s\n",(getConf())[CONF_MIXER_TYPE]);
exit(EXIT_FAILURE);
else if(strcmp(param->value ,VOLUME_MIXER_SOFTWARE)==0) {
volume_mixerType = VOLUME_MIXER_TYPE_SOFTWARE;
volume_mixerDevice = VOLUME_MIXER_SOFTWARE_DEFAULT;
}
else {
ERROR("unknown mixer type %s at line %i\n",
param->value, param->line);
exit(EXIT_FAILURE);
}
}
if(strlen((getConf())[CONF_MIXER_DEVICE])) {
volume_mixerDevice = (getConf())[CONF_MIXER_DEVICE];
param = getConfigParam(CONF_MIXER_DEVICE);
if(param) {
volume_mixerDevice = param->value;
}
}
......@@ -383,7 +411,7 @@ int getVolumeLevel() {
case VOLUME_MIXER_TYPE_ALSA:
return getAlsaVolumeLevel();
#endif
#ifndef NO_OSS_MIXER
#ifdef HAVE_OSS
case VOLUME_MIXER_TYPE_OSS:
return getOssVolumeLevel();
#endif
......@@ -420,7 +448,7 @@ int changeVolumeLevel(FILE * fp, int change, int rel) {
case VOLUME_MIXER_TYPE_ALSA:
return changeAlsaVolumeLevel(fp,change,rel);
#endif
#ifndef NO_OSS_MIXER
#ifdef HAVE_OSS
case VOLUME_MIXER_TYPE_OSS:
return changeOssVolumeLevel(fp,change,rel);
#endif
......@@ -431,4 +459,3 @@ int changeVolumeLevel(FILE * fp, int change, int rel) {
break;
}
}
/* vim:set shiftwidth=4 tabstop=8 expandtab: */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment