Support to delegate various MIME types to caller as like voice recording 39/137239/6
authorsungwook79.park <sungwook79.park@samsung.com>
Wed, 5 Jul 2017 04:52:31 +0000 (13:52 +0900)
committersungwook park <sungwook79.park@samsung.com>
Wed, 5 Jul 2017 05:54:01 +0000 (05:54 +0000)
Change-Id: I2194134a1b599b79c5e05a6c4164fc9d94c619ad
Signed-off-by: sungwook79.park <sungwook79.park@samsung.com>
CMakeLists.txt
inc/voice-recorder.h [new file with mode: 0644]
inc/w-input-selector.h
org.tizen.inputdelegator.xml
packaging/org.tizen.inputdelegator.spec
src/voice-recorder.cpp [new file with mode: 0644]
src/w-input-emoticon.cpp
src/w-input-keyboard.cpp
src/w-input-selector.cpp
src/w-input-stt-ise.cpp
src/w-input-stt-voice.cpp

index 95b2d21..a2e1690 100755 (executable)
@@ -15,6 +15,7 @@ SET(INPUTDELEGATOR_SRCS
     src/w-input-stt-voice.cpp
     src/w-input-template.cpp
     src/w-input-smartreply.cpp
+    src/voice-recorder.cpp
 )
 
 SET(INPUTDELEGATOR_PACKAGE ${PROJECT_NAME})
@@ -51,6 +52,9 @@ SET(PKGS_CHECK_MODULES
         capi-media-audio-io
         capi-system-info
         smartreply
+        capi-media-recorder
+        capi-content-media-content
+        storage
         )
 
 
diff --git a/inc/voice-recorder.h b/inc/voice-recorder.h
new file mode 100644 (file)
index 0000000..b07d9ef
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * 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 __VOICE_RECORDER_H__
+#define __VOICE_RECORDER_H__
+
+#include <recorder.h>
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+struct _voice_recorder {
+       recorder_h recorder;
+       recorder_audio_codec_e *codec_list;
+       int codec_list_len;
+       char file_path[PATH_MAX];
+       char file_name[PATH_MAX];
+       recorder_audio_codec_e codec;
+       recorder_file_format_e file_format;
+       FILE *preproc_file;
+       app_control_h service;
+       int bitrate;
+       int sample_rate;
+       bool is_recording;
+       long long int limitsize;
+};
+typedef struct _voice_recorder voice_recorder;
+
+void init_voice_recorder(app_control_h service);
+void destroy_voice_recorder();
+void start_voice_recorder();
+void stop_voice_recorder();
+void _voice_recorder_set_data(void *data);
+voice_recorder *_voice_recorder_get_data();
+
+#endif // __VOICE_RECORDER_H__
index 985ee98..92662e1 100755 (executable)
@@ -118,7 +118,7 @@ typedef struct _InputTypeData InputTypeData;
 
 void _app_terminate(void* user_data);
 void reply_to_sender_by_callback_for_back();
-void reply_to_sender_by_callback(const char *value, const char *type);
+void reply_to_sender_by_callback(const char *value, const char *type, const char *path[]);
 char* get_resource_path();
 char* get_shared_resource_path();
 void show_gl_focus(Eina_Bool bVisible);
index 7b43160..41f8f2e 100755 (executable)
@@ -14,5 +14,7 @@
                <privilege>http://tizen.org/privilege/display</privilege>
                <privilege>http://tizen.org/privilege/recorder</privilege>
                <privilege>http://tizen.org/privilege/appmanager.launch</privilege>
+               <privilege>http://tizen.org/privilege/content.write</privilege>
+               <privilege>http://tizen.org/privilege/mediastorage</privilege>
        </privileges>
 </manifest>
index 389a9c4..8063566 100755 (executable)
@@ -42,6 +42,9 @@ BuildRequires: pkgconfig(sqlite3)
 BuildRequires: pkgconfig(capi-media-audio-io)
 BuildRequires: pkgconfig(capi-system-info)
 BuildRequires: pkgconfig(smartreply)
