Add feedback effect in voice layout 77/87277/7
authorsungwook79.park <sungwook79.park@samsung.com>
Wed, 7 Sep 2016 07:49:19 +0000 (16:49 +0900)
committersungwook79.park <sungwook79.park@samsung.com>
Wed, 7 Sep 2016 10:09:08 +0000 (19:09 +0900)
Change-Id: Ifcac157014d6cfc75136a1e08c74f1e8958b8593
Signed-off-by: sungwook79.park <sungwook79.park@samsung.com>
17 files changed:
CMakeLists.txt
po/en_US.po
res/edje/w-input-stt.edc
src/MicEffector.cpp [new file with mode: 0644]
src/SttFeedback.cpp [new file with mode: 0644]
src/SttManager.cpp [new file with mode: 0644]
src/WInputSttMicEffect.cpp [new file with mode: 0644]
src/include/MicEffector.h [new file with mode: 0644]
src/include/SttFeedback.h [new file with mode: 0644]
src/include/SttManager.h [new file with mode: 0644]
src/include/WInputSttMicEffect.h [new file with mode: 0644]
src/include/ise-stt-engine.h [deleted file]
src/include/ise-stt-mode.h
src/include/ise-stt-option.h
src/ise-stt-mode.cpp
src/ise-stt-option.cpp
src/ise.cpp

index f19f159..fb9dee0 100644 (file)
@@ -7,9 +7,12 @@ SET(ISE_SRCS
     src/config.cpp
     src/option.cpp
     src/imdata.cpp
-    src/ise-stt-engine.cpp
     src/ise-stt-mode.cpp
     src/ise-stt-option.cpp
+    src/MicEffector.cpp
+    src/SttFeedback.cpp
+    src/SttManager.cpp
+    src/WInputSttMicEffect.cpp
     src/sdk/ise_lang_table.cpp
     src/sdk/cji.cpp
     src/sdk/sdk.cpp
index 30363d0..5a235e5 100755 (executable)
@@ -104,4 +104,67 @@ msgid "IDS_VOICE_OPT_LANGUAGE_ABB"
 msgstr "Language"
 
 msgid "IDS_VC_BODY_AUTOMATIC"
-msgstr "Automatic"
\ No newline at end of file
+msgstr "Automatic"
+
+
+
+
+msgid "IDS_ACCS_BODY_DISABLED_TTS"
+msgstr "Turned off."
+
+msgid "IDS_MSG_BODY_SELECTED_TTS"
+msgstr "Selected."
+
+msgid "IDS_MSGS_BODY_NOT_SELECTED_T_TTS"
+msgstr "Not selected"
+
+msgid "IDS_WNOTI_TPOP_CHECK_YOUR_PHONE_ABB"
+msgstr "Check your phone."
+
+msgid "IDS_ST_TPOP_CONNECT_VIA_BLUETOOTH_TO_REVIEW_AND_ACCEPT_THE_LEGAL_NOTICE_ABB"
+msgstr "Connect via Bluetooth to review and accept the legal notice."
+
+msgid "IDS_IME_HEADER_INPUT_LANGUAGES_ABB"
+msgstr "Input languages"
+
+msgid "IDS_TTS_TBBODY_DOUBLE_TAP_TO_SEND"
+msgstr "Double tap to send."
+
+msgid "IDS_VTR_BODY_SPEAK_IN_PS_NOW"
+msgstr "Speak in %s now."
+
+msgid "IDS_IME_BODY_FAILED_TO_RECOGNISE_VOICE"
+msgstr "Failed to recognize voice."
+
+msgid "IDS_VC_HEADER_VOICE_INPUT_LANGUAGE"
+msgstr "Voice input language"
+
+msgid "IDS_ST_ACBUTTON_AGREE_ABB"
+msgstr "AGREE"
+
+msgid "IDS_IME_POP_NETWORK_CONNECTION_ERROR"
+msgstr "Network connection error."
+
+msgid "IDS_ST_POP_NETWORK_ERROR"
+msgstr "Network error."
+
+msgid "IDS_VOICE_NPBODY_SPEAK_NOW_ABB"
+msgstr "Speak now"
+
+msgid "IDS_VOICE_TPOP_RECOGNITION_FAILED_ABB"
+msgstr "Recognition failed."
+
+msgid "IDS_VOICE_MBODY_NETWORK_ERROR_ABB"
+msgstr "Network error"
+
+msgid "IDS_AMEMO_BUTTON_SEND"
+msgstr "Send"
+
+msgid "IDS_TTS_TBBODY_DOUBLE_TAP_TO_SPEAK"
+msgstr "Double tap to speak."
+
+msgid "IDS_VTR_BODY_RECOGNITION_SERVICE_BUSY"
+msgstr "Recognition service busy."
+
+msgid "IDS_VOICE_NPBODY_TAP_TO_PAUSE_ABB"
+msgstr "Tap to pause"
\ No newline at end of file
index b56e430..b627c6f 100644 (file)
@@ -801,7 +801,7 @@ collections
                                                fit: 1 1;
                                                style, "textblock_style";
                                        }
-                                       color, 120 120 120 120;
+                                       color, 255 255 255 255;
                                }
                                description
                                {
@@ -812,7 +812,7 @@ collections
                                                fit: 1 1;
                                                style, "textblock_style_bottom";
                                        }
-                                       color, 120 120 120 120;
+                                       color, 255 255 255 255;
                                }
                        }
                }
