uncomment implemented functions
[melted_gui] / src / instance.c
1 /*
2 * instance.c -- GTK+ 2 melted gui
3 * Copyright (C) 2012 Maksym Veremeyenko <verem@m1stereo.tv>
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 Foundation,
17 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20 #ifndef _GNU_SOURCE
21 #define _GNU_SOURCE
22 #endif
23
24 #ifdef HAVE_CONFIG_H
25 # include <config.h>
26 #endif
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <gtk/gtk.h>
32 #include <gdk/gdkkeysyms.h>
33 #include <pthread.h>
34
35 #include "instance.h"
36 #include "ui.h"
37 #include "opts.h"
38 #include "timecode.h"
39 #include "player.h"
40 #include "library.h"
41 #include "playlist.h"
42
43 GtkTargetEntry drag_targets[] = { { (char*) "application/playlist_item_t", 0, 0 } };
44
45 static gboolean library_tree_key(GtkWidget *widget, GdkEventKey *event, gpointer data)
46 {
47 instance_t* app = (instance_t*)data;
48
49 switch(event->keyval)
50 {
51 case GDK_C:
52 case GDK_c:
53 if(event->state & GDK_CONTROL_MASK)
54 {
55 int count;
56 playlist_item_t* items;
57
58 items = library_get_selected_items(app, &count);
59
60 if(items)
61 {
62 int i;
63
64 for(i = 0; i < count; i++)
65 app->clipboard.item[i] = items[i];
66
67 app->clipboard.count = count;
68 };
69
70 return TRUE;
71 };
72 break;
73 case GDK_V:
74 case GDK_v:
75 if(event->state & GDK_CONTROL_MASK)
76 {
77 g_warning("CTRL+v\n");
78 return TRUE;
79 };
80 break;
81 case GDK_X:
82 case GDK_x:
83 if(event->state & GDK_CONTROL_MASK)
84 {
85 g_warning("CTRL+x\n");
86 return TRUE;
87 };
88 break;
89 case GDK_KEY_BackSpace:
90 // omnplay_library_add(app, 0);
91 return TRUE;
92 case GDK_KEY_F5:
93 // omnplay_library_refresh(app);
94 return TRUE;
95 };
96
97 return FALSE;
98 };
99
100 static gboolean playlist_grid_key(GtkWidget *widget, GdkEventKey *event, gpointer data)
101 {
102 instance_t* app = (instance_t*)data;
103
104 switch(event->keyval)
105 {
106 case GDK_C:
107 case GDK_c:
108 if(event->state & GDK_CONTROL_MASK)
109 {
110 playlist_item_copy(app);
111 return TRUE;
112 };
113 break;
114 case GDK_V:
115 case GDK_v:
116 if(event->state & GDK_CONTROL_MASK)
117 {
118 playlist_item_paste(app, 0);
119 return TRUE;
120 };
121 break;
122 case GDK_X:
123 case GDK_x:
124 if(event->state & GDK_CONTROL_MASK)
125 {
126 playlist_item_copy(app);
127 playlist_delete_selected_items(app);
128 return TRUE;
129 };
130 break;
131 case GDK_S:
132 case GDK_s:
133 if(event->state & GDK_CONTROL_MASK)
134 {
135 playlist_save(app);
136 return TRUE;
137 };
138 break;
139 case GDK_O:
140 case GDK_o:
141 if(event->state & GDK_CONTROL_MASK)
142 {
143 playlist_load(app);
144 return TRUE;
145 };
146 break;
147 case GDK_KEY_uparrow:
148 if(event->state & GDK_CONTROL_MASK)
149 {
150 playlist_item_swap(app, -1);
151 return TRUE;
152 };
153 break;
154 case GDK_KEY_downarrow:
155 if(event->state & GDK_CONTROL_MASK)
156 {
157 playlist_item_swap(app, -1);
158 return TRUE;
159 };
160 break;
161 case GDK_KEY_space:
162 // omnplay_ctl(app, BUTTON_PLAYER_PLAY);
163 return TRUE;
164 case GDK_KEY_Return:
165 // omnplay_ctl(app, BUTTON_PLAYER_CUE);
166 return TRUE;
167 case GDK_KEY_Insert:
168 // omnplay_playlist_item_add(app, 0);
169 return TRUE;
170 case GDK_KEY_Delete:
171 playlist_delete_selected_items(app);
172 return TRUE;
173 case GDK_E:
174 case GDK_e:
175 playlist_item_edit(app);
176 return TRUE;
177 };
178
179 return FALSE;
180 };
181
182 static gboolean library_tree_button(GtkWidget *widget, GdkEventButton *event, gpointer data)
183 {
184 // g_warning("on_library_grid_button: event->button=%d, event->type=%d", event->button, event->type);
185
186 if(event->button==1 && event->type==GDK_2BUTTON_PRESS)
187 {
188 playlist_item_add_from_library((instance_t* )data, 0);
189 return TRUE;
190 };
191
192 return FALSE;
193 };
194
195 static gboolean playlist_grid_button(GtkWidget *widget, GdkEventButton *event, gpointer data)
196 {
197 instance_t* app = (instance_t*)data;
198
199 // g_warning("on_playlist_grid_button");
200
201 if(event->button==1 && event->type==GDK_2BUTTON_PRESS)
202 {
203 playlist_item_edit(app);
204 return TRUE;
205 };
206
207 return FALSE;
208 };
209
210 static gboolean instance_button_click(instance_t* app, control_buttons_t button)
211 {
212 switch(button)
213 {
214 case BUTTON_PLAYLIST_ITEM_ADD:
215 playlist_item_add(app, 0);
216 break;
217 case BUTTON_PLAYLIST_ITEM_DEL:
218 playlist_delete_selected_items(app);
219 break;
220 case BUTTON_PLAYLIST_ITEM_EDIT:
221 playlist_item_edit(app);
222 break;
223 case BUTTON_PLAYLIST_LOAD:
224 playlist_load(app);
225 break;
226 case BUTTON_PLAYLIST_SAVE:
227 playlist_save(app);
228 break;
229 case BUTTON_PLAYLIST_BLOCK_SINGLE:
230 case BUTTON_PLAYLIST_BLOCK_LOOP:
231 playlist_block(app, (BUTTON_PLAYLIST_BLOCK_LOOP == button)?1:0);
232 break;
233 case BUTTON_PLAYLIST_ITEM_UP:
234 playlist_item_swap(app, -1);
235 break;
236 case BUTTON_PLAYLIST_ITEM_DOWN:
237 playlist_item_swap(app, +1);
238 break;
239 case BUTTON_PLAYER_CUE:
240 case BUTTON_PLAYER_PLAY:
241 case BUTTON_PLAYER_PAUSE:
242 case BUTTON_PLAYER_STOP:
243 // omnplay_ctl(app, button);
244 break;
245 case BUTTON_LIBRARY_ADD:
246 playlist_item_add_from_library(app, 0);
247 break;
248 case BUTTON_LIBRARY_REFRESH:
249 // omnplay_library_refresh(app);
250 break;
251 case BUTTON_LIBRARY_FIND:
252 // omnplay_library_search(app, 0);
253 break;
254 case BUTTON_LIBRARY_FIND_NEXT:
255 // omnplay_library_search(app, 1);
256 break;
257 case BUTTON_PLAYLIST_RELINK:
258 // omnplay_playlist_relink(app);
259 break;
260 default:
261 g_warning("instance_button_click: unknow button clicked");
262 };
263 return TRUE;
264 };
265
266 static gboolean on_button_click(GtkWidget *button, gpointer user_data)
267 {
268 int i;
269 instance_t* app = (instance_t*)user_data;
270
271 for(i = 1; i < BUTTON_LAST; i++)
272 if(app->buttons[i] == button)
273 return instance_button_click(app, (control_buttons_t)i);
274
275 return FALSE;
276 };
277
278 static gboolean on_main_window_delete_event( GtkWidget *widget, GdkEvent *event, gpointer user_data )
279 {
280 g_print ("delete event occurred [start]\n");
281 gdk_threads_leave();
282 instance_release((instance_t*)user_data);
283 gdk_threads_enter();
284 g_print ("delete event occurred [finish]\n");
285
286 return FALSE;
287 }
288
289 static void on_main_window_destroy( GtkWidget *widget, gpointer user_data )
290 {
291 g_print ("destroy occurred\n");
292 gtk_main_quit();
293 }
294
295 instance_t* instance_create(int argc, char** argv)
296 {
297 int i, c;
298 instance_t* app;
299
300 /* prepare application instance */
301 app = (instance_t*)malloc(sizeof(instance_t));
302 memset(app, 0, sizeof(instance_t));
303
304 /* load parameters from command line */
305 if(!instance_opt(argc, argv, app) && app->players.count)
306 app->window = ui_create(app);
307 else
308 instance_usage();
309
310 return app;
311 };
312
313 void instance_destroy(instance_t* app)
314 {
315 free(app);
316 };
317
318 void instance_init(instance_t* app)
319 {
320 int i;
321 pthread_mutexattr_t attr;
322
323 gtk_signal_connect( GTK_OBJECT( app->window ), "delete-event",
324 GTK_SIGNAL_FUNC(on_main_window_delete_event), app);
325
326 gtk_signal_connect( GTK_OBJECT( app->window ), "destroy",
327 GTK_SIGNAL_FUNC(on_main_window_destroy), app);
328
329 gtk_widget_add_events(app->playlist_grid, GDK_BUTTON_PRESS_MASK);
330 gtk_widget_add_events(app->playlist_grid, GDK_KEY_PRESS_MASK);
331 gtk_signal_connect(GTK_OBJECT(app->playlist_grid), "key-press-event",
332 GTK_SIGNAL_FUNC(playlist_grid_key), app);
333
334 gtk_widget_add_events(app->library_tree, GDK_BUTTON_PRESS_MASK);
335 gtk_widget_add_events(app->library_tree, GDK_KEY_PRESS_MASK);
336 gtk_signal_connect(GTK_OBJECT(app->library_tree), "key-press-event",
337 GTK_SIGNAL_FUNC(library_tree_key), app);
338
339 gtk_signal_connect(GTK_OBJECT(app->playlist_grid), "button-press-event",
340 GTK_SIGNAL_FUNC(playlist_grid_button), app);
341
342 gtk_signal_connect(GTK_OBJECT(app->library_tree), "button-press-event",
343 GTK_SIGNAL_FUNC(library_tree_button), app);
344
345 /* create lock */
346 pthread_mutexattr_init(&attr);
347 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
348 pthread_mutex_init(&app->players.lock, &attr);
349 pthread_mutex_init(&app->playlist.lock, &attr);
350 pthread_mutex_init(&app->library.lock, &attr);
351 pthread_mutexattr_destroy(&attr);
352
353 /* run unit monitoring threads */
354 for(i = 0; i < app->players.count; i++)
355 player_run(app, i);
356
357 /* attach buttons click */
358 for(i = 1; i < BUTTON_LAST; i++)
359 gtk_signal_connect(GTK_OBJECT(app->buttons[i]), "clicked",
360 GTK_SIGNAL_FUNC( on_button_click), app );
361
362 /* init library */
363 library_init(app);
364
365 /* init playlist */
366 playlist_init(app);
367 };
368
369 void instance_release(instance_t* app)
370 {
371 int i;
372
373 app->f_exit = 1;
374
375 /* stop unit monitoring threads */
376 for(i = 0; i < app->players.count; i++)
377 player_stop(app, i);
378
379 /* release laylist */
380 playlist_release(app);
381
382 /* release library */
383 library_release(app);
384
385 /* destroy lock */
386 pthread_mutex_destroy(&app->players.lock);
387
388 /* destroy lock */
389 pthread_mutex_destroy(&app->playlist.lock);
390
391 /* destroy library lock */
392 pthread_mutex_destroy(&app->library.lock);
393 };