diff options
author | Carsten Haitzler (Rasterman) <raster@rasterman.com> | 2016-10-31 13:55:07 +0900 |
---|---|---|
committer | Carsten Haitzler (Rasterman) <raster@rasterman.com> | 2016-10-31 19:53:34 +0900 |
commit | d79232d605433374b898b7d1462608e595112170 (patch) | |
tree | 638974ab9f0bd8994347659c3dd7f277a4bf248e | |
parent | fb6ffc6ac52f92de67c2602975df2418e3af0d62 (diff) |
ecore audio - fix hang in wayland due to pulse audio connecting to x
pulse insists on connecting to the xserver on init/setup context if:
1. DISPLAY is set
AND
2. DISPLAY is not empty
so to do a pretty horrible worka-round, empty off the display if its
set so pa doesnt go connect to x and do this if WAYLAND_DISPLAy is set
assuming we'll use wayland then. this is far better than a solid
rock-hard hang. :)
@fix
-rw-r--r-- | src/lib/ecore_audio/ecore_audio_obj_out_pulse.c | 45 |
1 files changed, 44 insertions, 1 deletions
diff --git a/src/lib/ecore_audio/ecore_audio_obj_out_pulse.c b/src/lib/ecore_audio/ecore_audio_obj_out_pulse.c index 676d72d..73f9c72 100644 --- a/src/lib/ecore_audio/ecore_audio_obj_out_pulse.c +++ b/src/lib/ecore_audio/ecore_audio_obj_out_pulse.c | |||
@@ -265,8 +265,9 @@ EOLIAN static Eo * | |||
265 | _ecore_audio_out_pulse_efl_object_constructor(Eo *eo_obj, Ecore_Audio_Out_Pulse_Data *_pd EINA_UNUSED) | 265 | _ecore_audio_out_pulse_efl_object_constructor(Eo *eo_obj, Ecore_Audio_Out_Pulse_Data *_pd EINA_UNUSED) |
266 | { | 266 | { |
267 | int argc; | 267 | int argc; |
268 | char **argv; | 268 | char **argv, *disp = NULL; |
269 | Ecore_Audio_Output *out_obj = efl_data_scope_get(eo_obj, ECORE_AUDIO_OUT_CLASS); | 269 | Ecore_Audio_Output *out_obj = efl_data_scope_get(eo_obj, ECORE_AUDIO_OUT_CLASS); |
270 | static char *dispenv = NULL; | ||
270 | 271 | ||
271 | if (!EPA_LOAD()) return NULL; | 272 | if (!EPA_LOAD()) return NULL; |
272 | eo_obj = efl_constructor(efl_super(eo_obj, MY_CLASS)); | 273 | eo_obj = efl_constructor(efl_super(eo_obj, MY_CLASS)); |
@@ -274,6 +275,35 @@ _ecore_audio_out_pulse_efl_object_constructor(Eo *eo_obj, Ecore_Audio_Out_Pulse_ | |||
274 | out_obj->need_writer = EINA_FALSE; | 275 | out_obj->need_writer = EINA_FALSE; |
275 | 276 | ||
276 | if (!class_vars.context) { | 277 | if (!class_vars.context) { |
278 | |||
279 | // if we're in a wayland world rather than x11... but DISPLAY also set... | ||
280 | if (getenv("WAYLAND_DISPLAY")) disp = getenv("DISPLAY"); | ||
281 | // make a tmp copy of display locally as we'll overwrite this | ||
282 | if (disp) disp = strdup(disp); | ||
283 | // if we had a previously allocated env var buffer for DISPLAY then | ||
284 | // free it only if DISPLAY env var changed | ||
285 | if (dispenv) { | ||
286 | if (!((disp) && (!strcmp(dispenv + 8/*"DISPLAY="*/, disp)))) { | ||
287 | free(dispenv); | ||
288 | dispenv = NULL; | ||
289 | } | ||
290 | } | ||
291 | // no previous display env but we have a display, then allocate a buffer | ||
292 | // that stays around until the next time here with the evn var string | ||
293 | // but have space for disp string too | ||
294 | if ((!dispenv) && (disp)) { | ||
295 | dispenv = malloc(8/*"DISPLAY="*/ + strlen(disp) + 1); | ||
296 | } | ||
297 | // ensure env var is empty and to a putenv as pulse wants to use DISPLAY | ||
298 | // and if its non-empty it'll try connect to the xserver and we do not | ||
299 | // want this to happen in a wayland universe | ||
300 | if (dispenv) { | ||
301 | strcpy(dispenv, "DISPLAY="); | ||
302 | putenv(dispenv); | ||
303 | } | ||
304 | // now hopefully getenv("DISPLAY") inside pulse will return NULL or it | ||
305 | // will return an empty string "" which pulse thinsk is the same as NULL | ||
306 | |||
277 | ecore_app_args_get(&argc, &argv); | 307 | ecore_app_args_get(&argc, &argv); |
278 | if (!argc) { | 308 | if (!argc) { |
279 | DBG("Could not get program name, pulse outputs will be named ecore_audio"); | 309 | DBG("Could not get program name, pulse outputs will be named ecore_audio"); |
@@ -281,6 +311,19 @@ _ecore_audio_out_pulse_efl_object_constructor(Eo *eo_obj, Ecore_Audio_Out_Pulse_ | |||
281 | } else { | 311 | } else { |
282 | class_vars.context = EPA_CALL(pa_context_new)(class_vars.api, basename(argv[0])); | 312 | class_vars.context = EPA_CALL(pa_context_new)(class_vars.api, basename(argv[0])); |
283 | } | 313 | } |
314 | // if we had a display value and a displayenv buffer then let's restore | ||
315 | // the previous value content of DISPLAY as we duplicated it above and | ||
316 | // add to the env of the dispenv buffer, then putenv that back. as the | ||
317 | // buffer is malloced this will be safe, but as the displayenv is local | ||
318 | // and static we wont go allocating these buffers forever. just this one | ||
319 | // here and then replace/re-use it. | ||
320 | if ((disp) && (dispenv)) { | ||
321 | strcat(dispenv, disp); | ||
322 | putenv(dispenv); | ||
323 | } | ||
324 | // free up our temporary local DISPLAY env sring copy if we have it | ||
325 | if (disp) free(disp); | ||
326 | |||
284 | EPA_CALL(pa_context_set_state_callback)(class_vars.context, _state_cb, NULL); | 327 | EPA_CALL(pa_context_set_state_callback)(class_vars.context, _state_cb, NULL); |
285 | EPA_CALL(pa_context_connect)(class_vars.context, NULL, PA_CONTEXT_NOFLAGS, NULL); | 328 | EPA_CALL(pa_context_connect)(class_vars.context, NULL, PA_CONTEXT_NOFLAGS, NULL); |
286 | } | 329 | } |