2 * omnplay.c -- GTK+ 2 omnplay
3 * Copyright (C) 2011 Maksym Veremeyenko <verem@m1stereo.tv>
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.
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.
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 Foundation,
17 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
32 #include <gdk/gdkkeysyms.h>
40 #include "omplrclnt.h"
42 static gboolean
on_main_window_delete_event( GtkWidget
*widget
, GdkEvent
*event
, gpointer user_data
)
48 omnplay_instance_t
* omnplay_create(int argc
, char** argv
)
51 omnplay_instance_t
* app
;
53 /* prepare application instance */
54 app
= (omnplay_instance_t
*)malloc(sizeof(omnplay_instance_t
));
55 memset(app
, 0, sizeof(omnplay_instance_t
));
57 /* load parameters from command line */
58 if(!omnplay_opt(argc
, argv
, app
) && app
->players
.count
)
59 app
->window
= ui_omnplay(app
);
66 void omnplay_destroy(omnplay_instance_t
* app
)
71 static int find_index_of_playlist_item(omnplay_instance_t
* app
, int start
, int idx
)
75 if(app
->playlist
.item
[start
].omn_idx
== idx
)
78 if(app
->playlist
.item
[start
].type
& OMNPLAY_PLAYLIST_BLOCK_END
)
87 static void omnplay_update_status(omnplay_player_t
* player
, OmPlrStatus
*prev
, OmPlrStatus
*curr
)
90 char tc_cur
[32], tc_rem
[32], state
[32], status
[32];
95 frames2tc(curr
->pos
- curr
->minPos
, 25.0, tc_cur
);
96 frames2tc(curr
->maxPos
- curr
->pos
, 25.0, tc_rem
);
97 strcpy(status
, "ONLINE");
98 clip
= curr
->currClipName
;
102 case omPlrStateStopped
: strcpy(state
, "STOPPED"); break;
103 case omPlrStateCuePlay
: strcpy(state
, "CUE_PLAY"); break;
104 case omPlrStatePlay
: strcpy(state
, "PLAY"); break;
105 case omPlrStateCueRecord
: strcpy(state
, "CUE_RECORD"); break;
106 case omPlrStateRecord
: strcpy(state
, "RECORD"); break;
115 strcpy(status
, "OFFLINE");
118 /* update status in status page */
120 gtk_label_set_text(GTK_LABEL (player
->label_tc_cur
), tc_cur
);
121 gtk_label_set_text(GTK_LABEL (player
->label_tc_rem
), tc_rem
);
122 gtk_label_set_text(GTK_LABEL (player
->label_state
), state
);
123 gtk_label_set_text(GTK_LABEL (player
->label_status
), status
);
124 gtk_label_set_text(GTK_LABEL (player
->label_clip
), clip
);
128 /* update remaining time */
130 pthread_mutex_lock(&player
->app
->playlist
.lock
);
131 pthread_mutex_lock(&player
->app
->players
.lock
);
132 if(curr
->state
== omPlrStatePlay
|| curr
->state
== omPlrStateCuePlay
)
134 idx
= find_index_of_playlist_item(player
->app
, player
->playlist_start
, curr
->currClipNum
);
137 frames2tc(curr
->currClipStartPos
+ curr
->currClipLen
- curr
->pos
, 25.0, tc_rem
);
138 omnplay_playlist_draw_item_rem(player
->app
, idx
, tc_rem
);
140 if(curr
->currClipNum
!= prev
->currClipNum
&& 1 != prev
->numClips
)
143 idx
= find_index_of_playlist_item(player
->app
, player
->playlist_start
, prev
->currClipNum
);
145 omnplay_playlist_draw_item_rem(player
->app
, idx
, tc_rem
);
151 idx
= find_index_of_playlist_item(player
->app
, player
->playlist_start
, curr
->currClipNum
);
153 omnplay_playlist_draw_item_rem(player
->app
, idx
, tc_rem
);
154 idx
= find_index_of_playlist_item(player
->app
, player
->playlist_start
, prev
->currClipNum
);
156 omnplay_playlist_draw_item_rem(player
->app
, idx
, tc_rem
);
158 pthread_mutex_unlock(&player
->app
->players
.lock
);
159 pthread_mutex_unlock(&player
->app
->playlist
.lock
);
164 memcpy(prev
, curr
, sizeof(OmPlrStatus
));
167 static void* omnplay_thread_proc(void* data
)
170 OmPlrStatus st_curr
, st_prev
;
171 omnplay_player_t
* player
= (omnplay_player_t
*)data
;
174 pthread_mutex_lock(&player
->app
->players
.lock
);
175 r
= OmPlrOpen(player
->host
, player
->name
, (OmPlrHandle
*)&player
->handle
);
176 pthread_mutex_unlock(&player
->app
->players
.lock
);
179 fprintf(stderr
, "ERROR: OmPlrOpen(%s, %s) failed with 0x%.8X\n",
180 player
->host
, player
->name
, r
);
185 /* setup to do not reconnect */
186 pthread_mutex_lock(&player
->app
->players
.lock
);
187 OmPlrSetRetryOpen((OmPlrHandle
)player
->handle
, 0);
188 pthread_mutex_unlock(&player
->app
->players
.lock
);
190 /* setup directory */
191 if(player
->app
->players
.path
[0])
193 pthread_mutex_lock(&player
->app
->players
.lock
);
194 r
= OmPlrClipSetDirectory((OmPlrHandle
)player
->handle
, player
->app
->players
.path
);
195 pthread_mutex_unlock(&player
->app
->players
.lock
);
199 fprintf(stderr
, "ERROR: OmPlrClipSetDirectory(%s) failed with 0x%.8X\n",
200 player
->app
->players
.path
, r
);
202 pthread_mutex_lock(&player
->app
->players
.lock
);
203 OmPlrClose((OmPlrHandle
)player
->handle
);
204 pthread_mutex_unlock(&player
->app
->players
.lock
);
211 for(r
= 0 ; !player
->app
->f_exit
&& !r
;)
217 pthread_mutex_lock(&player
->app
->players
.lock
);
218 st_curr
.size
= sizeof(OmPlrStatus
);
219 r
= OmPlrGetPlayerStatus((OmPlrHandle
)player
->handle
, &st_curr
);
220 pthread_mutex_unlock(&player
->app
->players
.lock
);
223 fprintf(stderr
, "ERROR: OmPlrGetPlayerStatus failed with 0x%.8X\n", r
);
225 if(memcmp(&st_curr
, &st_prev
, sizeof(OmPlrStatus
)))
226 omnplay_update_status(player
, &st_prev
, &st_curr
);
229 pthread_mutex_lock(&player
->app
->players
.lock
);
230 OmPlrClose((OmPlrHandle
)player
->handle
);
231 pthread_mutex_unlock(&player
->app
->players
.lock
);
236 void get_selected_items_playlist_proc(GtkTreeModel
*model
, GtkTreePath
*path
, GtkTreeIter
*iter
, gpointer data
)
238 int idx
, *list
= (int*)data
;
239 gtk_tree_model_get(model
, iter
, 7, &idx
, -1);
240 list
[list
[0] + 1] = idx
;
241 list
[0] = list
[0] + 1;
244 static int* get_selected_items_playlist(omnplay_instance_t
* app
)
247 GtkTreeSelection
*selection
;
249 selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(app
->playlist_grid
));
252 list
= (int*)malloc(sizeof(int) * (MAX_PLAYLIST_ITEMS
+ 1));
253 memset(list
, 0, sizeof(int) * (MAX_PLAYLIST_ITEMS
+ 1));
255 gtk_tree_selection_selected_foreach(
257 get_selected_items_playlist_proc
,
270 static int idx_in_players_range(omnplay_instance_t
* app
, int idx
)
274 for(i
= 0; i
< app
->players
.count
&& !r
; i
++)
278 a
= app
->players
.item
[i
].playlist_start
;
279 b
= app
->players
.item
[i
].playlist_length
;
286 if(idx
>= a
&& idx
<= b
) r
= 1;
292 static int idxs_in_players_range(omnplay_instance_t
* app
, int start
, int stop
)
296 for(i
= 0; i
< app
->players
.count
&& !r
; i
++)
300 a
= app
->players
.item
[i
].playlist_start
;
301 b
= app
->players
.item
[i
].playlist_length
;
308 #define IN_RANGE(A,B,C) (A <= C && C <= B)
309 if( IN_RANGE(a
,b
,start
) ||
310 IN_RANGE(a
,b
,stop
) ||
311 IN_RANGE(start
,stop
,a
) ||
312 IN_RANGE(start
,stop
,b
))
319 static void omnplay_playlist_block(omnplay_instance_t
* app
, control_buttons_t button
)
321 int start
, stop
, r
, i
;
322 int* list
= get_selected_items_playlist(app
);
327 pthread_mutex_lock(&app
->playlist
.lock
);
328 pthread_mutex_lock(&app
->players
.lock
);
331 stop
= list
[list
[0]];
333 if(!idxs_in_players_range(app
, start
, stop
))
335 int loop
= (button
== BUTTON_PLAYLIST_BLOCK_LOOP
)?OMNPLAY_PLAYLIST_BLOCK_LOOP
:0;
337 /* update selected item */
338 for(i
= start
; i
<= stop
; i
++)
340 int t
= OMNPLAY_PLAYLIST_BLOCK_BODY
| loop
;
342 if(i
== start
) t
|= OMNPLAY_PLAYLIST_BLOCK_BEGIN
;
343 if(i
== stop
) t
|= OMNPLAY_PLAYLIST_BLOCK_END
;
345 app
->playlist
.item
[i
].type
= (playlist_item_type_t
)t
;
347 omnplay_playlist_draw_item(app
, i
);
350 /* update border items */
351 if(!start
&& !(app
->playlist
.item
[start
- 1].type
& OMNPLAY_PLAYLIST_BLOCK_END
))
353 app
->playlist
.item
[start
- 1].type
= (playlist_item_type_t
)(OMNPLAY_PLAYLIST_BLOCK_END
354 | app
->playlist
.item
[start
- 1].type
);
355 omnplay_playlist_draw_item(app
, start
- 1);
357 if((stop
+ 1) < app
->playlist
.count
&& !(app
->playlist
.item
[stop
+ 1].type
& OMNPLAY_PLAYLIST_BLOCK_BEGIN
))
359 app
->playlist
.item
[stop
+ 1].type
= (playlist_item_type_t
)(OMNPLAY_PLAYLIST_BLOCK_BEGIN
360 | app
->playlist
.item
[stop
+ 1].type
);
361 omnplay_playlist_draw_item(app
, stop
+ 1);
365 fprintf(stderr
, "omnplay_playlist_block: range [%d %d] do OVERLAP player\n",
368 pthread_mutex_unlock(&app
->players
.lock
);
369 pthread_mutex_unlock(&app
->playlist
.lock
);
374 static int get_first_selected_item_playlist(omnplay_instance_t
* app
)
377 int* list
= get_selected_items_playlist(app
);
384 static int get_playlist_block(omnplay_instance_t
* app
, int idx
, int* start_ptr
, int* stop_ptr
)
388 for(start
= idx
; start
>= 0; start
--)
389 if(app
->playlist
.item
[start
].type
& OMNPLAY_PLAYLIST_BLOCK_BEGIN
)
392 for(stop
= idx
; stop
< app
->playlist
.count
; stop
++)
393 if(app
->playlist
.item
[stop
].type
& OMNPLAY_PLAYLIST_BLOCK_END
)
396 fprintf(stderr
, "get_playlist_block: range %d -> %d\n", start
, stop
);
398 /* check block range */
399 if(start
>= 0 && stop
< app
->playlist
.count
)
403 return (stop
- start
+ 1);
409 static omnplay_player_t
*get_player_at_pos(omnplay_instance_t
* app
, int pos
)
411 /* check player range */
412 if(app
->playlist
.item
[pos
].player
> -1 && app
->playlist
.item
[pos
].player
< app
->players
.count
)
413 return &app
->players
.item
[app
->playlist
.item
[pos
].player
];
418 static void omnplay_playlist_delete_items(omnplay_instance_t
* app
, int* idxs
, int count
)
423 pthread_mutex_lock(&app
->playlist
.lock
);
424 pthread_mutex_lock(&app
->players
.lock
);
426 for(j
= 0; j
< count
; j
++)
430 /* fix block types */
432 app
->playlist
.item
[idx
- 1].type
= (playlist_item_type_t
)(app
->playlist
.item
[idx
- 1].type
|
433 OMNPLAY_PLAYLIST_BLOCK_END
);
434 if(idx
+ 1 < app
->playlist
.count
)
435 app
->playlist
.item
[idx
+ 1].type
= (playlist_item_type_t
)(app
->playlist
.item
[idx
+ 1].type
|
436 OMNPLAY_PLAYLIST_BLOCK_BEGIN
);
438 /* shift playlist items */
441 &app
->playlist
.item
[idx
],
442 &app
->playlist
.item
[idx
+ 1],
443 (app
->playlist
.count
- idx
- 1) * sizeof(playlist_item_t
)
446 /* decrement items count */
447 app
->playlist
.count
--;
449 /* increment servers indexes */
450 for(i
= 0; i
< app
->players
.count
; i
++)
451 if(app
->players
.item
[i
].playlist_start
>= idx
)
452 app
->players
.item
[i
].playlist_start
--;
457 /* redraw playlist */
458 omnplay_playlist_draw(app
);
461 path
= gtk_tree_path_new_from_indices(idxs
[0], -1);
462 gtk_tree_selection_select_path(gtk_tree_view_get_selection(GTK_TREE_VIEW(app
->playlist_grid
)), path
);
463 gtk_tree_view_set_cursor(GTK_TREE_VIEW(app
->playlist_grid
), path
, NULL
, FALSE
);
464 gtk_tree_path_free(path
);
467 pthread_mutex_unlock(&app
->players
.lock
);
468 pthread_mutex_unlock(&app
->playlist
.lock
);
471 static void omnplay_playlist_item_del(omnplay_instance_t
* app
)
476 list
= get_selected_items_playlist(app
);
479 list2
= (int*)malloc(sizeof(int) * list
[0]);
481 for(i
= 0, c
= 0; i
< list
[0]; i
++)
483 /* check for playing block */
484 if(idx_in_players_range(app
, list
[i
+ 1]))
488 list2
[c
++] = list
[i
+ 1];
492 omnplay_playlist_delete_items(app
, list2
, c
);
498 static int omnplay_playlist_insert_check(omnplay_instance_t
* app
, int idx
, playlist_item_type_t
* t
)
500 *t
= OMNPLAY_PLAYLIST_ITEM_BLOCK_SINGLE
;
502 /* before or after playlist */
503 if(!idx
|| idx
== app
->playlist
.count
)
506 /* check for block borders */
507 if( app
->playlist
.item
[idx
- 1].type
& OMNPLAY_PLAYLIST_BLOCK_END
&&
508 app
->playlist
.item
[idx
+ 0].type
& OMNPLAY_PLAYLIST_BLOCK_BEGIN
)
511 /* check for playing block */
512 if(idx_in_players_range(app
, idx
))
515 if(app
->playlist
.item
[idx
].type
& OMNPLAY_PLAYLIST_BLOCK_LOOP
)
516 *t
= OMNPLAY_PLAYLIST_ITEM_LOOP_BODY
;
518 *t
= OMNPLAY_PLAYLIST_ITEM_BLOCK_BODY
;
523 static void omnplay_playlist_insert_items(omnplay_instance_t
* app
, int idx
,
524 playlist_item_t
* items
, int count
)
529 pthread_mutex_lock(&app
->playlist
.lock
);
530 pthread_mutex_lock(&app
->players
.lock
);
532 /* shift playlist items */
535 &app
->playlist
.item
[idx
+ count
],
536 &app
->playlist
.item
[idx
],
537 (app
->playlist
.count
- idx
) * sizeof(playlist_item_t
)
543 &app
->playlist
.item
[idx
],
545 count
* sizeof(playlist_item_t
)
548 /* increment servers indexes */
549 for(i
= 0; i
< app
->players
.count
; i
++)
550 if(app
->players
.item
[i
].playlist_start
>= idx
)
551 app
->players
.item
[i
].playlist_start
+= idx
;
553 /* increment items count */
554 app
->playlist
.count
+= count
;
556 /* redraw playlist */
557 omnplay_playlist_draw(app
);
560 path
= gtk_tree_path_new_from_indices(idx
+ count
, -1);
561 gtk_tree_selection_select_path(gtk_tree_view_get_selection(GTK_TREE_VIEW(app
->playlist_grid
)), path
);
562 gtk_tree_view_set_cursor(GTK_TREE_VIEW(app
->playlist_grid
), path
, NULL
, FALSE
);
563 gtk_tree_path_free(path
);
565 pthread_mutex_unlock(&app
->players
.lock
);
566 pthread_mutex_unlock(&app
->playlist
.lock
);
569 static void omnplay_playlist_item_add(omnplay_instance_t
* app
, int after
)
572 playlist_item_t item
;
573 playlist_item_type_t t
;
575 /* find insert position */
576 idx
= get_first_selected_item_playlist(app
);
582 if(!omnplay_playlist_insert_check(app
, idx
, &t
))
585 fprintf(stderr
, "allowed insert into idx=%d\n", idx
);
588 memset(&item
, 0, sizeof(playlist_item_t
));
589 if(ui_playlist_item_dialog(app
, &item
))
592 omnplay_playlist_insert_items(app
, idx
, &item
, 1);
596 static void omnplay_playlist_item_edit(omnplay_instance_t
* app
)
599 playlist_item_t item
;
601 /* find insert position */
602 idx
= get_first_selected_item_playlist(app
);
607 /* check for playing block */
608 if(idx_in_players_range(app
, idx
))
611 item
= app
->playlist
.item
[idx
];
613 if(ui_playlist_item_dialog(app
, &item
))
615 app
->playlist
.item
[idx
] = item
;
616 omnplay_playlist_draw_item(app
, idx
);
620 static void omnplay_ctl(omnplay_instance_t
* app
, control_buttons_t button
)
623 int idx
, start
, stop
;
624 omnplay_player_t
*player
;
626 pthread_mutex_lock(&app
->playlist
.lock
);
628 idx
= get_first_selected_item_playlist(app
);
632 pthread_mutex_unlock(&app
->playlist
.lock
);
636 fprintf(stderr
, "cue: selected item is %d\n", idx
);
638 if(get_playlist_block(app
, idx
, &start
, &stop
) < 0)
640 pthread_mutex_unlock(&app
->playlist
.lock
);
644 fprintf(stderr
, "cue: range %d -> %d\n", start
, stop
);
646 player
= get_player_at_pos(app
, start
);
650 pthread_mutex_unlock(&app
->playlist
.lock
);
654 pthread_mutex_lock(&app
->players
.lock
);
656 if(BUTTON_PLAYER_STOP
== button
|| BUTTON_PLAYER_CUE
== button
)
659 OmPlrStop((OmPlrHandle
)player
->handle
);
661 /* detach previous clips */
662 player
->playlist_length
= -1;
663 OmPlrDetachAllClips((OmPlrHandle
)player
->handle
);
666 if(BUTTON_PLAYER_CUE
== button
)
670 /* Attach clips to timeline */
671 for(i
= start
, c
= 0, o
= 0; i
<= stop
; i
++)
676 clip
.maxMsTracks
= 0;
677 clip
.size
= sizeof(clip
);
678 r
= OmPlrClipGetInfo((OmPlrHandle
)player
->handle
, app
->playlist
.item
[i
].id
, &clip
);
684 fprintf(stderr
, "OmPlrClipGetInfo(%s): firstFrame=%d, lastFrame=%d\n",
685 app
->playlist
.item
[i
].id
, clip
.firstFrame
, clip
.lastFrame
);
687 /* should we fix playlist clip timings */
689 app
->playlist
.item
[i
].in
>= clip
.firstFrame
&&
690 app
->playlist
.item
[i
].in
+ app
->playlist
.item
[i
].dur
<= clip
.lastFrame
) ||
691 !app
->playlist
.item
[i
].dur
)
693 fprintf(stderr
, "cue: item [%s] will be updated [%d;%d]->[%d;%d]\n",
694 app
->playlist
.item
[i
].id
,
695 app
->playlist
.item
[i
].in
, app
->playlist
.item
[i
].dur
,
696 clip
.firstFrame
, clip
.lastFrame
- clip
.firstFrame
);
698 app
->playlist
.item
[i
].in
= clip
.firstFrame
;
699 app
->playlist
.item
[i
].dur
= clip
.lastFrame
- clip
.firstFrame
;
700 omnplay_playlist_draw_item(app
, i
);
703 r
= OmPlrAttach((OmPlrHandle
)player
->handle
,
704 app
->playlist
.item
[i
].id
,
705 app
->playlist
.item
[i
].in
,
706 app
->playlist
.item
[i
].in
+ app
->playlist
.item
[i
].dur
,
707 0, omPlrShiftModeAfter
, &l
);
712 fprintf(stderr
, "cue: failed with %d, %s\n", r
, OmPlrGetErrorString((OmPlrError
)r
));
713 app
->playlist
.item
[i
].omn_idx
= -1;
714 app
->playlist
.item
[i
].omn_offset
= -1;
718 app
->playlist
.item
[i
].omn_idx
= c
;
719 app
->playlist
.item
[i
].omn_offset
= o
;
721 /* save selected item offset */
725 o
+= app
->playlist
.item
[i
].dur
;
733 /* Set timeline min/max */
734 OmPlrSetMinPosMin((OmPlrHandle
)player
->handle
);
735 OmPlrSetMaxPosMax((OmPlrHandle
)player
->handle
);
737 /* Set timeline position */
739 hs
.size
= sizeof(OmPlrStatus
);
740 OmPlrGetPlayerStatus((OmPlrHandle
)player
->handle
, &hs
);
741 OmPlrSetPos((OmPlrHandle
)player
->handle
, hs
.minPos
+ p
);
744 if(app
->playlist
.item
[start
].type
& OMNPLAY_PLAYLIST_BLOCK_LOOP
)
745 OmPlrLoop((OmPlrHandle
)player
->handle
, hs
.minPos
, hs
.maxPos
);
747 OmPlrLoop((OmPlrHandle
)player
->handle
, hs
.minPos
, hs
.minPos
);
749 player
->playlist_start
= start
;
750 player
->playlist_length
= stop
- start
+ 1;
753 OmPlrCuePlay((OmPlrHandle
)player
->handle
, 0.0);
757 if(BUTTON_PLAYER_PLAY
== button
)
760 OmPlrPlay((OmPlrHandle
)player
->handle
, 1.0);
763 if(BUTTON_PLAYER_PAUSE
== button
)
765 OmPlrPlay((OmPlrHandle
)player
->handle
, 0.0);
767 pthread_mutex_unlock(&app
->players
.lock
);
769 pthread_mutex_unlock(&app
->playlist
.lock
);
772 static gboolean
omnplay_button_click(omnplay_instance_t
* app
, control_buttons_t button
)
776 case BUTTON_PLAYLIST_ITEM_ADD
:
777 omnplay_playlist_item_add(app
, 0);
779 case BUTTON_PLAYLIST_ITEM_DEL
:
780 omnplay_playlist_item_del(app
);
782 case BUTTON_PLAYLIST_ITEM_EDIT
:
783 omnplay_playlist_item_edit(app
);
785 case BUTTON_PLAYLIST_LOAD
:
786 omnplay_playlist_load(app
);
788 case BUTTON_PLAYLIST_SAVE
:
789 omnplay_playlist_save(app
);
791 case BUTTON_PLAYLIST_BLOCK_SINGLE
:
792 case BUTTON_PLAYLIST_BLOCK_LOOP
:
793 omnplay_playlist_block(app
, button
);
795 case BUTTON_PLAYLIST_ITEM_UP
:
796 case BUTTON_PLAYLIST_ITEM_DOWN
:
798 case BUTTON_PLAYER_CUE
:
799 case BUTTON_PLAYER_PLAY
:
800 case BUTTON_PLAYER_PAUSE
:
801 case BUTTON_PLAYER_STOP
:
802 omnplay_ctl(app
, button
);
804 case BUTTON_LIBRARY_ADD
:
805 case BUTTON_LIBRARY_REFRESH
:
812 static gboolean
on_button_click(GtkWidget
*button
, gpointer user_data
)
815 omnplay_instance_t
* app
= (omnplay_instance_t
*)user_data
;
817 for(i
= 1; i
< BUTTON_LAST
; i
++)
818 if(app
->buttons
[i
] == button
)
819 return omnplay_button_click(app
, (control_buttons_t
)i
);
824 void omnplay_init(omnplay_instance_t
* app
)
827 pthread_mutexattr_t attr
;
829 pthread_mutexattr_settype(&attr
, PTHREAD_MUTEX_RECURSIVE
);
831 gtk_signal_connect( GTK_OBJECT( app
->window
), "destroy",
832 GTK_SIGNAL_FUNC(on_main_window_delete_event
), app
);
835 pthread_mutex_init(&app
->players
.lock
, &attr
);
837 /* create a omneon status thread */
838 for(i
= 0; i
< app
->players
.count
; i
++)
839 pthread_create(&app
->players
.item
[i
].thread
, NULL
,
840 omnplay_thread_proc
, &app
->players
.item
[i
]);
843 pthread_mutex_init(&app
->playlist
.lock
, &attr
);
845 /* attach buttons click */
846 for(i
= 1; i
< BUTTON_LAST
; i
++)
847 gtk_signal_connect(GTK_OBJECT(app
->buttons
[i
]), "clicked",
848 GTK_SIGNAL_FUNC( on_button_click
), app
);
852 void omnplay_release(omnplay_instance_t
* app
)
859 for(i
= 0; i
< app
->players
.count
; i
++)
860 /* create a omneon status thread */
861 pthread_join(app
->players
.item
[i
].thread
, &r
);
864 pthread_mutex_destroy(&app
->players
.lock
);
867 pthread_mutex_destroy(&app
->playlist
.lock
);