[Slim-Checkins] r12523 - in /trunk/softsqueeze/SlimProtoLib: ./ src/slimaudio/ src/slimproto/ src/squeezeslave/
robin at svn.slimdevices.com
robin at svn.slimdevices.com
Thu Aug 9 11:57:56 PDT 2007
Author: robin
Date: Thu Aug 9 11:57:56 2007
New Revision: 12523
URL: http://svn.slimdevices.com?rev=12523&view=rev
Log:
Apply patch submitted to forums by Dominique here:
http://forums.slimdevices.com/showthread.php?t=37460
His comments:
1. I have only tried this on Linux. I believe my touch-ups only use ANSI APIs (signal(), pause()), but I'm in no position to test on other configurations.
2. Because I'm changing files in .../slimproto and .../slimaudio, there will be consequences in the Java library (no API changes, though). I believe the consequence is that SoftSqueeze should work better, but I don't know how to test this.
3. This was my first time using subversion: hope my patch makes sense.
Actual patch file is here:
http://forums.slimdevices.com/attachment.php?attachmentid=3131&d=1186640145
My comments:
I have not tested this patch - just grabbed it from the forums and applied it!
Modified:
trunk/softsqueeze/SlimProtoLib/makefile.linux
trunk/softsqueeze/SlimProtoLib/src/slimaudio/slimaudio_decoder.c
trunk/softsqueeze/SlimProtoLib/src/slimaudio/slimaudio_decoder_flac.c
trunk/softsqueeze/SlimProtoLib/src/slimaudio/slimaudio_decoder_pcm.c
trunk/softsqueeze/SlimProtoLib/src/slimaudio/slimaudio_http.c
trunk/softsqueeze/SlimProtoLib/src/slimaudio/slimaudio_output.c
trunk/softsqueeze/SlimProtoLib/src/slimproto/slimproto.c
trunk/softsqueeze/SlimProtoLib/src/squeezeslave/squeezeslave.c
Modified: trunk/softsqueeze/SlimProtoLib/makefile.linux
URL: http://svn.slimdevices.com/trunk/softsqueeze/SlimProtoLib/makefile.linux?rev=12523&r1=12522&r2=12523&view=diff
==============================================================================
--- trunk/softsqueeze/SlimProtoLib/makefile.linux (original)
+++ trunk/softsqueeze/SlimProtoLib/makefile.linux Thu Aug 9 11:57:56 2007
@@ -29,7 +29,7 @@
ranlib lib/libslimproto.a
bin/squeezeslave : $(SQUEEZESLAVEFILES:.c=.o) $(PORTMIXERFILES:.c=.o) lib/libslimproto.a lib/libportaudio.a
- ${CC} -o bin/squeezeslave $^ /usr/local/lib/libmad.a /usr/local/lib/libFLAC.a /usr/lib/libvorbisfile.a /usr/lib/libvorbis.a /usr/lib/libogg.a -lpthread -lm
+ ${CC} -o bin/squeezeslave $^ /usr/lib/libmad.a /usr/lib/libFLAC.a /usr/lib/libvorbisfile.a /usr/lib/libvorbis.a /usr/lib/libogg.a -lpthread -lm
clean:
Modified: trunk/softsqueeze/SlimProtoLib/src/slimaudio/slimaudio_decoder.c
URL: http://svn.slimdevices.com/trunk/softsqueeze/SlimProtoLib/src/slimaudio/slimaudio_decoder.c?rev=12523&r1=12522&r2=12523&view=diff
==============================================================================
--- trunk/softsqueeze/SlimProtoLib/src/slimaudio/slimaudio_decoder.c (original)
+++ trunk/softsqueeze/SlimProtoLib/src/slimaudio/slimaudio_decoder.c Thu Aug 9 11:57:56 2007
@@ -62,8 +62,17 @@
if (slimaudio_decoder_pcm_init(audio) != 0)
return -1;
+ /*
+ * Acquire the decoder mutex before the thread is started, to make sure
+ * no other thread can acquire it before. This would lead to a deadlock
+ * as the decoder thread needs to enter its cond-variable wait before
+ * any other thread starts interacting with it.
+ */
+ pthread_mutex_lock(&audio->decoder_mutex);
+
if (pthread_create(&audio->decoder_thread, NULL, decoder_thread, (void*) audio) != 0) {
fprintf(stderr, "Error creating decoder thread\n");
+ pthread_mutex_unlock(&audio->decoder_mutex);
return -1;
}
@@ -93,12 +102,23 @@
audio->decoder_state = STREAM_STOPPED;
+ unsigned char first_time = 1;
+
while (true) {
DEBUGF("decoder_thread state %i\n", audio->decoder_state);
switch (audio->decoder_state) {
case STREAM_STOPPED:
- pthread_mutex_lock(&audio->decoder_mutex);
+ if (first_time == 1) {
+ /*
+ * The first time in, the mutex has already been
+ * acquired in the function that starts the thread.
+ */
+ first_time = 0;
+ }
+ else {
+ pthread_mutex_lock(&audio->decoder_mutex);
+ }
pthread_cond_wait(&audio->decoder_cond, &audio->decoder_mutex);
pthread_mutex_unlock(&audio->decoder_mutex);
break;
Modified: trunk/softsqueeze/SlimProtoLib/src/slimaudio/slimaudio_decoder_flac.c
URL: http://svn.slimdevices.com/trunk/softsqueeze/SlimProtoLib/src/slimaudio/slimaudio_decoder_flac.c?rev=12523&r1=12522&r2=12523&view=diff
==============================================================================
--- trunk/softsqueeze/SlimProtoLib/src/slimaudio/slimaudio_decoder_flac.c (original)
+++ trunk/softsqueeze/SlimProtoLib/src/slimaudio/slimaudio_decoder_flac.c Thu Aug 9 11:57:56 2007
@@ -119,7 +119,7 @@
}
int data_len = *bytes;
- slimaudio_buffer_status ok = slimaudio_buffer_read(audio->decoder_buffer, buffer, &data_len);
+ slimaudio_buffer_status ok = slimaudio_buffer_read(audio->decoder_buffer, (char*) buffer, &data_len);
if (ok == SLIMAUDIO_BUFFER_STREAM_END) {
audio->decoder_end_of_stream = true;
}
Modified: trunk/softsqueeze/SlimProtoLib/src/slimaudio/slimaudio_decoder_pcm.c
URL: http://svn.slimdevices.com/trunk/softsqueeze/SlimProtoLib/src/slimaudio/slimaudio_decoder_pcm.c?rev=12523&r1=12522&r2=12523&view=diff
==============================================================================
--- trunk/softsqueeze/SlimProtoLib/src/slimaudio/slimaudio_decoder_pcm.c (original)
+++ trunk/softsqueeze/SlimProtoLib/src/slimaudio/slimaudio_decoder_pcm.c Thu Aug 9 11:57:56 2007
@@ -61,7 +61,7 @@
}
data_len = AUDIO_CHUNK_SIZE-remainder;
- ok = slimaudio_buffer_read(audio->decoder_buffer, data+remainder, &data_len);
+ ok = slimaudio_buffer_read(audio->decoder_buffer, (char*)(data+remainder), &data_len);
int nsamples = data_len / 2;
/* convert buffer into samples */
@@ -101,7 +101,7 @@
}
#endif
- slimaudio_buffer_write(audio->output_buffer, data, nsamples * 2);
+ slimaudio_buffer_write(audio->output_buffer, (char*)data, nsamples * 2);
data_len -= nsamples * 2;
}
Modified: trunk/softsqueeze/SlimProtoLib/src/slimaudio/slimaudio_http.c
URL: http://svn.slimdevices.com/trunk/softsqueeze/SlimProtoLib/src/slimaudio/slimaudio_http.c?rev=12523&r1=12522&r2=12523&view=diff
==============================================================================
--- trunk/softsqueeze/SlimProtoLib/src/slimaudio/slimaudio_http.c (original)
+++ trunk/softsqueeze/SlimProtoLib/src/slimaudio/slimaudio_http.c Thu Aug 9 11:57:56 2007
@@ -65,9 +65,16 @@
int slimaudio_http_open(slimaudio_t *audio) {
pthread_mutex_init(&(audio->http_mutex), NULL);
pthread_cond_init(&(audio->http_cond), NULL);
+ /*
+ * We lock the mutex right here, knowing that http_thread will
+ * release it once it enters pthread_cond_wait inside its STOPPED
+ * state.
+ */
+ pthread_mutex_lock(&audio->http_mutex);
if (pthread_create( &audio->http_thread, NULL, http_thread, (void*) audio) != 0) {
fprintf(stderr, "Error creating http thread\n");
+ pthread_mutex_unlock(&audio->http_mutex);
return -1;
}
@@ -93,8 +100,6 @@
#ifdef SLIMPROTO_DEBUG
int last_state;
#endif
-
- pthread_mutex_lock(&audio->http_mutex);
audio->http_state = STREAM_STOPPED;
Modified: trunk/softsqueeze/SlimProtoLib/src/slimaudio/slimaudio_output.c
URL: http://svn.slimdevices.com/trunk/softsqueeze/SlimProtoLib/src/slimaudio/slimaudio_output.c?rev=12523&r1=12522&r2=12523&view=diff
==============================================================================
--- trunk/softsqueeze/SlimProtoLib/src/slimaudio/slimaudio_output.c (original)
+++ trunk/softsqueeze/SlimProtoLib/src/slimaudio/slimaudio_output.c Thu Aug 9 11:57:56 2007
@@ -172,7 +172,27 @@
switch (audio->output_state) {
case STOPPED:
case PAUSED:
- pthread_cond_wait(&audio->output_cond, &audio->output_mutex);
+ /*
+ * We report ourselves to the server every 5 seconds
+ * as a keep-alive. This is required for slimserver version
+ * 6.5.x although technically, "stat" is not a valid event
+ * code for the STAT Client->Server message. This was
+ * lifted by observing how a Squeezebox3 reports itself to
+ * the server using slimserver's d_slimproto and
+ * d_slimproto_v tracing services. Note that the value of 5
+ * seconds was made up: Squeezebox3 seems to report every 1
+ * second or so, but the server only drops the connection
+ * after 15-20 seconds of inactivity. So 5 seconds should
+ * work fine.
+ */
+ gettimeofday(&now, NULL);
+ timeout.tv_sec = now.tv_sec + 5;
+ timeout.tv_nsec = now.tv_usec * 1000;
+ err = pthread_cond_timedwait(&audio->output_cond, &audio->output_mutex, &timeout);
+
+ if (err == ETIMEDOUT) {
+ slimaudio_stat(audio, "stat");
+ }
break;
case PLAY:
Modified: trunk/softsqueeze/SlimProtoLib/src/slimproto/slimproto.c
URL: http://svn.slimdevices.com/trunk/softsqueeze/SlimProtoLib/src/slimproto/slimproto.c?rev=12523&r1=12522&r2=12523&view=diff
==============================================================================
--- trunk/softsqueeze/SlimProtoLib/src/slimproto/slimproto.c (original)
+++ trunk/softsqueeze/SlimProtoLib/src/slimproto/slimproto.c Thu Aug 9 11:57:56 2007
@@ -64,7 +64,7 @@
#define packN4(ptr, off, v) { ptr[off] = (char)(v >> 24) & 0xFF; ptr[off+1] = (v >> 16) & 0xFF; ptr[off+2] = (v >> 8) & 0xFF; ptr[off+3] = v & 0xFF; }
#define packN2(ptr, off, v) { ptr[off] = (char)(v >> 8) & 0xFF; ptr[off+1] = v & 0xFF; }
#define packC(ptr, off, v) { ptr[off] = v & 0xFF; }
-#define packA4(ptr, off, v) { strncpy(&ptr[off], v, 4); }
+#define packA4(ptr, off, v) { strncpy((char*)(&ptr[off]), v, 4); }
#define unpackN4(ptr, off) ((ptr[off] << 24) | (ptr[off+1] << 16) | (ptr[off+2] << 8) | ptr[off+3])
#define unpackN2(ptr, off) ((ptr[off] << 8) | ptr[off+1])
@@ -218,8 +218,22 @@
p->state = PROTO_CONNECT;
pthread_cond_broadcast(&p->slimproto_cond);
+ /*
+ * Wait for confirmation that thee connection opens correctly. This
+ * will fail, for example, if slimserver is not running when the
+ * connection attempt happens.
+ */
+ int return_value = 0;
+ while (p->state != PROTO_CONNECTED) {
+ pthread_cond_wait(&p->slimproto_cond, &p->slimproto_mutex);
+ if (p->state == PROTO_CLOSED) {
+ return_value = -1;
+ break;
+ }
+ }
+
pthread_mutex_unlock(&p->slimproto_mutex);
- return 0;
+ return return_value;
}
@@ -257,8 +271,10 @@
proto_connect_err:
p->state = PROTO_CLOSED;
+ DEBUGF("proto_connect: broadcast.\n" );
pthread_cond_broadcast(&p->slimproto_cond);
+ DEBUGF("proto_connect: unlock.\n" );
pthread_mutex_unlock(&p->slimproto_mutex);
return -1;
}
@@ -314,7 +330,7 @@
int i;
for (i=0; i<p->num_command_callbacks; i++) {
- if (strncmp(p->command_callbacks[i].cmd, buf+2, 4) == 0) {
+ if (strncmp(p->command_callbacks[i].cmd, (char*)(buf+2), 4) == 0) {
int ok = (p->command_callbacks[i].callback)(p, buf, len, p->command_callbacks[i].user_data);
if (ok < 0) {
fprintf(stderr, "Error in callback");
@@ -331,7 +347,7 @@
void slimproto_parse_command(const unsigned char *buf, int buf_len, slimproto_msg_t *msg) {
memset(msg, 0, sizeof(slimproto_msg_t));
- if (strncmp(buf+2, "strm", 4) == 0) {
+ if (strncmp((char*)(buf+2), "strm", 4) == 0) {
msg->strm.length = unpackN2(buf, 0);
memcpy(msg->strm.cmd, buf+2, 4);
msg->strm.command = unpackC(buf, 6);
@@ -358,7 +374,7 @@
}
*(msg->strm.http_hdr + http_len) = '\0';
}
- else if (strncmp(buf+2, "audg", 4) == 0) {
+ else if (strncmp((char*)(buf+2), "audg", 4) == 0) {
msg->audg.length = unpackN2(buf, 0);
memcpy(msg->audg.cmd, buf+2, 4);
msg->audg.old_left_gain = unpackN4(buf, 6);
Modified: trunk/softsqueeze/SlimProtoLib/src/squeezeslave/squeezeslave.c
URL: http://svn.slimdevices.com/trunk/softsqueeze/SlimProtoLib/src/squeezeslave/squeezeslave.c?rev=12523&r1=12522&r2=12523&view=diff
==============================================================================
--- trunk/softsqueeze/SlimProtoLib/src/squeezeslave/squeezeslave.c (original)
+++ trunk/softsqueeze/SlimProtoLib/src/squeezeslave/squeezeslave.c Thu Aug 9 11:57:56 2007
@@ -24,6 +24,7 @@
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
+#include <signal.h>
#include "slimproto/slimproto.h"
#include "slimaudio/slimaudio.h"
@@ -31,6 +32,10 @@
static int connect_callback(slimproto_t *p, bool isConnected, void *user_data);
static int parse_macaddress(char *macaddress, const char *str);
+void print_help(void);
+void signal_handler(int signal_number);
+
+volatile unsigned char signal_exit_flag = 0;
slimproto_t slimproto;
slimaudio_t slimaudio;
@@ -41,31 +46,32 @@
int main(int argc, char *argv[]) {
char *slimserver_address = "127.0.0.1";
int output_device_id = -1;
+ unsigned char use_signal_to_exit = 0;
char c;
int i;
while (1) {
static struct option long_options[] = {
- {"help", no_argument, 0, 'h'},
- {"debug", required_argument, 0, 'd'},
- {"mac", required_argument, 0, 'm'},
- {"output", required_argument, 0, 'o'},
- {0, 0, 0, 0}
- };
-
- /* getopt_long stores the option index here. */
- int option_index = 0;
+ {"help", no_argument, 0, 'h'},
+ {"debug", required_argument, 0, 'd'},
+ {"mac", required_argument, 0, 'm'},
+ {"output", required_argument, 0, 'o'},
+ {"signal", no_argument, 0, 's'},
+ {0, 0, 0, 0}
+ };
+
+ /* getopt_long stores the option index here. */
+ int option_index = 0;
- c = getopt_long (argc, argv, "hd:m:o:",
- long_options, &option_index);
-
+ c = getopt_long (argc, argv, "shd:m:o:",
+ long_options, &option_index);
if (c == -1)
break;
switch (c) {
case 'h':
- fprintf(stderr, "help ... todo\n");
+ print_help();
exit(0);
case 'd':
@@ -105,6 +111,9 @@
case 'o':
output_device_id = strtol(optarg, NULL, 0);
break;
+ case 's':
+ use_signal_to_exit = 1;
+ break;
}
}
@@ -129,7 +138,7 @@
printf("Output devices:\n");
for (i=0; i<num_devices; i++) {
printf("%i: %s\n", i, devices[i]);
- }
+ }
if (output_device_id >= 0) {
slimaudio_set_output_device(&slimaudio, output_device_id);
@@ -145,8 +154,15 @@
exit(-1);
}
- getc(stdin);
-
+ if (use_signal_to_exit) {
+ signal(SIGTERM, &signal_handler);
+ while (signal_exit_flag == 0) {
+ pause();
+ }
+ }
+ else {
+ getc(stdin);
+ }
#if 0
int ch = getc(stdin);
// This does not work on all platforms and I don't have time to sort it out right
@@ -196,6 +212,40 @@
return 0;
}
+void print_help() {
+ fprintf(stdout,
+"-h, --help: Prints this message.\n"
+"-m, --mac <mac_address>: Sets the mac address for this instance.\n"
+" Use the colon-separated notation.\n"
+" The default is 01:01:01:01:01.\n"
+" Slimserver uses this value to distinguish\n"
+" multiple instances, allowing per-player settings.\n"
+"-o, --output <device_id>: Sets the output device id.\n"
+" The default id is 0.\n"
+" The output device ids are enumerated at startup.\n"
+"-s, --signal: Causes the program to wait for SIGTERM to exit.\n"
+" The default is to wait for a keyboard entry, which\n"
+" prevents the program from running in background.\n"
+"-d, --debug <trace_name>: Turns on debug tracing for the specified level.\n"
+" The option can be used multiple times to enable\n"
+" multiple levels.\n"
+" Available levels:\n"
+" slimproto\n"
+" slimaudio\n"
+" slimaudio_buffer\n"
+" slimaudio_buffer_v\n"
+" slimaudio_decoder\n"
+" slimaudio_decoder_v\n"
+" slimaudio_http\n"
+" slimaudio_http_v\n"
+" slimaudio_output\n");
+}
+
+void signal_handler(int signal_number) {
+ fprintf(stderr,"Got signal.\n");
+ signal_exit_flag = 1;
+}
+
static int connect_callback(slimproto_t *p, bool isConnected, void *user_data) {
if (isConnected) {
if (slimproto_helo(&slimproto, 3, 2, (char *)&macaddress, 1, 0) < 0) {
More information about the checkins
mailing list