aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJ. Alexander Treuman <jat@spatialrift.net>2007-08-11 21:36:23 +0000
committerJ. Alexander Treuman <jat@spatialrift.net>2007-08-11 21:36:23 +0000
commit3fedc4d806e972c9676f82e88571a6381e61f3ff (patch)
treecfc6bfaca1be35405dd66796115bf5eacc111d87
parente195fb81002a38dd6c9de4a2b6433acc07b70a0b (diff)
downloadmpd-3fedc4d806e972c9676f82e88571a6381e61f3ff.tar.gz
mpd-3fedc4d806e972c9676f82e88571a6381e61f3ff.tar.xz
mpd-3fedc4d806e972c9676f82e88571a6381e61f3ff.zip
audioOutputs/audioOutput_shout: adding timers back
The shout plugin will now feign playback until the connect timeout is hit, preventing connection attempts from blocking playback on local outputs. Note that this patch is very different from remiss' original one. git-svn-id: https://svn.musicpd.org/mpd/trunk@6738 09075e82-0dd4-0310-85a5-a0d7c8717e4f
-rw-r--r--src/audioOutputs/audioOutput_shout.c107
1 files changed, 80 insertions, 27 deletions
diff --git a/src/audioOutputs/audioOutput_shout.c b/src/audioOutputs/audioOutput_shout.c
index 3bc8bb456..294d6a152 100644
--- a/src/audioOutputs/audioOutput_shout.c
+++ b/src/audioOutputs/audioOutput_shout.c
@@ -25,6 +25,7 @@
#include "../conf.h"
#include "../log.h"
#include "../pcm_utils.h"
+#include "../timer.h"
#include <string.h>
#include <time.h>
@@ -67,6 +68,8 @@ typedef struct _ShoutData {
int connAttempts;
time_t lastAttempt;
+ Timer *timer;
+
/* just a pointer to audioOutput->outAudioFormat */
AudioFormat *audioFormat;
} ShoutData;
@@ -85,6 +88,7 @@ static ShoutData *newShoutData(void)
ret->connAttempts = 0;
ret->lastAttempt = 0;
ret->audioFormat = NULL;
+ ret->timer = NULL;
return ret;
}
@@ -95,6 +99,8 @@ static void freeShoutData(ShoutData * sd)
shout_free(sd->shoutConn);
if (sd->tag)
freeMpdTag(sd->tag);
+ if (sd->timer)
+ timer_free(sd->timer);
free(sd);
}
@@ -347,13 +353,13 @@ static void clearEncoder(ShoutData * sd)
static void myShout_closeShoutConn(ShoutData * sd)
{
- if (sd->opened) {
+ if (sd->opened)
clearEncoder(sd);
- if (shout_close(sd->shoutConn) != SHOUTERR_SUCCESS) {
- ERROR("problem closing connection to shout server: "
- "%s\n", shout_get_error(sd->shoutConn));
- }
+ if (shout_get_connected(sd->shoutConn) != SHOUTERR_UNCONNECTED &&
+ shout_close(sd->shoutConn) != SHOUTERR_SUCCESS) {
+ ERROR("problem closing connection to shout server: %s\n",
+ shout_get_error(sd->shoutConn));
}
sd->opened = 0;
@@ -375,7 +381,10 @@ static void myShout_finishDriver(AudioOutput * audioOutput)
static void myShout_dropBufferedAudio(AudioOutput * audioOutput)
{
- /* needs to be implemented */
+ ShoutData *sd = (ShoutData *)audioOutput->data;
+ timer_reset(sd->timer);
+
+ /* needs to be implemented for shout */
}
static void myShout_closeDevice(AudioOutput * audioOutput)
@@ -384,6 +393,11 @@ static void myShout_closeDevice(AudioOutput * audioOutput)
myShout_closeShoutConn(sd);
+ if (sd->timer) {
+ timer_free(sd->timer);
+ sd->timer = NULL;
+ }
+
audioOutput->open = 0;
}
@@ -446,40 +460,52 @@ static int initEncoder(ShoutData * sd)
return 0;
}
-static int myShout_openShoutConn(AudioOutput * audioOutput)
+static int myShout_connect(ShoutData *sd)
{
- ShoutData *sd = (ShoutData *) audioOutput->data;
time_t t = time(NULL);
- int state;
+ int state = shout_get_connected(sd->shoutConn);
+
+ /* already connected */
+ if (state == SHOUTERR_CONNECTED)
+ return 0;
+
+ /* waiting to connect */
+ if (state == SHOUTERR_BUSY && sd->connAttempts != 0) {
+ /* timeout waiting to connect */
+ if ((t - sd->lastAttempt) > sd->timeout) {
+ ERROR("timeout connecting to shout server %s:%i "
+ "(attempt %i)\n",
+ shout_get_host(sd->shoutConn),
+ shout_get_port(sd->shoutConn),
+ sd->connAttempts);
+ return -1;
+ }
+ return 1;
+ }
+
+ /* we're in some funky state, so just reset it to unconnected */
+ if (state != SHOUTERR_UNCONNECTED)
+ shout_close(sd->shoutConn);
+
+ /* throttle new connection attempts */
if (sd->connAttempts != 0 &&
(t - sd->lastAttempt) <= CONN_ATTEMPT_INTERVAL) {
return -1;
}
+ /* initiate a new connection */
+
sd->connAttempts++;
sd->lastAttempt = t;
state = shout_open(sd->shoutConn);
-
- while (state == SHOUTERR_BUSY && (t - sd->lastAttempt) <= sd->timeout) {
- my_usleep(10000);
- state = shout_get_connected(sd->shoutConn);
- t = time(NULL);
- }
-
switch (state) {
case SHOUTERR_SUCCESS:
case SHOUTERR_CONNECTED:
- break;
+ return 0;
case SHOUTERR_BUSY:
- ERROR("timeout connecting to shout server %s:%i "
- "(attempt %i)\n",
- shout_get_host(sd->shoutConn),
- shout_get_port(sd->shoutConn),
- sd->connAttempts);
- shout_close(sd->shoutConn);
- return -1;
+ return 1;
default:
ERROR("problem opening connection to shout server %s:%i "
"(attempt %i): %s\n",
@@ -488,6 +514,16 @@ static int myShout_openShoutConn(AudioOutput * audioOutput)
sd->connAttempts, shout_get_error(sd->shoutConn));
return -1;
}
+}
+
+static int myShout_openShoutConn(AudioOutput * audioOutput)
+{
+ ShoutData *sd = (ShoutData *) audioOutput->data;
+ int status;
+
+ status = myShout_connect(sd);
+ if (status != 0)
+ return status;
if (initEncoder(sd) < 0) {
shout_close(sd->shoutConn);
@@ -528,6 +564,11 @@ static int myShout_openDevice(AudioOutput * audioOutput)
if (!sd->opened && myShout_openShoutConn(audioOutput) < 0)
return -1;
+ if (sd->timer)
+ timer_free(sd->timer);
+
+ sd->timer = timer_new(&audioOutput->outAudioFormat);
+
audioOutput->open = 1;
return 0;
@@ -571,13 +612,25 @@ static int myShout_play(AudioOutput * audioOutput, char *playChunk, int size)
float **vorbbuf;
int samples;
int bytes = sd->audioFormat->bits / 8;
+ int status;
+
+ if (!sd->timer->started)
+ timer_start(sd->timer);
+
+ timer_add(sd->timer, size);
if (sd->opened && sd->tagToSend)
myShout_sendMetadata(sd);
- if (!sd->opened && myShout_openShoutConn(audioOutput) < 0) {
- myShout_closeDevice(audioOutput);
- return -1;
+ if (!sd->opened) {
+ status = myShout_openShoutConn(audioOutput);
+ if (status < 0) {
+ myShout_closeDevice(audioOutput);
+ return -1;
+ } else if (status > 0) {
+ timer_sync(sd->timer);
+ return 0;
+ }
}
samples = size / (bytes * sd->audioFormat->channels);