Codebase list squeezelite / fc4f1fb
0.9beta8 - add an additional mutex to protect decode state which could lead to crashes - fix problem skipping two tracks on windows - change mp3 dll names on windows to match common sources Adrian Smith 11 years ago
5 changed file(s) with 72 addition(s) and 40 deletion(s). Raw diff Collapse all Expand all
2828 extern struct streamstate stream;
2929 extern struct outputstate output;
3030
31 struct decodestate decode;
32 struct codec *codecs[MAX_CODECS];
33 static struct codec *codec;
34 static bool running = true;
35
3136 #define LOCK_S mutex_lock(streambuf->mutex)
3237 #define UNLOCK_S mutex_unlock(streambuf->mutex)
3338 #define LOCK_O mutex_lock(outputbuf->mutex)
3439 #define UNLOCK_O mutex_unlock(outputbuf->mutex)
35
36 struct decodestate decode;
37 struct codec *codecs[MAX_CODECS];
38 static struct codec *codec;
39 static bool running = true;
40 #define LOCK_D mutex_lock(decode.mutex);
41 #define UNLOCK_D mutex_unlock(decode.mutex);
4042
4143 static void *decode_thread() {
4244
4345 while (running) {
4446 size_t bytes, space;
4547 bool toend;
46 decode_state state;
48 bool ran = false;
4749
4850 LOCK_S;
4951 bytes = _buf_used(streambuf);
5153 UNLOCK_S;
5254 LOCK_O;
5355 space = _buf_space(outputbuf);
54 state = decode.state;
5556 UNLOCK_O;
5657
57 if (state == DECODE_RUNNING) {
58 LOCK_D;
59
60 if (decode.state == DECODE_RUNNING) {
5861
5962 LOG_SDEBUG("streambuf bytes: %u outputbuf space: %u", bytes, space);
6063
6164 if (space > codec->min_space && (bytes > codec->min_read_bytes || toend)) {
6265
63 state = codec->decode();
66 decode.state = codec->decode();
6467
65 if (state != DECODE_RUNNING) {
68 if (decode.state != DECODE_RUNNING) {
6669
67 LOG_INFO("decode %s", state == DECODE_COMPLETE ? "complete" : "error");
70 LOG_INFO("decode %s", decode.state == DECODE_COMPLETE ? "complete" : "error");
6871
6972 LOCK_O;
70 decode.state = state;
7173 if (output.fade_mode) _checkfade(false);
7274 UNLOCK_O;
7375
7476 wake_controller();
7577 }
7678
77 } else {
78 usleep(100000);
79 ran = true;
7980 }
81 }
82
83 UNLOCK_D;
8084
81 } else {
85 if (!ran) {
8286 usleep(100000);
8387 }
84
8588 }
8689
8790 return 0;
108111 if ( !opt || strstr(opt, "mp3") || strstr(opt, "mad")) codecs[i] = register_mad();
109112 if ((!opt || strstr(opt, "mp3") || strstr(opt, "mpg")) && !codecs[i]) codecs[i] = register_mpg();
110113
114 mutex_create(decode.mutex);
115
111116 #if LINUX || OSX
112117 pthread_attr_t attr;
113118 pthread_attr_init(&attr);
125130
126131 void decode_close(void) {
127132 LOG_INFO("close decode");
133 LOCK_D;
128134 if (codec) {
129135 codec->close();
136 codec = NULL;
130137 }
131 codec = NULL;
132138 running = false;
139 UNLOCK_D;
140 mutex_destroy(decode.mutex);
133141 }
134142
135143 void codec_open(u8_t format, u8_t sample_size, u8_t sample_rate, u8_t channels, u8_t endianness) {
137145
138146 LOG_INFO("codec open: '%c'", format);
139147
140 LOCK_O;
148 LOCK_D;
149
141150 decode.new_stream = true;
142151 decode.state = DECODE_STOPPED;
143 UNLOCK_O;
144152
145153 // find the required codec
146154 for (i = 0; i < MAX_CODECS; ++i) {
155163 codec = codecs[i];
156164
157165 codec->open(sample_size, sample_rate, channels, endianness);
158
166
167 UNLOCK_D;
159168 return;
160169 }
161170 }
162171
172 UNLOCK_D;
173
163174 LOG_ERROR("codec not found");
164175 }
13011301 output.latency = latency;
13021302 pa.stream = NULL;
13031303
1304 LOG_INFO("requested latency: %u", output.latency);
1305
13041306 if ((err = Pa_Initialize()) != paNoError) {
13051307 LOG_WARN("error initialising port audio: %s", Pa_GetErrorText(err));
13061308 return;
3434 #define LOCAL_PLAYER_PORT 0x0d9b // 3483
3535 #endif
3636
37 static sockfd sock;
37 static sockfd sock = -1;
3838 static in_addr_t slimproto_ip;
3939
4040 extern struct buffer *streambuf;
5252 #define UNLOCK_S mutex_unlock(streambuf->mutex)
5353 #define LOCK_O mutex_lock(outputbuf->mutex)
5454 #define UNLOCK_O mutex_unlock(outputbuf->mutex)
55 #define LOCK_D mutex_lock(decode.mutex)
56 #define UNLOCK_D mutex_unlock(decode.mutex)
5557
5658 static struct {
5759 u32_t updated;
9395 const char *base_cap = "Model=squeezelite,ModelName=SqueezeLite,AccuratePlayPoints=1,HasDigitalOut=1";
9496 struct HELO_packet pkt;
9597
98 memset(&pkt, 0, sizeof(pkt));
9699 memcpy(&pkt.opcode, "HELO", 4);
97100 pkt.length = htonl(sizeof(struct HELO_packet) - 8 + strlen(base_cap) + strlen(fixed_cap) + strlen(var_cap));
98101 pkt.deviceid = 12; // squeezeplay
255258 LOCK_O;
256259 output.state = jiffies ? OUTPUT_START_AT : OUTPUT_RUNNING;
257260 output.start_at = jiffies;
261 UNLOCK_O;
262 LOCK_D;
258263 decode.state = DECODE_RUNNING;
259 UNLOCK_O;
264 UNLOCK_D;
260265 LOG_INFO("unpause at: %u now: %u", jiffies, gettime_ms());
261266 sendSTAT("STMr", 0);
262267 }
525530 output.pa_reopen = false;
526531 }
527532 #endif
533 if (output.state == OUTPUT_RUNNING && !sentSTMu && status.output_full == 0 && status.stream_state <= DISCONNECT) {
534 _sendSTMu = true;
535 sentSTMu = true;
536 }
537 if (output.state == OUTPUT_RUNNING && !sentSTMo && status.output_full == 0 && status.stream_state == STREAMING_HTTP) {
538 _sendSTMo = true;
539 sentSTMo = true;
540 }
541 UNLOCK_O;
542
543 LOCK_D;
544 if (decode.state == DECODE_RUNNING && now - status.last > 1000) {
545 _sendSTMt = true;
546 status.last = now;
547 }
528548 if (decode.state == DECODE_COMPLETE) {
529549 _sendSTMd = true;
530550 decode.state = DECODE_STOPPED;
540560 sentSTMl = true;
541561 } else if (autostart == 1) {
542562 decode.state = DECODE_RUNNING;
563 LOCK_O;
543564 if (output.state == OUTPUT_STOPPED) {
544565 output.state = OUTPUT_BUFFER;
545566 }
567 UNLOCK_O;
546568 }
547569 // autostart 2 and 3 require cont to be received first
548570 }
549 if (output.state == OUTPUT_RUNNING && !sentSTMu && status.output_full == 0 && status.stream_state <= DISCONNECT) {
550 _sendSTMu = true;
551 sentSTMu = true;
552 }
553 if (output.state == OUTPUT_RUNNING && !sentSTMo && status.output_full == 0 && status.stream_state == STREAMING_HTTP) {
554 _sendSTMo = true;
555 sentSTMo = true;
556 }
557 if (decode.state == DECODE_RUNNING && now - status.last > 1000) {
558 _sendSTMt = true;
559 status.last = now;
560 }
561 UNLOCK_O;
571 UNLOCK_D;
562572
563573 // send packets once locks released as packet sending can block
564574 if (_sendDSCO) sendDSCO(disconnect);
1717 *
1818 */
1919
20 #define VERSION "v0.9beta7"
20 #define VERSION "v0.9beta8"
2121
2222 // build detection
2323 #if defined(linux)
8181
8282 #if WIN
8383 #define LIBFLAC "libFLAC.dll"
84 #define LIBMAD "libmad.dll"
85 #define LIBMPG "libmpg123.dll"
84 #define LIBMAD "libmad-0.dll"
85 #define LIBMPG "libmpg123-0.dll"
8686 #define LIBVORBIS "libvorbisfile.dll"
8787 #define LIBTREMOR "libvorbisidec.dll"
8888 #define LIBFAAD "libfaad2.dll"
338338 struct decodestate {
339339 decode_state state;
340340 bool new_stream;
341 mutex_type mutex;
341342 };
342343
343344 struct codec {
9898
9999 LOCK;
100100
101 // check socket has not been closed while in poll
102 if (fd < 0) {
103 UNLOCK;
104 continue;
105 }
106
101107 if ((pollinfo.revents & POLLOUT) && stream.state == SEND_HEADERS) {
102108 send_header();
103109 stream.header_len = 0;
375381
376382 void stream_disconnect(void) {
377383 LOCK;
378 closesocket(fd);
379 fd = -1;
384 if (fd != -1) {
385 closesocket(fd);
386 fd = -1;
387 }
380388 stream.state = STOPPED;
381389 UNLOCK;
382390 }