mirror of
				https://github.com/albfan/miraclecast.git
				synced 2025-03-09 23:38:56 +00:00 
			
		
		
		
	miracle-wfdctl: set XAUTHORITY and DISPLAY before create gstreamer
pipeline, and now we can pass device name to pulseaudio
This commit is contained in:
		
							parent
							
								
									50f6ccf303
								
							
						
					
					
						commit
						07ca224397
					
				
					 7 changed files with 120 additions and 40 deletions
				
			
		| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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),*/
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			@ -103,21 +107,35 @@ int wfd_out_session_new(struct wfd_session **out,
 | 
			
		|||
		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) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue