b18aab2f883fafca4be1a6451e1225964634cf03
[profile/tv/apps/native/videoplayer.git] / src / playermgr.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 <AppCommon.h>
20 #include <dbg.h>
21 #include "define.h"
22 #include "playermgr.h"
23
24 #define RATE_MAX 5.0
25 #define RATE_MIN -5.0
26
27 #define SPEED_MIN 0
28 #define SPEED_MAX 3
29
30 #define TIME_INTERVAL 1.0
31
32 static int _speed[] = {
33         0,
34         2000,
35         4000,
36         8000
37 };
38
39 struct SPlayerData {
40         player_h player;
41         Evas_Object *win;
42         Eina_List *media_list;
43
44         int display_mode;
45         int audio_effect;
46         int current;
47         int total;
48         int rew_speed;
49         int ff_speed;
50         int duration;
51
52         Ecore_Timer *ffrew_timer;
53 };
54
55 static void _destroy_list(Eina_List *list)
56 {
57         char *buf;
58         void *o;
59
60         EINA_LIST_FREE(list, o) {
61                 buf = (char *)o;
62                 free(buf);
63         }
64 }
65
66 static Eina_List *_create_list(const char *playlist)
67 {
68         Eina_List *list = NULL;
69         FILE *fp;
70         char buf[1024];
71
72         if (!playlist)
73                 return NULL;
74
75         fp = fopen(playlist, "r");
76         if (!fp)
77                 return NULL;
78
79         while (fscanf(fp, "%s\n", buf) != EOF)
80                 list = eina_list_append(list, strdup(buf));
81
82         fclose(fp);
83
84         return list;
85 }
86
87 static int _get_current(Eina_List *list, const char *path)
88 {
89         Eina_List *l;
90         const char *filepath;
91         void *o;
92         int cur;
93
94         if (!list || !path)
95                 return 0;
96
97         cur = 0;
98
99         EINA_LIST_FOREACH(list, l, o) {
100                 filepath = (const char *)o;
101                 if (!strcmp(filepath, path))
102                         break;
103                 cur++;
104         }
105
106         return cur;
107 }
108
109 bool CPlayer::Create(Evas_Object *win, const char *path, const char *playlist)
110 {
111         ASSERT(!m);
112
113         m = new SPlayerData;
114         if (!m) {
115                 _ERR("allocation fail");
116                 return false;
117         }
118
119         m->win = win;
120         m->display_mode = E_FULL_SCREEN;
121         m->audio_effect = 0;
122         m->rew_speed = 0;
123         m->ff_speed = 0;
124
125         m->media_list = _create_list(playlist);
126         if (!m->media_list) {
127                 _ERR("play list is null");
128                 delete m;
129                 return false;
130         }
131
132         m->current = _get_current(m->media_list, path);
133         m->total = eina_list_count(m->media_list);
134
135         if (player_create(&m->player) != PLAYER_ERROR_NONE) {
136                 _ERR("PLAYER CREATION ERROR");
137                 delete m;
138                 return false;
139         }
140
141         return true;
142 }
143
144 void CPlayer::Destroy(void)
145 {
146         ASSERT(m);
147
148         ecore_timer_del(m->ffrew_timer);
149
150         if (m->media_list)
151                 _destroy_list(m->media_list);
152
153         if (m->player) {
154                 player_pause(m->player);
155                 player_stop(m->player);
156                 player_unprepare(m->player);
157                 player_destroy(m->player);
158         }
159
160         delete m;
161         m = NULL;
162 }
163
164 bool CPlayer::m_Play(const char *path)
165 {
166         ASSERT(m);
167         ASSERT(m->player);
168
169         int r;
170
171         if (player_set_uri(m->player, path) != PLAYER_ERROR_NONE) {
172                 _ERR("PLAYER SET URI ERROR");
173                 return false;
174         }
175
176         r = player_set_display(m->player, PLAYER_DISPLAY_TYPE_OVERLAY,
177                         GET_DISPLAY(m->win));
178         if (r != PLAYER_ERROR_NONE) {
179                 _ERR("SETTING DISPLAY ERROR: %d", r);
180                 return false;
181         }
182
183         SetDisplayMode(m->display_mode);
184         SetAudioEffect(m->audio_effect);
185
186         r = player_prepare(m->player);
187         if (r != PLAYER_ERROR_NONE) {
188                 _ERR("PLAYER PREPARE ERROR: %d", r);
189                 return false;
190         }
191
192         r = player_start(m->player);
193         if (r != PLAYER_ERROR_NONE) {
194                 _ERR("PLAYER START ERROR: %d", r);
195                 return false;
196         }
197
198         return true;
199 }
200
201 bool CPlayer::Stop(void)
202 {
203         ASSERT(m);
204         ASSERT(m->player);
205
206         player_pause(m->player);
207         player_stop(m->player);
208         player_unprepare(m->player);
209
210         return true;
211 }
212
213 bool CPlayer::Play(void)
214 {
215         ASSERT(m);
216
217         const char *path;
218         bool r;
219
220         r = Stop();
221         if (!r)
222                 return r;
223
224         path = GetPath();
225         if (!path) {
226                 _ERR("video path is NULL");
227                 return false;
228         }
229
230         r = m_Play(path);
231
232         return r;
233 }
234
235 bool CPlayer::Prev(void)
236 {
237         ASSERT(m);
238
239         if (m->current == 0)
240                 m->current = m->total - 1;
241         else
242                 m->current--;
243
244         return true;
245 }
246
247 bool CPlayer::Next(bool repeat)
248 {
249         ASSERT(m);
250
251         if (m->current == m->total - 1) {
252                 m->current = 0;
253
254                 if (!repeat)
255                         return false;
256         } else {
257                 m->current++;
258         }
259
260         return true;
261 }
262
263 const char *CPlayer::GetPath(void)
264 {
265         ASSERT(m);
266
267         const char *path;
268
269         if (!m->media_list) {
270                 _ERR("invalid parameter");
271                 return NULL;
272         }
273
274         path = (const char *)eina_list_nth(m->media_list, m->current);
275
276         return path;
277 }
278
279 bool CPlayer::Pause(void)
280 {
281         player_state_e state;
282
283         ASSERT(m);
284         ASSERT(m->player);
285
286         GetState(&state);
287         if (state == PLAYER_STATE_PAUSED)
288                 return true;
289
290         if (player_pause(m->player) != PLAYER_ERROR_NONE) {
291                 _ERR("Player pause error");
292                 return false;
293         }
294
295         return true;
296 }
297
298 bool CPlayer::Resume(void)
299 {
300         player_state_e state;
301
302         ASSERT(m);
303         ASSERT(m->player);
304
305         GetState(&state);
306         if (state == PLAYER_STATE_PLAYING)
307                 return true;
308
309         if (player_start(m->player) != PLAYER_ERROR_NONE) {
310                 _ERR("Player resume error");
311                 return false;
312         }
313
314         return true;
315 }
316
317 bool CPlayer::GetState(player_state_e *state)
318 {
319         ASSERT(m);
320         ASSERT(m->player);
321
322         int r;
323
324         r = player_get_state(m->player, state);
325         if (r != PLAYER_ERROR_NONE) {
326                 _ERR("Player get state error");
327                 return false;
328         }
329
330         return true;
331 }
332
333 bool CPlayer::GetPosition(int *ms)
334 {
335         ASSERT(m);
336         ASSERT(m->player);
337
338         int r;
339
340         r = player_get_play_position(m->player, ms);
341         if (r != PLAYER_ERROR_NONE) {
342                 _ERR("Player get position error");
343                 return false;
344         }
345
346         return true;
347 }
348
349 bool CPlayer::SetPosition(int ms, player_seek_completed_cb cb, void *data)
350 {
351         ASSERT(m);
352         ASSERT(m->player);
353
354         int r;
355
356         r = player_set_play_position(m->player, ms, false, cb, data);
357         if (r != PLAYER_ERROR_NONE) {
358                 _ERR("Player set position error");
359                 return false;
360         }
361
362         return true;
363 }
364
365 bool CPlayer::SetAudioEffect(int value)
366 {
367         ASSERT(m);
368
369         /* audio_effect not supported, just return 0 */
370         m->audio_effect = value;
371
372         return true;
373 }
374
375 bool CPlayer::SetDisplayMode(int value)
376 {
377         ASSERT(m);
378         ASSERT(m->player);
379
380         int r;
381         player_display_mode_e mode;
382
383         /* display mode not supported, set to full screen forced */
384         mode = PLAYER_DISPLAY_MODE_FULL_SCREEN;
385
386         r = player_set_display_mode(m->player, mode);
387         if (r != PLAYER_ERROR_NONE) {
388                 _ERR("Player display mode set error");
389                 return false;
390         }
391
392         m->display_mode = value;
393
394         return true;
395 }
396
397 bool CPlayer::SetCompletedCb(player_completed_cb cb, void *data)
398 {
399         ASSERT(m);
400         ASSERT(m->player);
401
402         int r;
403
404         r = player_set_completed_cb(m->player, cb, data);
405         if (r != PLAYER_ERROR_NONE) {
406                 _ERR("Player set completed cb error");
407                 return false;
408         }
409
410         return true;
411 }
412
413 int CPlayer::GetTotal(void)
414 {
415         ASSERT(m);
416
417         return m->total;
418 }
419
420 int CPlayer::GetCurrent(void)
421 {
422         ASSERT(m);
423
424         return m->current;
425 }
426
427 Eina_Bool CPlayer::sm_CbFFRew(void *dt)
428 {
429         CPlayer *p;
430         SPlayerData *m;
431         int pos;
432
433         if (!dt)
434                 return ECORE_CALLBACK_CANCEL;
435
436         p = (CPlayer *)dt;
437         m = p->m;
438
439         ASSERT(m);
440
441         if (!m->player)
442                 return ECORE_CALLBACK_CANCEL;
443
444         p->GetPosition(&pos);
445
446         if (m->ff_speed) {
447                 pos = pos + _speed[m->ff_speed];
448                 if (pos > m->duration)
449                         pos = m->duration;
450         } else if (m->rew_speed) {
451                 pos = pos - _speed[m->rew_speed];
452                 if (pos < 0)
453                         pos = 0;
454         }
455
456         p->SetPosition(pos, NULL, NULL);
457
458         if (m->rew_speed && pos <= 0) {
459                 m->rew_speed = SPEED_MIN;
460                 return ECORE_CALLBACK_CANCEL;
461         }
462
463         if (m->ff_speed && pos >= m->duration) {
464                 m->ff_speed = SPEED_MIN;
465                 return ECORE_CALLBACK_CANCEL;
466         }
467
468         if (ecore_timer_interval_get(m->ffrew_timer) != TIME_INTERVAL)
469                 ecore_timer_interval_set(m->ffrew_timer, TIME_INTERVAL);
470
471         return ECORE_CALLBACK_RENEW;
472 }
473
474 void CPlayer::m_StartFFRew(void)
475 {
476         Pause();
477
478         if (!m->ffrew_timer) {
479                 m->ffrew_timer = ecore_timer_add(0.0, sm_CbFFRew, this);
480         } else {
481                 ecore_timer_interval_set(m->ffrew_timer, 0.0);
482                 ecore_timer_reset(m->ffrew_timer);
483         }
484 }
485
486 bool CPlayer::SetFF(int duration)
487 {
488         ASSERT(m);
489
490         bool r;
491
492         m->duration = duration;
493         m->rew_speed = SPEED_MIN;
494
495         if (m->ff_speed == SPEED_MAX)
496                 return false;
497
498         r = false;
499         if (m->ff_speed == SPEED_MIN) {
500                 m_StartFFRew();
501                 r = true;
502         }
503
504         m->ff_speed++;
505
506         return r;
507 }
508
509 bool CPlayer::SetRew(int duration)
510 {
511         ASSERT(m);
512
513         bool r;
514
515         m->duration = duration;
516         m->ff_speed = SPEED_MIN;
517
518         if (m->rew_speed == SPEED_MAX)
519                 return false;
520
521         r = false;
522         if (m->rew_speed == SPEED_MIN) {
523                 m_StartFFRew();
524                 r = true;
525         }
526
527         m->rew_speed++;
528
529         return r;
530 }
531
532 bool CPlayer::GetFFRew(void)
533 {
534         ASSERT(m);
535
536         if (m->ff_speed || m->rew_speed)
537                 return true;
538
539         return false;
540 }
541
542 void CPlayer::StopFFRew(void)
543 {
544         ASSERT(m);
545
546         m->ff_speed = SPEED_MIN;
547         m->rew_speed = SPEED_MIN;
548
549         ecore_timer_del(m->ffrew_timer);
550         m->ffrew_timer = NULL;
551 }