int main(void) { printf("01\t--------------------------------------------\n"); printf("02\t1 successor, 2 non threaded consumers\n"); printf("03\tConsumer 2 disconnects, consumer 1 continues\n"); printf("04\tgetting token, consumer 2 reconnects\n"); printf("03\t--------------------------------------------\n"); int con_delay = 0; int suc_delay = 0; pthread_t s1; stream_t suc1; stream_t cons1; stream_t cons2; init_stream(&suc1, &suc_delay); init_stream(&cons1, NULL); init_stream(&cons2, NULL); stream_connect(&cons1, &suc1); stream_connect(&cons2, &suc1); pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); pthread_create(&s1, &attr, suc, (void*)&suc1); printf("Both consumers connected\n"); sleep(con_delay); printf("Consumer 1 got: %d\n", *(int*)consume_single((void*)&cons1)); //print_buffers(&cons1); sleep(con_delay); printf("Consumer 1 got: %d\n", *(int*)consume_single((void*)&cons1)); //print_buffers(&cons1); sleep(con_delay); printf("Consumer 1 got: %d\n", *(int*)consume_single((void*)&cons1)); //print_buffers(&cons1); sleep(con_delay); printf("Consumer 2 got: %d\n", *(int*)consume_single((void*)&cons2)); //print_buffers(&cons2); sleep(con_delay); printf("Consumer 2 got: %d\n", *(int*)consume_single((void*)&cons2)); //print_buffers(&cons2); sleep(con_delay); printf("Consumer 2 got: %d\n", *(int*)consume_single((void*)&cons2)); //print_buffers(&cons2); printf("Disconnecting consumer 2\n"); sleep(con_delay); stream_disconnect(&cons2, &suc1); sleep(con_delay); printf(" Consumer 1 got: %d\n", *(int*)consume_single((void*)&cons1)); //print_buffers(&cons1); sleep(con_delay); printf(" Consumer 1 got: %d\n", *(int*)consume_single((void*)&cons1)); //print_buffers(&cons1); sleep(con_delay); printf(" Consumer 1 got: %d\n", *(int*)consume_single((void*)&cons1)); //print_buffers(&cons1); sleep(con_delay); printf(" Consumer 1 got: %d\n", *(int*)consume_single((void*)&cons1)); //print_buffers(&cons1); sleep(con_delay); printf(" Consumer 1 got: %d\n", *(int*)consume_single((void*)&cons1)); //print_buffers(&cons1); sleep(con_delay); printf(" Consumer 1 got: %d\n", *(int*)consume_single((void*)&cons1)); //print_buffers(&cons1); sleep(con_delay); printf(" Consumer 1 got: %d\n", *(int*)consume_single((void*)&cons1)); //print_buffers(&cons1); sleep(con_delay); printf(" Consumer 1 got: %d\n", *(int*)consume_single((void*)&cons1)); //print_buffers(&cons1); printf("Reconnecting consumer 2\n"); sleep(con_delay); stream_connect(&cons2, &suc1); sleep(con_delay); printf("Consumer 2 got: %d\n", *(int*)consume_single((void*)&cons2)); //print_buffers(&cons2); sleep(con_delay); printf("Consumer 2 got: %d\n", *(int*)consume_single((void*)&cons2)); //print_buffers(&cons2); sleep(con_delay); printf("Consumer 2 got: %d\n", *(int*)consume_single((void*)&cons2)); //print_buffers(&cons2); sleep(con_delay); printf("Consumer 1 got: %d\n", *(int*)consume_single((void*)&cons1)); //print_buffers(&cons1); sleep(con_delay); printf("Consumer 1 got: %d\n", *(int*)consume_single((void*)&cons1)); //print_buffers(&cons1); sleep(con_delay); printf("Consumer 1 got: %d\n", *(int*)consume_single((void*)&cons1)); //print_buffers(&cons1); sleep(con_delay); printf("Consumer 1 got: %d\n", *(int*)consume_single((void*)&cons1)); //print_buffers(&cons1); sleep(con_delay); printf("Consumer 1 got: %d\n", *(int*)consume_single((void*)&cons1)); //print_buffers(&cons1); printf("Disconnecting consumer 1\n"); sleep(con_delay); stream_disconnect(&cons1, &suc1); sleep(con_delay); printf("Consumer 2 got: %d\n", *(int*)consume_single((void*)&cons2)); //print_buffers(&cons2); sleep(con_delay); printf("Consumer 2 got: %d\n", *(int*)consume_single((void*)&cons2)); //print_buffers(&cons2); sleep(con_delay); printf("Consumer 2 got: %d\n", *(int*)consume_single((void*)&cons2)); //print_buffers(&cons2); printf("Reconnecting consumer 1\n"); sleep(con_delay); stream_connect(&cons1, &suc1); sleep(con_delay); printf("Consumer 1 got: %d\n", *(int*)consume_single((void*)&cons1)); //print_buffers(&cons1); sleep(con_delay); printf("Consumer 1 got: %d\n", *(int*)consume_single((void*)&cons1)); //print_buffers(&cons1); sleep(con_delay); printf("Consumer 1 got: %d\n", *(int*)consume_single((void*)&cons1)); //print_buffers(&cons1); sleep(con_delay); printf("done\n"); pthread_cancel(s1); kill_stream(&suc1); return 0; }
static void process_strm(u8_t *pkt, int len) { struct strm_packet *strm = (struct strm_packet *)pkt; LOG_INFO("strm command %c", strm->command); switch(strm->command) { case 't': sendSTAT("STMt", strm->replay_gain); // STMt replay_gain is no longer used to track latency, but support it break; case 'q': output_flush(); status.frames_played = 0; stream_disconnect(); sendSTAT("STMf", 0); buf_flush(streambuf); break; case 'f': output_flush(); status.frames_played = 0; if (stream_disconnect()) { sendSTAT("STMf", 0); } buf_flush(streambuf); break; case 'p': { unsigned interval = unpackN(&strm->replay_gain); LOCK_O; output.pause_frames = interval * status.current_sample_rate / 1000; output.state = interval ? OUTPUT_PAUSE_FRAMES : OUTPUT_STOPPED; UNLOCK_O; if (!interval) sendSTAT("STMp", 0); LOG_INFO("pause interval: %u", interval); } break; case 'a': { unsigned interval = unpackN(&strm->replay_gain); LOCK_O; output.skip_frames = interval * status.current_sample_rate / 1000; output.state = OUTPUT_SKIP_FRAMES; UNLOCK_O; LOG_INFO("skip ahead interval: %u", interval); } break; case 'u': { unsigned jiffies = unpackN(&strm->replay_gain); LOCK_O; output.state = jiffies ? OUTPUT_START_AT : OUTPUT_RUNNING; output.start_at = jiffies; UNLOCK_O; LOCK_D; decode.state = DECODE_RUNNING; UNLOCK_D; LOG_INFO("unpause at: %u now: %u", jiffies, gettime_ms()); sendSTAT("STMr", 0); } break; case 's': { unsigned header_len = len - sizeof(struct strm_packet); char *header = (char *)(pkt + sizeof(struct strm_packet)); in_addr_t ip = (in_addr_t)strm->server_ip; // keep in network byte order u16_t port = strm->server_port; // keep in network byte order if (ip == 0) ip = slimproto_ip; LOG_INFO("strm s autostart: %c transition period: %u transition type: %u", strm->autostart, strm->transition_period, strm->transition_type - '0'); autostart = strm->autostart - '0'; sendSTAT("STMf", 0); if (header_len > MAX_HEADER -1) { LOG_WARN("header too long: %u", header_len); break; } codec_open(strm->format, strm->pcm_sample_size, strm->pcm_sample_rate, strm->pcm_channels, strm->pcm_endianness); if (ip == LOCAL_PLAYER_IP && port == LOCAL_PLAYER_PORT) { // extension to slimproto for LocalPlayer - header is filename not http header, don't expect cont stream_file(header, header_len, strm->threshold * 1024); autostart -= 2; } else { stream_sock(ip, port, header, header_len, strm->threshold * 1024, autostart >= 2); } sendSTAT("STMc", 0); sentSTMu = sentSTMo = sentSTMl = false; LOCK_O; output.threshold = strm->output_threshold; output.next_replay_gain = unpackN(&strm->replay_gain); output.fade_mode = strm->transition_type - '0'; output.fade_secs = strm->transition_period; LOG_INFO("set fade mode: %u", output.fade_mode); UNLOCK_O; } break; default: LOG_INFO("unhandled strm %c", strm->command); break; } }