From 00d4148a9079395ddef3c4320a8dbedbb1ca357b Mon Sep 17 00:00:00 2001 From: ejurgensen Date: Fri, 12 Feb 2016 21:59:26 +0100 Subject: [PATCH] [raop] Move RAOP specific states away from the generic output state enum --- src/outputs.h | 31 +++------- src/outputs/raop.c | 148 ++++++++++++++++++++++++++++++--------------- 2 files changed, 105 insertions(+), 74 deletions(-) diff --git a/src/outputs.h b/src/outputs.h index bbe0179a..63df7158 100644 --- a/src/outputs.h +++ b/src/outputs.h @@ -32,35 +32,18 @@ enum output_types }; /* Output session state */ - -// Session is starting up -#define OUTPUT_STATE_F_STARTUP (1 << 14) -// Streaming is up (connection established) -#define OUTPUT_STATE_F_CONNECTED (1 << 15) enum output_device_state { + // Device is stopped (no session) OUTPUT_STATE_STOPPED = 0, - - // Session startup - // TODO Make this less RAOP-specific - OUTPUT_STATE_OPTIONS = OUTPUT_STATE_F_STARTUP | 0x01, - OUTPUT_STATE_ANNOUNCE = OUTPUT_STATE_F_STARTUP | 0x02, - OUTPUT_STATE_SETUP = OUTPUT_STATE_F_STARTUP | 0x03, - OUTPUT_STATE_RECORD = OUTPUT_STATE_F_STARTUP | 0x04, - - OUTPUT_STATE_STARTUP = OUTPUT_STATE_F_STARTUP, - - // Session established - // - streaming ready (RECORD sent and acked, connection established) - // - commands (SET_PARAMETER) are possible - OUTPUT_STATE_CONNECTED = OUTPUT_STATE_F_CONNECTED, - - // Audio data is being sent - OUTPUT_STATE_STREAMING = OUTPUT_STATE_F_CONNECTED | 0x01, - + // Device is starting up + OUTPUT_STATE_STARTUP = 1, + // Session established (streaming ready and commands are possible) + OUTPUT_STATE_CONNECTED = 2, + // Media data is being sent + OUTPUT_STATE_STREAMING = 3, // Session is failed, couldn't startup or error occurred OUTPUT_STATE_FAILED = -1, - // Password issue: unknown password or bad password OUTPUT_STATE_PASSWORD = -2, }; diff --git a/src/outputs/raop.c b/src/outputs/raop.c index 04d07993..91dd9956 100644 --- a/src/outputs/raop.c +++ b/src/outputs/raop.c @@ -117,6 +117,32 @@ enum raop_devtype { RAOP_DEV_OTHER, }; +// Session is starting up +#define RAOP_STATE_F_STARTUP (1 << 14) +// Streaming is up (connection established) +#define RAOP_STATE_F_CONNECTED (1 << 15) + +enum raop_state { + // Device is stopped (no session) + RAOP_STATE_STOPPED = 0, + // Session startup + RAOP_STATE_STARTUP = RAOP_STATE_F_STARTUP, + RAOP_STATE_OPTIONS = RAOP_STATE_F_STARTUP | 0x01, + RAOP_STATE_ANNOUNCE = RAOP_STATE_F_STARTUP | 0x02, + RAOP_STATE_SETUP = RAOP_STATE_F_STARTUP | 0x03, + RAOP_STATE_RECORD = RAOP_STATE_F_STARTUP | 0x04, + // Session established + // - streaming ready (RECORD sent and acked, connection established) + // - commands (SET_PARAMETER) are possible + RAOP_STATE_CONNECTED = RAOP_STATE_F_CONNECTED, + // Media data is being sent + RAOP_STATE_STREAMING = RAOP_STATE_F_CONNECTED | 0x01, + // Session is failed, couldn't startup or error occurred + RAOP_STATE_FAILED = -1, + // Password issue: unknown password or bad password + RAOP_STATE_PASSWORD = -2, +}; + // Info about the device, which is not required by the player, only internally struct raop_extra { @@ -130,7 +156,7 @@ struct raop_session { struct evrtsp_connection *ctrl; - enum output_device_state state; + enum raop_state state; unsigned req_has_auth:1; unsigned encrypt:1; unsigned auth_quirk_itunes:1; @@ -1172,7 +1198,7 @@ raop_add_headers(struct raop_session *rs, struct evrtsp_request *req, enum evrts DPRINTF(E_LOG, L_RAOP, "Could not add Authorization header\n"); if (ret == -2) - rs->state = OUTPUT_STATE_PASSWORD; + rs->state = RAOP_STATE_PASSWORD; return -1; } @@ -1665,6 +1691,45 @@ raop_send_req_options(struct raop_session *rs, evrtsp_req_cb cb) return 0; } +/* Maps our internal state to the generic output state and then makes a callback + * to the player to tell that state + */ +static void +raop_status(struct raop_session *rs) +{ + output_status_cb status_cb = rs->status_cb; + enum output_device_state state; + + switch (rs->state) + { + case RAOP_STATE_PASSWORD: + state = OUTPUT_STATE_PASSWORD; + break; + case RAOP_STATE_FAILED: + state = OUTPUT_STATE_FAILED; + break; + case RAOP_STATE_STOPPED: + state = OUTPUT_STATE_STOPPED; + break; + case RAOP_STATE_STARTUP ... RAOP_STATE_RECORD: + state = OUTPUT_STATE_STARTUP; + break; + case RAOP_STATE_CONNECTED: + state = OUTPUT_STATE_CONNECTED; + break; + case RAOP_STATE_STREAMING: + state = OUTPUT_STATE_STREAMING; + break; + default: + DPRINTF(E_LOG, L_RAOP, "Bug! Unhandled state in cast_status()\n"); + state = OUTPUT_STATE_FAILED; + } + + rs->status_cb = NULL; + if (status_cb) + status_cb(rs->device, rs->output_session, state); +} + static void raop_session_free(struct raop_session *rs) { @@ -1739,9 +1804,10 @@ static void raop_session_failure(struct raop_session *rs) { /* Session failed, let our user know */ - if (rs->state != OUTPUT_STATE_PASSWORD) - rs->state = OUTPUT_STATE_FAILED; - rs->status_cb(rs->device, rs->output_session, rs->state); + if (rs->state != RAOP_STATE_PASSWORD) + rs->state = RAOP_STATE_FAILED; + + raop_status(rs); raop_session_cleanup(rs); } @@ -1768,7 +1834,7 @@ raop_rtsp_close_cb(struct evrtsp_connection *evcon, void *arg) DPRINTF(E_LOG, L_RAOP, "ApEx %s closed RTSP connection\n", rs->devname); - rs->state = OUTPUT_STATE_FAILED; + rs->state = RAOP_STATE_FAILED; evutil_timerclear(&tv); evtimer_add(rs->deferredev, &tv); @@ -1822,7 +1888,7 @@ raop_session_make(struct output_device *rd, int family, output_status_cb cb) os->type = rd->type; rs->output_session = os; - rs->state = OUTPUT_STATE_STOPPED; + rs->state = RAOP_STATE_STOPPED; rs->reqs_in_flight = 0; rs->cseq = 1; @@ -2230,7 +2296,7 @@ raop_metadata_send(void *metadata, uint64_t rtptime, uint64_t offset, int startu { next = rs->next; - if (!(rs->state & OUTPUT_STATE_F_CONNECTED)) + if (!(rs->state & RAOP_STATE_F_CONNECTED)) continue; if (!rs->wants_metadata) @@ -2322,7 +2388,6 @@ raop_set_volume_internal(struct raop_session *rs, int volume, evrtsp_req_cb cb) static void raop_cb_set_volume(struct evrtsp_request *req, void *arg) { - output_status_cb status_cb; struct raop_session *rs; int ret; @@ -2345,9 +2410,7 @@ raop_cb_set_volume(struct evrtsp_request *req, void *arg) goto error; /* Let our user know */ - status_cb = rs->status_cb; - rs->status_cb = NULL; - status_cb(rs->device, rs->output_session, rs->state); + raop_status(rs); if (!rs->reqs_in_flight) evrtsp_connection_set_closecb(rs->ctrl, raop_rtsp_close_cb, rs); @@ -2370,7 +2433,7 @@ raop_set_volume_one(struct output_device *rd, output_status_cb cb) rs = rd->session->session; - if (!(rs->state & OUTPUT_STATE_F_CONNECTED)) + if (!(rs->state & RAOP_STATE_F_CONNECTED)) return 0; ret = raop_set_volume_internal(rs, rd->volume, raop_cb_set_volume); @@ -2389,7 +2452,6 @@ raop_set_volume_one(struct output_device *rd, output_status_cb cb) static void raop_cb_flush(struct evrtsp_request *req, void *arg) { - output_status_cb status_cb; struct raop_session *rs; int ret; @@ -2411,12 +2473,10 @@ raop_cb_flush(struct evrtsp_request *req, void *arg) if (ret < 0) goto error; - rs->state = OUTPUT_STATE_CONNECTED; + rs->state = RAOP_STATE_CONNECTED; /* Let our user know */ - status_cb = rs->status_cb; - rs->status_cb = NULL; - status_cb(rs->device, rs->output_session, rs->state); + raop_status(rs); if (!rs->reqs_in_flight) evrtsp_connection_set_closecb(rs->ctrl, raop_rtsp_close_cb, rs); @@ -2440,7 +2500,7 @@ raop_flush_timer_cb(int fd, short what, void *arg) for (rs = sessions; rs; rs = rs->next) { - if (!(rs->state & OUTPUT_STATE_F_CONNECTED)) + if (!(rs->state & RAOP_STATE_F_CONNECTED)) continue; raop_device_stop(rs->output_session); @@ -2461,7 +2521,7 @@ raop_flush(output_status_cb cb, uint64_t rtptime) { next = rs->next; - if (rs->state != OUTPUT_STATE_STREAMING) + if (rs->state != RAOP_STATE_STREAMING) continue; ret = raop_send_req_flush(rs, rtptime, raop_cb_flush); @@ -2833,7 +2893,7 @@ raop_v2_control_send_sync(uint64_t next_pkt, struct timespec *init) for (rs = sessions; rs; rs = rs->next) { - if (rs->state != OUTPUT_STATE_STREAMING) + if (rs->state != RAOP_STATE_STREAMING) continue; switch (rs->sa.ss.ss_family) @@ -3300,7 +3360,7 @@ raop_v2_write(uint8_t *buf, uint64_t rtptime) // raop_v2_send_packet may free rs on failure, so save rs->next now next = rs->next; - if (rs->state != OUTPUT_STATE_STREAMING) + if (rs->state != RAOP_STATE_STREAMING) continue; raop_v2_send_packet(rs, pkt); @@ -3417,9 +3477,9 @@ raop_v2_stream_open(struct raop_session *rs) * playback is in progress. */ if (sync_counter != 0) - rs->state = OUTPUT_STATE_STREAMING; + rs->state = RAOP_STATE_STREAMING; else - rs->state = OUTPUT_STATE_CONNECTED; + rs->state = RAOP_STATE_CONNECTED; return 0; @@ -3445,7 +3505,6 @@ raop_startup_cancel(struct raop_session *rs) static void raop_cb_startup_volume(struct evrtsp_request *req, void *arg) { - output_status_cb status_cb; struct raop_session *rs; int ret; @@ -3478,10 +3537,7 @@ raop_cb_startup_volume(struct evrtsp_request *req, void *arg) } /* Session startup and setup is done, tell our user */ - status_cb = rs->status_cb; - rs->status_cb = NULL; - - status_cb(rs->device, rs->output_session, rs->state); + raop_status(rs); if (!rs->reqs_in_flight) evrtsp_connection_set_closecb(rs->ctrl, raop_rtsp_close_cb, rs); @@ -3524,7 +3580,7 @@ raop_cb_startup_record(struct evrtsp_request *req, void *arg) else DPRINTF(E_DBG, L_RAOP, "RAOP audio latency is %s\n", param); - rs->state = OUTPUT_STATE_RECORD; + rs->state = RAOP_STATE_RECORD; /* Set initial volume */ raop_set_volume_internal(rs, rs->volume, raop_cb_startup_volume); @@ -3672,7 +3728,7 @@ raop_cb_startup_setup(struct evrtsp_request *req, void *arg) DPRINTF(E_DBG, L_RAOP, "Negotiated AirTunes v2 UDP streaming session %s; ports s=%u c=%u t=%u\n", rs->session, rs->server_port, rs->control_port, rs->timing_port); - rs->state = OUTPUT_STATE_SETUP; + rs->state = RAOP_STATE_SETUP; /* Send RECORD */ ret = raop_send_req_record(rs, raop_cb_startup_record); @@ -3709,7 +3765,7 @@ raop_cb_startup_announce(struct evrtsp_request *req, void *arg) if (ret < 0) goto cleanup; - rs->state = OUTPUT_STATE_ANNOUNCE; + rs->state = RAOP_STATE_ANNOUNCE; /* Send SETUP */ ret = raop_send_req_setup(rs, raop_cb_startup_setup); @@ -3752,7 +3808,7 @@ raop_cb_startup_options(struct evrtsp_request *req, void *arg) { DPRINTF(E_LOG, L_RAOP, "Bad password for device %s\n", rs->devname); - rs->state = OUTPUT_STATE_PASSWORD; + rs->state = RAOP_STATE_PASSWORD; goto cleanup; } @@ -3771,7 +3827,7 @@ raop_cb_startup_options(struct evrtsp_request *req, void *arg) return; } - rs->state = OUTPUT_STATE_OPTIONS; + rs->state = RAOP_STATE_OPTIONS; /* Send ANNOUNCE */ ret = raop_send_req_announce(rs, raop_cb_startup_announce); @@ -3788,7 +3844,6 @@ raop_cb_startup_options(struct evrtsp_request *req, void *arg) static void raop_cb_shutdown_teardown(struct evrtsp_request *req, void *arg) { - output_status_cb status_cb; struct raop_session *rs; int ret; @@ -3810,13 +3865,10 @@ raop_cb_shutdown_teardown(struct evrtsp_request *req, void *arg) if (ret < 0) goto error; - rs->state = OUTPUT_STATE_STOPPED; + rs->state = RAOP_STATE_STOPPED; /* Session shut down, tell our user */ - status_cb = rs->status_cb; - rs->status_cb = NULL; - - status_cb(rs->device, rs->output_session, rs->state); + raop_status(rs); raop_session_cleanup(rs); @@ -3829,7 +3881,6 @@ raop_cb_shutdown_teardown(struct evrtsp_request *req, void *arg) static void raop_cb_probe_options(struct evrtsp_request *req, void *arg) { - output_status_cb status_cb; struct raop_session *rs; int ret; @@ -3857,7 +3908,7 @@ raop_cb_probe_options(struct evrtsp_request *req, void *arg) { DPRINTF(E_LOG, L_RAOP, "Bad password for device %s\n", rs->devname); - rs->state = OUTPUT_STATE_PASSWORD; + rs->state = RAOP_STATE_PASSWORD; goto cleanup; } @@ -3876,13 +3927,10 @@ raop_cb_probe_options(struct evrtsp_request *req, void *arg) return; } - rs->state = OUTPUT_STATE_OPTIONS; + rs->state = RAOP_STATE_OPTIONS; /* Device probed successfully, tell our user */ - status_cb = rs->status_cb; - rs->status_cb = NULL; - - status_cb(rs->device, rs->output_session, rs->state); + raop_status(rs); /* We're not going further with this session */ raop_session_cleanup(rs); @@ -4189,7 +4237,7 @@ raop_device_stop(struct output_session *session) { struct raop_session *rs = session->session; - if (!(rs->state & OUTPUT_STATE_F_CONNECTED)) + if (!(rs->state & RAOP_STATE_F_CONNECTED)) raop_session_cleanup(rs); else raop_send_req_teardown(rs, raop_cb_shutdown_teardown); @@ -4213,8 +4261,8 @@ raop_playback_start(uint64_t next_pkt, struct timespec *ts) for (rs = sessions; rs; rs = rs->next) { - if (rs->state == OUTPUT_STATE_CONNECTED) - rs->state = OUTPUT_STATE_STREAMING; + if (rs->state == RAOP_STATE_CONNECTED) + rs->state = RAOP_STATE_STREAMING; } /* Send initial playback sync */