+BuildRequires: pkgconfig(capi-media-recorder)
+BuildRequires: pkgconfig(capi-content-media-content)
+BuildRequires: pkgconfig(storage)
 
 %if %{enable_log_manager}
 BuildRequires:  pkgconfig(bundle)
diff --git a/src/voice-recorder.cpp b/src/voice-recorder.cpp
new file mode 100644 (file)
index 0000000..ef2c017
--- /dev/null
@@ -0,0 +1,260 @@
+/*
+ * 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 <Elementary.h>
+#include <app_common.h>
+#include <app.h>
+#include <media_content.h>
+#include <dlog.h>
+#include <storage.h>
+#include "voice-recorder.h"
+
+#define MAX_TIME 1200
+
+#define VR_AUDIO_SOURCE_SAMPLERATE_LOW         8000
+#define VR_AUDIO_SOURCE_SAMPLERATE_HIGH                44100
+#define VR_AUDIO_ENCODER_BITRATE_AMR           12200
+#define VR_AUDIO_ENCODER_BITRATE_AAC           64000
+
+static voice_recorder *recorderhandle = NULL;
+
+static void _recorder_create(voice_recorder *view);
+static void _recorder_start(voice_recorder *view);
+static void _recorder_stop(voice_recorder *view);
+static void _recorder_apply_settings(voice_recorder *view);
+static void _on_recording_status_cb(unsigned long long elapsed_time, unsigned long long file_size, void *user_data);
+static void _on_recording_limit_reached_cb(recorder_recording_limit_type_e type, void *user_data);
+static bool _main_file_register(const char *filename);
+static void _recorder_destroy(voice_recorder *view);
+
+void init_voice_recorder(app_control_h service)
+{
+       voice_recorder *recorder = (voice_recorder *)malloc(sizeof(voice_recorder));
+       if (!recorder) {
+               LOGD("Error Failed to create recorder");
+               return;
+       }
+
+       _voice_recorder_set_data(recorder);
+
+       recorder->is_recording = FALSE;
+       recorder->service = service;
+       recorder->limitsize = 1000000;
+
+       _recorder_create(recorder);
+}
+
+void destroy_voice_recorder()
+{
+       LOGD("destroy_voice_recorder()");
+       voice_recorder *recorder = (voice_recorder *)_voice_recorder_get_data();
+       if (recorder) {
+               _recorder_destroy(recorder);
+       }
+       _voice_recorder_set_data(NULL);
+}
+
+void start_voice_recorder()
+{
+       voice_recorder *recorder = (voice_recorder *)_voice_recorder_get_data();
+       _recorder_start(recorder);
+}
+
+void stop_voice_recorder()
+{
+       voice_recorder *recorder = (voice_recorder *)_voice_recorder_get_data();
+       _recorder_stop(recorder);
+}
+
+void _voice_recorder_set_data(void *data)
+{
+       recorderhandle = (voice_recorder *)data;
+}
+
+voice_recorder *_voice_recorder_get_data()
+{
+       if (recorderhandle) {
+               return recorderhandle;
+       }
+       return NULL;
+}
+
+static void _recorder_create(voice_recorder *recorder)
+{
+       LOGD("_recorder_create");
+
+       int ret = recorder_create_audiorecorder(&recorder->recorder);
+       if (ret == RECORDER_ERROR_NONE) {
+               recorder_set_recording_status_cb(recorder->recorder, _on_recording_status_cb, recorder);
+               if (recorder->limitsize > 0) {
+                       recorder_attr_set_size_limit(recorder->recorder, (recorder->limitsize) / 1024);
+               }
+               recorder_set_recording_limit_reached_cb(recorder->recorder, _on_recording_limit_reached_cb, recorder);
+       } else {
+               LOGD("recorder_create_audiorecorder not successful error code: %d", ret);
+       }
+}
+
+static void _recorder_start(voice_recorder *recorder)
+{
+       LOGD("_recorder_start");
+       if (!recorder->recorder) {
+               LOGD("Error recorder->recorder is null");
+               return;
+       }
+
+       recorder_state_e rec_state;
+       recorder_get_state(recorder->recorder, &rec_state);
+
+       if (rec_state == RECORDER_STATE_PAUSED) {
+               recorder_start(recorder->recorder);
+               return;
+       }
+
+       struct tm localtime = {0, };
+       time_t rawtime = time(NULL);
+       char filename[256] = {'\0', };
+       char *voice_content_path = NULL;
+       storage_get_directory(STORAGE_TYPE_INTERNAL, STORAGE_DIRECTORY_SOUNDS, &voice_content_path);
+       if (voice_content_path == NULL) {
+               LOGD("voice_content_path is NULL");
+               return;
+       }
+
+#if 1
+       /*For MMS*/
+       recorder->codec = RECORDER_AUDIO_CODEC_AMR;
+       recorder->file_format = RECORDER_FILE_FORMAT_AMR;
+       recorder->sample_rate = VR_AUDIO_SOURCE_SAMPLERATE_LOW;
+       recorder->bitrate = VR_AUDIO_ENCODER_BITRATE_AMR;
+       if (localtime_r(&rawtime, &localtime) != NULL) {
+               snprintf(filename, sizeof(filename), "Voice-%04i-%02i-%02i_%02i:%02i:%02i.amr",
+                        localtime.tm_year + 1900, localtime.tm_mon + 1, localtime.tm_mday,
+                        localtime.tm_hour, localtime.tm_min, localtime.tm_sec);
+       }
+#else
+       /*For High Quality*/
+       recorder->codec = RECORDER_AUDIO_CODEC_AAC;
+       recorder->file_format = RECORDER_FILE_FORMAT_MP4;
+       recorder->sample_rate = VR_AUDIO_SOURCE_SAMPLERATE_HIGH;
+       recorder->bitrate = VR_AUDIO_ENCODER_BITRATE_AAC;
+       if (localtime_r(&rawtime, &localtime) != NULL) {
+               snprintf(filename, sizeof(filename), "Voice-%04i-%02i-%02i_%02i:%02i:%02i.m4a",
+                        localtime.tm_year + 1900, localtime.tm_mon + 1, localtime.tm_mday,
+                        localtime.tm_hour, localtime.tm_min, localtime.tm_sec);
+       }
+#endif
+       /*set file path*/
+       snprintf(recorder->file_path, PATH_MAX, "%s/%s", voice_content_path, filename);
+       LOGD("recorder->file_path = %s", recorder->file_path);
+       _recorder_apply_settings(recorder);
+       recorder_prepare(recorder->recorder);
+       recorder_start(recorder->recorder);
+}
+
+static void _recorder_stop(voice_recorder *recorder)
+{
+       LOGD("_recorder_stop");
+       int commitResult = RECORDER_ERROR_NONE;
+
+       if (recorder->recorder) {
+               commitResult = recorder_commit(recorder->recorder);
+               if (commitResult != RECORDER_ERROR_NONE) {
+                       LOGD("recorder_commit failed Error [%d]", recorder_commit);
+               }
+               _main_file_register(recorder->file_path);
+       }
+}
+
+static void _recorder_apply_settings(voice_recorder *recorder)
+{
+       if (recorder->recorder) {
+               recorder_attr_set_audio_channel(recorder->recorder, 2);
+               recorder_attr_set_audio_device(recorder->recorder, RECORDER_AUDIO_DEVICE_MIC);
+               recorder_attr_set_time_limit(recorder->recorder, MAX_TIME);
+
+               recorder_set_filename(recorder->recorder, recorder->file_path);
+               recorder_set_file_format(recorder->recorder, recorder->file_format);
+               LOGD("file_format: %d", recorder->file_format);
+               recorder_set_audio_encoder(recorder->recorder, recorder->codec);
+               recorder_attr_set_audio_samplerate(recorder->recorder, recorder->sample_rate);
+               recorder_attr_set_audio_encoder_bitrate(recorder->recorder, recorder->bitrate);
+
+               recorder_prepare(recorder->recorder);
+       }
+}
+
+static void _on_recording_status_cb(unsigned long long elapsed_time, unsigned long long file_size, void *user_data)
+{
+       voice_recorder *recorder = (voice_recorder *)user_data;
+
+       if (recorder) {
+               recorder_state_e rec_state = RECORDER_STATE_NONE;
+               recorder_get_state(recorder->recorder, &rec_state);
+               if (rec_state == RECORDER_STATE_PAUSED || rec_state == RECORDER_STATE_READY) {
+                       return;
+               }
+       }
+}
+
+static void _on_recording_limit_reached_cb(recorder_recording_limit_type_e type, void *user_data)
+{
+       voice_recorder *recorder = (voice_recorder *)user_data;
+       if (recorder) {
+               if (type == RECORDER_RECORDING_LIMIT_TIME) {
+                       _recorder_stop(recorder);
+               } else if (type == RECORDER_RECORDING_LIMIT_SIZE) {
+                       _recorder_stop(recorder);
+               }
+       }
+}
+
+static bool _main_file_register(const char *filename)
+{
+       LOGD("_main_file_register");
+       int err_code = 0;
+       media_info_h info = NULL;
+
+       char *register_file = strdup(filename);
+       if (register_file == NULL) {
+               LOGD("Failed to allocate memory");
+               return FALSE;
+       }
+
+       err_code = media_info_insert_to_db(register_file, &info);
+       if (err_code != MEDIA_CONTENT_ERROR_NONE) {
+               LOGD("failed to media_file_register() : [%s], [%d]", register_file, err_code);
+               media_info_destroy(info);
+               free(register_file);
+               return FALSE;
+       }
+
+       media_info_destroy(info);
+       free(register_file);
+
+       return TRUE;
+}
+
+static void _recorder_destroy(voice_recorder *recorder)
+{
+       LOGD("_recorder_destroy");
+       if (recorder->recorder) {
+               recorder_cancel(recorder->recorder);
+               recorder_unprepare(recorder->recorder);
+               recorder_destroy(recorder->recorder);
+               recorder->recorder = NULL;
+       }
+}
index 0ead5fb..4bd585b 100755 (executable)
@@ -376,7 +376,7 @@ static void _emoticon_item_clicked_cb(void *data, Evas_Object * obj, void *event
     const Eina_Unicode unicode_event[2] = { (Eina_Unicode)emoticon_info[index].code, 0 };
     char* utf_8 = eina_unicode_unicode_to_utf8(unicode_event, &length);
 
-    reply_to_sender_by_callback((const char*)utf_8, "emoticon");
+    reply_to_sender_by_callback((const char*)utf_8, "emoticon", NULL);
 
     PRINTFUNC(SECURE_DEBUG, "[%d]%s", index, utf_8);
     if (utf_8)
index 869cfb5..9257a12 100755 (executable)
@@ -82,7 +82,7 @@ void btn_clicked_cb(void *data, Evas_Object *obj, void *event_info)
        app_control_set_operation(app_control, APP_CONTROL_OPERATION_DEFAULT);
        set_source_caller_app_id(app_control);
        free(app_id);
-       reply_to_sender_by_callback(getText, "keyboard");
+       reply_to_sender_by_callback(getText, "keyboard", NULL);
        ui_app_exit();
 }
 
