mirror of
https://gitlab.xiph.org/xiph/ezstream.git
synced 2025-01-03 14:56:35 -05:00
Allow users to restrict the number of reconnection attempts. This also changes
how reconnections are handled in general: A recovered connection always skips to the next tune as well, as it seems that at least for Ogg Vorbis, libshout wants to see an Ogg header after a shout_open(). The new code makes this behavior consistent among all formats. git-svn-id: https://svn.xiph.org/trunk/ezstream@12599 0101bb08-14d6-0310-b084-bc0e0c8e3800
This commit is contained in:
parent
2a511a64fc
commit
956f674a44
2
NEWS
2
NEWS
@ -11,6 +11,8 @@ Changes in 0.3.0, (SVN trunk):
|
||||
the new <playlist_program> configuration option to 1.
|
||||
- New <stream_once> configuration option, which makes ezstream play a media
|
||||
file or playlist once and then exit.
|
||||
- New <reconnect_tries> option to restrict the number of reconnection
|
||||
attempts to a server in case the connection goes down.
|
||||
- Add feature to skip the currently streaming track, done by sending the
|
||||
SIGUSR1 signal to the ezstream process.
|
||||
- New command line option `-q': Suppress standard error output from external
|
||||
|
@ -198,6 +198,13 @@ to stream \&<filename/\&> content only once, and to
|
||||
.Pq zero
|
||||
for continuous streaming
|
||||
.Pq the default .
|
||||
.It Sy \&<reconnect_tries\ /\&>
|
||||
Set how many attempts should be made to reconnect to the Icecast server in case
|
||||
the connection is interrupted.
|
||||
The default is to try indefinitely, which is equal to setting this
|
||||
configuration option to
|
||||
.Sy 0
|
||||
.Pq zero .
|
||||
.It Sy \&<svrinfoname\ /\&>
|
||||
.Pq Optional.
|
||||
Set the name of the broadcast.
|
||||
|
@ -140,8 +140,8 @@ parseConfig(const char *fileName)
|
||||
xmlDocPtr doc;
|
||||
xmlNodePtr cur;
|
||||
char *ls_xmlContentPtr;
|
||||
int program_set, shuffle_set, streamOnce_set,
|
||||
svrinfopublic_set;
|
||||
int program_set, reconnect_set, shuffle_set,
|
||||
streamOnce_set, svrinfopublic_set;
|
||||
|
||||
xmlLineNumbersDefault(1);
|
||||
if ((doc = xmlParseFile(fileName)) == NULL) {
|
||||
@ -160,6 +160,7 @@ parseConfig(const char *fileName)
|
||||
memset(&ezConfig, '\000', sizeof(ezConfig));
|
||||
|
||||
program_set = 0;
|
||||
reconnect_set = 0;
|
||||
shuffle_set = 0;
|
||||
streamOnce_set = 0;
|
||||
svrinfopublic_set = 0;
|
||||
@ -270,6 +271,19 @@ parseConfig(const char *fileName)
|
||||
streamOnce_set = 1;
|
||||
}
|
||||
}
|
||||
if (!xmlStrcmp(cur->name, BAD_CAST "reconnect_tries")) {
|
||||
if (reconnect_set) {
|
||||
printf("%s[%ld]: Error: Cannot have multiple <reconnect_tries> elements.\n",
|
||||
fileName, xmlGetLineNo(cur));
|
||||
goto config_error;
|
||||
}
|
||||
if (cur->xmlChildrenNode != NULL) {
|
||||
ls_xmlContentPtr = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
|
||||
ezConfig.reconnectAttempts = atoi(ls_xmlContentPtr);
|
||||
xmlFree(ls_xmlContentPtr);
|
||||
reconnect_set = 1;
|
||||
}
|
||||
}
|
||||
if (!xmlStrcmp(cur->name, BAD_CAST "svrinfoname")) {
|
||||
if (ezConfig.serverName != NULL) {
|
||||
printf("%s[%ld]: Error: Cannot have multiple <svrinfoname> elements.\n",
|
||||
|
@ -59,6 +59,7 @@ typedef struct tag_EZCONFIG {
|
||||
int shuffle;
|
||||
int fileNameIsProgram;
|
||||
int streamOnce;
|
||||
unsigned int reconnectAttempts;
|
||||
} EZCONFIG;
|
||||
|
||||
EZCONFIG * getEZConfig(void);
|
||||
|
101
src/ezstream.c
101
src/ezstream.c
@ -83,6 +83,11 @@
|
||||
# define STRNCASECMP strncasecmp
|
||||
#endif /* WIN32 */
|
||||
|
||||
#define STREAM_DONE 0
|
||||
#define STREAM_CONT 1
|
||||
#define STREAM_SKIP 2
|
||||
#define STREAM_SERVERR 3
|
||||
|
||||
#ifdef HAVE___PROGNAME
|
||||
extern char *__progname;
|
||||
#else
|
||||
@ -130,6 +135,7 @@ void setMetadata(shout_t *, const char *);
|
||||
char * buildCommandString(const char *, const char *, const char *);
|
||||
char * processMetadata(shout_t *, const char *, const char *);
|
||||
FILE * openResource(shout_t *, const char *, int *, char **, int *);
|
||||
int reconnectServer(shout_t *, int);
|
||||
int sendStream(shout_t *, FILE *, const char *, int, void *);
|
||||
int streamFile(shout_t *, const char *);
|
||||
int streamPlaylist(shout_t *, const char *);
|
||||
@ -565,13 +571,59 @@ openResource(shout_t *shout, const char *fileName, int *popenFlag,
|
||||
return (filep);
|
||||
}
|
||||
|
||||
int
|
||||
reconnectServer(shout_t *shout, int closeConn)
|
||||
{
|
||||
unsigned int i;
|
||||
int close_conn = closeConn;
|
||||
|
||||
printf("%s: Connection to %s lost.\n", __progname, pezConfig->URL);
|
||||
|
||||
i = 0;
|
||||
while (++i) {
|
||||
printf("%s: Attempting reconnection #", __progname);
|
||||
if (pezConfig->reconnectAttempts > 0)
|
||||
printf("%u/%u: ", i,
|
||||
pezConfig->reconnectAttempts);
|
||||
else
|
||||
printf("%u: ", i);
|
||||
|
||||
if (close_conn == 0)
|
||||
close_conn = 1;
|
||||
else
|
||||
shout_close(shout);
|
||||
if (shout_open(shout) == SHOUTERR_SUCCESS) {
|
||||
printf("OK\n%s: Reconnect to %s successful.\n",
|
||||
__progname, pezConfig->URL);
|
||||
return (1);
|
||||
}
|
||||
|
||||
printf("FAILED: %s\n", shout_get_error(shout));
|
||||
|
||||
if (pezConfig->reconnectAttempts > 0 &&
|
||||
i >= pezConfig->reconnectAttempts)
|
||||
break;
|
||||
|
||||
printf("%s: Waiting 5s for %s to come back ...\n",
|
||||
__progname, pezConfig->URL);
|
||||
#ifdef WIN32
|
||||
Sleep(5000);
|
||||
#else
|
||||
sleep(5);
|
||||
#endif
|
||||
};
|
||||
|
||||
printf("%s: Giving up.\n", __progname);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
sendStream(shout_t *shout, FILE *filepstream, const char *fileName,
|
||||
int isStdin, void *tv)
|
||||
{
|
||||
unsigned char buff[4096];
|
||||
size_t read, total, oldTotal;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
#ifdef HAVE_GETTIMEOFDAY
|
||||
double kbps = -1.0;
|
||||
struct timeval timeStamp, *startTime = (struct timeval *)tv;
|
||||
@ -587,7 +639,14 @@ sendStream(shout_t *shout, FILE *filepstream, const char *fileName,
|
||||
#endif /* HAVE_GETTIMEOFDAY */
|
||||
|
||||
total = oldTotal = 0;
|
||||
ret = STREAM_DONE;
|
||||
while ((read = fread(buff, 1, sizeof(buff), filepstream)) > 0) {
|
||||
if (shout_get_connected(shout) != SHOUTERR_CONNECTED &&
|
||||
reconnectServer(shout, 0) == 0) {
|
||||
ret = STREAM_SERVERR;
|
||||
break;
|
||||
}
|
||||
|
||||
if (rereadPlaylist_notify) {
|
||||
rereadPlaylist_notify = 0;
|
||||
if (!pezConfig->fileNameIsProgram)
|
||||
@ -596,7 +655,7 @@ sendStream(shout_t *shout, FILE *filepstream, const char *fileName,
|
||||
}
|
||||
if (skipTrack) {
|
||||
skipTrack = 0;
|
||||
ret = 2;
|
||||
ret = STREAM_SKIP;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -605,27 +664,11 @@ sendStream(shout_t *shout, FILE *filepstream, const char *fileName,
|
||||
if (shout_send(shout, buff, read) != SHOUTERR_SUCCESS) {
|
||||
printf("%s: shout_send(): %s\n", __progname,
|
||||
shout_get_error(shout));
|
||||
while (1) {
|
||||
printf("%s: Disconnected from server, reconnecting ...\n",
|
||||
__progname);
|
||||
shout_close(shout);
|
||||
if (shout_open(shout) == SHOUTERR_SUCCESS) {
|
||||
printf("%s: Reconnect to server successful.\n",
|
||||
__progname);
|
||||
if (shout_send(shout, buff, read) == SHOUTERR_SUCCESS)
|
||||
break;
|
||||
printf("%s: shout_send(): %s\n",
|
||||
__progname,
|
||||
shout_get_error(shout));
|
||||
} else {
|
||||
printf("%s: Reconnect failed. Waiting 5 seconds ...\n",
|
||||
__progname);
|
||||
#ifdef WIN32
|
||||
Sleep(5000);
|
||||
#else
|
||||
sleep(5);
|
||||
#endif
|
||||
}
|
||||
if (reconnectServer(shout, 1))
|
||||
break;
|
||||
else {
|
||||
ret = STREAM_SERVERR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -680,7 +723,7 @@ sendStream(shout_t *shout, FILE *filepstream, const char *fileName,
|
||||
if (ferror(filepstream)) {
|
||||
if (errno == EINTR) {
|
||||
clearerr(filepstream);
|
||||
ret = 1;
|
||||
ret = STREAM_CONT;
|
||||
} else
|
||||
printf("%s: streamFile(): Error while reading '%s': %s\n",
|
||||
__progname, fileName, strerror(errno));
|
||||
@ -725,18 +768,22 @@ streamFile(shout_t *shout, const char *fileName)
|
||||
do {
|
||||
ret = sendStream(shout, filepstream, fileName, isStdin, NULL);
|
||||
#endif
|
||||
if (ret != 0) {
|
||||
if (ret != STREAM_DONE) {
|
||||
if (skipTrack && rereadPlaylist) {
|
||||
skipTrack = 0;
|
||||
ret = 1;
|
||||
}
|
||||
if (ret == 2 || skipTrack) {
|
||||
if (ret == STREAM_SKIP || skipTrack) {
|
||||
skipTrack = 0;
|
||||
if (!isStdin && vFlag)
|
||||
printf("%s: SIGUSR1 signal received, skipping current track.\n",
|
||||
__progname);
|
||||
retval = 1;
|
||||
ret = 0;
|
||||
ret = STREAM_DONE;
|
||||
}
|
||||
if (ret == STREAM_SERVERR) {
|
||||
retval = 0;
|
||||
ret = STREAM_DONE;
|
||||
}
|
||||
} else
|
||||
retval = 1;
|
||||
|
Loading…
Reference in New Issue
Block a user