a8d3c62590212e986066db2aa700be6f9b26bcb9
[platform/core/uifw/inputdelegator.git] / src / MicEffector.cpp
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <string.h>
18 #include <efl_assist.h>
19 #include "MicEffector.h"
20
21 using namespace is::ui;
22
23 /**
24  * animation configuration values
25  *
26  */
27 static size_t start_stop_anim_count = 28;
28 static size_t spectrum_count = SAMPLE_COUNT;
29 static float spectrum_posx = 40.0f;
30
31 static float timeout_s = 1.0f / 60.0f;
32
33 #define MATH_PI (3.141592)
34
35 double cubic_easy_in_out (double index, double start, double end, double duration)
36 {
37         index /= duration/2;
38         if (index < 1)
39                 return end/2*index*index*index + start;
40
41         index -= 2;
42         return end/2*(index*index*index + 2) + start;
43 }
44
45 double cubic_easy_in(double index, double start, double end, double duration)
46 {
47         index /= duration;
48         return end*index*index*index*index*index + start;
49 }
50
51 double cubic_easy_out(double index, double start, double end, double duration)
52 {
53         index /= duration;
54         index--;
55         return end*(index*index*index + 1) + start;
56 }
57
58
59 /**
60  * Constructor
61  *
62  * #1. Create ea_vector handle for drawing effect.
63  *     ( 1 canvas, 1 paint and 45 paths )
64  * #2. Drawing empty frame to avoid broken screen.
65  *
66  */
67
68 MicEffector::MicEffector(Evas_Object *canvas, Evas_Object *layout, IMicEffector& effect)
69         : drawcount(0)
70         , forcestop(false)
71         , started(false)
72         , timer(NULL)
73         , layout(layout)
74         , ieffect(effect)
75         , fake(false)
76 {
77 //      path = ea_vector_path_create();
78 //      paint = ea_vector_paint_create();
79 //      ea_vector_paint_set_style(paint, EA_VECTOR_PAINT_STYLE_STROKE);
80 //      ea_vector_paint_set_line_cap(paint, EA_VECTOR_PAINT_LINE_CAP_ROUND);
81 //      ea_vector_paint_set_line_join(paint, EA_VECTOR_PAINT_LINE_JOIN_ROUND);
82 //      ea_vector_paint_set_line_width(paint, 3.0);
83 //      ea_vector_paint_set_color(paint, 1.0f, 1.0f, 1.0f, 1.0f);
84
85 //      this->canvas = ea_vector_canvas_create(canvas);
86
87         DrawDummyFrame();
88 };
89
90
91
92 /**
93  * Destructor
94  *
95  * #1. Destroy ea_vector handle
96  *
97  */
98 MicEffector::~MicEffector()
99 {
100         if(timer)
101         {
102                 ecore_timer_del(timer);
103                 timer = NULL;
104         }
105
106 //      ea_vector_path_destroy(path);
107 //      ea_vector_paint_destroy(paint);
108 //      ea_vector_canvas_destroy(canvas);
109 }
110
111
112
113 /**
114  * Draw empty frame to remove or initiate screen
115  *
116  */
117 void MicEffector::DrawDummyFrame()
118 {
119 //      ea_vector_path_reset(path);
120 //      ea_vector_path_move_to(path, 0, 0);
121 //      ea_vector_path_line_to(path, 0, 0);
122 //      ea_vector_canvas_draw(canvas, path, paint);
123 }
124
125
126
127 /**
128  * Draw Que animation
129  *
130  * In case of start, it shows 2 more dots per one time.
131  * In case of stop, it remove 2 dots per one time.
132  *
133  * it works during 22 times.
134  *
135  */
136 void MicEffector::DrawQue(int idx, bool is_start)
137 {
138         float margin = spectrum_posx;
139         float posx = 0.0;
140
141         double speed = cubic_easy_out(idx + 1.0, 0.0, 23.0, 23);
142
143         unsigned int start = start_stop_anim_count - (int) speed;
144         unsigned int end = start_stop_anim_count + (int) speed;
145
146         double opacity;
147
148         if(is_start) {
149                 opacity = cubic_easy_out(idx, 0.0, 1.0, 26.0);
150         }
151         else {
152                 opacity = cubic_easy_out(idx, 0, 1.0, 26.0);
153         }
154
155 //      ea_vector_path_reset(path);
156
157         for(unsigned int i = start; i < end; i++)
158         {
159                 posx = margin + (i * 5);
160
161 //              ea_vector_path_move_to(path, posx, 37.0f);
162 //              ea_vector_path_line_to(path, posx, 38.0f);
163
164 //              ea_vector_paint_set_color(paint, 1.0f, 1.0f, 1.0f, opacity);
165         }
166
167 //      ea_vector_canvas_draw(canvas, path, paint);
168 }
169
170
171
172 float MicEffector::GetAmplifyValue(unsigned int idx)
173 {
174         float amplify = 0.0;
175
176         int max[SAMPLE_COUNT] = {
177                 /**
178                  * dot "A" (9)
179                  *
180                  */
181                 1, 1, 1, 1,
182
183
184                 1, 1, 1, 1, 1, 1, 1, 1, 1,
185
186                 /**
187                  * dot "B" (9)
188                  *
189                  */
190                 10, 8, 2, 3, 10, 11, 6, 12, 4,
191
192                 /**
193                  * dot "C" (15)
194                  *
195                  */
196                  3, 5, 9, 12, 11, 8, 14, 15, 13, 11, 12, 6, 8, 3, 2,
197
198                 /**
199                  * reverse dot "B" (9)
200                  *
201                  */
202                  4, 12, 6, 11, 10, 3, 2, 8, 10,
203
204                 /**
205                  * dot "A" (9)
206                  *
207                  */
208                 1, 1, 1, 1, 1, 1, 1, 1, 1,
209
210                 1, 1, 1, 1
211         };
212
213         amplify = (float) max[idx] / 10.0f * 1.9f;
214
215         return amplify;
216 }
217
218 /**
219  * Draw effect animation
220  *
221  * It draws volume effect. during 5 times.
222  * Center of effect area, it applies amplified value.
223  *
224  */
225 void MicEffector::DrawWave(unsigned int idx, int amount, int prev_amount, double opacity,bool is_lastcmd)
226 {
227         float ratio = GetAmplifyValue(idx);
228
229         float am = ((float) amount) * ratio;
230         float pam = ((float) prev_amount) * ratio;
231         float cnt = (float) drawcount;
232
233         float posx = spectrum_posx;
234
235         float height = pam > am?
236                 pam - cubic_easy_in_out(cnt + 1.0, am, pam, 7):
237                 cubic_easy_in_out(cnt + 1.0, pam, am, 7);
238
239         posx += idx * 5;
240
241 //      ea_vector_path_move_to(path, posx, (37.0f - (height / 2.0)));
242 //      ea_vector_path_line_to(path, posx, (38.0f + (height / 2.0)));
243
244         if(is_lastcmd) {
245 //              ea_vector_paint_set_color(paint, 0.1451f, 0.204f, 0.255f, opacity);//RGB = 37:52:65
246         }
247         else {
248 //              ea_vector_paint_set_color(paint, 1.0f, 1.0f, 1.0f, opacity);//RGB: 255 255 255
249         }
250 }
251
252
253
254 /**
255  * Effect Start
256  *
257  */
258 void MicEffector::Start()
259 {
260         if(timer) {
261                 ecore_timer_del(timer);
262                 timer = NULL;
263         }
264
265         drawcount = 0;
266
267         prev.clear();
268         current.clear();
269
270         for(size_t i = 0; i < spectrum_count; i++)
271         {
272                 prev.push_back(0);
273                 current.push_back(0);
274         }
275
276         Listening();
277
278         /**
279          * Que animation
280          *
281          */
282         timer = ecore_timer_add ( timeout_s,
283                                 [](void *data)->Eina_Bool
284                                 {
285                                         MicEffector *effector = static_cast<MicEffector*>(data);
286
287                                         effector->DrawQue(effector->drawcount);
288
289                                         if(effector->drawcount < (int) start_stop_anim_count)
290                                         {
291                                                 effector->drawcount += 2;
292                                                 return ECORE_CALLBACK_RENEW;
293                                         }
294                                         else
295                                         {
296                                                 for(unsigned int i = 0; i < spectrum_count; i++)
297                                                         effector->DrawWave(i, 0, 0);
298
299 //                                              ea_vector_canvas_draw(effector->canvas, effector->path, effector->paint);
300
301                                                 effector->drawcount = 0;
302                                                 effector->timer = NULL;
303                                                 effector->VolumeCheck();
304                                                 effector->Effect();
305                                                 return ECORE_CALLBACK_CANCEL;
306                                         }
307                                 },
308                                 this);
309 }
310
311
312
313 /**
314  * Volume effect
315  *
316  */
317 void MicEffector::Effect(bool fake)
318 {
319         /**
320          * Volume effect animation
321          *
322          */
323         if ( timer ) {
324                         ecore_timer_del(timer);
325                         timer = NULL;
326         }
327
328         timer = ecore_timer_add ( timeout_s,
329                                 [](void *data)->Eina_Bool
330                                 {
331
332                                         MicEffector *effector = static_cast<MicEffector *>(data);
333
334                                         bool is_empty_prev = effector->prev.empty();
335
336
337 //                                      ea_vector_path_reset(effector->path);
338
339                                         for(unsigned int i = 0; i < effector->current.size(); i++)
340                                         {
341                                                 if(is_empty_prev)
342                                                         effector->DrawWave(i, effector->current.at(i), 0);
343                                                 else
344                                                         effector->DrawWave(i, effector->current.at(i), effector->prev.at(i));
345                                         }
346 //                                      ea_vector_canvas_draw(effector->canvas, effector->path, effector->paint);
347
348                                         if(effector->drawcount < 7)     {
349                                                 effector->drawcount++;
350                                         }
351                                         else {
352                                                 effector->drawcount = 0;
353                                                 effector->VolumeCheck(effector->fake);
354                                         }
355
356                                         return ECORE_CALLBACK_RENEW;
357                                 }, this);
358 }
359
360
361
362 /**
363  * Stop volume animation effect
364  *
365  */
366 void MicEffector::Stop(bool forced)
367 {
368         if(timer)
369         {
370                 ecore_timer_del(timer);
371                 timer = NULL;
372         }
373
374         if(!started)
375         {
376                 Idle();
377                 return;
378         }
379
380         forcestop = forced;
381
382         timer = ecore_timer_add(timeout_s,
383                 [](void *data)->Eina_Bool
384                 {
385                         MicEffector *effector = static_cast<MicEffector*>(data);
386
387                         effector->DrawQue(start_stop_anim_count - effector->drawcount, false);
388
389                         if(effector->drawcount < (int) start_stop_anim_count)
390                         {
391                                 effector->drawcount += 2;
392                                 return ECORE_CALLBACK_RENEW;
393                         }
394                         else
395                         {
396                                 if(!effector->forcestop) {
397                                         effector->Processing();
398                                 }
399                                 else {
400                                         effector->Idle();
401                                 }
402
403                                 effector->forcestop = false;
404                                 effector->drawcount = 0;
405                                 effector->timer = NULL;
406                                 return ECORE_CALLBACK_CANCEL;
407                         }
408
409                 }, this);
410 }
411
412
413
414 /**
415  * Signal. Refresh volume effect
416  *
417  */
418 void MicEffector::VolumeCheck(bool fake)
419 {
420         std::vector<int> volumes;
421
422         this->fake = fake;
423
424         if(!fake) {
425                 volumes = ieffect.GetVolume();
426         }
427         else {
428                 for(unsigned int i = 0; i < spectrum_count; i++) {
429                         volumes.push_back(rand() % 2);
430                 }
431         }
432
433         prev.clear();
434         prev.assign(current.begin(), current.end());
435
436         current.clear();
437         current.assign(volumes.begin(), volumes.end());
438 }
439
440
441
442 /**
443  * Signal. Listening effect
444  *
445  */
446 void MicEffector::Listening()
447 {
448         started = true;
449
450         elm_object_signal_emit(layout, "elm,state,eq,show", "eq");
451         elm_object_signal_emit(layout, "elm,state,listening", "elm");
452 }
453
454
455
456 /**
457  * Signal. Processing effect
458  *
459  */
460 void MicEffector::Processing()
461 {
462         started = false;
463
464         elm_object_signal_emit(layout, "elm,state,eq,hide", "eq");
465         elm_object_signal_emit(layout, "elm,state,processing", "elm");
466
467         ieffect.ProcessingAnimationStart();
468 }
469
470
471
472 /**
473  * Signal. Idle effect
474  *
475  */
476 void MicEffector::Idle()
477 {
478         const char *text;
479         const char *state;
480         double val;
481
482         started = false;
483
484         elm_object_signal_emit(layout, "elm,state,eq,hide", "eq");
485
486         text = elm_object_part_text_get(layout, "elm.text");
487         state = edje_object_part_state_get(elm_layout_edje_get(layout), "guide_text_block", &val);
488
489         if ((text && strlen(text) > 0) && (state && !strcmp(state, "bottom")))
490                 elm_object_signal_emit(layout, "elm,state,init_message", "elm");
491         else
492                 elm_object_signal_emit(layout, "elm,state,init", "elm");
493
494         ieffect.ProcessingAnimationStop();
495 }
496