diff --git a/res/miracle-wfdctl-demo b/res/miracle-wfdctl-demo index 9c533c0..b0435d2 100755 --- a/res/miracle-wfdctl-demo +++ b/res/miracle-wfdctl-demo @@ -204,6 +204,13 @@ invoke org.freedesktop.miracle.wfd \ /org/freedesktop/miracle/wfd/sink/$peer_id \ org.freedesktop.miracle.wfd.Sink \ Peer /org/freedesktop/miracle/wifi/peer/$peer_id \ - StartSession sqqqq 'x://:0.0' 0 0 1920 1080 + StartSession ssqqqqs \ + "$XAUTHORITY" \ + 'x://:0.0' \ + 0 \ + 0 \ + 1920 \ + 1080 \ + 'alsa_output.pci-0000_00_1b.0.analog-stereo.monitor' wait diff --git a/src/ctl/ctl.h b/src/ctl/ctl.h index b19574a..1e38df6 100644 --- a/src/ctl/ctl.h +++ b/src/ctl/ctl.h @@ -172,11 +172,13 @@ enum wfd_session_state int wfd_out_session_new(struct wfd_session **out, struct wfd_sink *sink, + const char *authority, const char *display, uint16_t x, uint16_t y, uint16_t width, - uint16_t height); + uint16_t height, + const char *audio_dev); int wfd_session_start(struct wfd_session *s, uint64_t id); enum wfd_session_dir wfd_session_get_dir(struct wfd_session *s); uint64_t wfd_session_get_id(struct wfd_session *s); @@ -218,11 +220,13 @@ const char * wfd_sink_get_label(struct wfd_sink *sink); const union wfd_sube * wfd_sink_get_dev_info(struct wfd_sink *sink); int wfd_sink_start_session(struct wfd_sink *sink, struct wfd_session **out, + const char *authority, const char *display, uint16_t x, uint16_t y, uint16_t width, - uint16_t height); + uint16_t height, + const char *audio_dev); void wfd_sink_handle_session_ended(struct wfd_sink *sink); bool wfd_sink_is_session_started(struct wfd_sink *sink); static inline void wfd_sink_freep(struct wfd_sink **s) diff --git a/src/ctl/wfd-dbus.c b/src/ctl/wfd-dbus.c index 70e6489..c678f75 100644 --- a/src/ctl/wfd-dbus.c +++ b/src/ctl/wfd-dbus.c @@ -372,19 +372,31 @@ static int wfd_dbus_sink_start_session(sd_bus_message *m, struct wfd_sink *sink = userdata; _wfd_session_free_ struct wfd_session *session = NULL; _shl_free_ char *path = NULL; - char *display = NULL; + const char *authority; + const char *display; uint16_t x, y, width, height; + const char *audio_dev; int r; - r = sd_bus_message_read(m, "sqqqq", &display, &x, &y, &width, &height); + r = sd_bus_message_read(m, + "ssqqqqs", + &authority, + &display, + &x, + &y, + &width, + &height, + &audio_dev); if(0 > r) { return r; } r = wfd_sink_start_session(sink, &session, + authority, display, - x, y, width, height); + x, y, width, height, + audio_dev); if(0 > r) { return r; } @@ -644,7 +656,7 @@ static const sd_bus_vtable wfd_dbus_vtable[] = { static const sd_bus_vtable wfd_dbus_sink_vtable[] = { SD_BUS_VTABLE_START(0), - SD_BUS_METHOD("StartSession", "sqqqq", "o", wfd_dbus_sink_start_session, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("StartSession", "ssqqqqs", "o", wfd_dbus_sink_start_session, SD_BUS_VTABLE_UNPRIVILEGED), /*SD_BUS_PROPERTY("AudioFormats", "a{sv}", wfd_dbus_sink_get_audio_formats, 0, SD_BUS_VTABLE_PROPERTY_CONST),*/ /*SD_BUS_PROPERTY("VideoFormats", "a{sv}", wfd_dbus_sink_get_video_formats, 0, SD_BUS_VTABLE_PROPERTY_CONST),*/ /*SD_BUS_PROPERTY("HasAudio", "b", wfd_dbus_sink_has_audio, 0, SD_BUS_VTABLE_PROPERTY_CONST),*/ diff --git a/src/ctl/wfd-out-session.c b/src/ctl/wfd-out-session.c index 3fa5561..67a3846 100644 --- a/src/ctl/wfd-out-session.c +++ b/src/ctl/wfd-out-session.c @@ -46,6 +46,7 @@ struct wfd_out_session sd_event_source *gst_term_source; enum wfd_display_type display_type; + char *authority; char *display_name; uint16_t x; uint16_t y; @@ -53,6 +54,7 @@ struct wfd_out_session uint16_t height; enum wfd_resolution_standard std; uint32_t mask; + char *audio_dev; GstElement *pipeline; }; @@ -61,16 +63,18 @@ static const struct rtsp_dispatch_entry out_session_rtsp_disp_tbl[]; int wfd_out_session_new(struct wfd_session **out, struct wfd_sink *sink, + const char *authority, const char *display, uint16_t x, uint16_t y, uint16_t width, - uint16_t height) + uint16_t height, + const char *audio_dev) { _shl_free_ char *display_schema = NULL; _shl_free_ char *display_name = NULL; + _wfd_session_free_ struct wfd_session *s; enum wfd_display_type display_type; - struct wfd_out_session *s; enum wfd_resolution_standard std; uint32_t mask; int r; @@ -97,27 +101,41 @@ int wfd_out_session_new(struct wfd_session **out, if(0 > r) { return -EINVAL; } - + s = calloc(1, sizeof(struct wfd_out_session)); if(!s) { return -ENOMEM; } + wfd_out_session(s)->authority = strdup(authority); + if(!wfd_out_session(s)->authority) { + free(s); + return -ENOMEM; + } + + wfd_out_session(s)->audio_dev = strdup(audio_dev); + if(!wfd_out_session(s)->audio_dev) { + free(s); + return -ENOMEM; + } + wfd_session(s)->dir = WFD_SESSION_DIR_OUT; wfd_session(s)->rtsp_disp_tbl = out_session_rtsp_disp_tbl; - s->fd = -1; - s->sink = sink; - s->display_type = display_type; - s->display_name = display_name; - display_name = NULL; - s->x = x; - s->y = y; - s->width = width; - s->height = height; - s->mask = mask; - s->std = std; + wfd_out_session(s)->fd = -1; + wfd_out_session(s)->sink = sink; + wfd_out_session(s)->display_type = display_type; + wfd_out_session(s)->display_name = display_name; + wfd_out_session(s)->x = x; + wfd_out_session(s)->y = y; + wfd_out_session(s)->width = width; + wfd_out_session(s)->height = height; + wfd_out_session(s)->mask = mask; + wfd_out_session(s)->std = std; *out = wfd_session(s); + s = NULL; + + display_name = NULL; return 0; } @@ -267,11 +285,21 @@ void wfd_out_session_destroy(struct wfd_session *s) os->gst_launch_source = NULL; } + if(os->audio_dev) { + free(os->audio_dev); + os->audio_dev = NULL; + } + if(os->display_name) { free(os->display_name); os->display_name = NULL; } + if(os->authority) { + free(os->authority); + os->authority = NULL; + } + if(os->pipeline) { gst_element_set_state(os->pipeline, GST_STATE_NULL); g_object_unref(os->pipeline); @@ -497,14 +525,23 @@ inline static char * uint16_to_str(uint16_t i, char *buf, size_t len) return buf; } +inline static char * quote_str(const char *s, char *d, size_t len) +{ + snprintf(d, len, "\"%s\"", s); + + return d; +} + static int wfd_out_session_create_pipeline(struct wfd_session *s) { char x[16], y[16], width[16], height[16]; char rrtp_port[16], rrtcp_port[16], lrtcp_port[16]; + char audio_dev[256]; struct wfd_out_session *os = wfd_out_session(s); GstElement *pipeline; GError *error = NULL; - GstStateChangeReturn r; + const char **tmp; + int r; const char *pipeline_desc[96] = { "ximagesrc", "use-damage=false", @@ -541,7 +578,7 @@ static int wfd_out_session_create_pipeline(struct wfd_session *s) "pulsesrc", "do-timestamp=true", "client-name=miraclecast", - "device=\"alsa_output.pci-0000_00_1b.0.analog-stereo.monitor\"", + "device=", quote_str(os->audio_dev, audio_dev, sizeof(audio_dev)), "!", "audioconvert", "!", "audio/x-raw,", "rate=48000,", @@ -558,7 +595,6 @@ static int wfd_out_session_create_pipeline(struct wfd_session *s) "!", "session.recv_rtcp_sink_0", NULL }; - const char **tmp; if(s->stream.rtcp_port) { tmp = pipeline_desc; @@ -574,7 +610,24 @@ static int wfd_out_session_create_pipeline(struct wfd_session *s) *tmp ++ = "async=false"; } - snprintf(rrtcp_port, sizeof(rrtcp_port), "%hu", s->stream.rtcp_port); + r = snprintf(rrtcp_port, sizeof(rrtcp_port), "%hu", s->stream.rtcp_port); + if(0 > r) { + return r; + } + + /* bad pratice, but since we are in the same process, + I think this is the only way to do it */ + if(WFD_DISPLAY_TYPE_X == os->display_type) { + r = setenv("XAUTHORITY", os->authority, 1); + if(0 > r) { + return r; + } + + r = setenv("DISPLAY", os->display_name, 1); + if(0 > r) { + return r; + } + } pipeline = gst_parse_launchv(pipeline_desc, &error); if(!pipeline) { diff --git a/src/ctl/wfd-session.c b/src/ctl/wfd-session.c index 4027c59..cf09314 100644 --- a/src/ctl/wfd-session.c +++ b/src/ctl/wfd-session.c @@ -188,7 +188,7 @@ int wfd_session_teardown(struct wfd_session *s) return session_vtbl[s->dir].teardown(s);; } - wfd_session_free(s); + //wfd_session_free(s); return 0; } @@ -219,6 +219,7 @@ void wfd_session_free(struct wfd_session *s) } if(s->rtsp) { + rtsp_detach_event(s->rtsp); rtsp_unref(s->rtsp); s->rtsp = NULL; } diff --git a/src/ctl/wfd-sink.c b/src/ctl/wfd-sink.c index b61d441..5925d32 100644 --- a/src/ctl/wfd-sink.c +++ b/src/ctl/wfd-sink.c @@ -119,11 +119,13 @@ struct ctl_peer * wfd_sink_get_peer(struct wfd_sink *sink) int wfd_sink_start_session(struct wfd_sink *sink, struct wfd_session **out, + const char *authority, const char *display, uint16_t x, uint16_t y, uint16_t width, - uint16_t height) + uint16_t height, + const char *audio_dev) { int r; _wfd_session_free_ struct wfd_session *s = NULL; @@ -135,7 +137,15 @@ int wfd_sink_start_session(struct wfd_sink *sink, return -EALREADY; } - r = wfd_out_session_new(&s, sink, display, x, y, width, height); + r = wfd_out_session_new(&s, + sink, + authority, + display, + x, + y, + width, + height, + audio_dev); if(0 > r) { return r; } diff --git a/src/ctl/wfdctl.c b/src/ctl/wfdctl.c index 9c9931c..fc2fb15 100644 --- a/src/ctl/wfdctl.c +++ b/src/ctl/wfdctl.c @@ -363,23 +363,16 @@ void ctl_fn_peer_new(struct ctl_peer *p) void ctl_fn_peer_free(struct ctl_peer *p) { struct wfd_sink *s; - _shl_free_ char *label = NULL; int r; - log_info("peer %s down", p->label); - r = ctl_wfd_remove_sink_by_label(wfd, p->label, &s); - if(!r) { - return; + if(r) { + wfd_fn_sink_free(s); + log_info("sink %s removed", s->label); + wfd_sink_free(s); } - label = strdup(s->label); - - wfd_fn_sink_free(s); - - wfd_sink_free(s); - - log_info("sink %s removed", label); + log_info("peer %s down", p->label); } void ctl_fn_peer_provision_discovery(struct ctl_peer *p,