diff --git a/src/MicEffector.cpp b/src/MicEffector.cpp
new file mode 100644 (file)
index 0000000..f2602d1
--- /dev/null
@@ -0,0 +1,478 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <string.h>
+#include "MicEffector.h"
+
+using namespace is::ui;
+
+/**
+ * animation configuration values
+ *
+ */
+static size_t start_stop_anim_count = 28;
+static size_t spectrum_count = SAMPLE_COUNT;
+static float spectrum_posx = 40.0f;
+
+static float timeout_s = 1.0f / 60.0f;
+
+#define MATH_PI (3.141592)
+
+double cubic_easy_in_out(double index, double start, double end, double duration)
+{
+       index /= duration/2;
+       if (index < 1)
+               return end/2*index*index*index + start;
+
+       index -= 2;
+       return end/2*(index*index*index + 2) + start;
+}
+
+double cubic_easy_in(double index, double start, double end, double duration)
+{
+       index /= duration;
+       return end*index*index*index*index*index + start;
+}
+
+double cubic_easy_out(double index, double start, double end, double duration)
+{
+       index /= duration;
+       index--;
+       return end*(index*index*index + 1) + start;
+}
+
+
+/**
+ * Constructor
+ *
+ * #1. Create ea_vector handle for drawing effect.
+ *     ( 1 canvas, 1 paint and 45 paths )
+ * #2. Drawing empty frame to avoid broken screen.
+ *
+ */
+
+MicEffector::MicEffector(Evas_Object *canvas, Evas_Object *layout, IMicEffector& effect)
+       : drawcount(0)
+       , forcestop(false)
+       , started(false)
+       , fake(false)
+       , timer(NULL)
+       , layout(layout)
+       , ieffect(effect)
+{
+//     path = ea_vector_path_create();
+//     paint = ea_vector_paint_create();
+//     ea_vector_paint_set_style(paint, EA_VECTOR_PAINT_STYLE_STROKE);
+//     ea_vector_paint_set_line_cap(paint, EA_VECTOR_PAINT_LINE_CAP_ROUND);
+//     ea_vector_paint_set_line_join(paint, EA_VECTOR_PAINT_LINE_JOIN_ROUND);
+//     ea_vector_paint_set_line_width(paint, 3.0);
+//     ea_vector_paint_set_color(paint, 1.0f, 1.0f, 1.0f, 1.0f);
+
+//     this->canvas = ea_vector_canvas_create(canvas);
+
+       DrawDummyFrame();
+};
+
+
+
+/**
+ * Destructor
+ *
+ * #1. Destroy ea_vector handle
+ *
+ */
+MicEffector::~MicEffector()
+{
+       if(timer)
+       {
+               ecore_timer_del(timer);
+               timer = NULL;
+       }
+
+//     ea_vector_path_destroy(path);
+//     ea_vector_paint_destroy(paint);
+//     ea_vector_canvas_destroy(canvas);
+}
+
+
+
+/**
+ * Draw empty frame to remove or initiate screen
+ *
+ */
+void MicEffector::DrawDummyFrame()
+{
+//     ea_vector_path_reset(path);
+//     ea_vector_path_move_to(path, 0, 0);
+//     ea_vector_path_line_to(path, 0, 0);
+//     ea_vector_canvas_draw(canvas, path, paint);
+}
+
+
+
+/**
+ * Draw Que animation
+ *
+ * In case of start, it shows 2 more dots per one time.
+ * In case of stop, it remove 2 dots per one time.
+ *
+ * it works during 22 times.
+ *
+ */
+void MicEffector::DrawQue(int idx, bool is_start)
+{
+//     float margin = spectrum_posx;
+//     float posx = 0.0;
+
+       double speed = cubic_easy_out(idx + 1.0, 0.0, 23.0, 23);
+
+       unsigned int start = start_stop_anim_count - (int) speed;
+       unsigned int end = start_stop_anim_count + (int) speed;
+
+//     double opacity;
+
+       if (is_start) {
+//             opacity = cubic_easy_out(idx, 0.0, 1.0, 26.0);
+       } else {
+//             opacity = cubic_easy_out(idx, 0, 1.0, 26.0);
+       }
+
+//     ea_vector_path_reset(path);
+
+       for(unsigned int i = start; i < end; i++)
+       {
+//             posx = margin + (i * 5);
+
+//             ea_vector_path_move_to(path, posx, 37.0f);
+//             ea_vector_path_line_to(path, posx, 38.0f);
+
+//             ea_vector_paint_set_color(paint, 1.0f, 1.0f, 1.0f, opacity);
+       }
+
+//     ea_vector_canvas_draw(canvas, path, paint);
+}
+
+
+
+float MicEffector::GetAmplifyValue(unsigned int idx)
+{
+       float amplify = 0.0;
+
+       int max[SAMPLE_COUNT] = {
+               /**
+                * dot "A" (9)
+                *
+                */
+               1, 1, 1, 1,
+
+
+               1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+               /**
+                * dot "B" (9)
+                *
+                */
+               10, 8, 2, 3, 10, 11, 6, 12, 4,
+
+               /**
+                * dot "C" (15)
+                *
+                */
+                3, 5, 9, 12, 11, 8, 14, 15, 13, 11, 12, 6, 8, 3, 2,
+
+               /**
+                * reverse dot "B" (9)
+                *
+                */
+                4, 12, 6, 11, 10, 3, 2, 8, 10,
+
+               /**
+                * dot "A" (9)
+                *
+                */
+               1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+               1, 1, 1, 1
+       };
+
+       amplify = (float) max[idx] / 10.0f * 1.9f;
+
+       return amplify;
+}
+
+/**
+ * Draw effect animation
+ *
+ * It draws volume effect. during 5 times.
+ * Center of effect area, it applies amplified value.
+ *
+ */
+void MicEffector::DrawWave(unsigned int idx, int amount, int prev_amount, double opacity, bool is_lastcmd)
+{
+//     float ratio = GetAmplifyValue(idx);
+
+//     float am = ((float) amount) * ratio;
+//     float pam = ((float) prev_amount) * ratio;
+//     float cnt = (float) drawcount;
+
+       float posx = spectrum_posx;
+
+//     float height = pam > am?
+//             pam - cubic_easy_in_out(cnt + 1.0, am, pam, 7):
+//             cubic_easy_in_out(cnt + 1.0, pam, am, 7);
+
+       posx += idx * 5;
+
+//     ea_vector_path_move_to(path, posx, (37.0f - (height / 2.0)));
+//     ea_vector_path_line_to(path, posx, (38.0f + (height / 2.0)));
+
+       if (is_lastcmd) {
+//             ea_vector_paint_set_color(paint, 0.1451f, 0.204f, 0.255f, opacity);//RGB = 37:52:65
+       } else {
+//             ea_vector_paint_set_color(paint, 1.0f, 1.0f, 1.0f, opacity);//RGB: 255 255 255
+       }
+}
+
+
+
+/**
+ * Effect Start
+ *
+ */
+void MicEffector::Start()
+{
+       if(timer) {
+               ecore_timer_del(timer);
+               timer = NULL;
+       }
+
+       drawcount = 0;
+
+       prev.clear();
+       current.clear();
+
+       for(size_t i = 0; i < spectrum_count; i++)
+       {
+               prev.push_back(0);
+               current.push_back(0);
+       }
+
+       Listening();
+
+       /**
+        * Que animation
+        *
+        */
+       timer = ecore_timer_add(timeout_s,
+                               [](void *data)->Eina_Bool
+                               {
+                                       MicEffector *effector = static_cast<MicEffector*>(data);
+
+                                       effector->DrawQue(effector->drawcount);
+
+                                       if(effector->drawcount < (int) start_stop_anim_count) {
+                                               effector->drawcount += 2;
+                                               return ECORE_CALLBACK_RENEW;
+                                       } else {
+                                               for(unsigned int i = 0; i < spectrum_count; i++)
+                                                       effector->DrawWave(i, 0, 0);
+
+//                                             ea_vector_canvas_draw(effector->canvas, effector->path, effector->paint);
+
+                                               effector->drawcount = 0;
+                                               effector->timer = NULL;
+                                               effector->VolumeCheck();
+                                               effector->Effect();
+                                               return ECORE_CALLBACK_CANCEL;
+                                       }
+                               },
+                               this);
+}
+
+/**
+ * Volume effect
+ *
+ */
+void MicEffector::Effect(bool fake)
+{
+       /**
+        * Volume effect animation
+        *
+        */
+       if ( timer ) {
+                       ecore_timer_del(timer);
+                       timer = NULL;
+       }
+
+       timer = ecore_timer_add(timeout_s,
+                               [](void *data)->Eina_Bool
+                               {
+                                       MicEffector *effector = static_cast<MicEffector *>(data);
+
+                                       bool is_empty_prev = effector->prev.empty();
+
+
+//                                     ea_vector_path_reset(effector->path);
+
+                                       for(unsigned int i = 0; i < effector->current.size(); i++)
+                                       {
+                                               if (is_empty_prev)
+                                                       effector->DrawWave(i, effector->current.at(i), 0);
+                                               else
+                                                       effector->DrawWave(i, effector->current.at(i), effector->prev.at(i));
+                                       }
+//                                     ea_vector_canvas_draw(effector->canvas, effector->path, effector->paint);
+
+                                       if (effector->drawcount < 7)    {
+                                               effector->drawcount++;
+                                       } else {
+                                               effector->drawcount = 0;
+                                               effector->VolumeCheck(effector->fake);
+                                       }
+
+                                       return ECORE_CALLBACK_RENEW;
+                               }, this);
+}
+
+
+
+/**
+ * Stop volume animation effect
+ *
+ */
+void MicEffector::Stop(bool forced)
+{
+       if(timer)
+       {
+               ecore_timer_del(timer);
+               timer = NULL;
+       }
+
+       if(!started)
+       {
+               Idle();
+               return;
+       }
+
+       forcestop = forced;
+
+       timer = ecore_timer_add(timeout_s,
+               [](void *data)->Eina_Bool
+               {
+                       MicEffector *effector = static_cast<MicEffector*>(data);
+
+                       effector->DrawQue(start_stop_anim_count - effector->drawcount, false);
+
+                       if(effector->drawcount < (int) start_stop_anim_count) {
+                               effector->drawcount += 2;
+                               return ECORE_CALLBACK_RENEW;
+                       } else {
+                               if(!effector->forcestop) {
+                                       effector->Processing();
+                               } else {
+                                       effector->Idle();
+                               }
+
+                               effector->forcestop = false;
+                               effector->drawcount = 0;
+                               effector->timer = NULL;
+                               return ECORE_CALLBACK_CANCEL;
+                       }
+               }, this);
+}
+
+/**
+ * Signal. Refresh volume effect
+ *
+ */
+void MicEffector::VolumeCheck(bool fake)
+{
+       std::vector<int> volumes;
+
+       this->fake = fake;
+
+       if(!fake) {
+               volumes = ieffect.GetVolume();
+       } else {
+               for(unsigned int i = 0; i < spectrum_count; i++) {
+                       volumes.push_back(rand_r((unsigned int*)time(NULL)) % 2);
+               }
+       }
+
+       prev.clear();
+       prev.assign(current.begin(), current.end());
+
+       current.clear();
+       current.assign(volumes.begin(), volumes.end());
+}
+
+
+
+/**
+ * Signal. Listening effect
+ *
+ */
+void MicEffector::Listening()
+{
+       started = true;
+
+       elm_object_signal_emit(layout, "elm,state,eq,show", "eq");
+       elm_object_signal_emit(layout, "elm,state,listening", "elm");
+}
+
+
+
+/**
+ * Signal. Processing effect
+ *
+ */
+void MicEffector::Processing()
+{
+       started = false;
+
+       elm_object_signal_emit(layout, "elm,state,eq,hide", "eq");
+       elm_object_signal_emit(layout, "elm,state,processing", "elm");
+
+       ieffect.ProcessingAnimationStart();
+}
+
+
+
+/**
+ * Signal. Idle effect
+ *
+ */
+void MicEffector::Idle()
+{
+       const char *text;
+       const char *state;
+       double val;
+
+       started = false;
+
+       elm_object_signal_emit(layout, "elm,state,eq,hide", "eq");
+
+       text = elm_object_part_text_get(layout, "elm.text");
+       state = edje_object_part_state_get(elm_layout_edje_get(layout), "guide_text_block", &val);
+
+       if ((text && strlen(text) > 0) && (state && !strcmp(state, "bottom")))
+               elm_object_signal_emit(layout, "elm,state,init_message", "elm");
+       else
+               elm_object_signal_emit(layout, "elm,state,init", "elm");
+
+       ieffect.ProcessingAnimationStop();
+}
+
diff --git a/src/SttFeedback.cpp b/src/SttFeedback.cpp
new file mode 100644 (file)
index 0000000..ec73e87
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "SttFeedback.h"
+#include "ise-stt-mode.h"
+
+
+using namespace is::stt;
+
+SttFeedback::SttFeedback()
+{
+    owner = NULL;
+}
+
+SttFeedback::~SttFeedback()
+{
+}
+
+void SttFeedback::OnResult(
+    std::string asrtype,
+    stt_result_event_e event,
+    std::vector<std::string> results,
+    std::string msg) {
+    if (!owner) return;
+
+    VoiceData& vd = *((VoiceData *) owner);
+
+    if (vd.state == STT_STATE_VAL_TERMINATING) {
+        LOGD("STT_STATE_VAL_TERMINATING");
+        return;
+    }
+
+    // asrtype
+    // Partial result case : STT_RECOGNITION_TYPE_FREE_PARTIAL
+    // Normal result case : STT_RECOGNITION_TYPE_FREE
+
+    if(results.size() < 1) {
+        LOGD("Result size : %d", results.size());
+        vd.state = STT_STATE_VAL_NOT_RECOGNISED;
+        set_animation_state(&vd);
+    } else {
+        for(std::vector<std::string>::iterator result = results.begin(); result != results.end(); std::advance(result, 1)) {
+            if(!result->empty() && result->length() > 0) {
+                LOGD("%s\n", result->c_str());
+                switch(event){
+                    case STT_RESULT_EVENT_FINAL_RESULT:
+                        LOGD("STT_RESULT_EVENT_FINAL_RESULT");
+                        vd.state = STT_STATE_VAL_INIT;
+                        set_animation_state(&vd);
+                        vd.result_type = STT_RESULT_EVENT_FINAL_RESULT;
+                        voice_get_string(result->c_str(), &vd);
+                        break;
+                    case STT_RESULT_EVENT_PARTIAL_RESULT:
+                        LOGD("STT_RESULT_EVENT_PARTIAL_RESULT");
+                        vd.result_type = STT_RESULT_EVENT_PARTIAL_RESULT;
+                        voice_get_string(result->c_str(), &vd);
+                        break;
+                    default:
+                        break;
+                }
+                return;
+            }
+        }
+
+        /**
+         * Note.
+         *
+         * if recognized result doesn't have any data,
+         * it will process as recognition fail.
+         *
+         */
+        //vd.state = STT_STATE_VAL_NOT_RECOGNISED;
+        vd.state = STT_STATE_VAL_INIT;
+        set_animation_state(&vd);
+    }
+}
+
+void SttFeedback::AutoStart(void) {
+    LOGD("SttFeedback : AutoStart");
+    start_by_press((VoiceData *) owner);
+}
+
+void SttFeedback::SttIdle(void)
+{
+    if (!owner) {
+        LOGD("no owner");
+        return;
+    }
+
+    VoiceData& vd = *((VoiceData *) owner);
+
+    /**
+     * Note.
+     *
+     * When recognition is failed, do nothing.
+     * Because after result, it's called continuous. So it looks not natural.
+     *
+     * So in this case, we will not change as INIT state.
+     * using 2 sec timer, it will change as idle state.
+     *
+     */
+    if (vd.state == STT_STATE_VAL_NOT_RECOGNISED) {
+        LOGD("Ignore when state was STT_STATE_VAL_NOT_RECOGNISED");
+        return;
+    }
+
+    LOGD("UI will go to idle state");
+
+    vd.state = STT_STATE_VAL_INIT;
+    set_animation_state(&vd);
+}
+
+void SttFeedback::SttRecording(void)
+{
+    if(!owner) {
+        LOGD("no owner");
+        return;
+    }
+
+    VoiceData& vd = *((VoiceData *) owner);
+
+    if(vd.partial_result){
+        free(vd.partial_result);
+        vd.partial_result = NULL;
+    }
+
+    LOGD("UI will go to listening state");
+
+    vd.state = STT_STATE_VAL_LISTENING;
+    set_animation_state(&vd);
+}
+
+void SttFeedback::SttProcessing(void)
+{
+    if(!owner) {
+        LOGD("no owner");
+        return;
+    }
+
+    VoiceData& vd = *((VoiceData *) owner);
+
+    LOGD("UI will go to processing state");
+
+    vd.state = STT_STATE_VAL_PROCESSING;
+    set_animation_state(&vd);
+}
+
+
+
+void SttFeedback::OnError(stt_error_e reason)
+{
+    if(!owner) {
+        LOGD("no owner");
+        return;
+    }
+
+    VoiceData& vd = *((VoiceData *) owner);
+
+    LOGD("error = %d\n", reason);
+    vd.state = STT_STATE_VAL_INIT;
+    set_animation_state(&vd);
+    show_error_message(&vd, reason);
+}
+
+
+void SttFeedback::SetVoiceData(void *data) {
+    if(!data) {
+        LOGD("no data");
+        return;
+    }
+    owner = data;
+}
diff --git a/src/SttManager.cpp b/src/SttManager.cpp
new file mode 100644 (file)
index 0000000..cc19d8a
--- /dev/null
@@ -0,0 +1,505 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <assert.h>
+#include <vconf.h>
+#include <vconf-keys.h>
+
+#include "SttManager.h"
+
+using namespace is::stt;
+
+enum {
+    READY = 0x0001,
+    RECORDING = 0x0010,
+    PROCESSING = 0x0100,
+    CREATE = 0x1000
+};
+
+static inline const char *stt_state_str(stt_state_e cur)
+{
+    if (cur == STT_STATE_CREATED)
+        return (const char *) "STT_STATE_CREATED";
+
+    else if (cur == STT_STATE_READY)
+        return (const char *) "STT_STATE_READY";
+
+    else if (cur == STT_STATE_RECORDING)
+        return (const char *) "STT_STATE_RECORDING";
+
+    else if (cur == STT_STATE_PROCESSING)
+        return (const char *) "STT_STATE_PROCESSING";
+
+    else
+        return (const char *) "ABNORMAL CASE";
+}
+
+SttManager::SttManager(ISttFeedback& feedback)
+: ifeedback(feedback),
+  iscancelled(false)
+{
+    try {
+        /**
+         * Create stt handle.
+         *
+         */
+        int ret = stt_create(&handle);
+
+        if(ret != STT_ERROR_NONE)
+            throw SttException(ret, ErrorString((stt_error_e)ret));
+
+        /**
+         * Set default properties
+         *
+         */
+        EnableFeedback();
+    }
+    catch(SttException &e) {
+        LOGD("reason : %s", e.what());
+        assert(0);
+    }
+}
+
+SttManager::~SttManager() {
+    try {
+        EnableFeedback(false);
+
+        Cancel();
+        UnPrepare();
+    }
+    catch(SttException &e) {
+        LOGD("reason : %s", e.what());
+        stt_destroy(handle);
+    }
+}
+
+void SttManager::Prepare() {
+    /**
+    * Prepare stt service.
+    *
+    */
+    int ret = stt_prepare(handle);
+
+    if(ret != STT_ERROR_NONE)
+        throw SttException(ret, ErrorString((stt_error_e)ret));
+}
+
+void SttManager::UnPrepare() {
+   /**
+    * UnPrepare stt service.
+    *
+    */
+   int ret = stt_unprepare(handle);
+
+   if (ret != STT_ERROR_NONE)
+        throw SttException(ret, ErrorString((stt_error_e)ret));
+}
+
+void SttManager::Start() {
+    if(!Validate((int) READY)) {
+        throw SttException((int) STT_ERROR_INVALID_STATE, "INVALID STATE - !STT_STATE_READY");
+    }
+
+    LOGD("HERE");
+
+    iscancelled = false;
+
+    /**
+    * Start stt service.
+    *
+    */
+    asrtype = STT_RECOGNITION_TYPE_FREE;
+    int ret;
+    ret = stt_start(handle, language.c_str(), asrtype.c_str());
+
+    if(ret != STT_ERROR_NONE)
+        throw SttException(ret, ErrorString((stt_error_e)ret));
+}
+
+void SttManager::Stop() {
+    if(!Validate((int) RECORDING)) {
+        throw SttException((int) STT_ERROR_INVALID_STATE, "INVALID STATE - !STT_STATE_RECORDING");
+    }
+
+    /**
+    * Stop stt service.
+    *
+    */
+    int ret = stt_stop(handle);
+
+    if(ret != STT_ERROR_NONE)
+        throw SttException(ret, ErrorString((stt_error_e)ret));
+}
+
+void SttManager::Cancel() {
+    if(iscancelled) {
+        LOGD("iscancelled (%d)", iscancelled);
+        return;
+    }
+
+    if(!Validate((int) (RECORDING|PROCESSING))) {
+        throw SttException((int) STT_ERROR_INVALID_STATE, "INVALID STATE - !(STT_STATE_RECORDING or STT_STATE_PROCESSING)");
+    }
+
+    /**
+    * Cancel stt service (recording, processing)
+    *
+    */
+    int ret = stt_cancel(handle);
+
+    if(ret != STT_ERROR_NONE)
+        throw SttException(ret, ErrorString((stt_error_e)ret));
+
+    iscancelled = true;
+    LOGD("iscancelled (%d)", iscancelled);
+
+    ifeedback.SttIdle();
+}
+
+
+bool SttManager::Validate(int state) {
+    stt_state_e cur;
+
+    int ret = stt_get_state(handle, &cur);
+    if (ret != STT_ERROR_NONE) {
+        return false;
+    }
+
+    LOGD("validate state - %d", state);
+    LOGD("stt deamon state - %s",
+        cur == STT_STATE_CREATED ? "STT_STATE_CREATED" :
+        cur == STT_STATE_READY ? "STT_STATE_READY" :
+        cur == STT_STATE_RECORDING ? "STT_STATE_RECORDING" :
+        cur == STT_STATE_PROCESSING ? "STT_STATE_PROCESSING" : "ABNORMAL");
+
+    switch(cur) {
+        case STT_STATE_CREATED :
+            if (state & CREATE) return true;
+            break;
+        case STT_STATE_READY :
+            if (state & READY) return true;
+            break;
+        case STT_STATE_RECORDING :
+            if (state & RECORDING) return true;
+            break;
+        case STT_STATE_PROCESSING :
+            if (state & PROCESSING) return true;
+            break;
+        default :
+            break;
+    }
+
+    return false;
+}
+
+void SttManager::Initialize() {
+   /** Todo. add routine to intialize */
+}
+
+void SttManager::PrintResultState(stt_result_event_e result_type)
+{
+    std::string result;
+
+    switch (result_type) {
+        case STT_RESULT_EVENT_FINAL_RESULT :
+            result = "STT_RESULT_EVENT_FINAL_RESULT";
+            break;
+        case STT_RESULT_EVENT_PARTIAL_RESULT :
+            result = "STT_RESULT_EVENT_PARTIAL_RESULT";
+            break;
+        case STT_RESULT_EVENT_ERROR :
+            result = "STT_RESULT_EVENT_ERROR";
+            break;
+        default :
+            result = "UNKNOWN";
+            break;
+    }
+    LOGD("result type : %s", result.c_str());
+}
+
+void SttManager::on_result(
+    stt_h handle,
+    stt_result_event_e event,
+    const char** data,
+    int size,
+    const char* msg,
+    void *user_data) {
+    PrintResultState(event);
+
+    if (!user_data) {
+        LOGD("user_data null");
+        throw SttException((int)STT_ERROR_INVALID_PARAMETER, "invalid self reference");
+    }
+
+    SttManager& manager = *((SttManager *) user_data);
+
+    std::vector<std::string> results;
+
+    LOGD("result size : %d, msg : %s", size, msg);
+
+    for (size_t i = 0; i < (size_t) size; i++) {
+        if (data[i]) {
+            results.push_back(std::string(data[i]));
+        }
+
+        if (msg)
+            manager.ifeedback.OnResult(manager.asrtype, event, results, std::string(msg));
+        else
+            manager.ifeedback.OnResult(manager.asrtype, event, results, std::string(""));
+    }
+}
+
+void SttManager::PrintState(stt_state_e previous, stt_state_e current)
+{
+    std::string prev;
+    std::string curr;
+
+    switch (previous) {
+        case STT_STATE_READY :
+            prev = "STT_STATE_READY";
+            break;
+        case STT_STATE_CREATED :
+            prev = "STT_STATE_CREATED";
+            break;
+        case STT_STATE_RECORDING :
+            prev = "STT_STATE_RECORDING";
+            break;
+        case STT_STATE_PROCESSING :
+            prev = "STT_STATE_PROCESSING";
+            break;
+        default :
+            prev = "UNKNOWN";
+            break;
+    }
+
+    switch (current) {
+        case STT_STATE_READY :
+            curr = "STT_STATE_READY";
+            break;
+        case STT_STATE_CREATED :
+            curr = "STT_STATE_CREATED";
+            break;
+        case STT_STATE_RECORDING :
+            curr = "STT_STATE_RECORDING";
+            break;
+        case STT_STATE_PROCESSING :
+            curr = "STT_STATE_PROCESSING";
+            break;
+        default :
+            curr = "UNKNOWN";
+            break;
+    }
+    LOGD("previous: %s(%d), current: %s(%d)", prev.c_str(), previous, curr.c_str(), current);
+}
+
+void SttManager::on_state_changed(
+    stt_h handle,
+    stt_state_e previous,
+    stt_state_e current,
+    void *user_data) {
+    PrintState(previous, current);
+    LOGD("SttManager::on_state_changed");
+
+    if (!user_data)
+        throw SttException((int)STT_ERROR_INVALID_PARAMETER, "invalid self reference");
+
+    SttManager& manager = *((SttManager *) user_data);
+
+    if (current== STT_STATE_READY) {
+        if (previous == STT_STATE_CREATED) {
+            manager.EnableSilenceDetection();
+            manager.ifeedback.AutoStart();
+        } else if (previous == STT_STATE_RECORDING) {
+            std::string msg;
+            std::vector<std::string> results;
+            manager.ifeedback.OnResult(manager.asrtype, STT_RESULT_EVENT_ERROR, results, msg);
+        } else {
+            manager.ifeedback.SttIdle();
+        }
+    } else if (current == STT_STATE_RECORDING) {
+        manager.ifeedback.SttRecording();
+    } else if (current == STT_STATE_PROCESSING) {
+        if (!manager.iscancelled) {
+            LOGD("iscancelled (%d)", manager.iscancelled);
+            manager.ifeedback.SttProcessing();
+        } else {
+            manager.iscancelled = false;
+            LOGD("iscancelled (%d)", manager.iscancelled);
+        }
+    }
+}
+
+void SttManager::PrintErrorState(stt_error_e reason)
+{
+    std::string res;
+
+    switch (reason) {
+        case STT_ERROR_OUT_OF_MEMORY :
+            res = "STT_ERROR_OUT_OF_MEMORY";
+            break;
+        case STT_ERROR_IO_ERROR :
+            res = "STT_ERROR_IO_ERROR";
+            break;
+        case STT_ERROR_INVALID_PARAMETER :
+            res = "STT_ERROR_INVALID_PARAMETER";
+            break;
+        case STT_ERROR_TIMED_OUT :
+            res = "STT_ERROR_TIMED_OUT";
+            break;
+        case STT_ERROR_RECORDER_BUSY :
+            res = "STT_ERROR_RECORDER_BUSY";
+            break;
+        case STT_ERROR_OUT_OF_NETWORK :
+            res = "STT_ERROR_OUT_OF_NETWORK";
+            break;
+        case STT_ERROR_PERMISSION_DENIED :
+            res = "STT_ERROR_PERMISSION_DENIED";
+            break;
+        case STT_ERROR_NOT_SUPPORTED :
+            res = "STT_ERROR_NOT_SUPPORTED";
+            break;
+        case STT_ERROR_INVALID_STATE :
+            res = "STT_ERROR_INVALID_STATE";
+            break;
+        case STT_ERROR_INVALID_LANGUAGE :
+            res = "STT_ERROR_INVALID_LANGUAGE";
+            break;
+        case STT_ERROR_ENGINE_NOT_FOUND :
+            res = "STT_ERROR_ENGINE_NOT_FOUND";
+            break;
+        case STT_ERROR_OPERATION_FAILED :
+            res = "STT_ERROR_OPERATION_FAILED";
+            break;
+        case STT_ERROR_NOT_SUPPORTED_FEATURE :
+            res = "STT_ERROR_NOT_SUPPORTED_FEATURE";
+            break;
+        default :
+            res = "UNKNOWN ERROR REASON";
+            break;
+    }
+    LOGD("Error reason %s(%d)", res.c_str(), reason);
+}
+
+void SttManager::on_error(
+    stt_h handle,
+    stt_error_e reason,
+    void *user_data) {
+    LOGD("stt-daemon error (%d)", reason);
+
+    if (!user_data)
+        throw SttException((int)STT_ERROR_INVALID_PARAMETER, "invalid self reference");
+
+    SttManager& manager = *((SttManager *) user_data);
+    manager.ifeedback.OnError(reason);
+}
+
+void SttManager::SetLanguage(std::string language) {
+    this->language = language;
+}
+
+void SttManager::EnableFeedback(bool enabled) {
+    LOGD("SttManager::EnableFeedback");
+    int ret = STT_ERROR_NONE;
+
+    void *udata = static_cast<void *>(this);
+
+    if (enabled) {
+        ret = stt_set_recognition_result_cb(handle, on_result, udata);
+        if (STT_ERROR_NONE != ret)
+            throw SttException(ret, ErrorString((stt_error_e)ret));
+
+        ret = stt_set_error_cb(handle, on_error, udata);
+        if (STT_ERROR_NONE != ret)
+            throw SttException(ret, ErrorString((stt_error_e)ret));
+
+        ret = stt_set_state_changed_cb(handle, on_state_changed, udata);
+        if (STT_ERROR_NONE != ret)
+            throw SttException(ret, ErrorString((stt_error_e)ret));
+    } else {
+        ret = stt_unset_error_cb(handle);
+        if (STT_ERROR_NONE != ret)
+            throw SttException(ret, ErrorString((stt_error_e)ret));
+
+        ret = stt_unset_state_changed_cb(handle);
+        if (STT_ERROR_NONE != ret)
+            throw SttException(ret, ErrorString((stt_error_e)ret));
+
+        ret = stt_unset_recognition_result_cb(handle);
+        if (STT_ERROR_NONE != ret)
+            throw SttException(ret, ErrorString((stt_error_e)ret));
+    }
+}
+
+const char* SttManager::ErrorString(int ecode) {
+    const char *str = NULL;
+
+    switch (ecode) {
+        case STT_ERROR_OUT_OF_MEMORY:
+            str = (const char *) "STT_ERROR_OUT_OF_MEMORY";
+            break;
+        case STT_ERROR_IO_ERROR:
+            str = (const char *) "STT_ERROR_IO_ERROR";
+            break;
+        case STT_ERROR_INVALID_PARAMETER:
+            str = (const char *) "STT_ERROR_INVALID_PARAMETER";
+            break;
+        case STT_ERROR_TIMED_OUT:
+            str = (const char *) "STT_ERROR_TIMED_OUT";
+            break;
+        case STT_ERROR_RECORDER_BUSY:
+            str = (const char *) "STT_ERROR_RECORDER_BUSY";
+            break;
+        case STT_ERROR_OUT_OF_NETWORK:
+            str = (const char *) "STT_ERROR_OUT_OF_NETWORK";
+            break;
+        case STT_ERROR_INVALID_STATE:
+            str = (const char *) " STT_ERROR_INVALID_STATE";
+            break;
+        case STT_ERROR_INVALID_LANGUAGE:
+            str = (const char *) "STT_ERROR_INVALID_LANGUAGE";
+            break;
+        case STT_ERROR_ENGINE_NOT_FOUND:
+            str = (const char *) "STT_ERROR_ENGINE_NOT_FOUND";
+            break;
+        case STT_ERROR_OPERATION_FAILED:
+            str = (const char *) "STT_ERROR_OPERATION_FAILED";
+            break;
+        case STT_ERROR_NOT_SUPPORTED_FEATURE:
+            str = (const char *) "STT_ERROR_NOT_SUPPORTED_FEATURE";
+            break;
+    }
+    return str;
+}
+
+void SttManager::SoundFeedback() {
+}
+
+void SttManager::EnableSilenceDetection(bool enabled) {
+    stt_option_silence_detection_e s_option;
+
+    if (enabled)
+        s_option = STT_OPTION_SILENCE_DETECTION_TRUE;
+    else
+        s_option = STT_OPTION_SILENCE_DETECTION_FALSE;
+
+    int ret = stt_set_silence_detection(handle, s_option);
+    if (STT_ERROR_NONE != ret) {
+        LOGD("error(%d) = %s", ret, ErrorString((stt_error_e) ret));
+    } else {
+        LOGD("stt_set_silence_detection Successful");
+    }
+}
+
diff --git a/src/WInputSttMicEffect.cpp b/src/WInputSttMicEffect.cpp
new file mode 100644 (file)
index 0000000..44a41d9
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cmath>
+#include <algorithm>
+#include <numeric>
+
+#include <efl_extension.h>
+#include "WInputSttMicEffect.h"
+
+namespace {
+template<class T>
+static unsigned long long SumSquare(unsigned long long const& a, T const& b) {
+       return a + b*b;
+}
+
+const double MAX_AMPLITUDE_MEAN_16 = 23170.115738161934;
+const double MAX_AMPLITUDE_MEAN_08 = 89.803909382810;
+
+unsigned int sample_count = SAMPLE_COUNT;
+
+}
+
+using namespace is::ui;
+
+
+WInputSttMicEffect::WInputSttMicEffect()
+       : square_sum(0)
+       , count(5)
+       , handle(NULL)
+       , processing_effect_timer(NULL)
+       , progressbar(NULL) {
+}
+
+WInputSttMicEffect::~WInputSttMicEffect() {
+       ProcessingAnimationStop();
+}
+
+std::vector<int> WInputSttMicEffect::GetVolume() {
+       std::vector<int> result;
+
+       short pcm[512] = {0};
+       int size = 0;
+       int ret = 0;
+
+//     ret = stt_get_spectrum(handle, (void *) pcm, &size);
+       count = 5;
+
+       if (STT_ERROR_NONE != ret) {
+
+       } else {
+               unsigned int level = 0;
+               unsigned int step = (unsigned int) (size/2/sample_count);
+
+               for (unsigned int k = 0; k < sample_count; k++ ){
+                       square_sum = std::accumulate(pcm + k*step, pcm + k*step + 5, 0ull, SumSquare<short>);
+                       level = ConvertLevel();
+                       result.push_back(level);
+               }
+       }
+       return result;
+}
+
+float WInputSttMicEffect::GetDecibel() const
+{
+       float rms = std::sqrt(square_sum/count);
+       return 20.0*log10(rms);
+}
+
+int WInputSttMicEffect::ConvertLevel()
+{
+       float db = GetDecibel();
+
+       if ( db <= 30.0 ){
+               return 0;
+       } else if ( db <= 33.3 ){
+               return 1;
+       } else if ( db <= 36.6 ){
+               return 2;
+       } else if ( db <= 40 ){
+               return 3;
+       } else if ( db <= 43.3 ){
+               return 4;
+       } else if ( db <= 46.6 ){
+               return 5;
+       } else if ( db <= 50 ){
+               return 6;
+       } else if ( db <= 53.3 ){
+               return 7;
+       } else if ( db <= 56.6 ){
+               return 8;
+       } else if ( db <= 60 ){
+               return 9;
+       } else {
+               return 10;
+       }
+}
+
+void WInputSttMicEffect::ProcessingAnimationStart() {
+       elm_progressbar_pulse(progressbar, EINA_TRUE);
+
+       processing_effect_timer = ecore_timer_add(0.1,
+               [](void *data)->Eina_Bool
+               {
+                       if(!data) return ECORE_CALLBACK_CANCEL;
+/*
+                       WInputSttMicEffect *effect = (WInputSttMicEffect *) data;
+                       Evas_Object *progressbar = effect->progressbar;
+
+                       double progress = eext_circle_value_get(progressbar);
+
+                       if (progress < 100)
+                               progress += 5.0;
+                       else
+                               progress = 0.0;
+
+                       eext_circle_value_set(progressbar, progress);
+*/
+                       return ECORE_CALLBACK_RENEW;
+               }, this);
+}
+
+void WInputSttMicEffect::ProcessingAnimationStop() {
+       if(processing_effect_timer)
+       {
+               ecore_timer_del(processing_effect_timer);
+               processing_effect_timer = NULL;
+       }
+       elm_progressbar_pulse(progressbar, EINA_FALSE);
+}
+
+
+
+void WInputSttMicEffect::SetSttHandle(stt_h handle) {
+       this->handle = handle;
+}
+
+
+
+void WInputSttMicEffect::SetProgressBar(Evas_Object *progress) {
+       this->progressbar = progress;
+}
diff --git a/src/include/MicEffector.h b/src/include/MicEffector.h
new file mode 100644 (file)
index 0000000..ca888eb
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <vector>
+#include <efl_extension.h>
+
+#define SAMPLE_COUNT 59
+
+namespace is { /** name space input selector */
+namespace ui { /** name space ui */
+
+/**
+ * Interface for external controller
+ *
+ */
+class IMicEffector
+{
+       public :
+               virtual ~IMicEffector() = 0;
+               virtual std::vector<int> GetVolume() = 0;
+               virtual void ProcessingAnimationStart() = 0;
+               virtual void ProcessingAnimationStop() = 0;
+};
+inline IMicEffector::~IMicEffector() { };
+
+/**
+ * Effect & Effect Controller
+ *
+ */
+class MicEffector
+{
+       public :
+               MicEffector(Evas_Object *canvas, Evas_Object *layout, IMicEffector& effect);
+               ~MicEffector();
+
+               /**
+                * Start Effect.
+                *
+                * It support signaling to edje and start animation.
+                *
+                */
+               void Start();
+
+               /**
+                * Equalizer Effect animation.
+                *
+                * @param volumes sampled volume values.
+                * @param fake default false. if it set as true, it works using fixed volume values.
+                *
+                */
+               void Effect(bool fake = false);
+
+               /**
+                * Stop Effect.
+                *
+                * It support signaling to edje and stop animation.
+                *
+                * @param forced default false. if it set as true, it should go idle state without processing.
+                *
+                */
+               void Stop(bool forced = false);
+
+               /**
+                * Get volumes via ieffect and refresh equalizer effect.
+                *
+                * @param fake default false. if it set as true, it works using fixed volume values.
+                *
+                */
+               void VolumeCheck(bool fake = false);
+
+               /**
+                * Draw image to show que animation.
+                *
+                * @param idx frame index value
+                *
+                */
+               void DrawQue(int idx, bool is_start = true);
+
+               /**
+                * Draw image to show que animation.
+                *
+                * @param idx frame index value
+                * @param amount current volume amount
+                * @param prev_amount previous volume amount
+                * @param opacity opacity value for effect
+                * @param is_lastcmd
+                *
+                */
+               void DrawWave(unsigned int idx, int amount, int prev_amount, double opacity = 1.0f, bool is_lastcmd = false);
+
+               /**
+                * Get ratio for tuned volume value.
+                *
+                * @param idx volume stick index
+                * @return ratio for each volume stick
+                *
+                */
+               float GetAmplifyValue(unsigned int idx);
+
+       private :
+               /**
+                * Support idle state actions.
+                *
+                */
+               void Idle();
+
+               /**
+                * Support listening state actions.
+                *
+                */
+               void Listening();
+
+               /**
+                * Support processing state actions.
+                *
+                */
+               void Processing();
+
+               /**
+                * Draw dummy frame to avoid broken frame showing.
+                * It have to be call one time internally.
+                *
+                */
+               void DrawDummyFrame();
+
+               /**
+                * Efl vector canvas handle
+                *
+                */
+//             ea_vector_canvas_h *canvas;
+//             ea_vector_path_h *path;
+//             ea_vector_paint_h *paint;
+
+               /**
+                * Volume values.
+                *
+                */
+               std::vector<int> prev;
+               std::vector<int> current;
+
+       public :
+               int startcount;
+               int drawcount;
+               bool forcestop;
+               bool started;
+               bool fake;
+
+               /**
+                * timer handle
+                *
+                */
+               Ecore_Timer *timer;
+
+               /**
+                * mic widget layout
+                *
+                */
+               Evas_Object *layout;
+
+               /**
+                * interface with app
+                *
+                */
+               IMicEffector& ieffect;
+};
+
+}} /** end of is::ui */
+
diff --git a/src/include/SttFeedback.h b/src/include/SttFeedback.h
new file mode 100644 (file)
index 0000000..f0c54b0
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#pragma once
+
+
+#include "SttManager.h"
+#include <dlog.h>
+#undef LOG_TAG
+#define LOG_TAG "ISE_DEFAULT"
+
+
+namespace is {
+namespace stt {
+
+class SttFeedback : public ISttFeedback
+{
+    public :
+        SttFeedback();
+        virtual ~SttFeedback();
+
+        virtual void OnResult(
+            std::string asrtype,
+            stt_result_event_e event,
+            std::vector<std::string> results,
+            std::string msg);
+
+        virtual void AutoStart(void);
+
+        virtual void SttIdle(void);
+
+        virtual void SttRecording(void);
+
+        virtual void SttProcessing(void);
+
+        virtual void OnError(stt_error_e reason);
+
+        void SetVoiceData(void *data);
+
+        void *owner;
+};
+
+}} /** end of is::stt*/
diff --git a/src/include/SttManager.h b/src/include/SttManager.h
new file mode 100644 (file)
index 0000000..1c31d41
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#pragma once
+
+#include <string>
+#include <vector>
+#include <stdexcept>
+#include <dlog.h>
+#undef LOG_TAG
+#define LOG_TAG "ISE_DEFAULT"
+
+
+extern "C" {
+    #include <stt.h>
+}
+
+namespace is {
+namespace stt {
+
+class SttException : public std::runtime_error {
+    public :
+        SttException(int code, const char *reason)
+            : std::runtime_error(reason)
+            , ecode(code) { };
+
+        int GetEcode() {
+            return ecode;
+        };
+
+        int ecode;
+};
+
+class ISttFeedback
+{
+    public :
+        virtual ~ISttFeedback() = 0;
+        /**
+         * Result event which can be overloaded
+         *
+         * @param event
+         * @param results
+         * @param msg
+         */
+        virtual void OnResult(
+            std::string asrtype,
+            stt_result_event_e event,
+            std::vector<std::string> results,
+            std::string msg) = 0;
+
+        virtual void AutoStart(void) = 0;
+
+        virtual void SttIdle(void) = 0;
+
+        virtual void SttRecording(void) = 0;
+
+        virtual void SttProcessing(void) = 0;
+
+        /**
+         * Error event which can be overloaded
+         *
+         * @param reason
+         */
+        virtual void OnError(stt_error_e reason) = 0;
+};
+inline ISttFeedback::~ISttFeedback() { };
+
+class SttManager
+{
+    private :
+        stt_h handle;
+        std::string language;
+
+    public :
+        ISttFeedback& ifeedback;
+        bool iscancelled;
+        std::string asrtype;
+
+    public :
+
+        SttManager(ISttFeedback& feedback);
+
+        ~SttManager();
+
+        /**
+         * Prepare stt service.
+         *
+         */
+        void Prepare();
+
+        /**
+         * Unprepare stt service
+         *
+         */
+        void UnPrepare();
+
+        /**
+         * Start stt service
+         *
+         */
+        void Start();
+
+        /**
+         * Stop stt service
+         *
+         */
+        void Stop();
+
+        /**
+         * Cancle stt service
+         *
+         */
+        void Cancel();
+
+        /**
+         * Initialize
+         *
+         */
+        void Initialize();
+
+        bool Validate(int state);
+
+
+        /**
+         * result cb for tizen stt api.
+         *
+         * @param handle
+         * @param event
+         * @param data
+         * @param data_count
+         * @param msg
+         * @param user_data
+         */
+        static void on_result(
+            stt_h handle,
+            stt_result_event_e event,
+            const char **data,
+            int data_count,
+            const char *msg,
+            void *user_data);
+
+        /**
+          * state changed cb for tizen stt api.
+          *
+          * @param handle
+          * @param previous
+          * @param current
+          * @param user_data
+          */
+        static void on_state_changed(
+            stt_h handle,
+            stt_state_e previous,
+            stt_state_e current,
+            void *user_data);
+
+        /**
+          * error cb for tizen stt api.
+          *
+          * @param handle
+          * @param reason
+          * @param user_data
+          */
+        static void on_error(stt_h handle, stt_error_e reason, void *user_data);
+
+        /**
+          * Setter language property
+          *
+          * @param language
+          */
+        void SetLanguage(std::string language);
+
+        /**
+          * Enable cb event or not
+          *
+          * @param enabled
+          */
+        void EnableFeedback(bool enabled = true);
+
+        /**
+          * Enable silence detect
+          *
+          * @param enabled
+          */
+        void EnableSilenceDetection(bool enabled = false);
+
+        /**
+          * Sound feedback
+          *
+          */
+        void SoundFeedback();
+
+        /**
+          * Convert erroro code as string
+          *
+          * @param errocode
+          * @return human readable string about error code.
+          */
+        const char *ErrorString(int ecode);
+
+        stt_state_e GetCurrent(void) {
+            stt_state_e cur;
+            stt_get_state(handle, &cur);
+
+            return cur;
+        };
+
+        stt_h GetSttHandle() { return handle;  }
+
+    private :
+        static void PrintErrorState(stt_error_e reason);
+        static void PrintState(stt_state_e previous, stt_state_e current);
+        static void PrintResultState(stt_result_event_e result_type);
+};
+
+}} /** end of is::stt */
diff --git a/src/include/WInputSttMicEffect.h b/src/include/WInputSttMicEffect.h
new file mode 100644 (file)
index 0000000..41331d0
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <vector>
+
+extern "C" {
+       #include <stt.h>
+}
+
+#include <Evas.h>
+#include <Ecore.h>
+
+#include "MicEffector.h"
+
+namespace is {
+namespace ui {
+
+class WInputSttMicEffect : public IMicEffector
+{
+       private :
+               unsigned long long square_sum;
+               unsigned int count;
+
+
+       public :
+               WInputSttMicEffect();
+
+               virtual ~WInputSttMicEffect();
+
+               std::vector<int> GetVolume();
+
+               void ProcessingAnimationStart();
+
+               void ProcessingAnimationStop();
+
+               float GetDecibel() const;
+
+               int ConvertLevel();
+
+               void SetSttHandle(stt_h handle);
+
+               void SetProgressBar(Evas_Object *progress);
+
+               stt_h handle;
+
+               Ecore_Timer *processing_effect_timer;
+               Evas_Object *progressbar;
+};
+
+}} /** end of is::ui */
diff --git a/src/include/ise-stt-engine.h b/src/include/ise-stt-engine.h
deleted file mode 100644 (file)
index 0fbd7a8..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-#ifndef ISE_STT_ENGINE_H_
-#define ISE_STT_ENGINE_H_
-
-/*
- * This file will be included from ISE
- */
-
-
-#include <Elementary.h>
-
-#ifdef EAPI
-# undef EAPI
-#endif
-
-
-#ifdef __GNUC__
-# if __GNUC__ >= 4
-#  define EAPI __attribute__ ((visibility("default")))
-# else
-#  define EAPI
-# endif
-#else
-# define EAPI
-#endif
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-void ise_stt_start();
-void ise_stt_finish();
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* ISE_STT_ENGINE_H_ */
index f2c2e71..13eae21 100644 (file)
 
 #include <Elementary.h>
 
