handle exists too - and it gets written!
[profile/ivi/emotion.git] / src / modules / emotion_xine.c
1 #include "Emotion.h"
2 #include "emotion_private.h"
3 #include "emotion_xine.h"
4
5 /* module api */
6 static unsigned char  em_init                    (Evas_Object *obj, void **emotion_video, Emotion_Module_Options *opt);
7 static int            em_shutdown                (void *ef);
8 static unsigned char  em_file_open               (const char *file, Evas_Object *obj, void *ef);
9 static void           em_file_close              (void *ef);
10 static void           em_play                    (void *ef, double pos);
11 static void           em_stop                    (void *ef);
12 static void           em_size_get                (void *ef, int *w, int *h);
13 static void           em_pos_set                 (void *ef, double pos);
14 static void           em_vis_set                 (void *ef, Emotion_Vis vis);
15 static double         em_len_get                 (void *ef);
16 static int            em_fps_num_get             (void *ef);
17 static int            em_fps_den_get             (void *ef);
18 static double         em_fps_get                 (void *ef);
19 static double         em_pos_get                 (void *ef);
20 static Emotion_Vis    em_vis_get                 (void *ef);
21 static double         em_ratio_get               (void *ef);
22 static int            em_seekable                (void *ef);
23 static void           em_frame_done              (void *ef);
24 static Emotion_Format em_format_get              (void *ef);
25 static void           em_video_data_size_get     (void *ef, int *w, int *h);
26 static int            em_yuv_rows_get            (void *ef, int w, int h, unsigned char **yrows, unsigned char **urows, unsigned char **vrows);
27 static int            em_bgra_data_get           (void *ef, unsigned char **bgra_data);
28 static void           em_event_feed              (void *ef, int event);
29 static void           em_event_mouse_button_feed (void *ef, int button, int x, int y);
30 static void           em_event_mouse_move_feed   (void *ef, int x, int y);
31 static int            em_video_channel_count     (void *ef);
32 static void           em_video_channel_set       (void *ef, int channel);
33 static int            em_video_channel_get       (void *ef);
34 static const char    *em_video_channel_name_get  (void *ef, int channel);
35 static void           em_video_channel_mute_set  (void *ef, int mute);
36 static int            em_video_channel_mute_get  (void *ef);
37 static int            em_audio_channel_count     (void *ef);
38 static void           em_audio_channel_set       (void *ef, int channel);
39 static int            em_audio_channel_get       (void *ef);
40 static const char    *em_audio_channel_name_get  (void *ef, int channel);
41 static void           em_audio_channel_mute_set  (void *ef, int mute);
42 static int            em_audio_channel_mute_get  (void *ef);
43 static void           em_audio_channel_volume_set(void *ef, double vol);
44 static double         em_audio_channel_volume_get(void *ef);
45 static int            em_spu_channel_count       (void *ef);
46 static void           em_spu_channel_set         (void *ef, int channel);
47 static int            em_spu_channel_get         (void *ef);
48 static const char    *em_spu_channel_name_get    (void *ef, int channel);
49 static void           em_spu_channel_mute_set    (void *ef, int mute);
50 static int            em_spu_channel_mute_get    (void *ef);
51 static int            em_chapter_count           (void *ef);
52 static void           em_chapter_set             (void *ef, int chapter);
53 static int            em_chapter_get             (void *ef);
54 static const char    *em_chapter_name_get        (void *ef, int chapter);
55 static void           em_speed_set               (void *ef, double speed);
56 static double         em_speed_get               (void *ef);
57 static int            em_eject                   (void *ef);
58 static const char    *em_meta_get                (void *ef, int meta);
59
60 /* internal util calls */
61 static void *_em_slave         (void *par);
62 static void  _em_slave_event   (void *data, int type, void *arg);
63 static int   _em_fd_active     (void *data, Ecore_Fd_Handler *fdh);
64 static void  _em_event         (void *data, const xine_event_t *event);
65 static void  _em_module_event  (void *data, int type);
66 static int   _em_fd_ev_active  (void *data, Ecore_Fd_Handler *fdh);
67 //static int   _em_timer         (void *data);
68 static void *_em_get_pos_len_th(void *par);
69 static void  _em_get_pos_len   (Emotion_Xine_Video *ev);
70
71 extern plugin_info_t emotion_xine_plugin_info[];
72
73 /* this is a slave controller thread for the xine module - libxine loves
74  * to deadlock, internally stall and otherwise have unpredictable behavior
75  * if we use the main process thread for many things - so a lot will be
76  * farmed off to this slave. its job is to handle opening, closing, file
77  * opening, recoder init etc. and all sorts of things can that often block.
78  * anything this thread needs to return, it will return via the event pipe.
79  */
80 static void *
81 _em_slave(void *par)
82 {
83    Emotion_Xine_Video *ev;
84    void *buf[2];
85    int len;
86    
87    ev = (Emotion_Xine_Video *)par;
88    while ((len = read(ev->fd_slave_read, buf, sizeof(buf))) > 0)
89      {
90         if (len == sizeof(buf))
91           {
92              Emotion_Xine_Event *eev;
93
94              ev = buf[0];
95              eev = buf[1];
96              switch (eev->mtype)
97                {
98                 case 0: /* noop */
99                   break;
100                 case 1: /* init */
101                     {
102                        ev->decoder = xine_new();
103                        xine_init(ev->decoder);
104                        xine_register_plugins(ev->decoder, emotion_xine_plugin_info);
105                        if (1)
106                          {
107                             xine_cfg_entry_t cf;
108                             if (xine_config_lookup_entry(ev->decoder, "input.dvd_use_readahead", &cf))
109                               {
110                                  cf.num_value = 1; // 0 or 1
111                                  xine_config_update_entry(ev->decoder, &cf);
112                               }
113                          }
114                        printf("OPEN VIDEO PLUGIN...\n");
115                        if (!ev->opt_no_video)
116                          ev->video = xine_open_video_driver(ev->decoder, "emotion",
117                                                             XINE_VISUAL_TYPE_NONE, ev);
118                        printf("RESULT: xine_open_video_driver() = %p\n", ev->video);
119                        // Let xine autodetect the best audio output driver
120                        if (!ev->opt_no_audio)
121                          ev->audio = xine_open_audio_driver(ev->decoder, NULL, ev);
122                        //   ev->audio = xine_open_audio_driver(ev->decoder, "oss", ev);
123                        // dont use alsa - alsa has oss emulation.   
124                        //   ev->audio = xine_open_audio_driver(ev->decoder, "alsa", ev);
125                        //   ev->audio = xine_open_audio_driver(ev->decoder, "arts", ev);
126                        //   ev->audio = xine_open_audio_driver(ev->decoder, "esd", ev);
127                        ev->stream = xine_stream_new(ev->decoder, ev->audio, ev->video);
128                        ev->queue = xine_event_new_queue(ev->stream);
129                        xine_event_create_listener_thread(ev->queue, _em_event, ev);
130                        ev->opening = 0;
131                        ev->play_ok = 1;
132                        _em_module_event(ev, 1); /* event - open done */
133                     }
134                   break;
135                 case 3: /* shutdown */
136                     {
137                        _em_module_event(ev, 3);
138                        printf("EX shutdown stop\n");
139                        xine_stop(ev->stream);
140                        //   pthread_mutex_lock(&(ev->get_pos_len_mutex));
141                        if (!ev->get_pos_thread_deleted)
142                          {
143                             printf("closing get_pos thread, %p\n", ev);
144                             pthread_mutex_lock(&(ev->get_pos_len_mutex));
145                             pthread_cond_broadcast(&(ev->get_pos_len_cond));
146                             pthread_mutex_unlock(&(ev->get_pos_len_mutex));
147                             while (ev->get_poslen);
148                          }
149                        printf("EX dispose %p\n", ev);
150                        xine_dispose(ev->stream);
151                        printf("EX dispose evq %p\n", ev);
152                        xine_event_dispose_queue(ev->queue);
153                        printf("EX close video drv %p\n", ev);
154                        if (ev->video) xine_close_video_driver(ev->decoder, ev->video);
155                        printf("EX wait for vo to go\n");
156                        while (ev->have_vo);
157                        printf("EX vo gone\n");
158                        printf("EX close audio drv %p\n", ev);
159                        if (ev->audio) xine_close_audio_driver(ev->decoder, ev->audio);
160                        printf("EX xine exit %p\n", ev);
161                        xine_exit(ev->decoder);
162                        printf("EX DONE %p\n", ev);
163                        close(ev->fd_write);
164                        close(ev->fd_read);
165                        close(ev->fd_ev_write);
166                        close(ev->fd_ev_read);
167                        close(ev->fd_slave_write);
168                        close(ev->fd_slave_read);
169                        ev->closing = 0;
170                        if (eev->xine_event) free(eev->xine_event);
171                        free(eev);
172                        free(ev);
173                        return NULL;
174                     }
175                   break;
176                 case 2: /* file open */
177                     {
178                        int pos_stream = 0;
179                        int pos_time = 0;
180                        int length_time = 0;
181                        uint32_t v;
182                        char *file;
183                        
184                        file = eev->xine_event;
185                        printf("OPN STREAM %s\n", file);
186                        if (xine_open(ev->stream, file))
187                          {
188                             if (xine_get_pos_length(ev->stream, &pos_stream, &pos_time, &length_time))
189                               {
190                                  if (length_time == 0)
191                                    {
192                                       ev->pos = (double)pos_stream / 65535;
193                                       ev->len = 1.0;
194                                       ev->no_time = 1;
195                                    }
196                                  else
197                                    {
198                                       ev->pos = 0.0;
199                                       ev->len = (double)length_time / 1000.0;
200                                    }
201                               }
202                             else
203                               {
204                                  ev->pos = 0.0;
205                                  ev->len = 1.0;
206                               }
207                             v = xine_get_stream_info(ev->stream, XINE_STREAM_INFO_FRAME_DURATION);
208                             if (v > 0) ev->fps = 90000.0 / (double)v;
209                             v = xine_get_stream_info(ev->stream, XINE_STREAM_INFO_VIDEO_WIDTH);
210                             ev->w = v;
211                             v = xine_get_stream_info(ev->stream, XINE_STREAM_INFO_VIDEO_HEIGHT);
212                             ev->h = v;
213                             v = xine_get_stream_info(ev->stream, XINE_STREAM_INFO_VIDEO_RATIO);
214                             ev->ratio = (double)v / 10000.0;
215                             ev->just_loaded = 1;
216                             ev->get_poslen = 0;
217                          }
218                        _em_module_event(ev, 2); /* event - open done */
219                     }
220                   break;
221                 case 11: /* file close */
222                     {
223                        printf("EX done %p\n", ev);
224                        em_frame_done(ev); 
225                        printf("EX stop %p\n", ev);
226                        xine_stop(ev->stream);
227                        printf("EX close %p\n", ev);
228                        xine_close(ev->stream);
229                        printf("EX close done %p\n", ev);
230                        _em_module_event(ev, 11);
231                     }
232                   break;
233                 case 4: /* play */
234                     {
235                        double pos;
236                        int pos_stream, pos_time, length_time;
237                        
238                        pos = *((double *)eev->xine_event);
239                        if ((xine_get_param(ev->stream, XINE_PARAM_SPEED) == XINE_SPEED_PAUSE) &&
240                            (pos == ev->pos) &&
241                            (!ev->just_loaded))
242                          {
243                             xine_set_param(ev->stream, XINE_PARAM_SPEED, XINE_SPEED_NORMAL);
244                          }
245                        else
246                          {
247                             if (ev->no_time)
248                               xine_play(ev->stream, pos * 65535, 0);
249                             else
250                               xine_play(ev->stream, 0, pos * 1000);
251                          }
252                        ev->just_loaded = 0;
253                        
254                        if (xine_get_pos_length(ev->stream,
255                                                &pos_stream,
256                                                &pos_time,
257                                                &length_time))
258                          {
259                             if (length_time == 0)
260                               {
261                                  ev->pos = (double)pos_stream / 65535;
262                                  ev->len = 1.0;
263                                  ev->no_time = 1;
264                               }
265                             else
266                               {
267                                  ev->pos = (double)pos_time / 1000.0;
268                                  ev->len = (double)length_time / 1000.0;
269                               }
270                          }
271                        _em_module_event(ev, 4);
272                     }
273                   break;
274                 case 5: /* stop */
275                     {
276                        xine_set_param(ev->stream, XINE_PARAM_SPEED, XINE_SPEED_PAUSE);
277                        _em_module_event(ev, 5);
278                     }
279                   break;
280                 case 6: /* seek */
281                     {
282                        double pos;
283                        
284                        pos = *((double *)eev->xine_event);
285                        if (ev->seeked_pos != ev->seek_to_pos)
286                          {
287                             if (ev->no_time)
288                               xine_play(ev->stream, pos * 65535, 0);
289                             else
290                               xine_play(ev->stream, 0, pos * 1000);
291                             if (!ev->play)
292                               xine_set_param(ev->stream, XINE_PARAM_SPEED, XINE_SPEED_PAUSE);
293                             ev->seeked_pos = ev->seek_to_pos;
294                          }
295                        _em_module_event(ev, 6);
296                     }
297                   break;
298                 case 7: /* eject */
299                     {
300                        xine_eject(ev->stream);
301                        _em_module_event(ev, 7);
302                     }
303                   break;
304                 case 8: /* spu mute */
305                     {
306                        xine_set_param(ev->stream, XINE_PARAM_IGNORE_SPU, ev->spu_mute);
307                        _em_module_event(ev, 8);
308                     }
309                   break;
310                 case 9: /* channel */
311                     {
312                        xine_set_param(ev->stream, XINE_PARAM_SPU_CHANNEL, ev->spu_channel);
313                        _em_module_event(ev, 9);
314                     }
315                   break;
316                 case 10: /* vol */
317                     {
318                        double vol;
319                        
320                        vol = *((double *)eev->xine_event);
321                        if (vol < 0.0) vol = 0.0;
322                        if (vol > 1.0) vol = 1.0;
323                        xine_set_param(ev->stream, XINE_PARAM_AUDIO_VOLUME, vol * 100);
324                        _em_module_event(ev, 10);
325                     }
326                   break;
327                 case 12: /* audio mute */
328                     {
329                        xine_set_param(ev->stream, XINE_PARAM_AUDIO_MUTE, ev->audio_mute);
330                     }
331                   break;
332                 case 13: /* audio mute */
333                     {
334                        xine_set_param(ev->stream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL, ev->audio_channel);
335                     }
336                   break;
337                 case 14: /* audio mute */
338                     {
339                        xine_set_param(ev->stream, XINE_PARAM_VIDEO_CHANNEL, ev->video_channel);
340                     }
341                   break;
342                 default:
343                   break;
344                }
345              if (eev->xine_event) free(eev->xine_event);
346              free(eev);
347           }
348      }
349    return NULL;
350 }
351 static void
352 _em_slave_event(void *data, int type, void *arg)
353 {
354    void *buf[2];
355    Emotion_Xine_Event *new_ev;
356    Emotion_Xine_Video *ev;
357    
358    ev = data;
359    new_ev = calloc(1, sizeof(Emotion_Xine_Event));
360    if (!new_ev) return;
361    new_ev->mtype = type;
362    new_ev->type = -1;
363    new_ev->xine_event = arg;
364    buf[0] = data;
365    buf[1] = new_ev;
366    write(ev->fd_slave_write, buf, sizeof(buf));
367 }
368
369 static unsigned char
370 em_init(Evas_Object *obj, void **emotion_video, Emotion_Module_Options *opt)
371 {
372    Emotion_Xine_Video *ev;
373    int fds[2];
374    
375    if (!emotion_video) return 0;
376    
377    ev = calloc(1, sizeof(Emotion_Xine_Video));
378    if (!ev) return 0;
379    ev->obj = obj;
380    
381    if (pipe(fds) == 0)
382      {
383         ev->fd_read = fds[0];
384         ev->fd_write = fds[1];
385         fcntl(ev->fd_read, F_SETFL, O_NONBLOCK);
386         ev->fd_handler = ecore_main_fd_handler_add(ev->fd_read, ECORE_FD_READ,
387                                                    _em_fd_active, ev, 
388                                                    NULL, NULL);
389         ecore_main_fd_handler_active_set(ev->fd_handler, ECORE_FD_READ);
390      }
391    if (pipe(fds) == 0)
392      {
393         ev->fd_ev_read = fds[0];
394         ev->fd_ev_write = fds[1];
395         fcntl(ev->fd_ev_read, F_SETFL, O_NONBLOCK);
396         ev->fd_ev_handler = ecore_main_fd_handler_add(ev->fd_ev_read,
397                                                       ECORE_FD_READ, _em_fd_ev_active, ev, NULL, NULL);
398         ecore_main_fd_handler_active_set(ev->fd_ev_handler, ECORE_FD_READ);
399      }
400    if (pipe(fds) == 0)
401      {
402         ev->fd_slave_read = fds[0];
403         ev->fd_slave_write = fds[1];
404         fcntl(ev->fd_slave_write, F_SETFL, O_NONBLOCK);
405      }
406    ev->delete_me = 0;
407    ev->get_pos_thread_deleted = 0;
408    ev->opening = 1;
409    ev->play_ok = 0;
410    
411    if (opt)
412      {
413         ev->opt_no_audio = opt->no_audio;
414         ev->opt_no_video = opt->no_video;
415      }
416    
417    pthread_cond_init(&(ev->get_pos_len_cond), NULL);
418    pthread_mutex_init(&(ev->get_pos_len_mutex), NULL);
419    pthread_create(&ev->get_pos_len_th, NULL, _em_get_pos_len_th, ev);
420
421    pthread_create(&ev->slave_th, NULL, _em_slave, ev);
422    pthread_detach(ev->slave_th);
423    _em_slave_event(ev, 1, NULL);
424    
425    *emotion_video = ev;
426    return 1;
427 }
428
429 static int
430 em_shutdown(void *ef)
431 {
432    Emotion_Xine_Video *ev;
433    
434    ev = (Emotion_Xine_Video *)ef;
435    ev->closing = 1;
436    ev->delete_me = 1;
437    printf("EXM del fds %p\n", ev);
438    ecore_main_fd_handler_del(ev->fd_handler);
439    ecore_main_fd_handler_del(ev->fd_ev_handler);
440    
441    ev->closing = 1;
442    _em_slave_event(ev, 3, NULL);
443    printf("EXM done %p\n", ev);
444    return 1;
445 }
446
447 static unsigned char
448 em_file_open(const char *file, Evas_Object *obj, void *ef)
449 {
450    Emotion_Xine_Video *ev;
451
452    ev = (Emotion_Xine_Video *)ef;
453    if (!ev) return 0;
454    _em_slave_event(ev, 2, strdup(file));
455    return 1;
456 }
457
458 static void
459 em_file_close(void *ef)
460 {
461    Emotion_Xine_Video *ev;
462    
463    ev = (Emotion_Xine_Video *)ef;
464    if (!ev) return;
465    _em_slave_event(ev, 11, NULL);
466 }
467
468 static void
469 em_play(void *ef, double pos)
470 {
471    Emotion_Xine_Video *ev;
472    double *ppos;
473    
474    ev = (Emotion_Xine_Video *)ef;
475    ev->play = 1;
476    ev->play_ok = 0;
477    ppos = malloc(sizeof(double));
478    *ppos = pos;
479    _em_slave_event(ev, 4, ppos);
480 }
481
482 static void
483 em_stop(void *ef)
484 {
485    Emotion_Xine_Video *ev;
486    
487    ev = (Emotion_Xine_Video *)ef;
488    ev->play = 0;
489    ev->play_ok = 0;
490    _em_slave_event(ev, 5, NULL);
491 }
492
493 static void 
494 em_size_get(void *ef, int *w, int *h)
495 {
496    Emotion_Xine_Video *ev;
497    
498    ev = (Emotion_Xine_Video *)ef;
499    if (w) *w = ev->w;
500    if (h) *h = ev->h;
501 }
502
503 static void
504 em_pos_set(void *ef, double pos)
505 {
506    Emotion_Xine_Video *ev;
507    double *ppos;
508    
509    ev = (Emotion_Xine_Video *)ef;
510    if (pos == ev->seek_to_pos) return;
511    ppos = malloc(sizeof(double));
512    *ppos = pos;
513    ev->seek_to_pos = pos;
514    _em_slave_event(ev, 6, ppos);
515 }
516
517 static void
518 em_vis_set(void       *ef,
519            Emotion_Vis vis)
520 {
521    Emotion_Xine_Video *ev;
522    
523    ev = (Emotion_Xine_Video *)ef;
524    if (ev->vis == vis) return;
525    ev->vis = vis;
526 }
527
528 static double
529 em_len_get(void *ef)
530 {
531    Emotion_Xine_Video *ev;
532    
533    ev = (Emotion_Xine_Video *)ef;
534    return ev->len;
535 }
536
537 static int
538 em_fps_num_get(void *ef)
539 {
540    Emotion_Xine_Video *ev;
541    
542    ev = (Emotion_Xine_Video *)ef;
543    return (int)(ev->fps * 10000.0);
544 }
545
546 static int
547 em_fps_den_get(void *ef)
548 {
549    Emotion_Xine_Video *ev;
550    
551    ev = (Emotion_Xine_Video *)ef;
552    return 10000;
553 }
554
555 static double
556 em_fps_get(void *ef)
557 {
558    Emotion_Xine_Video *ev;
559    
560    ev = (Emotion_Xine_Video *)ef;
561    return ev->fps;
562 }
563
564 static double
565 em_pos_get(void *ef)
566 {
567    Emotion_Xine_Video *ev;
568    
569    ev = (Emotion_Xine_Video *)ef;
570    return ev->pos;
571 }
572
573 static Emotion_Vis
574 em_vis_get(void *ef)
575 {
576    Emotion_Xine_Video *ev;
577    
578    ev = (Emotion_Xine_Video *)ef;
579
580    return ev->vis;
581 }
582
583 static double
584 em_ratio_get(void *ef)
585 {
586    Emotion_Xine_Video *ev;
587    
588    ev = (Emotion_Xine_Video *)ef;
589    return ev->ratio;
590 }
591
592 static int
593 em_video_handled(void *ef)
594 {
595    Emotion_Xine_Video *ev;
596    
597    ev = (Emotion_Xine_Video *)ef;
598    if (ev->opening || (!ev->play_ok)) return 0;
599    return (xine_get_stream_info(ev->stream, XINE_STREAM_INFO_HAS_VIDEO) &&
600       xine_get_stream_info(ev->stream, XINE_STREAM_INFO_VIDEO_HANDLED));
601 }
602
603 static int
604 em_audio_handled(void *ef)
605 {
606    Emotion_Xine_Video *ev;
607    
608    ev = (Emotion_Xine_Video *)ef;
609    if (ev->opening || (!ev->play_ok)) return 0;
610    return (xine_get_stream_info(ev->stream, XINE_STREAM_INFO_HAS_AUDIO) &&
611       xine_get_stream_info(ev->stream, XINE_STREAM_INFO_AUDIO_HANDLED));
612 }
613
614 static int
615 em_seekable(void *ef)
616 {
617    Emotion_Xine_Video *ev;
618    
619    ev = (Emotion_Xine_Video *)ef;
620    if (ev->opening || (!ev->play_ok)) return 0;
621    return xine_get_stream_info(ev->stream, XINE_STREAM_INFO_SEEKABLE);
622 }
623
624 static void
625 em_frame_done(void *ef)
626 {
627    Emotion_Xine_Video *ev;
628    
629    ev = (Emotion_Xine_Video *)ef;
630    if (ev->cur_frame)
631      {
632         ev->fq--;
633         if (ev->cur_frame->done_func)
634           ev->cur_frame->done_func(ev->cur_frame->done_data);
635         ev->cur_frame = NULL;
636      }
637 }
638
639 static Emotion_Format
640 em_format_get(void *ef)
641 {
642    Emotion_Xine_Video *ev;
643    volatile Emotion_Xine_Video_Frame *fr;
644    
645    ev = (Emotion_Xine_Video *)ef;
646    fr = ev->cur_frame;
647    if (fr) return fr->format;
648    return EMOTION_FORMAT_YV12;
649 }
650
651 static void
652 em_video_data_size_get(void *ef, int *w, int *h)
653 {
654    Emotion_Xine_Video *ev;
655    volatile Emotion_Xine_Video_Frame *fr;
656    
657    ev = (Emotion_Xine_Video *)ef;
658    fr = ev->cur_frame;
659    if (!fr)
660      {
661         if (w) *w = 0;
662         if (h) *h = 0;
663         return;
664      }
665    if (w) *w = fr->w;
666    if (h) *h = fr->h;
667 }
668
669 static int
670 em_yuv_rows_get(void *ef, int w, int h, unsigned char **yrows, unsigned char **urows, unsigned char **vrows)
671 {
672    Emotion_Xine_Video *ev;
673    volatile Emotion_Xine_Video_Frame *fr;
674    
675    ev = (Emotion_Xine_Video *)ef;
676    fr = ev->cur_frame;
677    if (!fr) return 0;
678    if (fr->y)
679      {
680         int i;
681         
682         for (i = 0; i < h; i++) yrows[i] = fr->y + (i * fr->y_stride);
683         for (i = 0; i < (h / 2); i++) urows[i] = fr->u + (i * fr->u_stride);
684         for (i = 0; i < (h / 2); i++) vrows[i] = fr->v + (i * fr->v_stride);
685         return 1;
686      }
687    return 0;
688 }
689
690 static int
691 em_bgra_data_get(void *ef, unsigned char **bgra_data)
692 {
693    Emotion_Xine_Video *ev;
694    volatile Emotion_Xine_Video_Frame *fr;
695    
696    ev = (Emotion_Xine_Video *)ef;
697    fr = ev->cur_frame;
698    if (!fr) return 0;
699    if (fr->bgra_data)
700      {
701         *bgra_data = fr->bgra_data;
702         return 1;
703      }
704    return 0;
705 }
706
707 static void
708 em_event_feed(void *ef, int event)
709 {
710    Emotion_Xine_Video *ev;
711    xine_event_t xine_event;
712
713    ev = (Emotion_Xine_Video *)ef;
714    if ((ev->opening) || (!ev->play_ok)) return;
715    xine_event.data_length = 0;
716    xine_event.data        = NULL;
717    xine_event.stream      = ev->stream;
718    gettimeofday(&xine_event.tv, NULL);
719    switch (event)
720      {
721       case EMOTION_EVENT_MENU1:
722         xine_event.type = XINE_EVENT_INPUT_MENU1;
723         break;
724       case EMOTION_EVENT_MENU2:
725         xine_event.type = XINE_EVENT_INPUT_MENU2;
726         break;
727       case EMOTION_EVENT_MENU3:
728         xine_event.type = XINE_EVENT_INPUT_MENU3;
729         break;
730       case EMOTION_EVENT_MENU4:
731         xine_event.type = XINE_EVENT_INPUT_MENU4;
732         break;
733       case EMOTION_EVENT_MENU5:
734         xine_event.type = XINE_EVENT_INPUT_MENU5;
735         break;
736       case EMOTION_EVENT_MENU6:
737         xine_event.type = XINE_EVENT_INPUT_MENU6;
738         break;
739       case EMOTION_EVENT_MENU7:
740         xine_event.type = XINE_EVENT_INPUT_MENU7;
741         break;
742       case EMOTION_EVENT_UP:
743         xine_event.type = XINE_EVENT_INPUT_UP;
744         break;
745       case EMOTION_EVENT_DOWN:
746         xine_event.type = XINE_EVENT_INPUT_DOWN;
747         break;
748       case EMOTION_EVENT_LEFT:
749         xine_event.type = XINE_EVENT_INPUT_LEFT;
750         break;
751       case EMOTION_EVENT_RIGHT:
752         xine_event.type = XINE_EVENT_INPUT_RIGHT;
753         break;
754       case EMOTION_EVENT_SELECT:
755         xine_event.type = XINE_EVENT_INPUT_SELECT;
756         break;
757       case EMOTION_EVENT_NEXT:
758         xine_event.type = XINE_EVENT_INPUT_NEXT;
759         break;
760       case EMOTION_EVENT_PREV:
761         xine_event.type = XINE_EVENT_INPUT_PREVIOUS;
762         break;
763       case EMOTION_EVENT_ANGLE_NEXT:
764         xine_event.type = XINE_EVENT_INPUT_ANGLE_NEXT;
765         break;
766       case EMOTION_EVENT_ANGLE_PREV:
767         xine_event.type = XINE_EVENT_INPUT_ANGLE_PREVIOUS;
768         break;
769       case EMOTION_EVENT_FORCE:
770         xine_event.type = XINE_EVENT_INPUT_BUTTON_FORCE;
771         break;
772       case EMOTION_EVENT_0:
773         xine_event.type = XINE_EVENT_INPUT_NUMBER_0;
774         break;
775       case EMOTION_EVENT_1:
776         xine_event.type = XINE_EVENT_INPUT_NUMBER_1;
777         break;
778       case EMOTION_EVENT_2:
779         xine_event.type = XINE_EVENT_INPUT_NUMBER_2;
780         break;
781       case EMOTION_EVENT_3:
782         xine_event.type = XINE_EVENT_INPUT_NUMBER_3;
783         break;
784       case EMOTION_EVENT_4:
785         xine_event.type = XINE_EVENT_INPUT_NUMBER_4;
786         break;
787       case EMOTION_EVENT_5:
788         xine_event.type = XINE_EVENT_INPUT_NUMBER_5;
789         break;
790       case EMOTION_EVENT_6:
791         xine_event.type = XINE_EVENT_INPUT_NUMBER_6;
792         break;
793       case EMOTION_EVENT_7:
794         xine_event.type = XINE_EVENT_INPUT_NUMBER_7;
795         break;
796       case EMOTION_EVENT_8:
797         xine_event.type = XINE_EVENT_INPUT_NUMBER_8;
798         break;
799       case EMOTION_EVENT_9:
800         xine_event.type = XINE_EVENT_INPUT_NUMBER_9;
801         break;
802       case EMOTION_EVENT_10:
803         xine_event.type = XINE_EVENT_INPUT_NUMBER_10_ADD;
804         break;
805       default:
806         return;
807         break;
808      }
809    xine_event_send(ev->stream, &xine_event);
810 }
811
812 static void
813 em_event_mouse_button_feed(void *ef, int button, int x, int y)
814 {
815    Emotion_Xine_Video *ev;
816    xine_event_t xine_event;
817    xine_input_data_t xine_input;
818
819    ev = (Emotion_Xine_Video *)ef;
820    if ((ev->opening) || (!ev->play_ok)) return;
821    xine_event.stream      = ev->stream;
822    gettimeofday(&xine_event.tv, NULL);
823    xine_event.type = XINE_EVENT_INPUT_MOUSE_BUTTON;
824    xine_input.button = 1;
825    xine_input.x = x;
826    xine_input.y = y;
827    xine_event.data = &xine_input;
828    xine_event.data_length = sizeof(xine_input);
829    xine_event_send(ev->stream, &xine_event);
830 }
831
832 static void
833 em_event_mouse_move_feed(void *ef, int x, int y)
834 {
835    Emotion_Xine_Video *ev;
836    xine_event_t xine_event;
837    xine_input_data_t xine_input;
838
839    ev = (Emotion_Xine_Video *)ef;
840    if ((ev->opening) || (!ev->play_ok)) return;
841    xine_event.stream      = ev->stream;
842    gettimeofday(&xine_event.tv, NULL);
843    xine_event.type = XINE_EVENT_INPUT_MOUSE_MOVE;
844    xine_input.button = 0;
845    xine_input.x = x;
846    xine_input.y = y;
847    xine_event.data = &xine_input;
848    xine_event.data_length = sizeof(xine_input);
849    xine_event_send(ev->stream, &xine_event);
850 }
851
852 static int
853 em_video_channel_count(void *ef)
854 {
855    Emotion_Xine_Video *ev;
856    int v;
857    
858    ev = (Emotion_Xine_Video *)ef;
859    if (ev->opening || (!ev->play_ok)) return 0;
860    v = xine_get_stream_info(ev->stream, XINE_STREAM_INFO_VIDEO_CHANNELS);
861    if ((v < 1) &&
862        xine_get_stream_info(ev->stream, XINE_STREAM_INFO_HAS_VIDEO)) return 1;
863    return v;
864 }
865
866 static void
867 em_video_channel_set(void *ef, int channel)
868 {
869    Emotion_Xine_Video *ev;
870    
871    ev = (Emotion_Xine_Video *)ef;
872    if (channel < 0) channel = 0;
873    ev->video_channel = channel;
874    _em_slave_event(ev, 14, NULL);
875 }
876
877 static int
878 em_video_channel_get(void *ef)
879 {
880    Emotion_Xine_Video *ev;
881    
882    ev = (Emotion_Xine_Video *)ef;
883    if (ev->opening || (!ev->play_ok)) return 0;
884    return xine_get_param(ev->stream, XINE_PARAM_VIDEO_CHANNEL);
885 }
886
887 static const char *
888 em_video_channel_name_get(void *ef, int channel)
889 {
890    Emotion_Xine_Video *ev;
891    
892    ev = (Emotion_Xine_Video *)ef;
893    return NULL;
894 }
895
896 static void
897 em_video_channel_mute_set(void *ef, int mute)
898 {
899    Emotion_Xine_Video *ev;
900    
901    ev = (Emotion_Xine_Video *)ef;
902    ev->video_mute = mute;
903 }
904
905 static int
906 em_video_channel_mute_get(void *ef)
907 {
908    Emotion_Xine_Video *ev;
909    
910    ev = (Emotion_Xine_Video *)ef;
911    return ev->video_mute;
912 }
913
914 static int
915 em_audio_channel_count(void *ef)
916 {
917    Emotion_Xine_Video *ev;
918    
919    ev = (Emotion_Xine_Video *)ef;
920    if (ev->opening || (!ev->play_ok)) return 0;
921    return xine_get_stream_info(ev->stream, XINE_STREAM_INFO_MAX_AUDIO_CHANNEL);
922 }
923
924 static void
925 em_audio_channel_set(void *ef, int channel)
926 {
927    Emotion_Xine_Video *ev;
928    
929    ev = (Emotion_Xine_Video *)ef;
930    if (channel < -1) channel = -1;
931    ev->audio_channel = channel;
932    _em_slave_event(ev, 13, NULL);
933 }
934
935 static int
936 em_audio_channel_get(void *ef)
937 {
938    Emotion_Xine_Video *ev;
939    
940    ev = (Emotion_Xine_Video *)ef;
941    if (ev->opening || (!ev->play_ok)) return 0;
942    return xine_get_param(ev->stream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL);
943 }
944
945 static const char *
946 em_audio_channel_name_get(void *ef, int channel)
947 {
948    Emotion_Xine_Video *ev;
949    static char lang[XINE_LANG_MAX + 1];
950    
951    ev = (Emotion_Xine_Video *)ef;
952    if (ev->opening) return NULL;
953    lang[0] = 0;
954    if (xine_get_audio_lang(ev->stream, channel, lang)) return lang;
955    return NULL;
956 }
957
958 static void
959 em_audio_channel_mute_set(void *ef, int mute)
960 {
961    Emotion_Xine_Video *ev;
962    
963    ev = (Emotion_Xine_Video *)ef;
964    ev->audio_mute = mute;
965    _em_slave_event(ev, 12, NULL);
966 }
967
968 static int
969 em_audio_channel_mute_get(void *ef)
970 {
971    Emotion_Xine_Video *ev;
972    
973    ev = (Emotion_Xine_Video *)ef;
974    return ev->audio_mute;
975 }
976
977 static void
978 em_audio_channel_volume_set(void *ef, double vol)
979 {
980    Emotion_Xine_Video *ev;
981    double *ppos;
982    
983    ev = (Emotion_Xine_Video *)ef;
984    ppos = malloc(sizeof(double));
985    *ppos = vol;
986    _em_slave_event(ev, 10, ppos);
987 }
988
989 static double
990 em_audio_channel_volume_get(void *ef)
991 {
992    Emotion_Xine_Video *ev;
993    
994    ev = (Emotion_Xine_Video *)ef;
995    if (ev->opening || (!ev->play_ok)) return 0;
996    return (double)xine_get_param(ev->stream, XINE_PARAM_AUDIO_VOLUME) / 100.0;
997 }
998
999 static int
1000 em_spu_channel_count(void *ef)
1001 {
1002    Emotion_Xine_Video *ev;
1003    
1004    ev = (Emotion_Xine_Video *)ef;
1005    if (ev->opening || (!ev->play_ok)) return 0;
1006    return xine_get_stream_info(ev->stream, XINE_STREAM_INFO_MAX_SPU_CHANNEL);
1007 }
1008
1009 static void
1010 em_spu_channel_set(void *ef, int channel)
1011 {
1012    Emotion_Xine_Video *ev;
1013    
1014    ev = (Emotion_Xine_Video *)ef;
1015    if (channel < 0) channel = 0;
1016    ev->spu_channel = channel;
1017    _em_slave_event(ev, 9, NULL);
1018 }
1019
1020 static int
1021 em_spu_channel_get(void *ef)
1022 {
1023    Emotion_Xine_Video *ev;
1024    
1025    ev = (Emotion_Xine_Video *)ef;
1026    if (ev->opening || (!ev->play_ok)) return 0;
1027    return xine_get_param(ev->stream, XINE_PARAM_SPU_CHANNEL);
1028 }
1029
1030 static const char *
1031 em_spu_channel_name_get(void *ef, int channel)
1032 {
1033    Emotion_Xine_Video *ev;
1034    static char lang[XINE_LANG_MAX + 1];
1035    
1036    ev = (Emotion_Xine_Video *)ef;
1037    if (ev->opening) return NULL;
1038    lang[0] = 0;
1039    if (xine_get_spu_lang(ev->stream, channel, lang)) return lang;
1040    return NULL;
1041 }
1042
1043 static void
1044 em_spu_channel_mute_set(void *ef, int mute)
1045 {
1046    Emotion_Xine_Video *ev;
1047    
1048    ev = (Emotion_Xine_Video *)ef;
1049    ev->spu_mute = mute;
1050    _em_slave_event(ev, 8, NULL);
1051 }
1052
1053 static int
1054 em_spu_channel_mute_get(void *ef)
1055 {
1056    Emotion_Xine_Video *ev;
1057    
1058    ev = (Emotion_Xine_Video *)ef;
1059    return ev->spu_mute;
1060 }
1061
1062 static int
1063 em_chapter_count(void *ef)
1064 {
1065    Emotion_Xine_Video *ev;
1066    
1067    ev = (Emotion_Xine_Video *)ef;
1068    if (ev->opening || (!ev->play_ok)) return 0;
1069    if (xine_get_stream_info(ev->stream, XINE_STREAM_INFO_HAS_CHAPTERS))
1070      return 99;
1071    return 0;
1072 }
1073
1074 static void
1075 em_chapter_set(void *ef, int chapter)
1076 {
1077    Emotion_Xine_Video *ev;
1078    
1079    ev = (Emotion_Xine_Video *)ef;
1080 }
1081
1082 static int
1083 em_chapter_get(void *ef)
1084 {
1085    Emotion_Xine_Video *ev;
1086    
1087    ev = (Emotion_Xine_Video *)ef;
1088    return 0;
1089 }
1090
1091 static const char *
1092 em_chapter_name_get(void *ef, int chapter)
1093 {
1094    Emotion_Xine_Video *ev;
1095    
1096    ev = (Emotion_Xine_Video *)ef;
1097    return NULL;
1098 }
1099
1100 static void
1101 em_speed_set(void *ef, double speed)
1102 {
1103    Emotion_Xine_Video *ev;
1104    
1105    ev = (Emotion_Xine_Video *)ef;
1106 }
1107
1108 static double
1109 em_speed_get(void *ef)
1110 {
1111    Emotion_Xine_Video *ev;
1112    
1113    ev = (Emotion_Xine_Video *)ef;
1114    return 1.0;
1115 }
1116
1117 static int
1118 em_eject(void *ef)
1119 {
1120    Emotion_Xine_Video *ev;
1121    
1122    ev = (Emotion_Xine_Video *)ef;
1123    _em_slave_event(ev, 7, NULL);
1124    return 1;
1125 }
1126
1127 static const char *
1128 em_meta_get(void *ef, int meta)
1129 {
1130    Emotion_Xine_Video *ev;
1131    
1132    ev = (Emotion_Xine_Video *)ef;
1133    if ((ev->opening) || (!ev->play_ok)) return NULL;
1134    switch (meta)
1135      {
1136       case META_TRACK_TITLE:
1137         return xine_get_meta_info(ev->stream, XINE_META_INFO_TITLE);
1138         break;
1139       case META_TRACK_ARTIST:
1140         return xine_get_meta_info(ev->stream, XINE_META_INFO_ARTIST);
1141         break;
1142       case META_TRACK_GENRE:
1143         return xine_get_meta_info(ev->stream, XINE_META_INFO_GENRE);
1144         break;
1145       case META_TRACK_COMMENT:
1146         return xine_get_meta_info(ev->stream, XINE_META_INFO_COMMENT);
1147         break;
1148       case META_TRACK_ALBUM:
1149         return xine_get_meta_info(ev->stream, XINE_META_INFO_ALBUM);
1150         break;
1151       case META_TRACK_YEAR:
1152         return xine_get_meta_info(ev->stream, XINE_META_INFO_YEAR);
1153         break;
1154       case META_TRACK_DISCID:
1155         return xine_get_meta_info(ev->stream, XINE_META_INFO_CDINDEX_DISCID);
1156         break;
1157       default:
1158         break;
1159      }
1160    return NULL;
1161 }
1162
1163 static int
1164 _em_fd_active(void *data, Ecore_Fd_Handler *fdh)
1165 {
1166    void *buf;
1167    int fd, len;
1168    Emotion_Xine_Video_Frame *fr;
1169    Emotion_Xine_Video *ev;
1170    
1171    ev = data;
1172    fd = ecore_main_fd_handler_fd_get(fdh);
1173    while ((len = read(fd, &buf, sizeof(buf))) > 0)
1174      {
1175         if (len == sizeof(buf))
1176           {
1177              fr = buf;
1178              ev = _emotion_video_get(fr->obj);
1179              if (ev)
1180                {
1181                   em_frame_done(ev);
1182                   ev->cur_frame = fr;
1183                   _em_get_pos_len(ev);
1184                   if ((xine_get_stream_info(ev->stream, XINE_STREAM_INFO_HAS_VIDEO)) &&
1185                       (xine_get_stream_info(ev->stream, XINE_STREAM_INFO_VIDEO_HANDLED)))
1186                     {
1187                        if (ev->video_mute) em_frame_done(ev);
1188                        else _emotion_frame_new(fr->obj);
1189                     }
1190                   _emotion_frame_resize(fr->obj, fr->w, fr->h, fr->ratio);
1191                   _emotion_video_pos_update(fr->obj, ev->pos, ev->len);
1192                }
1193           }
1194      }
1195    return 1;
1196 }
1197
1198 static void
1199 _em_event(void *data, const xine_event_t *event)
1200 {
1201    void *buf[2];
1202    Emotion_Xine_Event *new_ev;
1203    Emotion_Xine_Video *ev;
1204    
1205    ev = data;
1206    new_ev = calloc(1, sizeof(Emotion_Xine_Event));
1207    if (!new_ev) return;
1208    new_ev->mtype = 0;
1209    new_ev->type = event->type;
1210    if (event->data)
1211      {
1212         new_ev->xine_event = malloc(event->data_length);
1213         if (!new_ev->xine_event)
1214           {
1215              free(new_ev);
1216              return;
1217           }
1218         memcpy(new_ev->xine_event, event->data, event->data_length);
1219      }
1220    buf[0] = data;
1221    buf[1] = new_ev;
1222    write(ev->fd_ev_write, buf, sizeof(buf));
1223 }
1224
1225 static void
1226 _em_module_event(void *data, int type)
1227 {
1228    void *buf[2];
1229    Emotion_Xine_Event *new_ev;
1230    Emotion_Xine_Video *ev;
1231    
1232    ev = data;
1233    new_ev = calloc(1, sizeof(Emotion_Xine_Event));
1234    if (!new_ev) return;
1235    new_ev->mtype = type;
1236    new_ev->type = -1;
1237    buf[0] = data;
1238    buf[1] = new_ev;
1239    write(ev->fd_ev_write, buf, sizeof(buf));
1240 }
1241
1242 static int
1243 _em_fd_ev_active(void *data, Ecore_Fd_Handler *fdh)
1244 {
1245    Emotion_Xine_Video *ev;
1246    int fd, len;
1247    void *buf[2];
1248    
1249    ev = data;
1250    fd = ecore_main_fd_handler_fd_get(fdh);
1251    while ((len = read(fd, buf, sizeof(buf))) > 0)
1252      {
1253         if (len == sizeof(buf))
1254           {
1255              Emotion_Xine_Event *eev;
1256              
1257              ev = buf[0];
1258              eev = buf[1];
1259              if (eev->mtype != 0)
1260                {
1261                   switch (eev->mtype)
1262                     {
1263                      case 1: /* init done */
1264                        ev->play_ok = 1;
1265                        break;
1266                      case 2: /* open done */
1267                        ev->play_ok = 1;
1268                        break;
1269                      case 3: /* shutdown done */
1270                        ev->play_ok = 1;
1271                        break;
1272                      case 4: /* play done */
1273                        ev->play_ok = 1;
1274                        break;
1275                      case 5: /* stop done */
1276                        ev->play_ok = 1;
1277                        break;
1278                      case 6: /* seek done */
1279                        ev->play_ok = 1;
1280                        break;
1281                      case 7: /* eject done */
1282                        ev->play_ok = 1;
1283                        break;
1284                      case 8: /* spu mute done */
1285                        ev->play_ok = 1;
1286                        break;
1287                      case 9: /* channel done */
1288                        ev->play_ok = 1;
1289                        break;
1290                      case 10: /* volume done */
1291                        ev->play_ok = 1;
1292                        break;
1293                      case 11: /* close done */
1294                        ev->play_ok = 1;
1295                        break;
1296                      default:
1297                        break;
1298                     }
1299                }
1300              else
1301                {
1302                   switch (eev->type)
1303                     {
1304                      case XINE_EVENT_UI_PLAYBACK_FINISHED:
1305                          {
1306                             ev->play = 0;
1307                             _emotion_decode_stop(ev->obj);
1308                             _emotion_playback_finished(ev->obj);
1309                          }
1310                        break;
1311                      case XINE_EVENT_UI_CHANNELS_CHANGED:
1312                          {
1313                             _emotion_channels_change(ev->obj);
1314                          }
1315                        break;
1316                      case XINE_EVENT_UI_SET_TITLE:
1317                          {
1318                             xine_ui_data_t *e;
1319                             
1320                             e = (xine_ui_data_t *)eev->xine_event;
1321                             _emotion_title_set(ev->obj, e->str);
1322                          }
1323                        break;
1324                      case XINE_EVENT_FRAME_FORMAT_CHANGE:
1325                          {
1326                             xine_format_change_data_t *e;
1327                             
1328                             e = (xine_format_change_data_t *)eev->xine_event;
1329                          }
1330                        break;
1331                      case XINE_EVENT_UI_MESSAGE:
1332                          {
1333                             xine_ui_message_data_t *e;
1334                             
1335                             e = (xine_ui_message_data_t *)eev->xine_event;
1336                             printf("EV: UI Message [FIXME: break this out to emotion api]\n");
1337                             // e->type = error type(XINE_MSG_NO_ERROR, XINE_MSG_GENERAL_WARNING, XINE_MSG_UNKNOWN_HOST etc.)
1338                             // e->messages is a list of messages DOUBLE null terminated
1339                          }
1340                        break;
1341                      case XINE_EVENT_AUDIO_LEVEL:
1342                          {
1343                             xine_audio_level_data_t *e;
1344                             
1345                             e = (xine_audio_level_data_t *)eev->xine_event;
1346                             _emotion_audio_level_change(ev->obj);
1347                             printf("EV: Audio Level [FIXME: break this out to emotion api]\n");
1348                             // e->left (0->100) 
1349                             // e->right
1350                             // e->mute
1351                          }
1352                        break;
1353                      case XINE_EVENT_PROGRESS:
1354                          {
1355                             xine_progress_data_t *e;
1356                             
1357                             e = (xine_progress_data_t *)eev->xine_event;
1358                             printf("PROGRESS: %i\n", e->percent);
1359                             _emotion_progress_set(ev->obj, (char *)e->description, (double)e->percent / 100.0);
1360                          }
1361                        break;
1362                      case XINE_EVENT_MRL_REFERENCE:
1363                          {
1364                             xine_mrl_reference_data_t *e;
1365                             
1366                             e = (xine_mrl_reference_data_t *)eev->xine_event;
1367                             _emotion_file_ref_set(ev->obj, e->mrl, e->alternative);
1368                          }
1369                        break;
1370                      case XINE_EVENT_UI_NUM_BUTTONS:
1371                          {
1372                             xine_ui_data_t *e;
1373                             
1374                             e = (xine_ui_data_t *)eev->xine_event;
1375                             _emotion_spu_button_num_set(ev->obj, e->num_buttons);
1376                          }
1377                        break;
1378                      case XINE_EVENT_SPU_BUTTON:
1379                          {
1380                             xine_spu_button_t *e;
1381                             
1382                             e = (xine_spu_button_t *)eev->xine_event;
1383                             if (e->direction == 1)
1384                               _emotion_spu_button_set(ev->obj, e->button);
1385                             else
1386                               _emotion_spu_button_set(ev->obj, -1);
1387                          }
1388                        break;
1389                      case XINE_EVENT_DROPPED_FRAMES:
1390                          {
1391                             xine_dropped_frames_t *e;
1392                             
1393                             e = (xine_dropped_frames_t *)eev->xine_event;
1394                             printf("EV: Dropped Frames (skipped %i) (discarded %i) [FIXME: break this out to the emotion api]\n", e->skipped_frames, e->discarded_frames);
1395                             // e->skipped_frames = % frames skipped * 10
1396                             // e->discarded_frames = % frames skipped * 10
1397                          }
1398                        break;
1399                      default:
1400                        // printf("EV: unknown event type %i\n", eev->type);
1401                        break;
1402                     }
1403                }
1404              if (eev->xine_event) free(eev->xine_event);
1405              free(eev);
1406           }
1407      }
1408    return 1;
1409 }
1410
1411 static void *
1412 _em_get_pos_len_th(void *par)
1413 {
1414    Emotion_Xine_Video *ev;
1415    
1416    ev = (Emotion_Xine_Video *)par;
1417    
1418    for (;;)
1419      {
1420         pthread_mutex_lock(&(ev->get_pos_len_mutex));
1421         pthread_cond_wait(&(ev->get_pos_len_cond), &(ev->get_pos_len_mutex));
1422         pthread_mutex_unlock(&(ev->get_pos_len_mutex));
1423         if (ev->get_poslen)
1424           {
1425              int pos_stream = 0;
1426              int pos_time = 0;
1427              int length_time = 0;
1428              
1429              if (xine_get_pos_length(ev->stream, &pos_stream, &pos_time, &length_time))
1430                {
1431                   if (length_time == 0)
1432                     {
1433                        ev->pos = (double)pos_stream / 65535;
1434                        ev->len = 1.0;
1435                        ev->no_time = 1;
1436                     }
1437                   else
1438                     {
1439                        ev->pos = (double)pos_time / 1000.0;
1440                        ev->len = (double)length_time / 1000.0;
1441                        ev->no_time = 0;
1442                     }
1443                }
1444              ev->get_poslen = 0;
1445              //printf("get pos %3.3f\n", ev->pos);
1446           }
1447         if (ev->delete_me)
1448           {
1449              ev->get_pos_thread_deleted = 1;
1450              return NULL;     
1451           }
1452      }
1453    return NULL;
1454 }
1455
1456 static void
1457 _em_get_pos_len(Emotion_Xine_Video *ev)
1458 {
1459    if (ev->get_poslen) return;
1460    ev->get_poslen = 1;
1461    pthread_mutex_lock(&(ev->get_pos_len_mutex));
1462    pthread_cond_broadcast(&(ev->get_pos_len_cond));
1463    pthread_mutex_unlock(&(ev->get_pos_len_mutex));
1464 }
1465
1466 static Emotion_Video_Module em_module =
1467 {
1468    em_init, /* init */
1469      em_shutdown, /* shutdown */
1470      em_file_open, /* file_open */
1471      em_file_close, /* file_close */
1472      em_play, /* play */
1473      em_stop, /* stop */
1474      em_size_get, /* size_get */
1475      em_pos_set, /* pos_set */
1476      em_vis_set, /* vis_set */
1477      em_len_get, /* len_get */
1478      em_fps_num_get, /* fps_num_get */
1479      em_fps_den_get, /* fps_den_get */
1480      em_fps_get, /* fps_get */
1481      em_pos_get, /* pos_get */
1482      em_vis_get, /* vis_get */
1483      em_ratio_get, /* ratio_get */
1484      em_video_handled, /* video_handled */
1485      em_audio_handled, /* audio_handled */
1486      em_seekable, /* seekable */
1487      em_frame_done, /* frame_done */
1488      em_format_get, /* format_get */
1489      em_video_data_size_get, /* video_data_size_get */
1490      em_yuv_rows_get, /* yuv_rows_get */
1491      em_bgra_data_get, /* bgra_data_get */
1492      em_event_feed, /* event_feed */
1493      em_event_mouse_button_feed, /* event_mouse_button_feed */
1494      em_event_mouse_move_feed, /* event_mouse_move_feed */
1495      em_video_channel_count, /* video_channel_count */
1496      em_video_channel_set, /* video_channel_set */
1497      em_video_channel_get, /* video_channel_get */
1498      em_video_channel_name_get, /* video_channel_name_get */
1499      em_video_channel_mute_set, /* video_channel_mute_set */
1500      em_video_channel_mute_get, /* video_channel_mute_get */
1501      em_audio_channel_count, /* audio_channel_count */
1502      em_audio_channel_set, /* audio_channel_set */
1503      em_audio_channel_get, /* audio_channel_get */
1504      em_audio_channel_name_get, /* audio_channel_name_get */
1505      em_audio_channel_mute_set, /* audio_channel_mute_set */
1506      em_audio_channel_mute_get, /* audio_channel_mute_get */
1507      em_audio_channel_volume_set, /* audio_channel_volume_set */
1508      em_audio_channel_volume_get, /* audio_channel_volume_get */
1509      em_spu_channel_count, /* spu_channel_count */
1510      em_spu_channel_set, /* spu_channel_set */
1511      em_spu_channel_get, /* spu_channel_get */
1512      em_spu_channel_name_get, /* spu_channel_name_get */
1513      em_spu_channel_mute_set, /* spu_channel_mute_set */
1514      em_spu_channel_mute_get, /* spu_channel_mute_get */
1515      em_chapter_count, /* chapter_count */
1516      em_chapter_set, /* chapter_set */
1517      em_chapter_get, /* chapter_get */
1518      em_chapter_name_get, /* chapter_name_get */
1519      em_speed_set, /* speed_set */
1520      em_speed_get, /* speed_get */
1521      em_eject, /* eject */
1522      em_meta_get, /* meta_get */
1523      
1524      NULL /* handle */
1525 };
1526
1527 unsigned char
1528 module_open(Evas_Object *obj, const Emotion_Video_Module **module, void **video, Emotion_Module_Options *opt)
1529 {
1530    if (!module)
1531       return 0;
1532    
1533    if (!em_module.init(obj, video, opt))
1534       return 0;
1535
1536    *module = &em_module;
1537    return 1;
1538 }
1539
1540 void
1541 module_close(Emotion_Video_Module *module, void *video)
1542 {
1543    em_module.shutdown(video);
1544 }
1545
1546 #if 0
1547 void
1548 em_debug(Emotion_Xine_Video *ev)
1549 {
1550    int has_chapters = 0;
1551    int max_spu = 0;
1552    int max_audio = 0;
1553    int video_channels = 0;
1554    int video_streams = 0;
1555    int video_seekable = 0;
1556    char *title;
1557    char *comment;
1558    char *artist;
1559    char *genre;
1560    char *album;
1561    char *year;
1562    char *cdindex_discid;
1563    int video_channel = 0;
1564    int audio_channel = 0;
1565    int spu_channel = 0;
1566    int video_ratio = 0;
1567    int audio_mode = 0;
1568
1569 //   return;
1570    has_chapters = xine_get_stream_info(ev->stream, XINE_STREAM_INFO_HAS_CHAPTERS);
1571    max_spu = xine_get_stream_info(ev->stream, XINE_STREAM_INFO_MAX_SPU_CHANNEL);
1572    max_audio = xine_get_stream_info(ev->stream, XINE_STREAM_INFO_MAX_AUDIO_CHANNEL);
1573    video_channels = xine_get_stream_info(ev->stream, XINE_STREAM_INFO_VIDEO_CHANNELS);
1574    video_streams = xine_get_stream_info(ev->stream, XINE_STREAM_INFO_VIDEO_STREAMS);
1575    video_seekable = xine_get_stream_info(ev->stream, XINE_STREAM_INFO_SEEKABLE);
1576    title = xine_get_meta_info(ev->stream, XINE_META_INFO_TITLE);
1577    comment = xine_get_meta_info(ev->stream, XINE_META_INFO_COMMENT);
1578    artist = xine_get_meta_info(ev->stream, XINE_META_INFO_ARTIST);
1579    genre = xine_get_meta_info(ev->stream, XINE_META_INFO_GENRE);
1580    album = xine_get_meta_info(ev->stream, XINE_META_INFO_ALBUM);
1581    year = xine_get_meta_info(ev->stream, XINE_META_INFO_YEAR);
1582    cdindex_discid = xine_get_meta_info(ev->stream, XINE_META_INFO_CDINDEX_DISCID);
1583    video_channel = xine_get_param(ev->stream, XINE_PARAM_VIDEO_CHANNEL);
1584    audio_channel = xine_get_param(ev->stream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL);
1585    spu_channel = xine_get_param(ev->stream, XINE_PARAM_SPU_CHANNEL);
1586    video_ratio = xine_get_stream_info(ev->stream, XINE_STREAM_INFO_VIDEO_RATIO);
1587    audio_mode = xine_get_stream_info(ev->stream, XINE_STREAM_INFO_AUDIO_MODE);
1588    printf("has_chapters = %i\n", has_chapters);
1589    printf("max_spu = %i\n", max_spu);
1590    printf("max_audio = %i\n", max_audio);
1591    printf("video_channels = %i\n", video_channels);
1592    printf("video_streams = %i\n", video_streams);
1593    printf("video_seekable = %i\n", video_seekable);
1594    printf("title = %s\n", title);
1595    printf("comment = %s\n", comment);
1596    printf("artist = %s\n", artist);
1597    printf("genre = %s\n", genre);
1598    printf("album = %s\n", album);
1599    printf("year = %s\n", year);
1600    printf("cdindex_discid = %s\n", cdindex_discid);
1601    printf("video_channel = %i\n", video_channel);
1602    printf("audio_channel = %i\n", audio_channel);
1603    printf("spu_channels = %i\n", spu_channel);
1604    printf("video_ratio = %i\n", video_ratio);
1605    printf("audio_mode = %i\n", audio_mode);
1606      {
1607         int i;
1608         
1609         for (i = 0; i <= max_audio; i++)
1610           {
1611              char lang[XINE_LANG_MAX + 1];
1612              
1613              lang[0] = 0;
1614              printf("  AUDIO %i = ", i);
1615              if (xine_get_audio_lang(ev->stream, i, lang))
1616                printf("%s\n", lang);
1617              else
1618                printf("NONE\n");
1619           }
1620         for (i = 0; i <= max_spu; i++)
1621           {
1622              char lang[XINE_LANG_MAX + 1];
1623              
1624              lang[0] = 0;
1625              printf("  SPU %i = ", i);
1626              if (xine_get_spu_lang(ev->stream, i, lang))
1627                printf("%s\n", lang);
1628              else
1629                printf("NONE\n");
1630           }
1631      }
1632 }
1633 #endif