index d6feeec..ed22ea2 100755 (executable)
@@ -222,7 +222,7 @@ static void __ise_smartreply_gl_sel(void *data, Evas_Object *obj, void *event_in
                char *reply = input_smartreply_get_nth_item(index, &type);
                if (reply) {
                        input_smartreply_send_feedback(reply);
-                       reply_to_sender_by_callback(reply, "smartreply");
+                       reply_to_sender_by_callback(reply, "smartreply", NULL);
                        free(reply);
                        elm_exit();
                }
@@ -241,7 +241,7 @@ static void __ise_template_gl_sel(void *data, Evas_Object *obj, void *event_info
                const std::vector<TemplateData>  template_list = input_template_get_list();
 
                if (index < (int)template_list.size()) {
-                       reply_to_sender_by_callback(gettext(template_list[index].text.c_str()), "template");
+                       reply_to_sender_by_callback(gettext(template_list[index].text.c_str()), "template", NULL);
                        ui_app_exit();
                }
        }
@@ -480,7 +480,7 @@ void set_source_caller_app_id(app_control_h app_control)
        }
 }
 
-void reply_to_sender_by_callback(const char *value, const char *type)
+void reply_to_sender_by_callback(const char *value, const char *type, const char *path[])
 {
        PRINTFUNC(DLOG_DEBUG, "");
 
@@ -495,6 +495,10 @@ void reply_to_sender_by_callback(const char *value, const char *type)
                if (type)
                        app_control_add_extra_data(app_control, "reply_type", type);
 
+               if (path != NULL) {
+                       app_control_add_extra_data_array(app_control, APP_CONTROL_DATA_PATH, path, 1);
+               }
+
                set_source_caller_app_id(app_control);
 
                ret = app_control_reply_to_launch_request(app_control, app_data->source_app_control, APP_CONTROL_RESULT_SUCCEEDED);
@@ -624,7 +628,7 @@ void _back_to_genlist_for_selector()
        }
        if (app_data->app_type == APP_TYPE_STT || app_data->app_type == APP_TYPE_EMOTICON || app_data->app_type == APP_TYPE_KEYBOARD){
                PRINTFUNC(DLOG_DEBUG, "launched as STT/EMOTICON/KEYBOARD mode, So exit here.");
-               reply_to_sender_by_callback(NULL, NULL);
+               reply_to_sender_by_callback(NULL, NULL, NULL);
                ui_app_exit();
        }
 }
