1 /*
2 * Copyright (C) 2002-2008 Stefan Holst
3 * Copyright (C) 2005-2019 the xine project
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA.
18 *
19 * oxine main program
20 */
21
22 #define LOG
23
24 #include "config.h"
25
26 #include <stdio.h>
27 #include <ctype.h>
28 #include <dirent.h>
29 #include <string.h>
30 #include <sys/stat.h>
31 #include <fcntl.h>
32 #include <getopt.h>
33
34 #include <xine.h>
35 #include "common.h"
36 #include "oxine.h"
37 #include "odk.h"
38 #include "otk.h"
39 #include "oxine_event.h"
40 #include "xine/xmlparser.h"
41 #include "utils.h"
42 #include "globals.h"
43
44 #include "mediamarks.h"
45 #include "playlist.h"
46
47 static oxine_t *oxine_instance_get(void);
48 static void oxine_instance_unget(oxine_t *oxine);
49
50
51 typedef struct menuitem_s menuitem_t;
52
53 struct menuitem_s {
54 char *title;
55 void *data;
56 int x, y, w, h;
57 void (*func)(void *data);
58 };
59
60
61 static void main_menu_cb(void *data);
62 #if 0
63 static void media_stop_cb(void *data);
64 static void media_info_cb(void *data);
65 static void media_pause_cb(void *data, int i);
66
67 //static void event_delay(void *data);
68
69 const char *playpause_strings[] = { "<", ">" };
70
71 static void media_pause_cb(void *data, int i) {
72 oxine_t *oxine = (oxine_t*) data;
73
74 switch(i) {
75 case 1:
76 odk_set_speed(oxine->odk, ODK_SPEED_NORMAL);
77 break;
78 case 2:
79 odk_set_speed(oxine->odk, ODK_SPEED_PAUSE);
80 break;
81 }
82 }
83
84 static void format_time(char *buf, int sec) {
85 sprintf(buf, "%d:%02d:%02d", sec/3600, (sec%3600)/60, ((sec%3600)%60));
86 }
87
88 static void media_stop_cb(void *data) {
89 oxine_t *oxine = (oxine_t*) data;
90
91 odk_stop(oxine->odk);
92 oxine->main_menu_cb(oxine);
93 }
94
95 static void media_tracks_list_cb(void *data, void *entry) {
96 oxine_t *oxine = (oxine_t *) data;
97 char *mrl = (char *) entry;
98
99 odk_stop(oxine->odk);
100 odk_open_and_play(oxine->odk, mrl);
101 }
102
103 static void media_tracks_quit(void *data) {
104 oxine_t *oxine = (oxine_t*) data;
105
106 oxine->need_draw = 0;
107 printf("%d\n", oxine->mode);
108 oxine->mode = OXINE_MODE_NORMAL;
109 printf("%d\n", oxine->mode);
110 oxine->pauseplay = NULL;
111 otk_clear(oxine->otk);
112 }
113
114 static void media_tracks_cb(void *data) {
115 oxine_t *oxine = (oxine_t *) data;
116 int num, i = 0;
117 char **str;
118 otk_widget_t *list;
119
120 oxine->pauseplay = NULL;
121 oxine->main_window = NULL;
122 oxine->info_window = NULL;
123 otk_clear(oxine->otk);
124 oxine->main_window = otk_window_new (oxine->otk, NULL, 50, 50, 550, 500);
125 list = otk_list_new(oxine->main_window, 10, 10, 500, 490, media_tracks_list_cb, oxine);
126
127 str = xine_get_autoplay_mrls (oxine->xine, "CD", &num);
128 while(i < num) {
129 /* printf("%d %s\n", i, str[i]); */
130 otk_add_listentry(list, str[i], str[i], -1);
131 i++;
132 }
133 otk_list_set_pos(list, 0);
134 otk_set_focus(list);
135 otk_draw_all(oxine->otk);
136 }
137
138 static void info_button_time(void *data) {
139 oxine_t *oxine = (oxine_t *)data;
140 int ret, pos_time, length;
141
142 ret = odk_get_pos_length_high(oxine->odk, NULL, &pos_time, &length);
143 /* oxine->time = malloc(sizeof(char)*255); */
144 if(ret) {
145 pos_time /= 1000;
146 length /= 1000;
147 sprintf(oxine->time, "(%d:%02d:%02d / %d:%02d:%02d)", pos_time/3600, (pos_time%3600)/60, ((pos_time%3600)%60),
148 length/3600, (length%3600)/60, ((length%3600)%60));
149 }
150 else sprintf(oxine->time, "N/A");
151 }
152 #endif
153
media_info_close_cb(void * data)154 static void media_info_close_cb(void *data) {
155 oxine_t *oxine = (oxine_t*) data;
156
157 if (!oxine->info_window) return;
158
159 otk_destroy_widget(oxine->info_window);
160 oxine->info_window = NULL;
161 otk_draw_all(oxine->otk);
162
163 if (oxine->lines[0]) ho_free(oxine->lines[0]);
164 if (oxine->lines[1]) ho_free(oxine->lines[1]);
165 if (oxine->lines[2]) ho_free(oxine->lines[2]);
166 }
167
168 #if 0
169 static void media_info_cb(void *data) {
170 oxine_t *oxine = (oxine_t*) data;
171 int pos_time, length, ret;
172 int cline = 0;
173 const char *buf1;
174 char *buf2;
175 /* otk_widget_t *b, *layout; */
176
177 oxine->media_info_close_cb = media_info_close_cb;
178 oxine->pauseplay = NULL;
179 if (oxine->info_window) {
180 otk_destroy_widget(oxine->info_window);
181 oxine->info_window = NULL;
182 otk_draw_all(oxine->otk);
183 return;
184 }
185 /* otk_clear(oxine->otk); */
186
187 buf2 = NULL;
188 buf1 = odk_get_mrl(oxine->odk);
189 if (buf1) {
190 buf2 = strrchr(buf1,'/');
191 if (buf2) buf2++; else buf2 = buf1;
192 }
193
194 if (oxine->lines[0]) ho_free(oxine->lines[0]);
195 if (oxine->lines[1]) ho_free(oxine->lines[1]);
196 if (oxine->lines[2]) ho_free(oxine->lines[2]);
197
198 oxine->lines[0] = odk_get_meta_info(oxine->odk, XINE_META_INFO_TITLE);
199 if(!oxine->lines[0] && buf2) oxine->lines[0] = ho_strdup(buf2);
200 if(oxine->lines[0]) cline++;
201 buf1 = odk_get_meta_info(oxine->odk, XINE_META_INFO_ARTIST);
202 buf2 = odk_get_meta_info(oxine->odk, XINE_META_INFO_ALBUM);
203 if (buf1 && buf2) {
204 oxine->lines[cline] = ho_newstring(strlen(buf1)+strlen(buf2)+10);
205 sprintf(oxine->lines[cline], "%s: %s", buf1, buf2);
206 cline++;
207 } else if (buf1 && (strlen(buf1)>0)) {
208 oxine->lines[cline++] = ho_strdup(buf1);
209 } else if (buf2 && (strlen(buf2)>0)) {
210 oxine->lines[cline++] = ho_strdup(buf2);
211 }
212 /*
213 oxine->genre = odk_get_meta_info(oxine->odk, XINE_META_INFO_GENRE);
214 if(!oxine->genre) oxine->genre = ho_strdup("Genre N/A");
215 oxine->year = odk_get_meta_info(oxine->odk, XINE_META_INFO_YEAR);
216 if(!oxine->year) oxine->year = ho_strdup("Year N/A");
217 */
218 ret = odk_get_pos_length_high(oxine->odk, NULL, &pos_time, &length);
219
220 if(ret && (length > 0)) {
221 oxine->lines[cline] = ho_newstring(255);
222 pos_time /= 1000;
223 length /= 1000;
224 format_time(oxine->lines[cline], length);
225 }
226
227 oxine->info_window = otk_window_new (oxine->otk, NULL, 5, 5, 790, 240);
228
229 if (oxine->lines[0])
230 otk_label_new(oxine->info_window, 5, 40, OTK_ALIGN_LEFT|OTK_ALIGN_VCENTER, oxine->lines[0]);
231
232 if (oxine->lines[1])
233 otk_label_new(oxine->info_window, 5, 110, OTK_ALIGN_LEFT|OTK_ALIGN_VCENTER, oxine->lines[1]);
234
235 if (oxine->lines[2])
236 otk_label_new(oxine->info_window, 5, 180, OTK_ALIGN_LEFT|OTK_ALIGN_VCENTER, oxine->lines[2]);
237
238 /*
239 layout = otk_layout_new(oxine->info_window, 10, 10, 680, 480, 6, 1);
240
241 b = otk_button_grid_new(oxine->title, media_freeandreturnto_cb, oxine);
242 otk_layout_add_widget(layout, b, 0, 0, 1, 1);
243 otk_set_focus(b);
244
245 b = otk_button_grid_new(oxine->artist, media_freeandreturnto_cb, oxine);
246 otk_layout_add_widget(layout, b, 0, 1, 1, 1);
247
248 b = otk_button_grid_new(oxine->genre, media_freeandreturnto_cb, oxine);
249 otk_layout_add_widget(layout, b, 0, 2, 1, 1);
250
251 b = otk_button_grid_new(oxine->album, media_freeandreturnto_cb, oxine);
252 otk_layout_add_widget(layout, b, 0, 3, 1, 1);
253
254 b = otk_button_grid_new(oxine->year, media_freeandreturnto_cb, oxine);
255 otk_layout_add_widget(layout, b, 0, 4, 1, 1);
256
257 b = otk_button_grid_new(oxine->time, media_freeandreturnto_cb, oxine);
258 otk_layout_add_widget(layout, b, 0, 5, 1, 1);
259 otk_button_uc_set(b, info_button_time, oxine);
260 */
261
262 otk_draw_all(oxine->otk);
263
264 schedule_job(5000, media_info_close_cb, oxine);
265 }
266 #endif
267
shutdown_cb(void * data)268 static void shutdown_cb (void *data) {
269 gui_execute_action_id (gGui, ACTID_QUIT);
270 }
271
mrl_cb(void * data)272 static void mrl_cb (void *data) {
273 char *parameter = (char *) data;
274 oxine_t *oxine = oxine_instance_get();
275 if (!oxine)
276 return;
277
278 oxine->pauseplay = NULL;
279 oxine->main_window = NULL;
280 otk_clear(oxine->otk);
281 oxine->mode = OXINE_MODE_NORMAL;
282 odk_open_and_play(oxine->odk, parameter);
283
284 oxine_instance_unget(oxine);
285 }
286
autoplay_cb(void * data)287 static void autoplay_cb (void *data) {
288 char *parameter = (char *) data;
289 oxine_t *oxine = oxine_instance_get();
290 int num_mrls, j;
291 #if XINE_MAJOR_VERSION < 1 || (XINE_MAJOR_VERSION == 1 && XINE_MINOR_VERSION < 2)
292 char **autoplay_mrls;
293 #else
294 const char * const *autoplay_mrls;
295 #endif
296
297 if (!oxine)
298 return;
299
300 autoplay_mrls = xine_get_autoplay_mrls (__xineui_global_xine_instance,
301 parameter,
302 &num_mrls);
303
304 if(autoplay_mrls) {
305 playlist_delete_all(NULL, NULL);
306
307 for (j = 0; j < num_mrls; j++)
308 mediamark_append_entry((const char *)autoplay_mrls[j],
309 (const char *)autoplay_mrls[j], NULL, 0, -1, 0, 0);
310
311 oxine->pauseplay = NULL;
312 oxine->main_window = NULL;
313 otk_clear(oxine->otk);
314 oxine->mode = OXINE_MODE_NORMAL;
315
316 gGui->playlist.cur = 0;
317 gui_set_current_mmk(mediamark_get_current_mmk());
318
319 gui_xine_open_and_play(gGui->mmk.mrl, gGui->mmk.sub, 0,
320 gGui->mmk.start, gGui->mmk.av_offset, gGui->mmk.spu_offset, 0);
321 }
322
323 oxine_instance_unget(oxine);
324 }
325
326
327 #if 0
328 static void playing_menu_update(void *data) {
329 oxine_t *oxine = (oxine_t *) data;
330 int pos_time, length;
331
332 if (oxine->pos_str)
333 if (odk_get_pos_length_high(oxine->odk, NULL, &pos_time, &length)) {
334 pos_time /= 1000;
335 format_time(oxine->pos_str, pos_time);
336 }
337 }
338
339 static void playing_menu_cb(void *data) {
340 oxine_t *oxine = (oxine_t *) data;
341 otk_widget_t *b, *l;
342 otk_widget_t *layout;
343 int pos_time, length;
344
345 oxine->pauseplay = NULL;
346 if (oxine->main_window) {
347 otk_destroy_widget(oxine->main_window);
348 oxine->main_window = NULL;
349 otk_draw_all(oxine->otk);
350 }
351
352 /* otk_clear(oxine->otk); */
353
354 if(oxine->mode == OXINE_MODE_PLAY_MENU) {
355 oxine->mode = OXINE_MODE_NORMAL;
356 return ;
357 }
358 oxine->mode = OXINE_MODE_PLAY_MENU;
359
360 oxine->main_window = otk_window_new (oxine->otk, NULL, 50, 400, 700, 150);
361 layout = otk_layout_new(oxine->main_window, 10, 10, 680, 130, 2, 6);
362 oxine->pauseplay = otk_selector_grid_new (playpause_strings, 2, media_pause_cb, oxine);
363 otk_layout_add_widget(layout, oxine->pauseplay, 0, 0, 1, 1);
364 otk_set_focus(oxine->pauseplay);
365 if (odk_get_speed(oxine->odk) == ODK_SPEED_PAUSE) otk_selector_set(oxine->pauseplay, 2);
366
367 b = otk_button_grid_new ("}", media_stop_cb, oxine);
368 otk_layout_add_widget(layout, b, 1, 0, 1, 1);
369
370 /* b = otk_button_grid_new ("Volume", NULL, NULL);
371 otk_layout_add_widget(layout, b, 0, 1, 1, 1);
372
373 b = otk_slider_grid_new (odk_get_volume);
374 otk_layout_add_widget(layout, b, 1, 1, 1, 1);
375
376 if(!oxine->cd_in_use) {
377 b = otk_button_grid_new("Seek", NULL, NULL);
378 otk_layout_add_widget(layout, b, 0, 2, 1, 1);
379 }else {
380 b = otk_button_grid_new ("T", media_tracks_cb, oxine);
381 otk_layout_add_widget(layout, b, 0, 2, 1, 1);
382 }*/
383
384 if(oxine->cd_in_use) {
385 b = otk_button_grid_new ("T", media_tracks_cb, oxine);
386 otk_layout_add_widget(layout, b, 3, 0, 1, 1);
387 }
388
389 b = otk_slider_grid_new (odk_get_seek);
390 otk_layout_add_widget(layout, b, 2, 1, 4, 1);
391 otk_set_update(b,1);
392
393 b = otk_button_grid_new ("i", media_info_cb, oxine);
394 otk_layout_add_widget(layout, b, 2, 0, 1, 1);
395
396 if (!oxine->pos_str) oxine->pos_str = ho_newstring(64);
397 if (odk_get_pos_length_high(oxine->odk, NULL, &pos_time, &length)) {
398 pos_time /= 1000;
399 format_time(oxine->pos_str, pos_time);
400 }
401
402 l = otk_label_new (oxine->main_window, 110, 100, OTK_ALIGN_CENTER|OTK_ALIGN_VCENTER, oxine->pos_str);
403 otk_set_update(l,1);
404 otk_button_uc_set(b, playing_menu_update, oxine);
405
406 /* oxine->need_draw = 1; */
407
408 otk_draw_all(oxine->otk);
409 }
410 #endif
411
read_entire_file(const char * mrl,int * file_size)412 static char *read_entire_file (const char *mrl, int *file_size) {
413
414 char *buf;
415 struct stat statb;
416 int fd;
417
418 if (stat (mrl, &statb) < 0) {
419 lprintf ("cannot stat '%s'\n", mrl);
420 return NULL;
421 }
422
423 *file_size = statb.st_size;
424
425 fd = xine_open_cloexec(mrl, O_RDONLY);
426 if (fd<0)
427 return NULL;
428
429 buf = ho_newstring((*file_size)+1);
430
431 if (!buf)
432 return NULL;
433
434 buf[*file_size]=0;
435
436 *file_size = read (fd, buf, *file_size);
437
438 close (fd);
439
440 return buf;
441 }
442
menuitem_load(xml_node_t * node)443 static menuitem_t *menuitem_load(xml_node_t *node) {
444
445 menuitem_t *item = ho_new(menuitem_t);
446
447 item->x = atoi(xml_parser_get_property(node, "x"));
448 item->y = atoi(xml_parser_get_property(node, "y"));
449 item->w = atoi(xml_parser_get_property(node, "width"));
450 item->h = atoi(xml_parser_get_property(node, "height"));
451 item->func = NULL;
452 item->title = NULL;
453 item->data = NULL;
454
455 if ( (node = node->child) == NULL )
456 return item;
457
458 do {
459 if (!strcasecmp (node->name, "title")) {
460 item->title = ho_strdup (node->data);
461 } else if (!strcasecmp (node->name, "action")) {
462 const char *type = xml_parser_get_property(node, "type");
463
464 if(type) {
465 if(!strcasecmp(type, "autoplay")) {
466 item->data = ho_strdup(xml_parser_get_property (node, "parameter"));
467 item->func = autoplay_cb;
468 } else if(!strcasecmp(type, "mrl")) {
469 item->data = ho_strdup(xml_parser_get_property (node, "parameter"));
470 item->func = mrl_cb;
471 } else if(!strcasecmp(type, "mediamarks")) {
472 item->func = mediamarks_cb;
473 } else if(!strcasecmp(type, "playlist")) {
474 item->func = playlist_cb;
475 } else if(!strcasecmp(type, "shutdown")) {
476 item->func = shutdown_cb;
477 } else if(!strcasecmp(type, "shell")) {
478 }
479 }
480 }
481 } while ( (node = node->next) != NULL );
482
483 return item;
484 }
485
read_main_menu(oxine_t * oxine,list_t * list,const char * mrl)486 static int read_main_menu(oxine_t *oxine, list_t *list, const char *mrl) {
487
488 int size;
489 char *file = read_entire_file(mrl, &size);
490 xml_node_t *node;
491
492 if (!file) return 0;
493
494 xml_parser_init_R (xml_parser_t *xml, file, strlen (file), XML_PARSER_CASE_INSENSITIVE);
495
496 if (xml_parser_build_tree_R (xml, &node)<0) {
497 lprintf("xml parsing of %s failed\n", mrl);
498 xml_parser_finalize_R (xml);
499 return 0;
500 }
501
502 if (strcasecmp (node->name, "oxinemm")) {
503 lprintf ("error, root node must be OXINEMM\n");
504 xml_parser_finalize_R (xml);
505 return 0;
506 }
507
508 node = node->child;
509
510 if (!node || strcasecmp (node->name, "window")) {
511 lprintf ("error, node WINDOW expected (%s found)\n", (!node) ? "(null)" : node->name );
512 xml_parser_finalize_R (xml);
513 return 0;
514 }
515
516 oxine->win_x = atoi(xml_parser_get_property(node, "x"));
517 oxine->win_y = atoi(xml_parser_get_property(node, "y"));
518 oxine->win_w = atoi(xml_parser_get_property(node, "width"));
519 oxine->win_h = atoi(xml_parser_get_property(node, "height"));
520
521 node = node->child;
522
523 while (node) {
524
525 if (!strcasecmp (node->name, "entry")) {
526 menuitem_t *item = menuitem_load(node);
527 if( item )
528 list_append_content(list, item);
529 }
530
531 node=node->next;
532 }
533
534 xml_parser_free_tree(node);
535 xml_parser_finalize_R (xml);
536 ho_free(file);
537
538 return 1;
539 }
540
main_menu_init(oxine_t * oxine)541 static void main_menu_init(oxine_t *oxine)
542 {
543 char mmpath[XITK_NAME_MAX];
544
545 oxine->main_menu_items = list_new();
546
547 memset(mmpath,0,sizeof(mmpath));
548 snprintf(mmpath,sizeof(mmpath),"%s/.xine/oxine/mainmenu", xine_get_homedir());
549 if (!read_main_menu(oxine, oxine->main_menu_items, mmpath)) {
550 lprintf("trying to load system wide mainmenu\n");
551 snprintf(mmpath, sizeof(mmpath),"%s/mainmenu", XINE_OXINEDIR);
552 if (read_main_menu(oxine, oxine->main_menu_items, mmpath)) {
553 /**/
554 } else {
555 list_free(oxine->main_menu_items);
556 oxine->main_menu_items = NULL;
557 }
558 } else {
559 /**/
560 }
561 }
562
main_menu_free(list_t * list)563 static void main_menu_free(list_t *list) {
564
565 menuitem_t *item;
566
567 if (!list) return;
568
569 item = list_first_content(list);
570 while (item) {
571 if (item->title) ho_free(item->title);
572 if (item->data) ho_free(item->data);
573 list_delete_current(list);
574 ho_free(item);
575 item = list_first_content(list);
576 }
577
578 list_free(list);
579 }
580
main_menu_cb(void * data)581 static void main_menu_cb(void *data) {
582
583 oxine_t *oxine = (oxine_t*) data;
584 menuitem_t *item;
585 otk_widget_t *b;
586
587 lock_job_mutex();
588 if (oxine->info_window) {
589 media_info_close_cb(oxine);
590 }
591 unlock_job_mutex();
592
593 oxine->pauseplay = NULL;
594 oxine->main_window = NULL;
595
596 otk_clear(oxine->otk);
597
598 #if 0
599 oxine->main_window = otk_window_new (oxine->otk, NULL, 50, 130, 700, 420);
600
601 /*
602 b = otk_button_new (oxine->main_window, 50, 45, 290, 60, "Play Disc", disc_cb, oxine);
603 otk_set_focus(b);
604 */
605
606 b = otk_button_new (oxine->main_window, 360, 45, 290, 60, "Mediamarks", mediamarks_cb, oxine);
607 otk_set_focus(b);
608
609 /*
610 b = otk_button_new (oxine->main_window, 50, 150, 290, 60, "Analogue TV", tv_cb, oxine);
611 otk_set_focus(b);
612 */
613
614 otk_button_new (oxine->main_window, 360, 150, 290, 60, "Playlist", playlist_cb, oxine);
615
616 /*
617 otk_button_new (oxine->main_window, 50, 255, 290, 60, "Digital TV", dvb_cb, oxine);
618
619 otk_button_new (oxine->main_window, 360, 255, 290, 60, "Control", control_cb, oxine);
620 */
621
622 otk_button_new (oxine->main_window, 205, 320, 290, 60, "Shutdown", shutdown_cb, oxine);
623
624 /* otk_button_new (oxine->main_window, 50, 180, 290, 60, "File", file_cb, oxine);
625 otk_button_new (oxine->main_window, 50, 260, 290, 60, "Streaming", streaming_cb, oxine);*/
626 #endif
627
628 oxine->main_window = otk_window_new (oxine->otk, NULL, oxine->win_x, oxine->win_y,
629 oxine->win_w, oxine->win_h);
630
631 item = list_first_content(oxine->main_menu_items);
632
633 while (item) {
634
635 b = otk_button_new (oxine->main_window, item->x, item->y, item->w, item->h,
636 item->title, item->func, (item->data) ? item->data : oxine);
637 otk_set_focus(b);
638
639 item = list_next_content(oxine->main_menu_items);
640 }
641
642
643 otk_draw_all(oxine->otk);
644 }
645
return_cb(void * this)646 static void return_cb(void *this) {
647 oxine_t *oxine = (oxine_t*) this;
648
649 if (oxine->reentry)
650 oxine->reentry(oxine->reentry_data);
651 else
652 oxine->main_menu_cb(oxine);
653 return;
654 }
655
oxine_error_msg(const char * text)656 static void oxine_error_msg(const char *text)
657 {
658 oxine_t *oxine = oxine_instance_get();
659 otk_widget_t *b;
660 int l;
661 char *text2, *s;
662
663 if (!oxine)
664 return;
665
666 s = text2 = strdup(text);
667
668 otk_clear(oxine->otk);
669 oxine->main_window = otk_window_new (oxine->otk, NULL, 100, 150, 600, 300);
670
671 for( l = 0; l < 4 && s && strlen(s); l++ ) {
672 char *line = s;
673 otk_widget_t *label;
674
675 if( (s = strchr(s,'\n')) ) {
676 *s++ = '\0';
677 }
678
679 label = otk_label_new(oxine->main_window, 300, 30 + l*25,
680 OTK_ALIGN_CENTER|OTK_ALIGN_VCENTER, line);
681 otk_label_set_font_size(label, 20);
682 }
683
684 b = otk_button_new(oxine->main_window, 260, 240, 80, 50, "OK", return_cb, oxine);
685 otk_set_focus(b);
686 oxine->mode = OXINE_MODE_MAINMENU;
687 otk_draw_all(oxine->otk);
688
689 free(text2);
690
691 oxine_instance_unget(oxine);
692 }
693
694 /*
695 * initialisation
696 */
697
create_oxine(void)698 static oxine_t *create_oxine(void) {
699
700 oxine_t *oxine;
701 xine_cfg_entry_t centry;
702
703 oxine = ho_new(oxine_t);
704
705 oxine->main_menu_cb = main_menu_cb;
706
707 oxine->xine = __xineui_global_xine_instance;
708
709 oxine->cd_mountpoint =
710 xine_config_register_string (oxine->xine,
711 "gui.osdmenu.dvd_mountpoint",
712 "/dvd",
713 "directory a media in dvd device will be mounted",
714 "directory a media in dvd device will be mounted",
715 10,
716 NULL,
717 NULL);
718
719 if (xine_config_lookup_entry (oxine->xine, "input.dvd_device", ¢ry)) {
720 oxine->cd_device = centry.str_value;
721 }
722
723 start_scheduler();
724
725 oxine->odk = odk_init();
726
727 oxine->otk = otk_init(oxine->odk);
728
729 oxine->mode = OXINE_MODE_NORMAL;
730
731 return oxine;
732 }
733
destroy_oxine(oxine_t * oxine)734 static void destroy_oxine(oxine_t *oxine) {
735
736 if (oxine->otk) otk_free(oxine->otk);
737 if (oxine->odk) odk_free(oxine->odk);
738
739 main_menu_free(oxine->main_menu_items);
740
741 ho_free(oxine);
742
743 stop_scheduler();
744
745 #ifdef DEBUG
746 heapstat();
747 #endif
748 }
749
oxine_menu(void)750 void oxine_menu(void)
751 {
752 oxine_t *oxine = oxine_instance_get();
753
754 if( !oxine )
755 return;
756
757 if( !oxine->main_menu_items )
758 main_menu_init(oxine);
759
760 if( !oxine->main_menu_items ) {
761 printf("oxine: main menu items missing, check ~/.xine/oxine/mainmenu\n");
762 oxine_instance_unget(oxine);
763 return;
764 }
765
766 oxine_adapt();
767
768 if( oxine->mode != OXINE_MODE_MAINMENU ) {
769 video_window_reset_ssaver (gGui->vwin);
770 gGui->nongui_error_msg = oxine_error_msg;
771
772 if( oxine->reentry )
773 oxine->reentry(oxine->reentry_data);
774 else
775 main_menu_cb(oxine);
776 oxine->mode = OXINE_MODE_MAINMENU;
777 } else {
778 oxine->mode = OXINE_MODE_NORMAL;
779 otk_clear(oxine->otk);
780 }
781
782 oxine_instance_unget(oxine);
783 }
784
oxine_action_event(int xine_event_type)785 int oxine_action_event(int xine_event_type)
786 {
787 oxine_t *oxine = oxine_instance_get();
788 oxine_event_t ev;
789
790 if( !oxine )
791 return 0;
792
793 if( oxine->mode == OXINE_MODE_NORMAL ) {
794 oxine_instance_unget(oxine);
795 return 0;
796 }
797
798 ev.type = OXINE_EVENT_KEY;
799
800 switch( xine_event_type ) {
801 default:
802 oxine_instance_unget(oxine);
803 return 0;
804 case XINE_EVENT_INPUT_UP:
805 ev.key = OXINE_KEY_UP;
806 break;
807 case XINE_EVENT_INPUT_DOWN:
808 ev.key = OXINE_KEY_DOWN;
809 break;
810 case XINE_EVENT_INPUT_LEFT:
811 ev.key = OXINE_KEY_LEFT;
812 break;
813 case XINE_EVENT_INPUT_RIGHT:
814 ev.key = OXINE_KEY_RIGHT;
815 break;
816 case XINE_EVENT_INPUT_SELECT:
817 gGui->nongui_error_msg = oxine_error_msg;
818 ev.key = OXINE_KEY_SELECT;
819 break;
820 }
821
822 video_window_reset_ssaver (gGui->vwin);
823 otk_send_event(oxine->otk, &ev);
824 oxine_instance_unget(oxine);
825 return 1;
826 }
827
oxine_mouse_event(int xine_event_type,int x,int y)828 int oxine_mouse_event(int xine_event_type, int x, int y) {
829 oxine_t *oxine = oxine_instance_get();
830 oxine_event_t ev;
831 int retval;
832
833 if( !oxine )
834 return 0;
835
836 if( oxine->mode == OXINE_MODE_NORMAL ) {
837 oxine_instance_unget(oxine);
838 return 0;
839 }
840
841 ev.x = x;
842 ev.y = y;
843
844 switch( xine_event_type ) {
845 default:
846 oxine_instance_unget(oxine);
847 return 0;
848 case XINE_EVENT_INPUT_MOUSE_MOVE:
849 ev.type = OXINE_EVENT_MOTION;
850 break;
851 case XINE_EVENT_INPUT_MOUSE_BUTTON:
852 gGui->nongui_error_msg = oxine_error_msg;
853 ev.type = OXINE_EVENT_BUTTON;
854 ev.key = OXINE_BUTTON1;
855 break;
856 }
857
858 video_window_reset_ssaver (gGui->vwin);
859 retval = otk_send_event(oxine->otk, &ev);
860 oxine_instance_unget(oxine);
861 return retval;
862 }
863
oxine_adapt(void)864 void oxine_adapt(void)
865 {
866 oxine_t *oxine = oxine_instance_get();
867 oxine_event_t ev;
868
869 if( !oxine )
870 return;
871
872 ev.type = OXINE_EVENT_FORMAT_CHANGED;
873 otk_send_event(oxine->otk, &ev);
874 oxine_instance_unget(oxine);
875 }
876
877 static pthread_mutex_t oxine_instance_mutex = PTHREAD_MUTEX_INITIALIZER;
878 static pthread_cond_t oxine_instance_unlocked = PTHREAD_COND_INITIALIZER;
879 static oxine_t *oxine_instance = NULL;
880 static int oxine_instance_locks = 0;
881
oxine_instance_get(void)882 oxine_t *oxine_instance_get(void)
883 {
884 oxine_t *oxine;
885
886 pthread_mutex_lock(&oxine_instance_mutex);
887
888 oxine = oxine_instance;
889 if (oxine)
890 oxine_instance_locks++;
891
892 pthread_mutex_unlock(&oxine_instance_mutex);
893
894 return oxine;
895 }
896
oxine_instance_unget(oxine_t * oxine)897 void oxine_instance_unget(oxine_t *oxine)
898 {
899 pthread_mutex_lock(&oxine_instance_mutex);
900
901 if (0 == --oxine_instance_locks)
902 pthread_cond_broadcast(&oxine_instance_unlocked);
903
904 pthread_mutex_unlock(&oxine_instance_mutex);
905 }
906
oxine_init(void)907 void oxine_init(void)
908 {
909 pthread_mutex_lock(&oxine_instance_mutex);
910
911 oxine_instance = create_oxine();
912 oxine_instance_locks = 1;
913
914 pthread_mutex_unlock(&oxine_instance_mutex);
915 }
916
oxine_exit(void)917 void oxine_exit(void)
918 {
919 oxine_t *oxine = oxine_instance;
920
921 pthread_mutex_lock(&oxine_instance_mutex);
922
923 oxine_instance = NULL;
924 oxine_instance_locks--;
925
926 while (oxine_instance_locks > 0)
927 pthread_cond_wait(&oxine_instance_unlocked, &oxine_instance_mutex);
928
929 destroy_oxine(oxine);
930
931 pthread_mutex_unlock(&oxine_instance_mutex);
932 }
933