fix exception handling
[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 (!strncmp(path, SOURCE_TV_PATH, SOURCE_PATH_LEN))
123                 source = SOURCE_TV;
124         else
125                 source = SOURCE_USB;
126         elm_object_part_text_set(m->base, PART_SOURCETEXT, _(source));
127
128         /* Playlist Count */
129         snprintf(buf, sizeof(buf), "%d/%d",
130                         m->player->GetCurrent() + 1, m->player->GetTotal());
131         elm_object_part_text_set(m->base, PART_CURRENTTEXT, buf);
132
133         /* Resolution */
134         snprintf(buf, sizeof(buf), "%dx%d", m->mediadata->GetWidth(),
135                         m->mediadata->GetHeight());
136
137         m->duration = m->mediadata->GetDuration();
138         m->position = m->mediadata->GetPosition();
139
140         elm_object_part_text_set(m->base, PART_RESOLUTIONTEXT, buf);
141 }
142
143 bool CPlayerView::m_PlayerInit(void)
144 {
145         const char *path;
146         bool r;
147
148         r = m->player->Play();
149
150         path = m->player->GetPath();
151
152         r = m->mediadata->Create(path);
153         if (r) {
154                 m_UpdateInfoBar();
155                 m->mediadata->Destroy();
156         }
157
158         m->slider->Reset(m->duration, m->position);
159         m->control->Signal(E_PLAYPAUSE_BTN, SIG_SET_PAUSE, "");
160
161         if (m->bar_hidden) {
162                 m_ShowBar();
163                 timeout_handler_reset(m->timeout_handle);
164         }
165
166         return r;
167 }
168
169 void CPlayerView::sm_EvtRewindBtn(void *dt)
170 {
171         SPlayerView *data;
172         bool r;
173
174         if (!dt)
175                 return;
176
177         data = (SPlayerView *)dt;
178
179         r = data->player->SetRew(data->duration);
180
181         if (r > 0) {
182                 data->slider->Pause();
183                 data->control->Signal(E_PLAYPAUSE_BTN, SIG_SET_PLAY, "");
184         }
185 }
186
187 void CPlayerView::sm_EvtForwardBtn(void *dt)
188 {
189         SPlayerView *data;
190         bool r;
191
192         if (!dt)
193                 return;
194
195         data = (SPlayerView *)dt;
196
197         r = data->player->SetFF(data->duration);
198
199         if (r > 0) {
200                 data->slider->Pause();
201                 data->control->Signal(E_PLAYPAUSE_BTN, SIG_SET_PLAY, "");
202         }
203 }
204
205 void CPlayerView::sm_EvtPrevBtn(void *dt)
206 {
207         SPlayerView *data;
208         update_action action;
209
210         if (!dt)
211                 return;
212
213         data = (SPlayerView *)dt;
214
215         data->player->StopFFRew();
216         data->player->Prev();
217
218         action = ACTION_INIT;
219         CViewMgr::GetInstance()->UpdateView(data->id, (void *)&action);
220 }
221
222 void CPlayerView::sm_EvtNextBtn(void *dt)
223 {
224         SPlayerView *data;
225         update_action action;
226
227         if (!dt)
228                 return;
229
230         data = (SPlayerView *)dt;
231
232         data->player->StopFFRew();
233         data->player->Next(true);
234
235         action = ACTION_INIT;
236         CViewMgr::GetInstance()->UpdateView(data->id, (void *)&action);
237 }
238
239 void CPlayerView::sm_EvtReapeatBtn(void *dt)
240 {
241         SPlayerView *data;
242
243         if (!dt)
244                 return;
245
246         data = (SPlayerView *)dt;
247
248         switch (data->repeat) {
249         case E_REPEAT_ALL:
250                 data->repeat = E_REPEAT_ONE;
251                 break;
252         case E_REPEAT_ONE:
253                 data->repeat = E_REPEAT_NONE;
254                 break;
255         case E_REPEAT_NONE:
256                 data->repeat = E_REPEAT_ALL;
257                 break;
258         default:
259                 break;
260         }
261 }
262
263 void CPlayerView::sm_EvtPlayBtn(void *dt)
264 {
265         SPlayerView *data;
266         player_state_e state;
267         bool r;
268
269         if (!dt)
270                 return;
271
272         data = (SPlayerView *)dt;
273
274         if (data->player->GetFFRew()) {
275                 data->player->StopFFRew();
276                 data->player->Resume();
277                 data->slider->Resume();
278                 return;
279         }
280
281         r = data->player->GetState(&state);
282         if (!r)
283                 return;
284
285         switch (state) {
286         case PLAYER_STATE_PLAYING:
287                 data->player->Pause();
288                 data->slider->Pause();
289                 break;
290
291         case PLAYER_STATE_PAUSED:
292                 data->player->Resume();
293                 data->slider->Resume();
294                 break;
295         default:
296                 break;
297         }
298 }
299
300 void CPlayerView::sm_EvtControlBtn(void *dt, const char *ev)
301 {
302         SPlayerView *data;
303         btn_event_cb cbs[] = {
304                 sm_EvtPrevBtn,
305                 sm_EvtRewindBtn,
306                 sm_EvtPlayBtn,
307                 sm_EvtForwardBtn,
308                 sm_EvtNextBtn,
309                 sm_EvtReapeatBtn,
310         };
311         int i;
312
313         if (!dt || !ev)
314                 return;
315
316         data = (SPlayerView *)dt;
317
318         for (i = 0; i < CONTROL_BTNS; i++) {
319                 if (!strcmp(_control_name[i], ev))
320                         cbs[i](data);
321         }
322 }
323
324 void CPlayerView::sm_CbPlayComplete(void *dt)
325 {
326         SPlayerView *data;
327         update_action action;
328         bool r;
329
330         if (!dt)
331                 return;
332
333         data = (SPlayerView *)dt;
334         r = EINA_TRUE;
335
336         if (data->repeat != E_REPEAT_ONE)
337                 r = data->player->Next(!data->repeat);
338
339         if (!r) {
340                 elm_exit();
341                 return;
342         }
343
344         action = ACTION_INIT;
345         CViewMgr::GetInstance()->UpdateView(data->id, (void *)&action);
346 }
347
348 void CPlayerView::sm_CbShowViewFinish(void *dt, Evas_Object *obj,
349                 const char *emission, const char *source)
350 {
351         SPlayerView *data;
352
353         if (!dt)
354                 return;
355
356         data = (SPlayerView *)dt;
357
358         data->control->Show();
359 }
360
361 void CPlayerView::m_ShowBar(void)
362 {
363         m->volume->Hide();
364
365         if (m->bar_hidden) {
366                 elm_object_signal_emit(m->base, SIG_SHOW_VIEW, "");
367                 m->bar_hidden = false;
368                 m->slider->Resume();
369         }
370 }
371
372 void CPlayerView::m_HideBar(void)
373 {
374         elm_object_signal_emit(m->base, SIG_HIDE_VIEW, "");
375         m->bar_hidden = true;
376
377         m->slider->Pause();
378         m->control->Hide();
379 }
380
381 void CPlayerView::sm_CbTimeoutEvent(void *dt, int type, void *ev)
382 {
383         SPlayerView *data;
384         update_action action;
385
386         if (!dt)
387                 return;
388
389         data = (SPlayerView *)dt;
390
391         action = ACTION_HIDE;
392         CViewMgr::GetInstance()->UpdateView(data->id, (void *)&action);
393 }
394
395 void CPlayerView::sm_EvtBack(void *dt, Evas_Object *obj, void *ev)
396 {
397         SPlayerView *data;
398
399         if (!dt)
400                 return;
401
402         data = (SPlayerView *)dt;
403
404         if (data->bar_hidden) {
405                 update_action action;
406
407                 action = ACTION_SHOW;
408                 CViewMgr::GetInstance()->UpdateView(data->id, (void *)&action);
409         } else {
410                 elm_exit();
411         }
412 }
413
414 void CPlayerView::sm_EvtVolume(SPlayerView *data, int val)
415 {
416         if (!data->bar_hidden) {
417                 update_action action;
418
419                 action = ACTION_HIDE;
420                 CViewMgr::GetInstance()->UpdateView(data->id, (void *)&action);
421         }
422
423         data->volume->Show((volume_val)val);
424 }
425
426 void CPlayerView::sm_CbEcoreEvent(void *dt, int type, void *ei)
427 {
428         SPlayerView *data;
429         bool update;
430
431         if (!dt)
432                 return;
433
434         data = (SPlayerView *)dt;
435         update = false;
436
437         if (type == ECORE_EVENT_KEY_UP) {
438                 Evas_Event_Key_Up *ev;
439
440                 ev = (Evas_Event_Key_Up *)ei;
441                 if (!ev)
442                         return;
443
444                 if (!strcmp(ev->keyname, KEY_VOLUMEUP) ||
445                                 !strcmp(ev->keyname, KEY_VOLUMEUP_REMOTE))
446                         sm_EvtVolume(data, E_VOLUME_UP);
447                 else if (!strcmp(ev->keyname, KEY_VOLUMEDOWN) ||
448                                 !strcmp(ev->keyname, KEY_VOLUMEDOWN_REMOTE))
449                         sm_EvtVolume(data, E_VOLUME_DOWN);
450                 else if (!strcmp(ev->keyname, KEY_MUTE) ||
451                                 !strcmp(ev->keyname, KEY_MUTE_REMOTE))
452                         sm_EvtVolume(data, E_VOLUME_MUTE);
453                 else
454                         update = true;
455         } else if (type == ECORE_EVENT_MOUSE_MOVE) {
456                 update = true;
457         }
458
459         if (update) {
460                 update_action action;
461
462                 action = ACTION_SHOW;
463                 CViewMgr::GetInstance()->UpdateView(data->id, (void *)&action);
464         }
465 }
466
467 bool CPlayerView::m_AddControls(void)
468 {
469         if (!m->control->Create(m->base, _control_name, CONTROL_BTNS))
470                 return false;
471
472         m->repeat = E_REPEAT_ALL;
473
474         m->control->AddHandler(sm_EvtControlBtn, m);
475
476         if (!m->slider->Create(m->base, m->player)) {
477                 m->control->Destroy();
478                 return false;
479         }
480
481         if (!m->volume->Create(m->win)) {
482                 m->control->Destroy();
483                 m->slider->Destroy();
484                 return false;
485         }
486
487         m->timeout_handle = timeout_handler_init(TIMEOUT_VIDEOPLAYER,
488                 sm_CbTimeoutEvent, m, sm_CbEcoreEvent, m);
489         if (!m->timeout_handle) {
490                 m->control->Destroy();
491                 m->slider->Destroy();
492                 m->volume->Destroy();
493                 return false;
494         }
495
496         eext_object_event_callback_add(m->base,
497                         EEXT_CALLBACK_BACK, sm_EvtBack, m);
498
499         return true;
500 }
501
502 Eina_Bool CPlayerView::sm_CbDrawAnimation(void *dt)
503 {
504         SPlayerView *data;
505
506         if (!dt)
507                 return ECORE_CALLBACK_CANCEL;
508
509         data = (SPlayerView *)dt;
510
511         elm_object_signal_emit(data->base, SIG_SHOW_VIEW, "");
512         data->control->Focus(E_PLAYPAUSE_BTN, EINA_TRUE);
513
514         data->drawanim_timer = NULL;
515
516         return ECORE_CALLBACK_CANCEL;
517 }
518
519 bool CPlayerView::m_ControlInit(SPlayerParam *param)
520 {
521         m->mediadata = new CMediaData;
522         if (!m->mediadata) {
523                 _ERR("mediadata init failed");
524                 return false;
525         }
526
527         if (param->id)
528                 m->id = strdup(param->id);
529
530         m->player = new CPlayer;
531         if (!m->player) {
532                 _ERR("player init failed");
533                 return false;
534         }
535
536         m->control = new CVideoController;
537         if (!m->control) {
538                 _ERR("control init failed");
539                 return false;
540         }
541
542         m->volume = new CVolume;
543         if (!m->volume) {
544                 _ERR("volume init failed");
545                 return false;
546         }
547
548         m->slider = new CVideoSlider;
549         if (!m->slider) {
550                 _ERR("slider init failed");
551                 return false;
552         }
553
554         return true;
555 }
556
557 bool CPlayerView::m_UiInit(void)
558 {
559         Evas_Object *base;
560
561         base = elm_layout_add(m->win);
562         if (!base) {
563                 _ERR("failed to add layout");
564                 return false;
565         }
566
567         m->base = base;
568
569         if (!elm_layout_file_set(base, EDJEFILE, GRP_VIDEO_PLAYER)) {
570                 _ERR("failed to layout file set");
571                 return false;
572         }
573
574         if (!m_AddControls()) {
575                 _ERR("failed to add controls");
576                 return false;
577         }
578
579         evas_object_size_hint_weight_set(base,
580                         EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
581
582         elm_win_resize_object_add(m->win, base);
583
584         evas_object_show(base);
585
586         elm_object_focus_allow_set(base, EINA_FALSE);
587
588         return true;
589 }
590
591 bool CPlayerView::Create(void *data)
592 {
593         ASSERT(!m);
594         ASSERT(data);
595
596         Evas_Object *win;
597         SPlayerParam *param;
598         bool r;
599
600         win = CViewMgr::GetInstance()->Window();
601         ASSERT(win);
602
603         m = new SPlayerView;
604         if (!m) {
605                 _ERR("alloc failed");
606                 return false;
607         }
608
609         m->win = win;
610         m->player = NULL;
611         m->volume = NULL;
612         m->control = NULL;
613         m->slider = NULL;
614         m->mediadata = NULL;
615         m->timeout_handle = NULL;
616         m->drawanim_timer = NULL;
617
618         param = (SPlayerParam *)data;
619
620         r = m_ControlInit(param);
621         if (!r) {
622                 _ERR("failed to init Controls");
623                 goto err;
624         }
625
626         r = m_UiInit();
627         if (!r) {
628                 _ERR("failed to init UI");
629                 goto err_control;
630         }
631
632         r = m->player->Create(m->win, param->filepath, param->playlist);
633         if (!r) {
634                 _ERR("player creation failed");
635                 goto err_control;
636         }
637
638         r = m_PlayerInit();
639         if (!r) {
640                 _ERR("failed to play video");
641                 goto err_player;
642         }
643
644         m->player->SetCompletedCb(sm_CbPlayComplete, m);
645
646         elm_object_signal_callback_add(m->base, "show,view,finish", "",
647                         sm_CbShowViewFinish, m);
648
649         m->drawanim_timer = ecore_timer_add(0.8, sm_CbDrawAnimation, m);
650         if (!m->drawanim_timer) {
651                 _ERR("failed to add draw timer");
652                 goto err;
653         }
654
655         CBaseView::Create(NULL);
656
657         return true;
658
659 err_player:
660         m->player->Destroy();
661 err_control:
662         m->control->Destroy();
663         m->slider->Destroy();
664         m->volume->Destroy();
665 err:
666         m_Fini();
667         return false;
668 }
669
670 void CPlayerView::m_Fini(void)
671 {
672         ecore_timer_del(m->drawanim_timer);
673
674         delete m->mediadata;
675
676         timeout_handler_fini(m->timeout_handle);
677
678         free(m->id);
679
680         delete m->player;
681         delete m->volume;
682         delete m->control;
683         delete m->slider;
684
685         delete m;
686         m = NULL;
687 }
688
689 void CPlayerView::Destroy(void)
690 {
691         ASSERT(m);
692
693         CBaseView::Destroy();
694
695         m->player->Destroy();
696         m->volume->Destroy();
697         m->control->Destroy();
698         m->slider->Destroy();
699
700         m_Fini();
701 }
702
703 Evas_Object *CPlayerView::Base(void)
704 {
705         ASSERT(m);
706
707         return m->base;
708 }
709
710 void CPlayerView::t_OnShow(void)
711 {
712         ASSERT(m);
713
714         evas_object_show(m->base);
715 }
716
717 void CPlayerView::t_OnPause(void)
718 {
719         elm_exit();
720 }
721
722 void CPlayerView::t_OnUpdate(void *dt)
723 {
724         update_action *action;
725
726         if (!dt)
727                 return;
728
729         action = (update_action *)dt;
730
731         switch (*action) {
732         case ACTION_HIDE:
733                 m_HideBar();
734                 break;
735         case ACTION_SHOW:
736                 m_ShowBar();
737                 break;
738         case ACTION_RESUME:
739                 m->player->Resume();
740                 m->slider->Resume();
741                 m->control->Signal(E_PLAYPAUSE_BTN, SIG_SET_PAUSE, "");
742                 timeout_handler_reset(m->timeout_handle);
743                 break;
744         case ACTION_PAUSE:
745                 m->player->Pause();
746                 m->slider->Pause();
747                 m->control->Signal(E_PLAYPAUSE_BTN, SIG_SET_PLAY, "");
748                 timeout_handler_reset(m->timeout_handle);
749                 break;
750         case ACTION_INIT:
751                 m_PlayerInit();
752                 break;
753         }
754 }