+/*
+ * 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;
+ }
+}