diff --git a/src/ctl/ctl.h b/src/ctl/ctl.h index d053127..09534ce 100644 --- a/src/ctl/ctl.h +++ b/src/ctl/ctl.h @@ -176,8 +176,10 @@ enum wfd_session_dir wfd_session_get_dir(struct wfd_session *s); uint64_t wfd_session_get_id(struct wfd_session *s); const char * wfd_session_get_stream_url(struct wfd_session *s); enum wfd_session_state wfd_session_get_state(struct wfd_session *s); -int wfd_session_is_started(struct wfd_session *s); -void wfd_session_end(struct wfd_session *s); +int wfd_session_is_established(struct wfd_session *s); +int wfd_session_resume(struct wfd_session *s); +int wfd_session_pause(struct wfd_session *s); +int wfd_session_teardown(struct wfd_session *s); void wfd_session_free(struct wfd_session *s); uint64_t wfd_session_get_id(struct wfd_session *s); struct wfd_sink * wfd_out_session_get_sink(struct wfd_session *s); diff --git a/src/ctl/wfd-dbus.c b/src/ctl/wfd-dbus.c index cfab4f0..07911f8 100644 --- a/src/ctl/wfd-dbus.c +++ b/src/ctl/wfd-dbus.c @@ -454,12 +454,55 @@ static int wfd_dbus_sink_get_peer(sd_bus *bus, //{ // return 0; //} - -static int wfd_dbus_session_end(sd_bus_message *m, +static int wfd_dbus_session_resume(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { - wfd_session_end(userdata); + struct wfd_session *s = userdata; + int r; + + if(wfd_session_is_established(s)) { + r = wfd_session_resume(s); + if(0 > r) { + return r; + } + } + else { + return -ENOTCONN; + } + + return sd_bus_reply_method_return(m, NULL); +} + +static int wfd_dbus_session_pause(sd_bus_message *m, + void *userdata, + sd_bus_error *ret_error) +{ + struct wfd_session *s = userdata; + int r; + + if(wfd_session_is_established(s)) { + r = wfd_session_pause(s); + if(0 > r) { + return r; + } + } + else { + return -ENOTCONN; + } + + return sd_bus_reply_method_return(m, NULL); +} + +static int wfd_dbus_session_teardown(sd_bus_message *m, + void *userdata, + sd_bus_error *ret_error) +{ + struct wfd_session *s = userdata; + int r = wfd_session_teardown(s); + if(0 > r) { + return r; + } return sd_bus_reply_method_return(m, NULL); } @@ -554,7 +597,9 @@ static const sd_bus_vtable wfd_dbus_sink_vtable[] = { static const sd_bus_vtable wfd_dbus_session_vtable[] = { SD_BUS_VTABLE_START(0), - SD_BUS_METHOD("End", NULL, NULL, wfd_dbus_session_end, 0), + SD_BUS_METHOD("Resume", NULL, NULL, wfd_dbus_session_resume, 0), + SD_BUS_METHOD("Pause", NULL, NULL, wfd_dbus_session_pause, 0), + SD_BUS_METHOD("Teardown", NULL, NULL, wfd_dbus_session_teardown, 0), SD_BUS_PROPERTY("Sink", "o", wfd_dbus_session_get_sink, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Url", "o", wfd_dbus_get_session_presentation_url, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("State", "i", wfd_dbus_get_session_state, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), diff --git a/src/ctl/wfd-out-session.c b/src/ctl/wfd-out-session.c index cb734b1..b30cce4 100644 --- a/src/ctl/wfd-out-session.c +++ b/src/ctl/wfd-out-session.c @@ -58,7 +58,7 @@ struct wfd_sink * wfd_out_session_get_sink(struct wfd_session *s) return wfd_out_session(s)->sink; } -static int wfd_out_session_handle_io(struct wfd_session *s, +int wfd_out_session_handle_io(struct wfd_session *s, int error, int *out_fd) { @@ -80,8 +80,6 @@ static int wfd_out_session_handle_io(struct wfd_session *s, log_info("RTSP connection established"); - //wfd_session_set_state(s, WFD_SESSION_STATE_CAPS_EXCHAING); - close(os->fd); os->fd = -1; *out_fd = fd; @@ -90,7 +88,7 @@ static int wfd_out_session_handle_io(struct wfd_session *s, return 0; } -static int wfd_out_session_initiate_io(struct wfd_session *s, +int wfd_out_session_initiate_io(struct wfd_session *s, int *out_fd, uint32_t *out_mask) { @@ -164,13 +162,40 @@ static int wfd_out_session_initiate_io(struct wfd_session *s, return 0; } -static void wfd_out_session_end(struct wfd_session *s) +static void wfd_out_session_kill_gst(struct wfd_session *s) +{ + if(-1 != s->stream.gst) { + kill(s->stream.gst, SIGTERM); + s->stream.gst = -1; + } +} + +int wfd_out_session_resume(struct wfd_session *s) +{ + return wfd_session_request(s, + RTSP_M5_TRIGGER, + &(struct wfd_arg_list) wfd_arg_list(wfd_arg_cstr("PLAY"))); +} + +int wfd_out_session_pause(struct wfd_session *s) +{ + return wfd_session_request(s, + RTSP_M5_TRIGGER, + &(struct wfd_arg_list) wfd_arg_list(wfd_arg_cstr("PAUSE"))); +} + +int wfd_out_session_teardown(struct wfd_session *s) +{ + return wfd_session_request(s, + RTSP_M5_TRIGGER, + &(struct wfd_arg_list) wfd_arg_list(wfd_arg_cstr("TEARDOWN"))); +} + +void wfd_out_session_end(struct wfd_session *s) { struct wfd_out_session *os = wfd_out_session(s); - if(-1 != s->stream.gst) { - kill(s->stream.gst, SIGTERM); - } + wfd_out_session_kill_gst(s); if(0 <= os->fd) { close(os->fd); @@ -178,15 +203,15 @@ static void wfd_out_session_end(struct wfd_session *s) } } -static void wfd_out_session_distruct(struct wfd_session *s) +void wfd_out_session_distruct(struct wfd_session *s) { } -static int wfd_out_session_initiate_request(struct wfd_session *s) +int wfd_out_session_initiate_request(struct wfd_session *s) { return wfd_session_request(s, RTSP_M1_REQUEST_SINK_OPTIONS, - &(struct wfd_arg_list) wfd_arg_list(wfd_arg_cstr("SETUP"))); + NULL); } static int wfd_out_session_handle_get_parameter_reply(struct wfd_session *s, @@ -448,15 +473,56 @@ static int wfd_out_session_handle_gst_term(sd_event_source *source, const siginfo_t *si, void *userdata) { - struct wfd_session *s = userdata; - log_trace("gst-launch(%d) terminated", si->si_pid); - if(WFD_SESSION_STATE_TEARING_DOWN != wfd_session_get_state(s)) { - s->stream.gst = -1; - wfd_session_end(s); + wfd_session_end(userdata); + + return 0; +} + +static int wfd_out_session_handle_pause_request(struct wfd_session *s, + struct rtsp_message *req, + struct rtsp_message **out_rep) +{ + _rtsp_message_unref_ struct rtsp_message *m = NULL; + int r; + + wfd_out_session_kill_gst(s); + + r = rtsp_message_new_reply_for(req, + &m, + RTSP_CODE_OK, + NULL); + if(0 > r) { + return r; } + *out_rep = m; + m = NULL; + + return 0; +} + +static int wfd_out_session_handle_teardown_request(struct wfd_session *s, + struct rtsp_message *req, + struct rtsp_message **out_rep) +{ + _rtsp_message_unref_ struct rtsp_message *m = NULL; + int r; + + wfd_out_session_kill_gst(s); + + r = rtsp_message_new_reply_for(req, + &m, + RTSP_CODE_OK, + NULL); + if(0 > r) { + return r; + } + + *out_rep = m; + m = NULL; + return 0; } @@ -513,8 +579,6 @@ static int wfd_out_session_handle_play_request(struct wfd_session *s, *out_rep = m; m = NULL; - /**new_state = WFD_SESSION_STATE_PLAYING;*/ - return 0; } @@ -680,16 +744,6 @@ static int wfd_out_session_request_set_parameter(struct wfd_session *s, return 0; } -const struct wfd_session_vtable session_vtables[] = { - [WFD_SESSION_DIR_OUT] = { - .initiate_io = wfd_out_session_initiate_io, - .handle_io = wfd_out_session_handle_io, - .initiate_request = wfd_out_session_initiate_request, - .end = wfd_out_session_end, - .distruct = wfd_out_session_distruct, - } -}; - static const struct rtsp_dispatch_entry out_session_rtsp_disp_tbl[] = { [RTSP_M1_REQUEST_SINK_OPTIONS] = { .request = wfd_out_session_request_options, @@ -739,10 +793,30 @@ static const struct rtsp_dispatch_entry out_session_rtsp_disp_tbl[] = { }, [RTSP_M7_PLAY] = { .handle_request = wfd_out_session_handle_play_request, + .rule = wfd_arg_list( + wfd_arg_dict( + wfd_arg_u(WFD_SESSION_ARG_NEW_STATE), + wfd_arg_u(WFD_SESSION_STATE_PLAYING) + ), + ) }, [RTSP_M8_TEARDOWN] = { + .handle_request = wfd_out_session_handle_teardown_request, + .rule = wfd_arg_list( + wfd_arg_dict( + wfd_arg_u(WFD_SESSION_ARG_NEW_STATE), + wfd_arg_u(WFD_SESSION_STATE_TEARING_DOWN) + ), + ) }, [RTSP_M9_PAUSE] = { + .handle_request = wfd_out_session_handle_pause_request, + .rule = wfd_arg_list( + wfd_arg_dict( + wfd_arg_u(WFD_SESSION_ARG_NEW_STATE), + wfd_arg_u(WFD_SESSION_STATE_PAUSED) + ), + ) }, [RTSP_M10_SET_ROUTE] = { .handle_request = wfd_out_session_request_not_implement @@ -764,10 +838,3 @@ static const struct rtsp_dispatch_entry out_session_rtsp_disp_tbl[] = { [RTSP_M16_KEEPALIVE] = { }, }; - -struct X -{ - int a; - int b; -}; - diff --git a/src/ctl/wfd-session.c b/src/ctl/wfd-session.c index 1af053d..1b18cba 100644 --- a/src/ctl/wfd-session.c +++ b/src/ctl/wfd-session.c @@ -34,9 +34,30 @@ ) static const char *rtsp_message_names[]; -extern const struct wfd_session_vtable session_vtables[]; extern const struct rtsp_dispatch_entry out_session_rtsp_disp_tbl[]; +extern int wfd_out_session_initiate_io(struct wfd_session *s, int *out_fd, uint32_t *out_mask); +extern int wfd_out_session_handle_io(struct wfd_session *s, int error, int *out_fd); +extern int wfd_out_session_initiate_request(struct wfd_session *); +extern int wfd_out_session_resume(struct wfd_session *); +extern int wfd_out_session_pause(struct wfd_session *); +extern int wfd_out_session_teardown(struct wfd_session *); +extern void wfd_out_session_end(struct wfd_session *); +extern void wfd_out_session_distruct(struct wfd_session *); + +const struct wfd_session_vtable session_vtbl[] = { + [WFD_SESSION_DIR_OUT] = { + .initiate_io = wfd_out_session_initiate_io, + .handle_io = wfd_out_session_handle_io, + .initiate_request = wfd_out_session_initiate_request, + .resume = wfd_out_session_resume, + .pause = wfd_out_session_pause, + .teardown = wfd_out_session_teardown, + .end = wfd_out_session_end, + .distruct = wfd_out_session_distruct, + } +}; + static inline int wfd_session_do_request(struct wfd_session *s, enum rtsp_message_id id, const struct wfd_arg_list *args, @@ -45,7 +66,11 @@ static inline int wfd_session_do_request(struct wfd_session *s, if(!rtsp_message_id_is_valid(id)) { return -EINVAL; } - assert(s->rtsp_disp_tbl[id].request); + + if(!s->rtsp_disp_tbl[id].request) { + log_warning("!!! request not implemented !!!"); + return -ENOTSUP; + } return (*s->rtsp_disp_tbl[id].request)(s, args, out); } @@ -58,7 +83,11 @@ static inline int wfd_session_do_handle_request(struct wfd_session *s, if(!rtsp_message_id_is_valid(id)) { return -EINVAL; } - assert(s->rtsp_disp_tbl[id].handle_request); + + if(!s->rtsp_disp_tbl[id].handle_request) { + log_warning("!!! request handler not implemented !!!"); + return -ENOTSUP; + } return (*s->rtsp_disp_tbl[id].handle_request)(s, req, @@ -102,11 +131,64 @@ static void wfd_session_set_state(struct wfd_session *s, wfd_fn_session_properties_changed(s, "State"); } -int wfd_session_is_started(struct wfd_session *s) +int wfd_session_is_established(struct wfd_session *s) { assert(wfd_is_session(s)); - return 0 != s->id; + return WFD_SESSION_STATE_ESTABLISHED <= s->state; +} + +int wfd_session_resume(struct wfd_session *s) +{ + assert(wfd_is_session(s)); + + if(WFD_SESSION_STATE_PLAYING == s->state) { + return 0; + } + else if(WFD_SESSION_STATE_PAUSED != s->state) { + return -EINVAL; + } + + if(!session_vtbl[s->dir].resume) { + return 0; + } + + return session_vtbl[s->dir].resume(s);; +} + +int wfd_session_pause(struct wfd_session *s) +{ + assert(wfd_is_session(s)); + + if(WFD_SESSION_STATE_PAUSED == s->state) { + return 0; + } + else if(WFD_SESSION_STATE_PLAYING != s->state) { + return -EINVAL; + } + + if(!session_vtbl[s->dir].pause) { + return 0; + } + + return session_vtbl[s->dir].pause(s);; +} + +int wfd_session_teardown(struct wfd_session *s) +{ + assert(wfd_is_session(s)); + + if(wfd_session_is_established(s)) { + if(!session_vtbl[s->dir].teardown) { + return 0; + } + + return session_vtbl[s->dir].teardown(s);; + } + + wfd_session_end(s); + + return 0; } void wfd_session_end(struct wfd_session *s) @@ -121,7 +203,7 @@ void wfd_session_end(struct wfd_session *s) wfd_session_set_state(s, WFD_SESSION_STATE_NULL); - (*session_vtables[s->dir].end)(s); + (*session_vtbl[s->dir].end)(s); if(s->rtsp) { rtsp_unref(s->rtsp); @@ -160,8 +242,8 @@ void wfd_session_free(struct wfd_session *s) wfd_session_end(s); - if(session_vtables[s->dir].distruct) { - (*session_vtables[s->dir].distruct)(s); + if(session_vtbl[s->dir].distruct) { + (*session_vtbl[s->dir].distruct)(s); } free(s); @@ -479,7 +561,7 @@ static int wfd_session_handle_io(sd_event_source *source, } if (mask & EPOLLIN || mask & EPOLLOUT) { - r = (*session_vtables[s->dir].handle_io)(s, err, &conn); + r = (*session_vtbl[s->dir].handle_io)(s, err, &conn); if(0 > r) { goto end; } @@ -506,7 +588,7 @@ static int wfd_session_handle_io(sd_event_source *source, wfd_session_set_state(s, WFD_SESSION_STATE_CAPS_EXCHANGING); - r = (*session_vtables[s->dir].initiate_request)(s); + r = (*session_vtbl[s->dir].initiate_request)(s); } if(mask & EPOLLHUP) { @@ -530,11 +612,11 @@ int wfd_session_start(struct wfd_session *s, uint64_t id) assert(wfd_is_session(s)); assert(id); - if(wfd_session_is_started(s)) { + if(WFD_SESSION_STATE_NULL != s->state) { return -EINPROGRESS; } - r = (*session_vtables[s->dir].initiate_io)(s, &fd, &mask); + r = (*session_vtbl[s->dir].initiate_io)(s, &fd, &mask); if(0 > r) { return r; } diff --git a/src/ctl/wfd-session.h b/src/ctl/wfd-session.h index c3e6ed4..dd2111a 100644 --- a/src/ctl/wfd-session.h +++ b/src/ctl/wfd-session.h @@ -86,6 +86,9 @@ struct wfd_session_vtable int (*initiate_io)(struct wfd_session *s, int *out_fd, uint32_t *out_mask); int (*handle_io)(struct wfd_session *s, int error, int *out_fd); int (*initiate_request)(struct wfd_session *s); + int (*resume)(struct wfd_session *); + int (*pause)(struct wfd_session *); + int (*teardown)(struct wfd_session *); void (*end)(struct wfd_session *s); void (*distruct)(struct wfd_session *s); }; @@ -118,6 +121,7 @@ int wfd_session_gen_stream_url(struct wfd_session *s, int wfd_session_request(struct wfd_session *s, enum rtsp_message_id id, const struct wfd_arg_list *args); +void wfd_session_end(struct wfd_session *s); struct wfd_sink * wfd_out_session_get_sink(struct wfd_session *s);