preprocess: Support source and source2 both
[platform/core/multimedia/pulseaudio-modules-tizen.git] / src / preprocessor / module-tizenaudio-preprocessor.c
index 37f93ff..19857b7 100644 (file)
@@ -59,8 +59,12 @@ struct userdata {
 
     pa_hook_slot *source_output_fixate_slot;
     pa_hook_slot *source_output_put_slot;
+    pa_hook_slot *source_output_unlink_slot;
     pa_hook_slot *source_output_unlink_post_slot;
 
+    pa_hook_slot *source_output_move_start_slot;
+    pa_hook_slot *source_output_move_finish_slot;
+
     pa_rtpoll *rtpoll;
     pa_thread *thread;
     pa_thread_mq thread_mq;
@@ -86,6 +90,31 @@ static const char* const valid_modargs[] = {
     NULL,
 };
 
+static bool proplist_test_tizen_version2(pa_proplist *p) {
+    const char *tizen_version;
+    uint32_t version;
+
+    pa_assert(p);
+
+    if (!(tizen_version = pa_proplist_gets(p, "tizen.version")))
+        return false;
+
+    if (pa_atou(tizen_version, &version))
+        return false;
+
+    if (version < 2)
+        return false;
+
+    return true;
+}
+
+static void process_msg_main_thread(pa_msgobject *o, int code, void *userdata) {
+    pa_assert(o);
+    pa_assert(userdata);
+
+    o->process_msg(o, code, userdata, 0UL, NULL);
+}
+
 static int proplist_get_fragment_size_usec(pa_proplist *p, pa_sample_spec *sample_spec, pa_usec_t *usec) {
     const char *prop_fragsize;
     uint32_t fragsize;
@@ -252,7 +281,7 @@ static pa_processor_holder *build_processor_holder(pa_core *core, pa_source_outp
     char *processor_str = NULL;
 
     pa_processor_holder *holder;
-    pa_usec_t process_usec;
+    pa_usec_t process_usec = 10 * PA_USEC_PER_MSEC;
 
     pa_assert(core);
     pa_assert(data);
@@ -266,11 +295,10 @@ static pa_processor_holder *build_processor_holder(pa_core *core, pa_source_outp
     processors_list = pa_proplist_gets(data->proplist, PA_PROP_MEDIA_PREPROCESSOR_METHOD);
     pa_assert(processors_list);
 
-    if (proplist_get_fragment_size_usec(data->source->proplist, &data->source->sample_spec, &process_usec) < 0) {
-        pa_processor_holder_free(holder);
-        pa_log_error("Failed to get source fragment usec. use default process usec");
-        return NULL;
-    }
+    if (proplist_get_fragment_size_usec(data->source->proplist, &data->source->sample_spec, &process_usec) < 0)
+        pa_log_warn("Failed to get source fragment usec. use default process usec");
+
+    pa_log_info("request to build processors_list(%s)", processors_list);
 
     while ((processor_str = pa_split(processors_list, ",", &state))) {
         pa_processor *processor;
@@ -357,7 +385,10 @@ static void destroy_source_output_preprocessor(pa_source_output *o) {
     pa_assert(o);
 
     holder = (pa_processor_holder *)o->thread_info.processor_holder;
-    pa_processor_holder_free(holder);
+    if (holder) {
+        pa_processor_holder_free(holder);
+        o->thread_info.processor_holder = NULL;
+    }
 
     o->preprocess = NULL;
     o->thread_info.processor_holder = NULL;
@@ -376,6 +407,7 @@ static int preprocess(pa_source_output *o, pa_memchunk *chunk, pa_memchunk *ochu
 
     /* chunk must contain resampled sound pcm */
     pa_processor_holder_push_data(holder, chunk);
+
     ret = pa_processor_holder_pump(holder);
     if (ret != PROCESSOR_OK) {
         if (ret != -PROCESSOR_ERR_BUFFERING)
@@ -564,15 +596,59 @@ static pa_hook_result_t source_output_put_cb(pa_core *c, pa_source_output *o, vo
         return PA_HOOK_OK;
 
     holder = (pa_processor_holder *)o->thread_info.processor_holder;
+    if (!holder) {
+        pa_log_error("Failed to get processor holder");
+        return PA_HOOK_OK;
+    }
 
-    pa_assert(holder);
-    pa_assert(pa_processor_holder_get_current_source(holder));  /* source must be set at ADD_SOURCE_OUTPUT */
+    if (!proplist_test_tizen_version2(o->source->proplist)) {
+        pa_msgobject *msgobject = PA_MSGOBJECT(u->preprocessor);
+        pa_assert(msgobject);
+
+        process_msg_main_thread(msgobject, PA_SOURCE_MESSAGE_PREPROCESSOR_ADD_OUTPUT, o);
+
+        connect_to_reference_sink(holder, PA_MSGOBJECT(u->preprocessor), u->asyncmsgq_sink, true);
+
+        return PA_HOOK_OK;
+    }
 
     connect_to_reference_sink(holder, PA_MSGOBJECT(u->preprocessor), u->asyncmsgq_sink, true);
 
     return PA_HOOK_OK;
 }
 
+static pa_hook_result_t source_output_unlink_cb(pa_core *c, pa_source_output *o, void *userdata) {
+    struct userdata *u = (struct userdata *)userdata;
+    pa_processor_holder *holder;
+
+    pa_assert(c);
+    pa_assert(o);
+    pa_assert(u);
+
+    if (!is_preprocessor_marked(o->flags))
+        return PA_HOOK_OK;
+
+    holder = (pa_processor_holder *)o->thread_info.processor_holder;
+    if (!holder) {
+        pa_log_error("Failed to get processor holder");
+        return PA_HOOK_OK;
+    }
+
+    /* in case of normal source(not tizen2)
+     * This should be destroy in unlink process
+     * because o->source wouldn't exist in the unlink_post step. */
+    if (!proplist_test_tizen_version2(o->source->proplist)) {
+        pa_msgobject *msgobject = PA_MSGOBJECT(u->preprocessor);
+        pa_assert(msgobject);
+
+        process_msg_main_thread(msgobject, PA_SOURCE_MESSAGE_PREPROCESSOR_DESTROY, o);
+
+        connect_to_reference_sink(holder, NULL, NULL, false);
+    }
+
+    return PA_HOOK_OK;
+}
+
 /* This function will be also called when source unlink */
 static pa_hook_result_t source_output_unlink_post_cb(pa_core *c, pa_source_output *o, void *userdata) {
     struct userdata *u = (struct userdata *)userdata;
@@ -586,6 +662,10 @@ static pa_hook_result_t source_output_unlink_post_cb(pa_core *c, pa_source_outpu
         return PA_HOOK_OK;
 
     holder = (pa_processor_holder *)o->thread_info.processor_holder;
+    if (!holder) {
+        pa_log_info("holder doesn't exist. source-output might not be connected to tizen2 source");
+        return PA_HOOK_OK;
+    }
 
     connect_to_reference_sink(holder, NULL, NULL, false);
 
@@ -595,6 +675,40 @@ static pa_hook_result_t source_output_unlink_post_cb(pa_core *c, pa_source_outpu
     return PA_HOOK_OK;
 }
 
+static pa_hook_result_t source_output_move_start_cb(pa_core *c, pa_source_output *o, void *userdata) {
+    struct userdata *u = (struct userdata *)userdata;
+
+    pa_assert(c);
+    pa_assert(o);
+    pa_assert(u);
+
+    if (!proplist_test_tizen_version2(o->source->proplist)) {
+        pa_msgobject *msgobject = PA_MSGOBJECT(u->preprocessor);
+        pa_assert(msgobject);
+
+        process_msg_main_thread(msgobject, PA_SOURCE_MESSAGE_PREPROCESSOR_REMOVE_OUTPUT, o);
+    }
+
+    return PA_HOOK_OK;
+}
+
+static pa_hook_result_t source_output_move_finish_cb(pa_core *c, pa_source_output *o, void *userdata) {
+    struct userdata *u = (struct userdata *)userdata;
+
+    pa_assert(c);
+    pa_assert(o);
+    pa_assert(u);
+
+    if (!proplist_test_tizen_version2(o->source->proplist)) {
+        pa_msgobject *msgobject = PA_MSGOBJECT(u->preprocessor);
+        pa_assert(msgobject);
+
+        process_msg_main_thread(msgobject, PA_SOURCE_MESSAGE_PREPROCESSOR_ADD_OUTPUT, o);
+    }
+
+    return PA_HOOK_OK;
+}
+
 static void thread_func(void *userdata) {
     struct userdata *u = (struct userdata *)userdata;
 
@@ -658,6 +772,10 @@ int pa__init(pa_module *m) {
         goto fail;
     }
 
+    u->source_output_unlink_slot =
+        pa_hook_connect(&u->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK],
+                    PA_HOOK_EARLY, (pa_hook_cb_t) source_output_unlink_cb, u);
+
     u->source_output_unlink_post_slot =
         pa_hook_connect(&u->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK_POST],
                     PA_HOOK_EARLY, (pa_hook_cb_t) source_output_unlink_post_cb, u);
@@ -672,6 +790,14 @@ int pa__init(pa_module *m) {
         pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_PUT],
                     PA_HOOK_LATE, (pa_hook_cb_t) source_output_put_cb, u);
 
+    u->source_output_move_start_slot =
+        pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_START],
+                    PA_HOOK_LATE, (pa_hook_cb_t) source_output_move_start_cb, u);
+
+    u->source_output_move_finish_slot =
+        pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_FINISH],
+                    PA_HOOK_LATE, (pa_hook_cb_t) source_output_move_finish_cb, u);
+
     /* TODO : need to check sink configuration change */
     pa_modargs_free(ma);