From cd3180c70180ae49c0c5611850c18ce0cebdd464 Mon Sep 17 00:00:00 2001
From: Warren Dukes <warren.dukes@gmail.com>
Date: Mon, 10 May 2004 02:20:15 +0000
Subject: [PATCH] stuff for configuring the audio output format (sampling rate,
 channels, bits)

git-svn-id: https://svn.musicpd.org/mpd/trunk@967 09075e82-0dd4-0310-85a5-a0d7c8717e4f
---
 src/audio.c  | 105 +++++++++++++++++++++++++++++++++++++++++++++------
 src/audio.h  |  10 ++++-
 src/conf.c   |   5 ++-
 src/conf.h   |   1 +
 src/decode.c |   6 +--
 src/main.c   |   2 +
 src/player.c |   2 +-
 7 files changed, 111 insertions(+), 20 deletions(-)

diff --git a/src/audio.c b/src/audio.c
index b532c95e4..243f65863 100644
--- a/src/audio.c
+++ b/src/audio.c
@@ -28,15 +28,23 @@
 #ifdef HAVE_AUDIO
 #include <ao/ao.h>
 
-int audio_write_size;
+static int audio_write_size;
 
-int audio_ao_driver_id;
-ao_option * audio_ao_options;
+static int audio_ao_driver_id;
+static ao_option * audio_ao_options;
 
-AudioFormat audio_format;
-ao_device * audio_device = NULL;
+static AudioFormat audio_format;
+static ao_device * audio_device = NULL;
 #endif
 