+#include <stt.h>
+#include "SttFeedback.h"
+#include "SttManager.h"
+#include "MicEffector.h"
+#include "WInputSttMicEffect.h"
+
 #ifdef EAPI
 # undef EAPI
 #endif
@@ -48,9 +54,82 @@ extern "C"
 
 #define STT_EDJ_FILE "edje/w-input-stt.edj"
 
+#define SK_INIT    "IDS_VOICE_BODY_TAP_MIC"
+#define SK_SPEAK_NOW    "IDS_VOICE_NPBODY_SPEAK_NOW_ABB"
+#define SK_RECOGNITION_FAILED    "IDS_VOICE_TPOP_RECOGNITION_FAILED_ABB"
+
+#define SK_DOUBLE_TAP_TO_SPEAK    "IDS_TTS_TBBODY_DOUBLE_TAP_TO_SPEAK"
+#define SK_TAP_TO_PAUSE    "IDS_VOICE_NPBODY_TAP_TO_PAUSE_ABB"
+
+#define TTS_NOT_SELECTED    "IDS_MSGS_BODY_NOT_SELECTED_T_TTS"
+#define TTS_SELECTED    "IDS_MSG_BODY_SELECTED_TTS"
+
+#define TTS_SEND    "IDS_AMEMO_BUTTON_SEND"
+#define TTS_DISABLED    "IDS_ACCS_BODY_DISABLED_TTS"
+
+#define SK_NETWORK_ERROR    "IDS_VOICE_MBODY_NETWORK_ERROR_ABB"
+#define SK_STT_BUSY    "IDS_VTR_BODY_RECOGNITION_SERVICE_BUSY"
+
+#define POPUP_OK_AGREE    "IDS_ST_ACBUTTON_AGREE_ABB"
+#define POPUP_OK_BTN    "IDS_ST_SK_OK"
+
+
+typedef enum _SttStateVal {
+    STT_STATE_VAL_INIT = 0,
+    STT_STATE_VAL_PREPARE_LISTENING,
+    STT_STATE_VAL_LISTENING,
+    STT_STATE_VAL_PREPARE_PROCESSING,
+    STT_STATE_VAL_PROCESSING,
+    STT_STATE_VAL_PREPARE_CANCEL,
+    STT_STATE_VAL_NOT_RECOGNISED,
+    STT_STATE_VAL_TERMINATING,
+    STT_STATE_VAL_MAX
+} SttStateVal;
+
+typedef struct _VoiceData VoiceData;
+
+struct _VoiceData
+{
+    int voicefw_state; //0 means init failed else success
+    stt_h voicefw_handle; //Wonyoung Lee added
+    Evas_Object *naviframe; //main window
+    Evas_Object *layout_main; //layout
+    Evas_Object *progressbar; //progressbar
+    Evas_Object *scroller; //scroller
+    Evas_Object *main_entry; //entry
+    Evas_Object *mic_button; //MIC button
+    SttStateVal state;
+    char *kbd_lang;
+    Ecore_Timer *start_timer;
+    Ecore_Timer *refresh_timer;
+    Ecore_Timer *progressbar_timer;
+    Ecore_Timer *textblock_timer;
+    Ecore_Timer *guide_text_timer;
+    Ecore_Timer *btn_disabling_timer;
+    Ecore_Timer *power_unlock_timer;
+
+    std::vector<std::string> stt_results;
+    char *partial_result;
+    int result_type;
+
+    int disclaimer;
+
+    is::stt::SttFeedback *sttfeedback;
+    is::stt::SttManager *sttmanager;
+
+    is::ui::WInputSttMicEffect *ieffect;
+    is::ui::MicEffector *effector;
+};
+
 
 void ise_show_stt_mode(Evas_Object *win);
 void ise_hide_stt_mode();
