From: sungwook79.park Date: Wed, 5 Jul 2017 04:52:31 +0000 (+0900) Subject: Support to delegate various MIME types to caller as like voice recording X-Git-Tag: accepted/tizen/4.0/unified/20170816.012804~4 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Finputdelegator.git;a=commitdiff_plain;h=4cc380f070db66e4c9593863ce582c1e97d1303b Support to delegate various MIME types to caller as like voice recording Change-Id: I2194134a1b599b79c5e05a6c4164fc9d94c619ad Signed-off-by: sungwook79.park --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 95b2d21..a2e1690 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 index 0000000..b07d9ef --- /dev/null +++ b/inc/voice-recorder.h @@ -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 + +#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__ diff --git a/inc/w-input-selector.h b/inc/w-input-selector.h index 985ee98..92662e1 100755 --- a/inc/w-input-selector.h +++ b/inc/w-input-selector.h @@ -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); diff --git a/org.tizen.inputdelegator.xml b/org.tizen.inputdelegator.xml index 7b43160..41f8f2e 100755 --- a/org.tizen.inputdelegator.xml +++ b/org.tizen.inputdelegator.xml @@ -14,5 +14,7 @@ http://tizen.org/privilege/display http://tizen.org/privilege/recorder http://tizen.org/privilege/appmanager.launch + http://tizen.org/privilege/content.write + http://tizen.org/privilege/mediastorage diff --git a/packaging/org.tizen.inputdelegator.spec b/packaging/org.tizen.inputdelegator.spec index 389a9c4..8063566 100755 --- a/packaging/org.tizen.inputdelegator.spec +++ b/packaging/org.tizen.inputdelegator.spec @@ -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 index 0000000..ef2c017 --- /dev/null +++ b/src/voice-recorder.cpp @@ -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 +#include +#include +#include +#include +#include +#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; + } +} diff --git a/src/w-input-emoticon.cpp b/src/w-input-emoticon.cpp index 0ead5fb..4bd585b 100755 --- a/src/w-input-emoticon.cpp +++ b/src/w-input-emoticon.cpp @@ -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) diff --git a/src/w-input-keyboard.cpp b/src/w-input-keyboard.cpp index 869cfb5..9257a12 100755 --- a/src/w-input-keyboard.cpp +++ b/src/w-input-keyboard.cpp @@ -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(); } diff --git a/src/w-input-selector.cpp b/src/w-input-selector.cpp index d6feeec..ed22ea2 100755 --- a/src/w-input-selector.cpp +++ b/src/w-input-selector.cpp @@ -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 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; diff --git a/src/w-input-stt-ise.cpp b/src/w-input-stt-ise.cpp index 965d36d..da6e71f 100755 --- a/src/w-input-stt-ise.cpp +++ b/src/w-input-stt-ise.cpp @@ -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) diff --git a/src/w-input-stt-voice.cpp b/src/w-input-stt-voice.cpp index 0aa4b21..595d417 100755 --- a/src/w-input-stt-voice.cpp +++ b/src/w-input-stt-voice.cpp @@ -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; }