+static AudioFormat * audio_configFormat = NULL;
+
+static void copyAudioFormat(AudioFormat * dest, AudioFormat * src) {
+        dest->sampleRate = src->sampleRate;
+        dest->bits = src->bits;
+        dest->channels = src->channels;
+}
+
 void initAudioDriver() {
 #ifdef HAVE_AUDIO
 	ao_info * ai;
@@ -115,6 +123,81 @@ void initAudioDriver() {
 #endif
 }
 
+void getOutputAudioFormat(AudioFormat * inAudioFormat, 
+                AudioFormat * outAudioFormat)
+{
+        if(audio_configFormat) {
+                copyAudioFormat(outAudioFormat,audio_configFormat);
+        }
+        else copyAudioFormat(outAudioFormat,inAudioFormat);
+}
+
+void initAudioConfig() {
+        char * conf = getConf()[CONF_AUDIO_OUTPUT_FORMAT];
+        char * test;
+
+        if(NULL == conf) return;
+
+        audio_configFormat = malloc(sizeof(AudioFormat));
+
+        memset(audio_configFormat,0,sizeof(AudioFormat));
+
+        audio_configFormat->sampleRate = strtol(conf,&test,10);
+       
+        if(*test!=':') {
+                ERROR("error parsing audio output format: %s\n",conf);
+                exit(EXIT_FAILURE);
+        }
+ 
+        switch(audio_configFormat->sampleRate) {
+        case 48000:
+        case 44100:
+                break;
+        default:
+                ERROR("sample rate %i can not be used for audio output\n",
+                        (int)audio_configFormat->sampleRate);
+                exit(EXIT_FAILURE);
+        }
+
+        audio_configFormat->bits = strtol(test,&test,10);
+        
+        if(*test!=':') {
+                ERROR("error parsing audio output format: %s\n",conf);
+                exit(EXIT_FAILURE);
+        }
+
+        switch(audio_configFormat->bits) {
+        case 8:
+        case 16:
+                break;
+        default:
+                ERROR("bits %i can not be used for audio output\n",
+                        (int)audio_configFormat->bits);
+                exit(EXIT_FAILURE);
+        }
+
+        audio_configFormat->channels = strtol(test,&test,10);
+        
+        if(*test!='\0') {
+                ERROR("error parsing audio output format: %s\n",conf);
+                exit(EXIT_FAILURE);
+        }
+
+        switch(audio_configFormat->channels) {
+        case 1:
+        case 2:
+                break;
+        default:
+                ERROR("channels %i can not be used for audio output\n",
+                        (int)audio_configFormat->channels);
+                exit(EXIT_FAILURE);
+        }
+}
+
+void finishAudioConfig() {
+        if(audio_configFormat) free(audio_configFormat);
+}
+
 void finishAudioDriver() {
 #ifdef HAVE_AUDIO
 	ao_free_options(audio_ao_options);
@@ -137,19 +220,17 @@ int isCurrentAudioFormat(AudioFormat * audioFormat) {
 	return 1;
 }
 
-int initAudio(AudioFormat * audioFormat) {
+int openAudioDevice(AudioFormat * audioFormat) {
 #ifdef HAVE_AUDIO
 	ao_sample_format format;
 
 	if(audio_device && !isCurrentAudioFormat(audioFormat)) {
-		finishAudio();
+		closeAudioDevice();
 	}
 
 	if(!audio_device) {
 		if(audioFormat) {
-			audio_format.bits = audioFormat->bits;
-			audio_format.sampleRate = audioFormat->sampleRate;
-			audio_format.channels = audioFormat->channels;
+                        copyAudioFormat(&audio_format,audioFormat);
 		}
 
 		format.bits = audio_format.bits;
@@ -184,7 +265,7 @@ int playAudio(char * playChunk, int size) {
 		if(ao_play(audio_device,playChunk,send)==0) {
 			audioError();
 			ERROR("closing audio device due to write error\n");
-			finishAudio();
+			closeAudioDevice();
 			return -1;
 		}
 
@@ -196,7 +277,7 @@ int playAudio(char * playChunk, int size) {
 	return 0;
 }
 
-void finishAudio() {
+void closeAudioDevice() {
 #ifdef HAVE_AUDIO
 	if(audio_device) {
 		blockSignals();
diff --git a/src/audio.h b/src/audio.h
index 98b44326e..a03c42ca9 100644
--- a/src/audio.h
+++ b/src/audio.h
@@ -33,15 +33,21 @@ typedef struct _AudioFormat {
 	volatile mpd_sint8 bits;
 } AudioFormat;
 
+void getOutputAudioFormat(AudioFormat * inFormat, AudioFormat * outFormat);
+
+void initAudioConfig();
+
+void finishAudioConfig();
+
 void initAudioDriver();
 
 void finishAudioDriver();
 
-int initAudio(AudioFormat * audioFormat);
+int openAudioDevice(AudioFormat * audioFormat);
 
 int playAudio(char * playChunk,int size);
 
-void finishAudio();
+void closeAudioDevice();
 
 void audioError();
 
diff --git a/src/conf.c b/src/conf.c
index 2027ae872..c9050b8b0 100644
--- a/src/conf.c
+++ b/src/conf.c
@@ -37,7 +37,7 @@
 
 #define CONF_COMMENT	'#'
 
-#define CONF_NUMBER_OF_PARAMS		28
+#define CONF_NUMBER_OF_PARAMS		29
 #define CONF_NUMBER_OF_PATHS		6
 #define CONF_NUMBER_OF_REQUIRED		5
 #define CONF_NUMBER_OF_ALLOW_CATS	1
@@ -124,7 +124,8 @@ char ** readConf(char * file) {
 		"password",
 		"default_permissions",
 		"buffer_size",
-                "replaygain"
+                "replaygain",
+                "audio_output_format"
 	};
 
 	int conf_absolutePaths[CONF_NUMBER_OF_PATHS] = {
diff --git a/src/conf.h b/src/conf.h
index 3999f7f1f..901cdefb7 100644
--- a/src/conf.h
+++ b/src/conf.h
@@ -49,6 +49,7 @@
 #define CONF_DEFAULT_PERMISSIONS		25
 #define CONF_BUFFER_SIZE			26
 #define CONF_REPLAYGAIN                         27
+#define CONF_AUDIO_OUTPUT_FORMAT                28
 
 #define CONF_CAT_CHAR				"\n"
 
diff --git a/src/decode.c b/src/decode.c
index 221ca4a9b..d386a201a 100644
--- a/src/decode.c
+++ b/src/decode.c
@@ -124,7 +124,7 @@ int waitOnDecode(PlayerControl * pc, AudioFormat * af, DecoderControl * dc,
 		return -1;
 	}
 
-	if(initAudio(af)<0) {
+	if(openAudioDevice(af)<0) {
 		strncpy(pc->erroredFile,pc->file,MAXPATHLEN);
 		pc->erroredFile[MAXPATHLEN] = '\0';
 		pc->error = PLAYER_ERROR_AUDIO;
@@ -190,7 +190,7 @@ void decodeSeek(PlayerControl * pc, AudioFormat * af, DecoderControl * dc,
 		pause = !pause; \
 		if(pause) pc->state = PLAYER_STATE_PAUSE; \
 		else { \
-			if(initAudio(NULL)<0) { \
+			if(openAudioDevice(NULL)<0) { \
 				strncpy(pc->erroredFile,pc->file,MAXPATHLEN); \
 				pc->erroredFile[MAXPATHLEN] = '\0'; \
 				pc->error = PLAYER_ERROR_AUDIO; \
@@ -201,7 +201,7 @@ void decodeSeek(PlayerControl * pc, AudioFormat * af, DecoderControl * dc,
 		} \
 		pc->pause = 0; \
 		kill(getppid(),SIGUSR1); \
-		if(pause) finishAudio(); \
+		if(pause) closeAudioDevice(); \
 	} \
 	if(pc->seek) { \
 		pc->totalPlayTime+= pc->elapsedTime-pc->beginTime; \
diff --git a/src/main.c b/src/main.c
index b95e052f2..e33ea6e90 100644
--- a/src/main.c
+++ b/src/main.c
@@ -353,6 +353,7 @@ int main(int argc, char * argv[]) {
 	}
 
         initCommands();
+        initAudioConfig();
         initAudioDriver();
         initPlayerData();
         initVolume();
@@ -443,6 +444,7 @@ int main(int argc, char * argv[]) {
         finishPlaylist();
         freePlayerData();
         finishAudioDriver();
+        finishAudioConfig();
         finishVolume();
 	finishPaths();
 	finishPermissions();
diff --git a/src/player.c b/src/player.c
index 57e489f64..f8d183baa 100644
--- a/src/player.c
+++ b/src/player.c
@@ -127,7 +127,7 @@ int playerInit() {
 			else if(pc->stop) pc->stop = 0;
 			else if(pc->pause) pc->pause = 0;
 			else if(pc->closeAudio) {
-				finishAudio();
+				closeAudioDevice();
 				pc->closeAudio = 0;
 				kill(getppid(),SIGUSR1);
 			}