+void start_by_press(VoiceData *voicedata);
+void set_animation_state(VoiceData *voicedata);
+void show_popup_toast(const char *text, bool check_img);
+void show_error_message(VoiceData *voicedata, stt_error_e reason);
+void voice_get_string(const char *keyValue, VoiceData *voicedata);
+
 
 
 #ifdef __cplusplus
index 1602f2a..e9e4f9d 100644 (file)
@@ -24,6 +24,7 @@
 
 
 #include <Elementary.h>
+#include "ise-stt-mode.h"
 
 #ifdef EAPI
 # undef EAPI
@@ -50,7 +51,9 @@ extern "C"
 
 
 void create_setting_window();
-char *get_stt_default_language();
+void get_stt_default_language(VoiceData *my_voicedata);
+void _stt_lang_changed_cb(keynode_t *key, void* data);
+int is_lang_supported_by_stt(char lang[]);
 
 
 #ifdef __cplusplus
index 204dcf1..2c5066e 100644 (file)
 
 #include "ise.h"
 #include "ise-stt-mode.h"
+#include "ise-stt-option.h"
 
 #define _EDJ(x)  elm_layout_edje_get(x)
 #define STT_EDJ_FILE "edje/w-input-stt.edj"
 
-static Evas_Object *layout_main = NULL;
-static Evas_Object *progress_bar = NULL;
+VoiceData *my_voicedata;
+static Evas_Object *win_main = NULL;
 
