ecore-audio - expose ready and fail events so multisense can avoid leaks

well well well. i WASN'T crazy. there WAS a leak. it was
ecore-audio+multisense. if a pulse audio output doesn't connect... NO
ONE KNOWS. all audio streams keep being appended to it forever just
consuming more memory indefinitely. there is no way to handle it.
expose events so it CAN be handled.
This commit is contained in:
Carsten Haitzler 2013-08-27 23:42:24 +09:00
parent 041e3af3e5
commit 12981b168e
3 changed files with 80 additions and 9 deletions

View File

@ -25,13 +25,19 @@ EAPI Eo_Op ECORE_AUDIO_OBJ_OUT_PULSE_BASE_ID = EO_NOOP;
#define MY_CLASS ECORE_AUDIO_OBJ_OUT_PULSE_CLASS
#define MY_CLASS_NAME "ecore_audio_obj_out_pulse"
const Eo_Event_Description _ECORE_AUDIO_EV_OUT_PULSE_CONTEXT_READY;
EAPI const Eo_Event_Description _ECORE_AUDIO_EV_OUT_PULSE_CONTEXT_READY =
EO_EVENT_DESCRIPTION("context,ready", "Called when the output is ready for playback.");
#define ECORE_AUDIO_EV_OUT_PULSE_CONTEXT_READY (&(_ECORE_AUDIO_EV_OUT_PULSE_CONTEXT_READY))
EAPI const Eo_Event_Description _ECORE_AUDIO_EV_OUT_PULSE_CONTEXT_FAIL =
EO_EVENT_DESCRIPTION("context,fail", "Called when context fails.");
#define ECORE_AUDIO_EV_OUT_PULSE_CONTEXT_FAIL (&(_ECORE_AUDIO_EV_OUT_PULSE_CONTEXT_FAIL))
struct _Ecore_Audio_Pulse_Class {
pa_mainloop_api *api;
pa_context *context;
pa_context_state_t state;
Ecore_Job *state_job;
Eina_List *outputs;
};
@ -213,17 +219,38 @@ static void _state_cb(pa_context *context, void *data EINA_UNUSED)
pa_context_state_t state;
state = pa_context_get_state(context);
class_vars.state = state;
if (state == PA_CONTEXT_READY) {
DBG("PA context ready.");
EINA_LIST_FOREACH(class_vars.outputs, out, eo_obj) {
eo_do(eo_obj, eo_event_callback_call(ECORE_AUDIO_EV_OUT_PULSE_CONTEXT_READY, NULL, NULL));
}
} else if ((state == PA_CONTEXT_FAILED) || (state == PA_CONTEXT_TERMINATED)) {
DBG("PA context fail.");
EINA_LIST_FOREACH(class_vars.outputs, out, eo_obj) {
eo_do(eo_obj, eo_event_callback_call(ECORE_AUDIO_EV_OUT_PULSE_CONTEXT_FAIL, NULL, NULL));
}
} else {
DBG("Connection state %i", state);
}
class_vars.state = state;
}
static void _state_job(void *data EINA_UNUSED)
{
if ((class_vars.state == PA_CONTEXT_FAILED) ||
(class_vars.state == PA_CONTEXT_TERMINATED))
{
Eo *eo_obj;
Eina_List *out;
DBG("PA context fail.");
EINA_LIST_FOREACH(class_vars.outputs, out, eo_obj) {
eo_do(eo_obj, eo_event_callback_call(ECORE_AUDIO_EV_OUT_PULSE_CONTEXT_FAIL, NULL, NULL));
}
}
class_vars.state_job = NULL;
}
static void _constructor(Eo *eo_obj, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED)
@ -249,6 +276,8 @@ static void _constructor(Eo *eo_obj, void *_pd EINA_UNUSED, va_list *list EINA_U
}
class_vars.outputs = eina_list_append(class_vars.outputs, eo_obj);
if (class_vars.state_job) eo_del(class_vars.state_job);
class_vars.state_job = ecore_job_add(_state_job, NULL);
}
static void _destructor(Eo *eo_obj, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED)
@ -281,6 +310,7 @@ static const Eo_Op_Description op_desc[] = {
static const Eo_Event_Description *event_desc[] = {
ECORE_AUDIO_EV_OUT_PULSE_CONTEXT_READY,
ECORE_AUDIO_EV_OUT_PULSE_CONTEXT_FAIL,
NULL
};

View File

@ -52,6 +52,28 @@ enum _Ecore_Audio_Obj_Out_Pulse_Sub_Ids
#define ECORE_AUDIO_OBJ_OUT_PULSE_ID(sub_id) (ECORE_AUDIO_OBJ_OUT_PULSE_BASE_ID + EO_TYPECHECK(enum _Ecore_Audio_Obj_Out_Pulse_Sub_Ids, sub_id))
extern EAPI const Eo_Event_Description _ECORE_AUDIO_EV_OUT_PULSE_CONTEXT_READY;
/**
* @brief The output context is ready
*
* @since 1.8
*
* Emitted when the outout context is ready for playback
*/
#define ECORE_AUDIO_EV_OUT_PULSE_CONTEXT_READY (&(_ECORE_AUDIO_EV_OUT_PULSE_CONTEXT_READY))
extern EAPI const Eo_Event_Description _ECORE_AUDIO_EV_OUT_PULSE_CONTEXT_FAIL;
/**
* @brief The output context has failed
*
* @since 1.8
*
* Emitted when the outout context has failed. At this point the output is unusable and will never work, so it is advisable to delete it.
*/
#define ECORE_AUDIO_EV_OUT_PULSE_CONTEXT_FAIL (&(_ECORE_AUDIO_EV_OUT_PULSE_CONTEXT_FAIL))
/**
* @}
*/

View File

@ -6,6 +6,7 @@
static Eo *out = NULL;
static int outs = 0;
static Eina_Bool outfail = EINA_FALSE;
static Eina_Bool _play_finished(void *data EINA_UNUSED, Eo *in, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
{
@ -14,6 +15,14 @@ static Eina_Bool _play_finished(void *data EINA_UNUSED, Eo *in, const Eo_Event_D
return EINA_TRUE;
}
static Eina_Bool _out_fail(void *data EINA_UNUSED, Eo *output EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
{
outfail = EINA_TRUE;
eo_del(out);
out = NULL;
return EINA_TRUE;
}
struct _edje_multisense_eet_data
{
sf_count_t offset, length;
@ -93,11 +102,13 @@ _edje_multisense_internal_sound_sample_play(Edje *ed, const char *sample_name, c
int i;
Eina_Bool ret;
if (!sample_name)
{
ERR("Given Sample Name is NULL\n");
return EINA_FALSE;
}
if (outfail) return EINA_FALSE;
if (!sample_name)
{
ERR("Given Sample Name is NULL\n");
return EINA_FALSE;
}
if ((!ed) || (!ed->file) || (!ed->file->sound_dir))
return EINA_FALSE;
@ -153,7 +164,8 @@ _edje_multisense_internal_sound_sample_play(Edje *ed, const char *sample_name, c
eo_event_callback_add(ECORE_AUDIO_EV_IN_STOPPED, _play_finished, NULL));
if (!out)
{
out = eo_add(ECORE_AUDIO_OBJ_OUT_PULSE_CLASS, NULL);
out = eo_add(ECORE_AUDIO_OBJ_OUT_PULSE_CLASS, NULL,
eo_event_callback_add(ECORE_AUDIO_EV_OUT_PULSE_CONTEXT_FAIL, _out_fail, NULL));
if (out) outs++;
}
if (!out)
@ -195,6 +207,9 @@ _edje_multisense_internal_sound_tone_play(Edje *ed, const char *tone_name, const
ERR("Given Tone Name is NULL");
return EINA_FALSE;
}
if (outfail) return EINA_FALSE;
if ((!ed) || (!ed->file) || (!ed->file->sound_dir))
return EINA_FALSE;
@ -210,7 +225,11 @@ _edje_multisense_internal_sound_tone_play(Edje *ed, const char *tone_name, const
eo_do(in, eo_event_callback_add(ECORE_AUDIO_EV_IN_STOPPED, _play_finished, NULL));
if (!out)
out = eo_add(ECORE_AUDIO_OBJ_OUT_PULSE_CLASS, NULL);
{
out = eo_add(ECORE_AUDIO_OBJ_OUT_PULSE_CLASS, NULL,
eo_event_callback_add(ECORE_AUDIO_EV_OUT_PULSE_CONTEXT_FAIL, _out_fail, NULL));
if (out) outs++;
}
eo_do(out, ecore_audio_obj_out_input_attach(in, &ret));
if (!ret) {