@@ -1038,7 +1042,7 @@ bool _app_create(void* user_data)
        Evas_Object* conform = NULL;
        Evas_Object* bg = NULL;
        Evas_Object* window = NULL;
-       Eext_Circle_Surface *surface;
+       Eext_Circle_Surface *surface = NULL;
 
        if (!user_data) {
                return false;
index 965d36d..da6e71f 100755 (executable)
@@ -21,6 +21,7 @@
 #include "w-input-stt-ise.h"
 #include "w-input-stt-voice.h"
 #include "w-input-stt-engine.h"
+#include "voice-recorder.h"
 
 
 VoiceData *my_voicedata = NULL;
@@ -88,6 +89,8 @@ void  pause_voice(){
                 on_destroy(my_voicedata);
                 my_voicedata = NULL;
         }
+
+       destroy_voice_recorder();
  }
 
  int is_lang_supported_by_voice_input(const char *lang)
index 0aa4b21..595d417 100755 (executable)
@@ -32,6 +32,7 @@
 #include "w-input-stt-voice.h"
 #include "w-input-stt-engine.h"
 #include "w-input-stt-ise.h"
+#include "voice-recorder.h"
 
 using namespace std;
 
@@ -473,7 +474,12 @@ static void on_confirm_button_clicked_cb(void *data, Evas_Object *obj, void *eve
 
        PRINTFUNC(DLOG_DEBUG, "result_text = %s", result_text.c_str());
 
-       reply_to_sender_by_callback(result_text.c_str(), "voice");
+       char *filePath = NULL;
+       voice_recorder *vr = _voice_recorder_get_data();
+       if (!vr)
+               filePath = vr->file_path;
+       char *path[] = {filePath, };
+       reply_to_sender_by_callback(result_text.c_str(), "voice", (const char **)path);
        destroy_voice();
        powerUnlock();
        ui_app_exit();
@@ -779,6 +785,9 @@ static Eina_Bool _start_timer_cb(void* data)
                }
                voicedata->start_timer = NULL;
        }
+
+       start_voice_recorder();
+
        return ECORE_CALLBACK_CANCEL;
 }
 
@@ -920,6 +929,7 @@ char *__get_genlist_item_label(void *data, Evas_Object *obj, const char *part)
                                        strncpy(text, s, p-s);
                                } else {
                                        strncpy(text, s, strlen(s));
+                                       text[strlen(s)] = '\0';
                                }
                        } else {
                                strncpy(text, "", strlen(""));
@@ -1808,6 +1818,8 @@ int init_voice(Evas_Object *parent, const char *lang, VoiceData *r_voicedata)
                voicedata->textblock_timer = NULL;
        }
 
+       init_voice_recorder(NULL);
+
        return TRUE;
 }