1537620e6b958fa092cbb81b3b0a0710659f0e12
[profile/tv/apps/native/videoplayer.git] / src / view_player.cpp
1 /*
2  * Copyright (c) 2014 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 <Elementary.h>
18 #include <Eina.h>
19 #include <efl_extension.h>
20 #include <AppCommon.h>
21 #include <ViewMgr.h>
22 #include <BaseView.h>
23 #include <InputHandler.h>
24 #include <media_content.h>
25 #include <dbg.h>
26 #include "define.h"
27 #include "i18n.h"
28 #include "playermgr.h"
29 #include "timeout_handler.h"
30 #include "mediadata.h"
31 #include "control.h"
32 #include "volume.h"
33 #include "slider.h"
34 #include "view_player.h"
35
36 #define BTN_ID "BTN_ID"
37
38 #define TEXT_NODATE N_("----.--.--")
39
40 #define SOURCE_PATH_LEN 6
41 #define SOURCE_TV_PATH "/home/"
42 #define SOURCE_TV N_("TV")
43 #define SOURCE_USB N_("USB")
44
45 #define CONTROL_BTNS 6
46
47 static const char *_control_name[] = {
48         "prev",
49         "rew",
50         "playpause",
51         "ff",
52         "next",
53         "repeat",
54 };
55
56 typedef void (*btn_event_cb)(void *dt);
57
58 struct SPlayerView {
59         Evas_Object *win;
60         Evas_Object *base;
61         char *id;
62
63         CPlayer *player;
64         CVolume *volume;
65         CVideoController *control;
66         CVideoSlider *slider;
67         CMediaData *mediadata;
68
69         timeout_handler *timeout_handle;
70         bool bar_hidden;
71
72         Ecore_Timer *drawanim_timer;
73         int duration;
74         int repeat;
75         int position;
76 };
77
78 enum _control_btn {
79         E_PREV_BTN = 0,
80         E_REW_BTN,
81         E_PLAYPAUSE_BTN,
82         E_FF_BTN,
83         E_NEXT_BTN,
84         E_REPEAT_BTN,
85 };
86
87 enum _repeat_option {
88         E_REPEAT_ALL = 0,
89         E_REPEAT_ONE,
90         E_REPEAT_NONE
91 };
92
93 void CPlayerView::m_UpdateInfoBar(void)
94 {
95         const char *name;
96         const char *source;
97         const char *path;
98         char buf[32];
99         time_t video_time;
100         struct tm tm;
101
102         /* Title */
103         name = m->mediadata->GetName();
104         if (name)
105                 elm_object_part_text_set(m->base, PART_TITLETEXT, name);
106
107         /* Created Time */
108         video_time = m->mediadata->GetTime();
109
110         if (video_time > 0) {
111                 localtime_r(&video_time, &tm);
112                 strftime(buf, sizeof(buf), "%Y.%m.%d", &tm);
113         } else {
114                 snprintf(buf, sizeof(buf), "%s", _(TEXT_NODATE));
115         }
116
117         elm_object_part_text_set(m->base, PART_DATETEXT, buf);
118
119         /* Source */
120         /* FIXME: when usb path is decided, this logic should be changed */
121         path = m->mediadata->GetPath();
122         if (path) {
123                 if (!strncmp(path, SOURCE_TV_PATH, SOURCE_PATH_LEN))
124                         source = SOURCE_TV;
125                 else
126                         source = SOURCE_USB;
127                 elm_object_part_text_set(m->base, PART_SOURCETEXT, _(source));
128         }
129
130         /* Playlist Count */
131         snprintf(buf, sizeof(buf), "%d/%d",
132                         m->player->GetCurrent() + 1, m->player->GetTotal());
133         elm_object_part_text_set(m->base, PART_CURRENTTEXT, buf);
134
135         /* Resolution */
136         snprintf(buf, sizeof(buf), "%dx%d", m->mediadata->GetWidth(),
137                         m->mediadata->GetHeight());
138
139         m->duration = m->mediadata->GetDuration();
140         m->position = m->mediadata->GetPosition();
141
142         elm_object_part_text_set(m->base, PART_RESOLUTIONTEXT, buf);
143 }
144
145 bool CPlayerView::m_PlayerInit(void)
146 {
147         const char *path;
148         bool r;
149
150         r = m->player->Play();
151         if (r < 0)
152                 return false;
153
154         path = m->player->GetPath();
155
156         r = m->mediadata->Create(path);
157         if (r) {
158                 m_UpdateInfoBar();
159                 m->mediadata->Destroy();
160         }
161
162         m->slider->Reset(m->duration, m->position);
163         m->control->Signal(E_PLAYPAUSE_BTN, SIG_SET_PAUSE, "");
164
165         if (m->bar_hidden) {
166                 m_ShowBar();
167                 timeout_handler_reset(m->timeout_handle);
168         }
169
170         return true;
171 }
172
173 void CPlayerView::sm_EvtRewindBtn(void *dt)
174 {
175         SPlayerView *data;
176         bool r;
177
178         if (!dt)
179                 return;
180
181         data = (SPlayerView *)dt;
182
183         r = data->player->SetRew(data->duration);
184
185         if (r > 0) {
186                 data->slider->Pause();
187                 data->control->Signal(E_PLAYPAUSE_BTN, SIG_SET_PLAY, "");
188         }
189 }
190
191 void CPlayerView::sm_EvtForwardBtn(void *dt)
192 {
193         SPlayerView *data;
194         bool r;
195
196         if (!dt)
197                 return;
198
199         data = (SPlayerView *)dt;
200
201         r = data->player->SetFF(data->duration);
202
203         if (r > 0) {
204                 data->slider->Pause();
205                 data->control->Signal(E_PLAYPAUSE_BTN, SIG_SET_PLAY, "");
206         }
207 }
208
209 void CPlayerView::sm_EvtPrevBtn(void *dt)
210 {
211         SPlayerView *data;
212         update_action action;
213
214         if (!dt)
215                 return;
216
217         data = (SPlayerView *)dt;
218
219         data->player->StopFFRew();
220         data->player->Prev();
221
222         action = ACTION_INIT;
223         CViewMgr::GetInstance()->UpdateView(data->id, (void *)&action);
224 }
225
226 void CPlayerView::sm_EvtNextBtn(void *dt)
227 {
228         SPlayerView *data;
229         update_action action;
230
231         if (!dt)
232                 return;
233
234         data = (SPlayerView *)dt;
235
236         data->player->StopFFRew();
237         data->player->Next(true);
238
239         action = ACTION_INIT;
240         CViewMgr::GetInstance()->UpdateView(data->id, (void *)&action);
241 }
242
243 void CPlayerView::sm_EvtReapeatBtn(void *dt)
244 {
245         SPlayerView *data;
246
247         if (!dt)
248                 return;
249
250         data = (SPlayerView *)dt;
251
252         switch (data->repeat) {
253         case E_REPEAT_ALL:
254                 data->repeat = E_REPEAT_ONE;
255                 break;
256         case E_REPEAT_ONE:
257                 data->repeat = E_REPEAT_NONE;
258                 break;
259         case E_REPEAT_NONE:
260                 data->repeat = E_REPEAT_ALL;
261                 break;
262         default:
263                 break;
264         }
265 }
266
267 void CPlayerView::sm_EvtPlayBtn(void *dt)
268 {
269         SPlayerView *data;
270         player_state_e state;
271         bool r;
272
273         if (!dt)
274                 return;
275
276         data = (SPlayerView *)dt;
277
278         if (data->player->GetFFRew()) {
279                 data->player->StopFFRew();
280                 data->player->Resume();
281                 data->slider->Resume();
282                 return;
283         }
284
285         r = data->player->GetState(&state);
286         if (!r)
287                 return;
288
289         switch (state) {
290         case PLAYER_STATE_PLAYING:
291                 data->player->Pause();
292                 data->slider->Pause();
293                 break;
294
295         case PLAYER_STATE_PAUSED:
296                 data->player->Resume();
297                 data->slider->Resume();
298                 break;
299         default:
300                 break;
301         }
302 }
303
304 void CPlayerView::sm_EvtControlBtn(void *dt, const char *ev)
305 {
306         SPlayerView *data;
307         btn_event_cb cbs[] = {
308                 sm_EvtPrevBtn,
309                 sm_EvtRewindBtn,
310                 sm_EvtPlayBtn,
311                 sm_EvtForwardBtn,
312                 sm_EvtNextBtn,
313                 sm_EvtReapeatBtn,
314         };
315         int i;
316
317         if (!dt || !ev)
318                 return;
319
320         data = (SPlayerView *)dt;
321
322         for (i = 0; i < CONTROL_BTNS; i++) {
323                 if (!strcmp(_control_name[i], ev))
324                         cbs[i](data);
325         }
326 }
327
328 void CPlayerView::sm_CbPlayComplete(void *dt)
329 {
330         SPlayerView *data;
331         update_action action;
332         bool r;
333
334         if (!dt)
335                 return;
336
337         data = (SPlayerView *)dt;
338         r = EINA_TRUE;
339
340         if (data->repeat != E_REPEAT_ONE)
341                 r = data->player->Next(!data->repeat);
342
343         if (!r) {
344                 elm_exit();
345                 return;
346         }
347
348         action = ACTION_INIT;
349         CViewMgr::GetInstance()->UpdateView(data->id, (void *)&action);
350 }
351
352 void CPlayerView::sm_CbShowViewFinish(void *dt, Evas_Object *obj,
353                 const char *emission, const char *source)
354 {
355         SPlayerView *data;
356
357         if (!dt)
358                 return;
359
360         data = (SPlayerView *)dt;
361
362         data->control->Show();
363 }
364
365 void CPlayerView::m_ShowBar(void)
366 {
367         m->volume->Hide();
368
369         if (m->bar_hidden) {
370                 elm_object_signal_emit(m->base, SIG_SHOW_VIEW, "");
371                 m->bar_hidden = false;
372                 m->slider->Resume();
373         }
374 }
375
376 void CPlayerView::m_HideBar(void)
377 {
378         elm_object_signal_emit(m->base, SIG_HIDE_VIEW, "");
379         m->bar_hidden = true;
380
381         m->slider->Pause();
382         m->control->Hide();
383 }
384
385 void CPlayerView::sm_CbTimeoutEvent(void *dt, int type, void *ev)
386 {
387         SPlayerView *data;
388         update_action action;
389
390         if (!dt)
391                 return;
392
393         data = (SPlayerView *)dt;
394
395         action = ACTION_HIDE;
396         CViewMgr::GetInstance()->UpdateView(data->id, (void *)&action);
397 }
398
399 void CPlayerView::sm_EvtBack(void *dt, Evas_Object *obj, void *ev)
400 {
401         SPlayerView *data;
402
403         if (!dt)
404                 return;
405
406         data = (SPlayerView *)dt;
407
408         if (data->bar_hidden) {
409                 update_action action;
410
411                 action = ACTION_SHOW;
412                 CViewMgr::GetInstance()->UpdateView(data->id, (void *)&action);
413         } else {
414                 elm_exit();
415         }
416 }
417
418 void CPlayerView::sm_EvtVolume(SPlayerView *data, int val)
419 {
420         if (!data->bar_hidden) {
421                 update_action action;
422
423                 action = ACTION_HIDE;
424                 CViewMgr::GetInstance()->UpdateView(data->id, (void *)&action);
425         }
426
427         data->volume->Show((volume_val)val);
428 }
429
430 void CPlayerView::sm_CbEcoreEvent(void *dt, int type, void *ei)
431 {
432         SPlayerView *data;
433         bool update;
434
435         if (!dt)
436                 return;
437
438         data = (SPlayerView *)dt;
439         update = false;
440
441         if (type == ECORE_EVENT_KEY_UP) {
442                 Evas_Event_Key_Up *ev;
443
444                 ev = (Evas_Event_Key_Up *)ei;
445                 if (!ev)
446                         return;
447
448                 if (!strcmp(ev->keyname, KEY_VOLUMEUP) ||
449                                 !strcmp(ev->keyname, KEY_VOLUMEUP_REMOTE))
450                         sm_EvtVolume(data, E_VOLUME_UP);
451                 else if (!strcmp(ev->keyname, KEY_VOLUMEDOWN) ||
452                                 !strcmp(ev->keyname, KEY_VOLUMEDOWN_REMOTE))
453                         sm_EvtVolume(data, E_VOLUME_DOWN);
454                 else if (!strcmp(ev->keyname, KEY_MUTE) ||
455                                 !strcmp(ev->keyname, KEY_MUTE_REMOTE))
456                         sm_EvtVolume(data, E_VOLUME_MUTE);
457                 else
458                         update = true;
459         } else if (type == ECORE_EVENT_MOUSE_MOVE) {
460                 update = true;
461         }
462
463         if (update) {
464                 update_action action;
465
466                 action = ACTION_SHOW;
467                 CViewMgr::GetInstance()->UpdateView(data->id, (void *)&action);
468         }
469 }
470
471 bool CPlayerView::m_AddControls(void)
472 {
473         if (!m->control->Create(m->base, _control_name, CONTROL_BTNS))
474                 return false;
475
476         m->repeat = E_REPEAT_ALL;
477
478         m->control->AddHandler(sm_EvtControlBtn, m);
479
480         if (!m->slider->Create(m->base, m->player))
481                 return false;
482
483         if (!m->volume->Create(m->win))
484                 return false;
485
486         m->timeout_handle = timeout_handler_init(TIMEOUT_VIDEOPLAYER,
487                 sm_CbTimeoutEvent, m, sm_CbEcoreEvent, m);
488
489         eext_object_event_callback_add(m->base,
490                         EEXT_CALLBACK_BACK, sm_EvtBack, m);
491
492         if (!m->timeout_handle)
493                 return false;
494
495         return true;
496 }
497
498 Eina_Bool CPlayerView::sm_CbDrawAnimation(void *dt)
499 {
500         SPlayerView *data;
501
502         if (!dt)
503                 return ECORE_CALLBACK_CANCEL;
504
505         data = (SPlayerView *)dt;
506
507         elm_object_signal_emit(data->base, SIG_SHOW_VIEW, "");
508         data->control->Focus(E_PLAYPAUSE_BTN, EINA_TRUE);
509
510         data->drawanim_timer = NULL;
511
512         return ECORE_CALLBACK_CANCEL;
513 }
514
515 void CPlayerView::m_ControlInit(SPlayerParam *param)
516 {
517         bool r;
518
519         m->mediadata = new CMediaData;
520         if (!m->mediadata)
521                 _ERR("mediadata init failed");
522
523         if (param->id)
524                 m->id = strdup(param->id);
525
526         m->player = new CPlayer;
527         if (!m->player)
528                 _ERR("player init failed");
529
530         r = m->player->Create(m->win, param->filepath, param->playlist);
531         if (!r)
532                 _ERR("player creation failed");
533
534         m->control = new CVideoController;
535         if (!m->control)
536                 _ERR("control init failed");
537
538         m->volume = new CVolume;
539         if (!m->volume)
540                 _ERR("volume init failed");
541
542         m->slider = new CVideoSlider;
543         if (!m->slider)
544                 _ERR("slider init failed");
545 }
546
547 bool CPlayerView::m_UiInit(void)
548 {
549         Evas_Object *base;
550
551         base = elm_layout_add(m->win);
552         if (!base) {
553                 _ERR("failed to add layout");
554                 return false;
555         }
556
557         m->base = base;
558
559         if (!elm_layout_file_set(base, EDJEFILE, GRP_VIDEO_PLAYER)) {
560                 _ERR("failed to layout file set");
561                 return false;
562         }
563
564         if (!m_AddControls()) {
565                 _ERR("failed to add controls");
566                 return false;
567         }
568
569         evas_object_size_hint_weight_set(base,
570                         EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
571
572         elm_win_resize_object_add(m->win, base);
573
574         evas_object_show(base);
575
576         elm_object_focus_allow_set(base, EINA_FALSE);
577
578         return true;
579 }
580
581 bool CPlayerView::Create(void *data)
582 {
583         ASSERT(!m);
584         ASSERT(data);
585
586         Evas_Object *win;
587         bool r;
588
589         win = CViewMgr::GetInstance()->Window();
590         ASSERT(win);
591
592         m = new SPlayerView;
593         if (!m) {
594                 _ERR("alloc failed");
595                 return false;
596         }
597
598         m->win = win;
599
600         m_ControlInit((SPlayerParam *)data);
601
602         r = m_UiInit();
603         if (!r) {
604                 _ERR("failed to init UI");
605                 goto err;
606         }
607
608         if (!m_PlayerInit()) {
609                 _ERR("failed to play video");
610                 goto err;
611         }
612
613         m->player->SetCompletedCb(sm_CbPlayComplete, m);
614
615         elm_object_signal_callback_add(m->base, "show,view,finish", "",
616                         sm_CbShowViewFinish, m);
617
618         m->drawanim_timer = ecore_timer_add(0.8, sm_CbDrawAnimation, m);
619         if (!m->drawanim_timer) {
620                 _ERR("failed to add draw timer");
621                 goto err;
622         }
623
624         CBaseView::Create(NULL);
625
626         return true;
627
628 err:
629         m_Fini();
630         return false;
631 }
632
633 void CPlayerView::m_Fini(void)
634 {
635         ecore_timer_del(m->drawanim_timer);
636         m->drawanim_timer = NULL;
637
638         delete m->mediadata;
639         m->mediadata = NULL;
640
641         m->player->Destroy();
642         delete m->player;
643         m->player = NULL;
644
645         timeout_handler_fini(m->timeout_handle);
646         m->timeout_handle = NULL;
647
648         free(m->id);
649         m->id = NULL;
650
651         m->volume->Destroy();
652         delete m->volume;
653         m->volume = NULL;
654
655         m->control->Destroy();
656         delete m->control;
657         m->control = NULL;
658
659         m->slider->Destroy();
660         delete m->slider;
661         m->slider = NULL;
662
663         delete m;
664         m = NULL;
665 }
666
667 void CPlayerView::Destroy(void)
668 {
669         ASSERT(m);
670
671         CBaseView::Destroy();
672
673         m_Fini();
674 }
675
676 Evas_Object *CPlayerView::Base(void)
677 {
678         ASSERT(m);
679
680         return m->base;
681 }
682
683 void CPlayerView::t_OnShow(void)
684 {
685         ASSERT(m);
686
687         evas_object_show(m->base);
688 }
689
690 void CPlayerView::t_OnPause(void)
691 {
692         elm_exit();
693 }
694
695 void CPlayerView::t_OnUpdate(void *dt)
696 {
697         update_action *action;
698
699         if (!dt)
700                 return;
701
702         action = (update_action *)dt;
703
704         switch (*action) {
705         case ACTION_HIDE:
706                 m_HideBar();
707                 break;
708         case ACTION_SHOW:
709                 m_ShowBar();
710                 break;
711         case ACTION_RESUME:
712                 m->player->Resume();
713                 m->slider->Resume();
714                 m->control->Signal(E_PLAYPAUSE_BTN, SIG_SET_PAUSE, "");
715                 timeout_handler_reset(m->timeout_handle);
716                 break;
717         case ACTION_PAUSE:
718                 m->player->Pause();
719                 m->slider->Pause();
720                 m->control->Signal(E_PLAYPAUSE_BTN, SIG_SET_PLAY, "");
721                 timeout_handler_reset(m->timeout_handle);
722                 break;
723         case ACTION_INIT:
724                 m_PlayerInit();
725                 break;
726         }
727 }