summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugene Kurzberg <i.kurtsberg@samsung.com>2017-11-03 11:45:50 +0200
committerEugene Kurzberg <i.kurtsberg@samsung.com>2017-11-09 13:17:02 +0200
commite7bb1c7b0214fe84054032bf960b2a37032f552b (patch)
tree3bce657f956a2c8c7bf7a9bae81c64782d7ea86b
parent7ab92c6beffb68a96e0f6530692180286c9e63cb (diff)
downloadvoice-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.h4
-rw-r--r--voice-app/inc/Voice/WaveformControl.h61
-rw-r--r--voice-app/res/voice/edje/VoiceLayout.h2
-rw-r--r--voice-app/src/Voice/FeedbackView.cpp4
-rw-r--r--voice-app/src/Voice/FloatingView.cpp13
-rw-r--r--voice-app/src/Voice/WaveformControl.cpp143
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;
+}