append only the mode for double click of fileslist
[rugen] / src / page_clips.c
1 /*
2 * page_clips.c -- Clips Page Handling
3 * Copyright (C) 2002-2003 Charles Yates <charles.yates@pandora.be>
4 * Copyright (C) 2010 Dan Dennedy <dan@dennedy.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21 #ifdef HAVE_CONFIG_H
22 # include <config.h>
23 #endif
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <gtk/gtk.h>
29 #include <gdk/gdkkeysyms.h>
30
31 #include "interface.h"
32 #include "support.h"
33 #include "dv1394app.h"
34 #include "page.h"
35
36 typedef struct
37 {
38 struct page_t parent;
39 dv1394app app;
40 GtkWidget *widget;
41 mvcp dv;
42 char *path;
43 int unit;
44 int generation;
45 int clip;
46
47 struct page_t *parent_page;
48 }
49 *page_clips, page_clips_t;
50
51 static GtkWidget *this_page_get_widget( page_clips this );
52
53 static void list_clips( page_clips this, char *path )
54 {
55 GtkWidget *treeview = lookup_widget( this_page_get_widget( this ), "list_clips" );
56 GtkWidget *dirview = lookup_widget( this_page_get_widget( this ), "list_dir" );
57 GtkWidget *label = lookup_widget( this_page_get_widget( this ), "label_directory" );
58 if ( path != NULL )
59 {
60 mvcp_dir dir = mvcp_dir_init( this->dv, path );
61 GtkListStore *dir_store = NULL;
62 GtkListStore *clip_store = NULL;
63 GtkTreeIter iter;
64 int index;
65 mvcp_dir_entry_t entry;
66
67 free( this->path );
68 this->path = strdup( path );
69
70 gtk_label_set_text( GTK_LABEL( label ), this->path );
71
72 if ( gtk_tree_view_get_model( GTK_TREE_VIEW( treeview ) ) == NULL )
73 {
74 GtkCellRenderer *renderer;
75 GtkTreeViewColumn *column;
76
77 clip_store = gtk_list_store_new( 2, G_TYPE_STRING, G_TYPE_STRING );
78 gtk_tree_view_set_model( GTK_TREE_VIEW( treeview ), GTK_TREE_MODEL( clip_store ) );
79
80 renderer = gtk_cell_renderer_text_new( );
81 column = gtk_tree_view_column_new_with_attributes ( "Description", renderer, "text", 0, NULL);
82 gtk_tree_view_column_set_sort_column_id( column, 0 );
83 gtk_tree_view_append_column( GTK_TREE_VIEW( treeview ), column );
84
85 dir_store = gtk_list_store_new( 2, G_TYPE_STRING, G_TYPE_STRING );
86 gtk_tree_view_set_model( GTK_TREE_VIEW( dirview ), GTK_TREE_MODEL( dir_store ) );
87
88 renderer = gtk_cell_renderer_text_new( );
89 column = gtk_tree_view_column_new_with_attributes ( "Description", renderer, "text", 0, NULL);
90 gtk_tree_view_column_set_sort_column_id( column, 0 );
91 gtk_tree_view_append_column( GTK_TREE_VIEW( dirview ), column );
92 }
93 else
94 {
95 clip_store = GTK_LIST_STORE( gtk_tree_view_get_model( GTK_TREE_VIEW( treeview ) ) );
96 dir_store = GTK_LIST_STORE( gtk_tree_view_get_model( GTK_TREE_VIEW( dirview ) ) );
97 gtk_list_store_clear( clip_store );
98 gtk_list_store_clear( dir_store );
99 }
100
101 if ( strcmp( path, "/" ) )
102 {
103 gtk_list_store_append( clip_store, &iter );
104 gtk_list_store_set( clip_store, &iter, 0, "..", -1 );
105 gtk_list_store_append( dir_store, &iter );
106 gtk_list_store_set( dir_store, &iter, 0, "..", -1 );
107 }
108
109 for ( index = 0; index < mvcp_dir_count( dir ); index ++ )
110 {
111 mvcp_dir_get( dir, index, &entry );
112 if ( strchr( entry.name, '/' ) )
113 {
114 gtk_list_store_append( dir_store, &iter );
115 gtk_list_store_set( dir_store, &iter, 0, entry.name, -1 );
116 }
117 else
118 {
119 gtk_list_store_append( clip_store, &iter );
120 gtk_list_store_set( clip_store, &iter, 0, entry.name, -1 );
121 }
122 }
123
124 mvcp_dir_close( dir );
125 }
126 else
127 {
128 gtk_label_set_text( GTK_LABEL( label ), "Disconnected" );
129 if ( gtk_tree_view_get_model( GTK_TREE_VIEW( treeview ) ) )
130 {
131 GtkListStore *list_store = GTK_LIST_STORE( gtk_tree_view_get_model( GTK_TREE_VIEW( treeview ) ) );
132 gtk_list_store_clear( list_store );
133 list_store = GTK_LIST_STORE( gtk_tree_view_get_model( GTK_TREE_VIEW( dirview ) ) );
134 gtk_list_store_clear( list_store );
135 treeview = lookup_widget( this_page_get_widget( this ), "treeview1" );
136 gtk_list_store_clear( list_store );
137 }
138 }
139 }
140
141 static void list_queue( page_clips this, int clip )
142 {
143 GtkWidget *treeview = lookup_widget( this_page_get_widget( this ), "treeview1" );
144 mvcp_list list = mvcp_list_init( this->dv, dv1394app_get_selected_unit( this->app ) );
145 GtkListStore *list_store = NULL;
146 GtkTreeIter iter;
147 GtkTreePath *path;
148 int index;
149 mvcp_list_entry_t entry;
150
151 if ( gtk_tree_view_get_model( GTK_TREE_VIEW( treeview ) ) == NULL )
152 {
153 GtkCellRenderer *renderer;
154 GtkTreeViewColumn *column;
155
156 list_store = gtk_list_store_new( 6,
157 G_TYPE_BOOLEAN,
158 G_TYPE_STRING,
159 G_TYPE_STRING,
160 G_TYPE_STRING,
161 G_TYPE_STRING,
162 G_TYPE_INT );
163 gtk_tree_view_set_model( GTK_TREE_VIEW( treeview ), GTK_TREE_MODEL( list_store ) );
164
165 renderer = gtk_cell_renderer_toggle_new( );
166 column = gtk_tree_view_column_new_with_attributes ( "", renderer, "active", 0, NULL);
167 gtk_tree_view_append_column( GTK_TREE_VIEW( treeview ), column );
168
169 renderer = gtk_cell_renderer_text_new( );
170 column = gtk_tree_view_column_new_with_attributes ( "Clip", renderer, "text", 1, NULL);
171 gtk_tree_view_append_column( GTK_TREE_VIEW( treeview ), column );
172
173 renderer = gtk_cell_renderer_text_new( );
174 column = gtk_tree_view_column_new_with_attributes ( "In", renderer, "text", 2, NULL);
175 gtk_tree_view_append_column( GTK_TREE_VIEW( treeview ), column );
176
177 renderer = gtk_cell_renderer_text_new( );
178 column = gtk_tree_view_column_new_with_attributes ( "Out", renderer, "text", 3, NULL);
179 gtk_tree_view_append_column( GTK_TREE_VIEW( treeview ), column );
180
181 renderer = gtk_cell_renderer_text_new( );
182 column = gtk_tree_view_column_new_with_attributes ( "Length", renderer, "text", 4, NULL);
183 gtk_tree_view_append_column( GTK_TREE_VIEW( treeview ), column );
184
185 }
186 else
187 {
188 list_store = GTK_LIST_STORE( gtk_tree_view_get_model( GTK_TREE_VIEW( treeview ) ) );
189 gtk_list_store_clear( list_store );
190 }
191
192 this->generation = list->generation;
193
194 for ( index = 0; index < mvcp_list_count( list ); index ++ )
195 {
196 char tc1[12], tc2[12], tc3[12];
197 mvcp_list_get( list, index, &entry );
198 gtk_list_store_append( list_store, &iter );
199 gtk_list_store_set( list_store, &iter,
200 0, index == clip,
201 1, entry.full,
202 2, frames2tc( entry.in, entry.fps, tc1),
203 3, frames2tc( entry.out, entry.fps, tc2),
204 4, frames2tc( entry.size, entry.fps, tc3),
205 5, entry.clip,
206 -1 );
207 }
208
209 this->clip = clip;
210 if ( clip < mvcp_list_count( list ) )
211 {
212 path = gtk_tree_path_new_from_indices( this->clip, -1 );
213 gtk_tree_view_scroll_to_cell( GTK_TREE_VIEW( treeview ), path, NULL, TRUE, 0.5, 0 );
214 gtk_tree_path_free( path );
215 }
216
217 mvcp_list_close( list );
218 }
219
220 static void list_active( page_clips this, int clip )
221 {
222 GtkWidget *treeview = lookup_widget( this_page_get_widget( this ), "treeview1" );
223 GtkListStore *list_store = GTK_LIST_STORE( gtk_tree_view_get_model( GTK_TREE_VIEW( treeview ) ) );
224 GtkTreePath *path = gtk_tree_path_new_from_indices( this->clip, -1 );
225 GtkTreeIter iter;
226
227 gtk_tree_model_get_iter( GTK_TREE_MODEL (list_store), &iter, path );
228 gtk_tree_path_free( path );
229 gtk_list_store_set( list_store, &iter, 0, FALSE, -1 );
230
231 this->clip = clip;
232 path = gtk_tree_path_new_from_indices( this->clip, -1 );
233 gtk_tree_view_scroll_to_cell( GTK_TREE_VIEW( treeview ), path, NULL, TRUE, 0.5, 0 );
234 gtk_tree_model_get_iter( GTK_TREE_MODEL (list_store), &iter, path );
235 gtk_tree_path_free( path );
236 gtk_list_store_set( list_store, &iter, 0, TRUE, -1 );
237 }
238
239 static gboolean on_ok( GtkWidget *dummy, gpointer data )
240 {
241 page_clips this = data;
242 GtkWidget *widget = lookup_widget( this_page_get_widget( this ), "list_clips" );
243 GtkTreeSelection *select = gtk_tree_view_get_selection( GTK_TREE_VIEW( widget ) );
244 GtkTreeModel *model;
245 GtkTreeIter iter;
246 gchar *text;
247
248 if ( gtk_tree_selection_get_selected( select, &model, &iter ) )
249 {
250 gtk_tree_model_get( model, &iter, 0, &text, -1 );
251
252 if ( !strcmp( text, ".." ) )
253 {
254 char *temp = strdup( this->path );
255 temp[ strlen( temp ) - 1 ] = '\0';
256 *( strrchr( temp, '/' ) + 1 ) = '\0';
257 list_clips( this, temp );
258 free( temp );
259 }
260 else
261 {
262 char *temp = malloc( strlen( this->path ) + strlen( text ) + 1 );
263 strcpy( temp, this->path );
264 strcat( temp, text );
265 mvcp_unit_append( this->dv, dv1394app_get_selected_unit( this->app ), temp, -1, -1 );
266 free( temp );
267 }
268
269 g_free( text );
270 }
271
272 return TRUE;
273 }
274
275 static gboolean on_dir( GtkWidget *dummy, gpointer data )
276 {
277 page_clips this = data;
278 GtkWidget *widget = lookup_widget( this_page_get_widget( this ), "list_dir" );
279 GtkTreeSelection *select = gtk_tree_view_get_selection( GTK_TREE_VIEW( widget ) );
280 GtkTreeModel *model;
281 GtkTreeIter iter;
282 gchar *text;
283
284 if ( gtk_tree_selection_get_selected( select, &model, &iter ) )
285 {
286 gtk_tree_model_get( model, &iter, 0, &text, -1 );
287
288 if ( !strcmp( text, ".." ) )
289 {
290 char *temp = strdup( this->path );
291 temp[ strlen( temp ) - 1 ] = '\0';
292 *( strrchr( temp, '/' ) + 1 ) = '\0';
293 list_clips( this, temp );
294 free( temp );
295 }
296 else if ( text[ strlen( text ) - 1 ] == '/' )
297 {
298 char *temp = malloc( strlen( this->path ) + strlen( text ) + 1 );
299 strcpy( temp, this->path );
300 strcat( temp, text );
301 list_clips( this, temp );
302 free( temp );
303 }
304
305 g_free( text );
306 }
307
308 return TRUE;
309 }
310
311 static gboolean on_queue_item( GtkWidget *dummy, gpointer data )
312 {
313 page_clips this = data;
314 GtkWidget *widget = lookup_widget( this_page_get_widget( this ), "treeview1" );
315 GtkTreeSelection *select = gtk_tree_view_get_selection( GTK_TREE_VIEW( widget ) );
316 GtkTreeModel *model;
317 GtkTreeIter iter;
318 int clip;
319
320 if ( gtk_tree_selection_get_selected( select, &model, &iter ) )
321 {
322 gtk_tree_model_get( model, &iter, 5, &clip, -1 );
323 mvcp_unit_clip_goto( this->dv, dv1394app_get_selected_unit( this->app ), mvcp_absolute, clip, 0 );
324 mvcp_unit_play( this->dv, dv1394app_get_selected_unit( this->app ) );
325 }
326
327 return TRUE;
328 }
329
330 static gboolean on_clip_selected( GtkWidget *widget, GdkEventButton *event, gpointer data )
331 {
332 if ( event->button==1 && event->type==GDK_2BUTTON_PRESS )
333 return on_ok( widget, data );
334 return FALSE;
335 }
336
337 static gboolean on_clip_key_press( GtkWidget *widget, GdkEventKey *event, gpointer data )
338 {
339 if ( event->keyval == GDK_Return )
340 return on_ok( widget, data );
341 return FALSE;
342 }
343
344 static gboolean on_dir_selected( GtkWidget *widget, GdkEventButton *event, gpointer data )
345 {
346 if ( event->button==1 && event->type==GDK_2BUTTON_PRESS )
347 return on_dir( widget, data );
348 return FALSE;
349 }
350
351 static gboolean on_dir_key_press( GtkWidget *widget, GdkEventKey *event, gpointer data )
352 {
353 if ( event->keyval == GDK_Return )
354 return on_dir( widget, data );
355 return FALSE;
356 }
357
358 static gboolean on_queue_selected( GtkWidget *widget, GdkEventButton *event, gpointer data )
359 {
360 if ( event->button==1 && event->type==GDK_2BUTTON_PRESS )
361 return on_queue_item( widget, data );
362 return FALSE;
363 }
364
365 static gboolean on_queue_key_press( GtkWidget *widget, GdkEventKey *event, gpointer data )
366 {
367 if ( event->keyval == GDK_Return )
368 return on_queue_item( widget, data );
369 return FALSE;
370 }
371
372 static gboolean on_home( GtkWidget *button, gpointer data )
373 {
374 page_clips this = data;
375 list_clips( this, "/" );
376 return TRUE;
377 }
378
379 static gboolean on_refresh( GtkWidget *button, gpointer data )
380 {
381 page_clips this = data;
382 char *temp = strdup( this->path );
383 list_clips( this, temp );
384 free( temp );
385
386 return TRUE;
387 }
388
389 static gboolean on_up( GtkWidget *dummy, gpointer data )
390 {
391 page_clips this = data;
392 GtkWidget *widget = lookup_widget( this_page_get_widget( this ), "treeview1" );
393 GtkTreeSelection *select = gtk_tree_view_get_selection( GTK_TREE_VIEW( widget ) );
394 GtkTreeModel *model;
395 GtkTreeIter iter;
396 int clip;
397
398 if ( gtk_tree_selection_get_selected( select, &model, &iter ) )
399 {
400 gtk_tree_model_get( model, &iter, 5, &clip, -1 );
401 mvcp_unit_clip_move( this->dv, dv1394app_get_selected_unit( this->app ), mvcp_absolute, clip, mvcp_absolute, clip - 1 < 0 ? 0 : clip - 1 );
402 }
403 return TRUE;
404 }
405
406 static gboolean on_down( GtkWidget *dummy, gpointer data )
407 {
408 page_clips this = data;
409 GtkWidget *widget = lookup_widget( this_page_get_widget( this ), "treeview1" );
410 GtkTreeSelection *select = gtk_tree_view_get_selection( GTK_TREE_VIEW( widget ) );
411 GtkTreeModel *model;
412 GtkTreeIter iter;
413 int clip;
414
415 if ( gtk_tree_selection_get_selected( select, &model, &iter ) )
416 {
417 gtk_tree_model_get( model, &iter, 5, &clip, -1 );
418 mvcp_unit_clip_move( this->dv, dv1394app_get_selected_unit( this->app ), mvcp_absolute, clip, mvcp_absolute, clip + 1 );
419 }
420 return TRUE;
421 }
422
423 static gboolean on_remove( GtkWidget *dummy, gpointer data )
424 {
425 page_clips this = data;
426 GtkWidget *widget = lookup_widget( this_page_get_widget( this ), "treeview1" );
427 GtkTreeSelection *select = gtk_tree_view_get_selection( GTK_TREE_VIEW( widget ) );
428 GtkTreeModel *model;
429 GtkTreeIter iter;
430 int clip;
431
432 if ( gtk_tree_selection_get_selected( select, &model, &iter ) )
433 {
434 gtk_tree_model_get( model, &iter, 5, &clip, -1 );
435 mvcp_unit_clip_remove( this->dv, dv1394app_get_selected_unit( this->app ), mvcp_absolute, clip );
436 }
437 return TRUE;
438 }
439
440 static gboolean on_clean( GtkWidget *dummy, gpointer data )
441 {
442 page_clips this = data;
443 mvcp_unit_clean( this->dv, dv1394app_get_selected_unit( this->app ) );
444 return TRUE;
445 }
446
447 static GtkWidget *this_page_get_widget( page_clips this )
448 {
449 if ( this->widget == NULL )
450 this->widget = this->parent_page->get_widget(this->parent_page);
451 return this->widget;
452 }
453
454 static void this_page_get_toolbar_info( page this, GtkIconSize size, GtkWidget **icon, char **label )
455 {
456 *icon = gtk_image_new_from_stock( "gtk-justify-fill", size );
457 *label = _("_Playlist");
458 }
459
460 static void this_page_on_connect( page_clips this )
461 {
462 this->dv = mvcp_init( dv1394app_get_parser( this->app ) );
463 list_clips( this, "/" );
464 }
465
466 static void this_page_on_unit_change( page_clips this, int unit )
467 {
468 if ( unit != this->unit )
469 this->unit = unit;
470 }
471
472 static void this_page_on_disconnect( page_clips this )
473 {
474 list_clips( this, NULL );
475 mvcp_close( this->dv );
476 }
477
478 static void this_page_show_status( page_clips this, mvcp_status status )
479 {
480 if ( status->status != unit_disconnected )
481 {
482 if ( this->generation != status->generation )
483 list_queue( this, status->clip_index );
484 else if ( this->clip != status->clip_index )
485 list_active( this, status->clip_index );
486 }
487 }
488
489 static void this_page_close( page_clips this )
490 {
491 if ( this != NULL )
492 free( this );
493 }
494
495 page page_clips_init( dv1394app app, struct page_t *parent_page)
496 {
497 page_clips this = calloc( 1, sizeof( page_clips_t ) );
498 GtkWidget *widget;
499
500 this->parent_page = parent_page;
501 this->parent.get_widget = ( GtkWidget *(*)( page ) )this_page_get_widget;
502 this->parent.get_toolbar_info = this_page_get_toolbar_info;
503 this->parent.on_connect = ( void (*)( page ) )this_page_on_connect;
504 this->parent.on_unit_change = ( void (*)( page, int ) )this_page_on_unit_change;
505 this->parent.on_disconnect = ( void (*)( page ) )this_page_on_disconnect;
506 this->parent.show_status = ( void (*)( page, mvcp_status ) )this_page_show_status;
507 this->parent.close = ( void (*)( page ) )this_page_close;
508 this->app = app;
509 this->generation = -1;
510
511 widget = lookup_widget( this_page_get_widget( this ), "list_clips" );
512 g_signal_connect( G_OBJECT( widget ), "button-press-event", G_CALLBACK( on_clip_selected ), this );
513 g_signal_connect( G_OBJECT( widget ), "key-press-event", G_CALLBACK( on_clip_key_press ), this );
514 widget = lookup_widget( this_page_get_widget( this ), "list_dir" );
515 g_signal_connect( G_OBJECT( widget ), "button-press-event", G_CALLBACK( on_dir_selected ), this );
516 g_signal_connect( G_OBJECT( widget ), "key-press-event", G_CALLBACK( on_dir_key_press ), this );
517 widget = lookup_widget( this_page_get_widget( this ), "button_clips_refresh" );
518 gtk_signal_connect( GTK_OBJECT( widget ), "clicked", GTK_SIGNAL_FUNC( on_refresh ), this );
519 widget = lookup_widget( this_page_get_widget( this ), "button_clips_home" );
520 gtk_signal_connect( GTK_OBJECT( widget ), "clicked", GTK_SIGNAL_FUNC( on_home ), this );
521 widget = lookup_widget( this_page_get_widget( this ), "button_up" );
522 gtk_signal_connect( GTK_OBJECT( widget ), "clicked", GTK_SIGNAL_FUNC( on_up ), this );
523 widget = lookup_widget( this_page_get_widget( this ), "button_down" );
524 gtk_signal_connect( GTK_OBJECT( widget ), "clicked", GTK_SIGNAL_FUNC( on_down ), this );
525 widget = lookup_widget( this_page_get_widget( this ), "button_remove" );
526 gtk_signal_connect( GTK_OBJECT( widget ), "clicked", GTK_SIGNAL_FUNC( on_remove ), this );
527 widget = lookup_widget( this_page_get_widget( this ), "button_clean" );
528 gtk_signal_connect( GTK_OBJECT( widget ), "clicked", GTK_SIGNAL_FUNC( on_clean ), this );
529
530 widget = lookup_widget( this_page_get_widget( this ), "table4" );
531 gtk_widget_show( widget );
532
533 widget = lookup_widget( this_page_get_widget( this ), "treeview1" );
534 g_signal_connect( G_OBJECT( widget ), "button-press-event", G_CALLBACK( on_queue_selected ), this );
535 g_signal_connect( G_OBJECT( widget ), "key-press-event", G_CALLBACK( on_queue_key_press ), this );
536
537 return ( page )this;
538 }