+static void set_guide_text(VoiceData *vd, const char* text, bool translatable = false);
+static void _popup_close_cb(void *data, Evas_Object *obj, void *event_info);
+static void _popup_back_cb(void *data, Evas_Object *obj, void *event_info);
 
-void start_by_press()
+void send_result_text(void *data)
 {
-    edje_object_signal_emit(_EDJ(layout_main), "mouse,clicked,1", "background");
+    if(!data)
+        return;
+
+    VoiceData* voicedata = (VoiceData*)data;
+    LOGD("result_text = %s", voicedata->partial_result);
+    ise_send_string(voicedata->partial_result);
+    ise_send_string(" ");
+}
+
+void voice_get_string(const char *keyValue, VoiceData *voicedata)
+{
+    if(!voicedata)
+        return;
+
+    char* strbuf = NULL;
+
+    strbuf = elm_entry_utf8_to_markup(keyValue);
+
+    LOGD("text : %s, voicedata->partial_result=%s", strbuf, voicedata->partial_result);
+
+    if(strbuf){
+        if(voicedata->partial_result){ // partial_result is not Null so replace
+            if(strcmp(voicedata->partial_result, strbuf)){
+                // different replace
+                LOGD("different replace");
+
+                voicedata->stt_results.pop_back();
+                voicedata->stt_results.push_back(strbuf);
+
+                free(voicedata->partial_result);
+                voicedata->partial_result = strdup(strbuf);
+           }
+        } else { // partial_result is Null so first case
+            LOGD("first push");
+            voicedata->stt_results.push_back(strbuf);
+            voicedata->partial_result = strdup(strbuf);
+        }
+    }
+
+    send_result_text(voicedata);
+
+    if(strbuf)
+        free(strbuf);
+
+    LOGD("ends");
+}
+
+
+static Eina_Bool _recognition_failure_cb(void *data)
+{
+    if(data) {
+        VoiceData *voicedata = (VoiceData *) data;
+
+        voicedata->state = STT_STATE_VAL_INIT;
+        set_animation_state(voicedata);
+        voicedata->refresh_timer = NULL;
+    }
+    return ECORE_CALLBACK_CANCEL;
+}
+
+static Eina_Bool hide_guide_text(void *data)
+{
+    if(data) {
+        VoiceData *voicedata = (VoiceData *) data;
+        voicedata->guide_text_timer = NULL;
+        elm_object_part_text_set(voicedata->layout_main, "elm.text", "");
+        set_guide_text(voicedata, SK_TAP_TO_PAUSE, true);
+    }
+
+    return ECORE_CALLBACK_CANCEL;
+}
+
+static void set_guide_text(VoiceData *vd, const char* text, bool translatable)
+{
+    elm_object_signal_emit(vd->layout_main, "idle,state,guide_text,bottom", "elm");
+
+    if(translatable)
+        elm_object_domain_translatable_part_text_set(vd->layout_main, "elm.text", PACKAGE, text);
+    else
+        elm_object_part_text_set(vd->layout_main, "elm.text", text);
+
+    if(!strcmp(text, SK_SPEAK_NOW)){
+        if(vd->guide_text_timer == NULL)
+            vd->guide_text_timer = ecore_timer_add(2.0, hide_guide_text, vd);
+    }
+}
+
+void show_popup_toast(const char *text, bool check_img)
+{
+    Evas_Object *popup;
+
+    popup = elm_popup_add(win_main);
+    elm_object_style_set(popup, "toast/circle");
+    elm_popup_orient_set(popup, ELM_POPUP_ORIENT_BOTTOM);
+    evas_object_size_hint_weight_set(popup, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+
+    if (check_img) {
+        std::string path = app_get_resource_path();
+        std::string path_ic = path + "/images/toast_check_icon.png";
+        Evas_Object * img = elm_image_add(popup);
+        elm_image_file_set(img, path_ic.c_str(), NULL);
+        elm_object_part_content_set(popup, "toast,icon", img);
+    }
+    if(text) {
+        elm_object_part_text_set(popup, "elm.text", text);
+    }
+
+    eext_object_event_callback_add(popup, EEXT_CALLBACK_BACK, _popup_back_cb, NULL);
+    evas_object_smart_callback_add(popup, "dismissed", _popup_close_cb, NULL);
+    evas_object_smart_callback_add(popup, "block,clicked", _popup_back_cb, NULL);
+
+    elm_popup_timeout_set(popup, 2.0);
+    evas_object_show(popup);
+}
+
+static void _popup_close_cb(void *data, Evas_Object *obj, void *event_info)
+{
+    if(obj){
+        evas_object_hide(obj);
+        evas_object_del(obj);
+    }
+}
+
+static void _popup_back_cb(void *data, Evas_Object *obj, void *event_info)
+{
+    if(obj)
+        elm_popup_dismiss(obj);
+}
+
+
+void start_by_press(VoiceData *voicedata)
+{
+    LOGD("start_by_press ");
+    edje_object_signal_emit(_EDJ(voicedata->layout_main), "mouse,clicked,1", "background");
     return;
 }
 
 static void on_mic_button_press_cb(void *data, Evas_Object *obj, void *event_info)
 {
     LOGD("on_mic_button_press_cb");
-    elm_object_signal_emit(layout_main, "idle,state,text,visible", "elm");
-    //edje_object_signal_emit(layout_main, "mouse,clicked,1", "background");
-    elm_object_domain_translatable_part_text_set(layout_main, "elm.text", PACKAGE, "Speak Now");
+    VoiceData *voicedata = (VoiceData *)data;
+    edje_object_signal_emit(_EDJ(voicedata->layout_main), "mouse,clicked,1", "background");
+}
+
+static Eina_Bool _mic_button_enable_cb(void *data)
+{
+    if(!data)
+        return ECORE_CALLBACK_CANCEL;
+
+    VoiceData* voicedata = (VoiceData*)data;
+    voicedata->btn_disabling_timer = NULL;
+    Evas_Object *button = (Evas_Object *)voicedata->mic_button;
+    elm_object_disabled_set(button, EINA_FALSE);
+
+    return ECORE_CALLBACK_CANCEL;
 }
 
+
 void init_customizing_theme(void)
 {
     std::string stt_edj_path = app_get_resource_path();
@@ -54,6 +204,250 @@ void init_customizing_theme(void)
     elm_theme_extension_add(NULL, stt_edj_path.c_str());
 }
 
+bool _app_stt_initialize(VoiceData *voice_data)
+{
+    LOGD("_app_stt_initialize ");
+    VoiceData *vd = (VoiceData *)voice_data;
+
+    try {
+        if(vd != NULL && vd->sttmanager) {
+            vd->sttmanager->Cancel();
+            delete vd->sttmanager;
+            vd->sttmanager = NULL;
+        }
+
+        if(vd != NULL && vd->sttfeedback) {
+            delete vd->sttfeedback;
+            vd->sttfeedback = NULL;
+        }
+
+        vd->sttfeedback = new is::stt::SttFeedback();
+        vd->sttfeedback->SetVoiceData(vd);
+
+        vd->sttmanager = new is::stt::SttManager(*(vd->sttfeedback));
+        vd->sttmanager->Prepare();
+    } catch(std::exception &e) {
+        LOGD("%s", e.what());
+        return false;
+    }
+
+    return true;
+}
+
+static Eina_Bool _idler_cb(void *data)
+{
+    LOGD("_idler_cb");
+    if(!data) return ECORE_CALLBACK_CANCEL;
+
+    if(my_voicedata == NULL) {
+        LOGD("_idler_cb : my_voicedata is null");
+        return ECORE_CALLBACK_CANCEL;
+    }
+
+    VoiceData *voicedata = (VoiceData *)data;
+
+    if (true == _app_stt_initialize(voicedata)) {
+        LOGD("_app_stt_initialize None Error");
+        voicedata->voicefw_state = 1;
+        voicedata->state = STT_STATE_VAL_INIT;
+    } else {
+        voicedata->voicefw_state = 0;
+        LOGD("Initialization Fail!<br>Check STT-daemon is running");
+    }
+
+    Evas_Object *canvas = elm_object_part_content_get(voicedata->layout_main, "EFFECT_BG");
+
+    is::ui::WInputSttMicEffect *ieffect = new is::ui::WInputSttMicEffect();
+    ieffect->SetSttHandle(voicedata->sttmanager->GetSttHandle());
+
+    is::ui::MicEffector *effector = new is::ui::MicEffector(canvas, voicedata->layout_main, *ieffect);
+    voicedata->ieffect = ieffect;
+    voicedata->effector = effector;
+
+    ieffect->SetProgressBar(voicedata->progressbar);
+    ieffect->SetSttHandle(voicedata->sttmanager->GetSttHandle());
+
+    elm_access_highlight_set(voicedata->mic_button);
+
+    return ECORE_CALLBACK_CANCEL;
+}
+
+/**
+ * @brief - function to send the signal to edc
+ *              to change the animation as per stt state
+ * @param - Ug data
+ */
+void set_animation_state(VoiceData *voicedata)
+{
+    if (voicedata->state == STT_STATE_VAL_INIT) {
+#if 0
+        if (voicedata->sttmanager->GetCurrent() == STT_STATE_READY) {
+            set_guide_text(voicedata, "", false);
+            //_elm_access_say(voicedata->layout_main, _(SK_INIT));
+        } else {
+            PRINTFUNC(DLOG_DEBUG, "SK_NETWORK_ERROR [%d]", voicedata->sttmanager->GetCurrent());
+            set_guide_text(voicedata, _(SK_NETWORK_ERROR));
+            //_elm_access_say(voicedata->layout_main, _(SK_NETWORK_CONNECTION_ERROR));
+        }
+#endif
+
+        if(voicedata->effector)
+            voicedata->effector->Stop(true);
+
+        set_guide_text(voicedata, "");
+
+    } else if (voicedata->state == STT_STATE_VAL_LISTENING) {
+        set_guide_text(voicedata, SK_SPEAK_NOW, true);
+
+        if(voicedata->effector)
+            voicedata->effector->Start();
+
+    } else if (voicedata->state == STT_STATE_VAL_PROCESSING) {
+        set_guide_text(voicedata, "");
+        if(voicedata->effector)
+            voicedata->effector->Stop();
+
+    } else {
+        set_guide_text(voicedata, _(SK_RECOGNITION_FAILED));
+        //_elm_access_say(voicedata->layout_main, _(SK_RECOGNITION_FAILED));
+
+        voicedata->state = STT_STATE_VAL_NOT_RECOGNISED;
+
+        if(voicedata->refresh_timer) {
+             ecore_timer_del(voicedata->refresh_timer);
+        }
+
+        if(voicedata->effector)
+            voicedata->effector->Stop(true);
+
+        voicedata->refresh_timer = ecore_timer_add(2.0, _recognition_failure_cb, voicedata);
+    }
+}
+
+void show_error_message(VoiceData *vd, stt_error_e reason)
+{
+    if(reason == STT_ERROR_OUT_OF_NETWORK) {
+        show_popup_toast(_(SK_NETWORK_ERROR), false);
+        vd->state = STT_STATE_VAL_INIT;
+    } else if (reason == STT_ERROR_RECORDER_BUSY) {
+        show_popup_toast(_(SK_STT_BUSY), false);
+        vd->state = STT_STATE_VAL_INIT;
+    } else {
+        show_popup_toast(_(SK_STT_BUSY), false);
+        vd->state = STT_STATE_VAL_INIT;
+    }
+}
+
+static Eina_Bool _start_timer_cb(void* data)
+{
+    LOGD("_start_timer_cb");
+    if(data) {
+        VoiceData *voicedata = (VoiceData *) data;
+
+        try {
+            voicedata->state = STT_STATE_VAL_PREPARE_LISTENING;
+            voicedata->sttmanager->Start();
+        }
+        catch (is::stt::SttException &e) {
+            if (e.GetEcode() == STT_ERROR_OUT_OF_NETWORK)
+            {
+                set_guide_text(voicedata, _(SK_NETWORK_ERROR));
+                voicedata->state = STT_STATE_VAL_INIT;
+            } else if (e.GetEcode() == STT_ERROR_RECORDER_BUSY) {
+                show_popup_toast(_(SK_STT_BUSY), false);
+                voicedata->state = STT_STATE_VAL_INIT;
+            } else {
+                show_popup_toast(_(SK_STT_BUSY), false);
+                voicedata->state = STT_STATE_VAL_INIT;
+            }
+        }
+        voicedata->start_timer = NULL;
+    }
+    return ECORE_CALLBACK_CANCEL;
+}
+
+/**
+ * @brief - cancel button press callback for cross button
+ * @param -
+ */
+
+void on_initial_anim_press_cb(void *data, Evas_Object *obj, const char *emission, const char *source)
+{
+    LOGD("on_initial_anim_press_cb");
+    VoiceData *vd = (VoiceData *)data;
+
+    int tempVal = vd->sttmanager->GetCurrent();
+    if(tempVal == STT_STATE_CREATED) {
+        LOGD("IGNORE TOUCH event before STT READY. STT is preparing", vd->state);
+        return;
+    }
+
+    LOGD("SttManager State : %d", vd->sttmanager->GetCurrent());
+    LOGD("Ui Voice State : %d", vd->state);
+
+    switch(vd->state) {
+        case STT_STATE_VAL_INIT:
+            LOGD("%s", "STT_STATE_VAL_INIT");
+            get_stt_default_language(vd);
+            vd->sttmanager->SetLanguage(std::string(vd->kbd_lang));
+
+            if(vd->start_timer) {
+                ecore_timer_del(vd->start_timer);
+                vd->start_timer = NULL;
+            }
+
+            vd->start_timer = ecore_timer_add(0.0, _start_timer_cb, vd);
+            break;
+
+        case STT_STATE_VAL_LISTENING :
+            LOGD("%s", "STT_STATE_VAL_LISTENING");
+            try {
+                vd->state = STT_STATE_VAL_PREPARE_PROCESSING;
+                vd->sttmanager->Stop();
+
+                /**
+                * Cuased touch reponse time, it can be called to stop animator.
+                *
+                */
+                set_guide_text(vd, "");
+
+                if(vd->effector)
+                    vd->effector->Stop();
+            }
+            catch (is::stt::SttException &e) {
+                LOGD("%s", e.what());
+                if(e.GetEcode() != STT_ERROR_INVALID_STATE) {
+                    set_guide_text(vd, _(SK_RECOGNITION_FAILED));
+                    vd->state = STT_STATE_VAL_INIT;
+
+                    if(vd->effector)
+                        vd->effector->Stop(true);
+                }
+            }
+            break;
+
+        case STT_STATE_VAL_PROCESSING:
+            LOGD("%s", "STT_STATE_VAL_PROCESSING");
+            try {
+                //vd->state = STT_STATE_VAL_PREPARE_CANCEL;
+                vd->sttmanager->Cancel();
+            }
+            catch (is::stt::SttException &e) {
+
+            }
+
+            break;
+
+        case STT_STATE_VAL_NOT_RECOGNISED:
+            LOGD("%s", "STT_STATE_VAL_NOT_RECOGNISED");
+            vd->state = STT_STATE_VAL_INIT ;
+            break;
+        default:
+            LOGD("default [%d]", vd->state);
+            break;
+    }
+}
+
 static Evas_Object *create_progressbar(Evas_Object *parent)
 {
     Evas_Object *progressbar = NULL;
@@ -65,22 +459,78 @@ static Evas_Object *create_progressbar(Evas_Object *parent)
     evas_object_size_hint_align_set(progressbar, EVAS_HINT_FILL, EVAS_HINT_FILL);
     evas_object_size_hint_weight_set(progressbar, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
 
+    //ea_theme_object_color_replace(progressbar, "B065L6", "AO012");
+
     evas_object_show(progressbar);
 
     return progressbar;
 }
 
-void ise_show_stt_mode(Evas_Object *win)
+int init_voice(Evas_Object *parent, const char *lang, VoiceData *r_voicedata)
 {
+    LOGD("init_voice");
+
+    VoiceData *voicedata = (VoiceData *)r_voicedata;
+    if (!voicedata) {
+        return FALSE;
+    }
+
+    if (!parent) {
+        LOGD("Parent is NULL\n");
+        return FALSE;
+    } else {
+        LOGD("Parent is there");
+    }
+
+    voicedata->voicefw_state = 0;
+
+    /* Set Voice Language */
+    if(voicedata->kbd_lang){
+        free(voicedata->kbd_lang);
+        voicedata->kbd_lang = NULL;
+    }
+
+    //stt_get_default_language(my_voicedata->voicefw_handle, &my_voicedata->kbd_lang);
+    get_stt_default_language(voicedata);
+    if(NULL == voicedata->kbd_lang || FALSE == is_lang_supported_by_stt(voicedata->kbd_lang)) {
+        voicedata->kbd_lang = strdup("en_US");
+    }
+
+    LOGD("Voice input active language is : %s", voicedata->kbd_lang);
+
+    voicedata->naviframe= parent;
+
+    if (NULL == voicedata->naviframe) {
+        return FALSE;
+    }
+
+    if (NULL != voicedata->textblock_timer) {
+        ecore_timer_del(voicedata->textblock_timer);
+        voicedata->textblock_timer = NULL;
+    }
+    LOGD("init_voice end");
+
+    return TRUE;
+}
+
+Evas_Object *create_fullview(Evas_Object *win, VoiceData *r_voicedata)
+{
+    LOGD("create_fullview");
+
+    //win_main = win;
+    VoiceData *voicedata = r_voicedata;
+
     int ret;
     Evas_Coord win_w, win_h;
 
     init_customizing_theme();
 
-    layout_main = elm_layout_add(win);
+    Evas_Object *layout_main = elm_layout_add(win);
     evas_object_size_hint_weight_set(layout_main, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
     evas_object_size_hint_align_set(layout_main, EVAS_HINT_FILL, EVAS_HINT_FILL);
 
+    voicedata->layout_main = layout_main;
+
     std::string edj_path = app_get_resource_path();
     edj_path = edj_path + STT_EDJ_FILE;
     LOGD("edj_path = %s", edj_path.c_str());
@@ -88,28 +538,230 @@ void ise_show_stt_mode(Evas_Object *win)
     ret = elm_layout_file_set(layout_main, edj_path.c_str(), "mic_control");
     LOGD("elm_layout_file_set result = %d", ret);
 
+    elm_object_content_set(win, layout_main);
+
     // MIC Button
     Evas_Object *m_mic_button = elm_button_add(layout_main);
     elm_object_style_set(m_mic_button, "vic/micbutton");
     elm_object_part_content_set(layout_main, "MIC", m_mic_button);
 
-    evas_object_smart_callback_add(m_mic_button, "clicked", on_mic_button_press_cb, NULL);
+    elm_object_disabled_set(m_mic_button, EINA_TRUE);
+    evas_object_smart_callback_add(m_mic_button, "clicked", on_mic_button_press_cb, (void *) voicedata);
+
+    voicedata->mic_button = m_mic_button;
+
+    if(voicedata->btn_disabling_timer == NULL){
+        voicedata->btn_disabling_timer = ecore_timer_add(2.0, _mic_button_enable_cb, voicedata);
+    }
+
+    ecore_timer_add(0.6, _idler_cb, voicedata);
 
     // Progress Bar
-    progress_bar = create_progressbar(layout_main);
+    Evas_Object *progress_bar = create_progressbar(layout_main);
     elm_object_part_content_set(layout_main, "PROGRESS_BAR", progress_bar);
+    voicedata->progressbar = progress_bar;
+
+    // add callback
+    elm_object_signal_callback_add(layout_main, "idle,state,pulse,visible", "", on_initial_anim_press_cb, voicedata);
 
     evas_object_geometry_get(win, NULL, NULL, &win_w, &win_h);
     evas_object_resize(layout_main, win_w, win_h);
 
     evas_object_layer_set(layout_main, 32000);
-    evas_object_show(layout_main);
+
+    return layout_main;
 }
 
-void ise_hide_stt_mode()
+Eina_Bool init_view(void *data)
+{
+    LOGD("init_view");
+
+    VoiceData *voicedata = (VoiceData *)data;
+
+    if(voicedata == NULL) {
+        LOGD("init_view : voicedata == NULL");
+        return ECORE_CALLBACK_CANCEL;
+    }
+
+    voicedata->layout_main = create_fullview(voicedata->naviframe, voicedata);
+
+    if (voicedata->layout_main) {
+        evas_object_show(voicedata->layout_main);
+    }
+
+    return ECORE_CALLBACK_CANCEL;
+}
+
+
+Evas_Object *show_voice_window(Evas_Object *parent, VoiceData *r_voicedata)
 {
-    if (layout_main) {
-        evas_object_del(layout_main);
-        layout_main = NULL;
+    LOGD("show_voice_window");
+
+    VoiceData *voicedata = (VoiceData *)r_voicedata;
+    if (!voicedata) {
+        return NULL;
+    }
+
+    if (!parent) {
+        LOGD("Parent is NULL\n");
+        return NULL;
+    } else {
+        LOGD("Parent is there");
+    }
+
+    if (NULL != voicedata->layout_main) {
+        evas_object_del((voicedata)->layout_main);
+        (voicedata)->layout_main = NULL;
     }
+
+    if (NULL != voicedata->effector) {
+        delete (voicedata->effector);
+        (voicedata)->effector = NULL;
+    }
+
+    if (NULL != voicedata->ieffect) {
+        delete (voicedata->ieffect);
+        voicedata->ieffect = NULL;
+    }
+
+    init_view((void *)voicedata);
+    return voicedata->layout_main;
+}
+
+void on_destroy(VoiceData *r_voicedata)
+{
+    LOGD("on_destroy");
+
+    VoiceData *voicedata = (VoiceData *)r_voicedata;
+
+    if (NULL != voicedata) {
+        if (NULL != voicedata->layout_main) {
+            evas_object_del(voicedata->layout_main);
+            voicedata->layout_main = NULL;
+        }
+
+        if (NULL != voicedata->naviframe) {
+            voicedata->naviframe = NULL;
+        }
+
+        if (NULL != voicedata->start_timer) {
+            ecore_timer_del(voicedata->start_timer);
+            voicedata->start_timer = NULL;
+        }
+
+        if (NULL != voicedata->refresh_timer) {
+            ecore_timer_del(voicedata->refresh_timer);
+            voicedata->refresh_timer = NULL;
+        }
+
+        if (NULL != voicedata->progressbar_timer) {
+            ecore_timer_del(voicedata->progressbar_timer);
+            voicedata->progressbar_timer = NULL;
+            elm_progressbar_pulse(voicedata->progressbar, EINA_FALSE);
+        }
+
+        if (NULL != voicedata->textblock_timer) {
+            ecore_timer_del(voicedata->textblock_timer);
+            voicedata->textblock_timer = NULL;
+        }
+
+        if (NULL != voicedata->guide_text_timer) {
+            ecore_timer_del(voicedata->guide_text_timer);
+            voicedata->guide_text_timer = NULL;
+        }
+
+        if (NULL != voicedata->btn_disabling_timer) {
+            ecore_timer_del(voicedata->btn_disabling_timer);
+            voicedata->btn_disabling_timer = NULL;
+        }
+
+        if (NULL != voicedata->power_unlock_timer) {
+            ecore_timer_del(voicedata->power_unlock_timer);
+            voicedata->power_unlock_timer = NULL;
+        }
+
+        if(voicedata->kbd_lang) {
+            free(voicedata->kbd_lang);
+            voicedata->kbd_lang = NULL;
+        }
+
+        if(voicedata->ieffect) {
+            delete voicedata->ieffect;
+            voicedata->ieffect = NULL;
+        }
+
+        if(voicedata->effector) {
+            delete voicedata->effector;
+            voicedata->effector = NULL;
+        }
+
+        if(voicedata->sttmanager) {
+            delete voicedata->sttmanager;
+            voicedata->sttmanager = NULL;
+        }
+
+        if(voicedata->sttfeedback) {
+            delete voicedata->sttfeedback;
+            voicedata->sttfeedback = NULL;
+        }
+
+        free(voicedata);
+    }
+}
+
+void destroy_voice()
+{
+    LOGD("destroy_voice");
+    vconf_ignore_key_changed(VCONFKEY_ISE_STT_LANGUAGE, _stt_lang_changed_cb);
+
+    if (my_voicedata) {
+        on_destroy(my_voicedata);
+        my_voicedata = NULL;
+    }
+}
+
+void show_voice_input(Evas_Object *parent, const char *lang, void (*get_string)(char *, int))
+{
+    LOGD("show_voice_input");
+    int init = 0;
+
+    destroy_voice();
+
+    if (!my_voicedata) {
+        my_voicedata = (VoiceData*)malloc(sizeof(VoiceData));
+        if (my_voicedata == NULL) {
+            LOGD("%d::::Heap Overflow, Voice Input cannot be shown!", __LINE__);
+            return;
+        }
+        memset(my_voicedata, 0, sizeof(VoiceData));
+    }
+
+    if (my_voicedata) {
+        init = init_voice(parent, lang, my_voicedata);
+        if (init) {
+            if (my_voicedata->naviframe) {
+                //ise_stt_start(my_voicedata);
+                show_voice_window(my_voicedata->naviframe, my_voicedata);
+            }
+        } else {
+            destroy_voice();
+            LOGD("%d::::Fail to create Voice window!", __LINE__);
+            return;
+        }
+    }
+
+    vconf_notify_key_changed(VCONFKEY_ISE_STT_LANGUAGE, _stt_lang_changed_cb, my_voicedata);
+}
+
+void ise_show_stt_mode(Evas_Object *win)
+{
+    if(!win)
+        return;
+
+    show_voice_input(win, NULL, NULL);
+}
+
+void ise_hide_stt_mode()
+{
+    destroy_voice();
 }
index e4e748c..5907e6d 100644 (file)
@@ -27,7 +27,7 @@
 
 #include "ise.h"
 #include "ise-stt-option.h"
-#include "ise-stt-engine.h"
+#include "ise-stt-mode.h"
 
 #define item_append(obj, style, index, cb, udata) \
                elm_genlist_item_append(obj, &(style), (void *)index, NULL, ELM_GENLIST_ITEM_NONE, cb, udata)
@@ -46,8 +46,7 @@ static Elm_Genlist_Item_Class itc_2text;
 const char* get_lang_label(char lang[]);
 static int get_language_value();
 static void set_language_value(int type);
-void _stt_lang_changed_cb(keynode_t *key, void* data);
-int is_lang_supported_by_stt(char lang[]);
+
 #ifdef _WEARABLE
 static char *__get_genlist_title_label(void *data, Evas_Object *obj, const char *part);
 #endif
@@ -146,7 +145,12 @@ static void set_language_value(int type)
 
 void _stt_lang_changed_cb(keynode_t *key, void* data)
 {
-    get_stt_default_language();
+    if(!data) return;
+
+    VoiceData *vd = (VoiceData *) data;
+    get_stt_default_language(vd);
+    vd->sttmanager->SetLanguage(std::string(vd->kbd_lang));
+
     return;
 }
 
@@ -167,25 +171,33 @@ int is_lang_supported_by_stt(char lang[])
     return FALSE;
 }
 
-char * get_stt_default_language()
+void get_stt_default_language(VoiceData *my_voicedata)
 {
+    if(!my_voicedata) {
+        return;
+    }
+
+    if(my_voicedata->kbd_lang) {
+        free(my_voicedata->kbd_lang);
+        my_voicedata->kbd_lang = NULL;
+    }
+
     STT_VOICE_LANGUAGE_N66_I stt_lang;
     stt_lang = (STT_VOICE_LANGUAGE_N66_I)get_language_value();
-    char *kbd_lang;
 
     LOGD("language type (%d)", stt_lang);
 
     switch (stt_lang) {
         case STT_VOICE_N66_AUTO :
             {
-                stt_get_default_language(g_stt, &kbd_lang);
+                stt_get_default_language(my_voicedata->voicefw_handle, &my_voicedata->kbd_lang);
 
                 // get system display language
                 char* value = NULL;
                 value = vconf_get_str(VCONFKEY_LANGSET);
                 if (NULL == value) {
                     LOGD("Fail to get display language");
-                    return NULL;
+                    return;
                 }
                 LOGD("system language (%s)", value);
 
@@ -197,10 +209,10 @@ char * get_stt_default_language()
                 // if supported, set the language
                 // otherwise, set language to en_US
                 if (is_lang_supported_by_stt(system_lang) == TRUE) {
-                    kbd_lang = strdup(system_lang);
+                    my_voicedata->kbd_lang = strdup(system_lang);
                     LOGD("Set auto language (%s)", system_lang);
                 } else {
-                    kbd_lang = strdup("en_US");
+                    my_voicedata->kbd_lang = strdup("en_US");
                     LOGD("System language is not supported by STT (%s), en_US will be set", system_lang);
                 }
             }
@@ -212,17 +224,15 @@ char * get_stt_default_language()
         case STT_VOICE_N66_KO_KR :
         case STT_VOICE_N66_ZH_CN :
             {
-                kbd_lang = strdup(supported_language[stt_lang]);
+                my_voicedata->kbd_lang = strdup(supported_language[stt_lang]);
             }
             break;
         default :
-            kbd_lang = strdup("en_US");
+            my_voicedata->kbd_lang = strdup("en_US");
             break;
     }
 
-    LOGD("stt language (%s)", kbd_lang);
-
-    return strdup(kbd_lang);
+    LOGD("stt language (%s)", my_voicedata->kbd_lang);
 }
 
 #ifdef _WEARABLE
@@ -337,7 +347,6 @@ static void close_setting_window()
     g_setting_naviframe = NULL;
     evas_object_del(g_setting_window);
     g_setting_window = NULL;
-    vconf_ignore_key_changed(VCONFKEY_ISE_STT_LANGUAGE, _stt_lang_changed_cb);
 }
 
 static Eina_Bool close_setting_window_idler_cb(void *data)
@@ -478,7 +487,7 @@ static Evas_Object *create_language_list(Evas_Object *parent)
 
 void create_setting_window()
 {
-    ise_stt_finish();
+    ise_hide_stt_mode();
 
     Evas_Object *window = NULL;
     Evas_Object *genlist = NULL;
index ca9a5d1..bb5476b 100644 (file)
@@ -34,7 +34,6 @@
 #include "candidate-factory.h"
 #include "ise-emoticon-mode.h"
 #include "cbhm.h"
-#include "ise-stt-engine.h"
 #include "ise-stt-mode.h"
 #include "ise-stt-option.h"
 #include "modeindicator.h"
@@ -1323,10 +1322,8 @@ ise_show(int ic)
     g_keyboard_state.visible_state = TRUE;
 #ifdef _WEARABLE
     if (g_keyboard_state.layout == ISE_LAYOUT_STYLE_VOICE) {
-        ise_stt_start();
         ise_show_stt_mode(NATIVE_WINDOW_CAST(g_core.get_main_window()));
     } else {
-        ise_stt_finish();
         ise_hide_stt_mode();
     }
 
@@ -1437,7 +1434,7 @@ ise_hide()
     _reset_multitap_state(true);
 
     if (g_keyboard_state.layout == ISE_LAYOUT_STYLE_VOICE) {
-        ise_stt_finish();
+        ise_hide_stt_mode();
     }
 
 #ifdef _WEARABLE