diff options
author | Eugene Kurzberg <i.kurtsberg@samsung.com> | 2017-11-03 11:45:50 +0200 |
---|---|---|
committer | Eugene Kurzberg <i.kurtsberg@samsung.com> | 2017-11-09 13:17:02 +0200 |
commit | e7bb1c7b0214fe84054032bf960b2a37032f552b (patch) | |
tree | 3bce657f956a2c8c7bf7a9bae81c64782d7ea86b | |
parent | 7ab92c6beffb68a96e0f6530692180286c9e63cb (diff) | |
download | voice-control-e7bb1c7b0214fe84054032bf960b2a37032f552b.tar.gz voice-control-e7bb1c7b0214fe84054032bf960b2a37032f552b.tar.bz2 voice-control-e7bb1c7b0214fe84054032bf960b2a37032f552b.zip |
TizenRefApp-9585 Implement wave animation
Change-Id: I1892c22c6b5a6af37dd9296a5a84a4da32b2ad7d
Signed-off-by: Eugene Kurzberg <i.kurtsberg@samsung.com>
-rw-r--r-- | voice-app/inc/Voice/FloatingView.h | 4 | ||||
-rw-r--r-- | voice-app/inc/Voice/WaveformControl.h | 61 | ||||
-rw-r--r-- | voice-app/res/voice/edje/VoiceLayout.h | 2 | ||||
-rw-r--r-- | voice-app/src/Voice/FeedbackView.cpp | 4 | ||||
-rw-r--r-- | voice-app/src/Voice/FloatingView.cpp | 13 | ||||
-rw-r--r-- | voice-app/src/Voice/WaveformControl.cpp | 143 |
6 files changed, 216 insertions, 11 deletions
diff --git a/voice-app/inc/Voice/FloatingView.h b/voice-app/inc/Voice/FloatingView.h index f72b80a..ce6340c 100644 --- a/voice-app/inc/Voice/FloatingView.h +++ b/voice-app/inc/Voice/FloatingView.h @@ -21,6 +21,8 @@ namespace Voice { + class WaveformControl; + /** * @brief Floating view. */ @@ -98,7 +100,7 @@ namespace Voice Evas_Object *createSimulationButton(Evas_Object *parent); bool m_IsFullScreen; - Evas_Object *m_Waveform; + WaveformControl *m_Waveform; BgPressCallback m_OnBgPressed; ButtonPressCallback m_OnButtonPressed; diff --git a/voice-app/inc/Voice/WaveformControl.h b/voice-app/inc/Voice/WaveformControl.h new file mode 100644 index 0000000..4dcb530 --- /dev/null +++ b/voice-app/inc/Voice/WaveformControl.h @@ -0,0 +1,61 @@ +/* + * Copyright 2017 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * 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_WAVEFORM_CONTROL_H +#define VOICE_WAVEFORM_CONTROL_H + +#include "Ui/Control.h" +#include <cairo.h> + +namespace Voice +{ + /** + * @brief Provides waveform animation. + */ + class WaveformControl : public Ui::Control + { + public: + WaveformControl(); + virtual ~WaveformControl() override; + + private: + virtual Evas_Object *onCreate(Evas_Object *parent) override; + + double calcWave(double angle, double phase); + void drawFrame(); + void drawWave(double phase); + void onResize(Evas *e, Evas_Object *obj, void *eventInfo); + Eina_Bool onAnimate(); + + Evas_Object *m_Image; + int m_Width; + int m_Height; + Ecore_Animator *m_Animator; + + cairo_t *m_Cairo; + cairo_surface_t *m_Surface; + + struct WaveComponent + { + double freq; + double ampl; + double param; + double paramDelta; + } m_WaveComponents[4]; + }; +} + +#endif /* VOICE_WAVEFORM_CONTROL_H */ diff --git a/voice-app/res/voice/edje/VoiceLayout.h b/voice-app/res/voice/edje/VoiceLayout.h index 531eb70..289793e 100644 --- a/voice-app/res/voice/edje/VoiceLayout.h +++ b/voice-app/res/voice/edje/VoiceLayout.h @@ -51,4 +51,6 @@ #define SIGNAL_PROCESS_SHOW "state,process,visible" +#define SCREEN_WH 360 + #endif /* VOICE_LAYOUT_H */ diff --git a/voice-app/src/Voice/FeedbackView.cpp b/voice-app/src/Voice/FeedbackView.cpp index d359eaa..2fb3884 100644 --- a/voice-app/src/Voice/FeedbackView.cpp +++ b/voice-app/src/Voice/FeedbackView.cpp @@ -24,8 +24,6 @@ using namespace Voice; -#define WINDOW_WH Ui::getScaledValue(360) - FeedbackView::FeedbackView(Model::Tts &tts) : m_Tts(tts), m_Window(nullptr), m_IsWindowAutoHide(true), m_IsFeedbackAutoHide(true), m_IsFeedbackVisible(false), @@ -132,7 +130,7 @@ Evas_Object *FeedbackView::onCreate(Evas_Object *parent) m_Window = window->getEvasObject(); elm_win_alpha_set(m_Window, EINA_TRUE); elm_win_floating_mode_set(m_Window, EINA_TRUE); - evas_object_resize(m_Window, WINDOW_WH, WINDOW_WH); + evas_object_resize(m_Window, Ui::getScaledValue(SCREEN_WH), Ui::getScaledValue(SCREEN_WH)); } return layout; diff --git a/voice-app/src/Voice/FloatingView.cpp b/voice-app/src/Voice/FloatingView.cpp index cf61706..62b1ae3 100644 --- a/voice-app/src/Voice/FloatingView.cpp +++ b/voice-app/src/Voice/FloatingView.cpp @@ -15,6 +15,7 @@ */ #include "Voice/FloatingView.h" +#include "Voice/WaveformControl.h" #include "App/Path.h" #include "Ui/Scale.h" @@ -27,7 +28,6 @@ using namespace Ui; using namespace Voice; -#define SCREEN_WH Ui::getScaledValue(360) #define BUTTON_DRAG_BOUNDARY Ui::getScaledValue(24) #define SIMULATION_KEY "simulation" @@ -107,10 +107,9 @@ Evas_Object *FloatingView::onCreate(Evas_Object *parent) elm_layout_signal_callback_add(layout, SIGNAL_CLOSED, "*", makeCallback(&FloatingView::onClosed), this); - m_Waveform = elm_image_add(layout); - elm_image_file_set(m_Waveform, App::getResourcePath(PATH_FEEDBACK_WAVE).c_str(), nullptr); - elm_image_animated_set(m_Waveform, EINA_TRUE); - elm_object_part_content_set(layout, PART_WAVEFORM, m_Waveform); + m_Waveform = new WaveformControl(); + m_Waveform->create(layout); + elm_object_part_content_set(layout, PART_WAVEFORM, m_Waveform->getEvasObject()); elm_object_part_content_set(layout, PART_SIMULATION_BUTTON, createSimulationButton(layout)); @@ -130,7 +129,7 @@ void FloatingView::shrinkWindow() void FloatingView::expandWindow() { - evas_object_geometry_set(getWindow(), 0, 0, SCREEN_WH, SCREEN_WH); + evas_object_geometry_set(getWindow(), 0, 0, Ui::getScaledValue(SCREEN_WH), Ui::getScaledValue(SCREEN_WH)); elm_layout_signal_emit(getEvasObject(), SIGNAL_FULL_SCREEN, ""); elm_layout_signal_emit(getEvasObject(), SIGNAL_BG_ENABLE, ""); } @@ -152,7 +151,7 @@ void FloatingView::onButtonDrag(Evas_Object *obj, const char *emission, const ch x += winX; y += winY; - static int radius = SCREEN_WH / 2; + static int radius = Ui::getScaledValue(SCREEN_WH / 2); static int boundary = pow(radius - BUTTON_DRAG_BOUNDARY, 2); if (pow(abs(radius - x), 2) + pow(abs(radius - y), 2) > boundary) { return; diff --git a/voice-app/src/Voice/WaveformControl.cpp b/voice-app/src/Voice/WaveformControl.cpp new file mode 100644 index 0000000..b1d680c --- /dev/null +++ b/voice-app/src/Voice/WaveformControl.cpp @@ -0,0 +1,143 @@ +/* + * Copyright 2017 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * 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 "Voice/WaveformControl.h" +#include "Ui/Scale.h" +#include "Utils/Callback.h" + +#include "VoiceLayout.h" + +#define WAVE_OFFSET 15 +#define WAVE_MAX_AMPL 10 +#define WAVE_WIDTH 2.0 +#define WAVE_COLOR 0.15, 0.47, 0.56, 1.0 + +using namespace Voice; + +WaveformControl::WaveformControl() + : m_Image(nullptr), m_Width(0), m_Height(0), m_Animator(nullptr), + m_Cairo(nullptr), m_Surface(nullptr), + m_WaveComponents{ + { 7, 0.2, 0.0, 0.0 }, + { 8, 0.3, 0.0, 0.1 }, + { 11, 0.25, 0.0, 0.1 }, + { 14, 0.25, 0.0, 0.0 } } +{ +} + +WaveformControl::~WaveformControl() +{ + ecore_animator_del(m_Animator); + cairo_destroy(m_Cairo); + cairo_surface_destroy(m_Surface); +} + +Evas_Object *WaveformControl::onCreate(Evas_Object *parent) +{ + Evas_Object *layout = elm_layout_add(parent); + elm_layout_theme_set(layout, "layout", "application", "default"); + + m_Image = evas_object_image_add(evas_object_evas_get(layout)); + evas_object_image_colorspace_set(m_Image, EVAS_COLORSPACE_ARGB8888); + evas_object_event_callback_add(m_Image, EVAS_CALLBACK_RESIZE, + makeCallback(&WaveformControl::onResize), this); + elm_object_content_set(layout, m_Image); + + /* FIXME: Creating animator right away causes crash for unknown reason */ + ecore_job_add([](void *data) { + auto control = (WaveformControl *) data; + control->m_Animator = ecore_animator_add(makeCallback(&WaveformControl::onAnimate), control); + }, this); + return layout; +} + +double WaveformControl::calcWave(double angle, double phase) +{ + double wave = 0.0; + for (auto &&component : m_WaveComponents) { + wave += sin(component.param + angle * component.freq + phase) * component.ampl; + } + return wave; +} + +void WaveformControl::drawFrame() +{ + cairo_save(m_Cairo); + cairo_set_operator(m_Cairo, CAIRO_OPERATOR_CLEAR); + cairo_paint(m_Cairo); + cairo_restore(m_Cairo); + + drawWave(0.0); + drawWave(M_PI_2); + + for (auto &&component : m_WaveComponents) { + component.param += component.paramDelta; + if (component.param > 2 * M_PI) { + component.param -= 2 * M_PI; + } + } + + evas_object_image_data_set(m_Image, cairo_image_surface_get_data(m_Surface)); + evas_object_image_data_update_add(m_Image, 0, 0, m_Width, m_Height); +} + +void WaveformControl::drawWave(double phase) +{ + static int screenSize = Ui::getScaledValue(SCREEN_WH); + + double scale = (double) m_Width / screenSize; + cairo_set_line_width(m_Cairo, WAVE_WIDTH * scale); + + for (int i = 0; i <= 360; i += 2) { + double angle = i * (M_PI / 180); + double offset = calcWave(angle, phase) * WAVE_MAX_AMPL - WAVE_OFFSET; + double radius = m_Width / 2.0 + offset * scale; + + double x = m_Width / 2.0 + radius * cos(angle); + double y = m_Height / 2.0 - radius * sin(angle); + cairo_line_to(m_Cairo, x, y); + } + cairo_close_path(m_Cairo); + cairo_stroke(m_Cairo); +} + +void WaveformControl::onResize(Evas *e, Evas_Object *obj, void *eventInfo) +{ + evas_object_geometry_get(m_Image, nullptr, nullptr, &m_Width, &m_Height); + if (!m_Width || !m_Height) { + return; + } + + evas_object_image_size_set(m_Image, m_Width, m_Height); + evas_object_image_fill_set(m_Image, 0, 0, m_Width, m_Height); + + if (m_Surface) { + cairo_destroy(m_Cairo); + cairo_surface_destroy(m_Surface); + } + + m_Surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, m_Width, m_Height); + m_Cairo = cairo_create(m_Surface); + cairo_set_source_rgba(m_Cairo, WAVE_COLOR); + + drawFrame(); +} + +Eina_Bool WaveformControl::onAnimate() +{ + drawFrame(); + return ECORE_CALLBACK_RENEW; +} |