dcebf7c741e271566fa5d129e36fcf7281352d25
[rugen] / src / dv1394app.c
1 /*
2 * dv1394app.c -- GTK+ 2 dv1394d client demo
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 #include "gtkenhancedscale.h"
36 #include <mvcp/mvcp_remote.h>
37 #include <melted/melted_local.h>
38
39
40 /** Window close event.
41 */
42
43 static gboolean on_main_window_delete_event( GtkWidget *widget, GdkEvent *event, gpointer user_data )
44 {
45 gtk_exit( 0 );
46 return TRUE;
47 }
48
49 static gboolean instance_connect( dv1394app this, char *server, char *port )
50 {
51 if ( this->parser == NULL )
52 {
53 if ( strstr( server, ".conf" ) == NULL )
54 this->parser = mvcp_parser_init_remote( server, atoi( port ) );
55 else
56 this->parser = melted_parser_init_local( );
57
58 this->command = mvcp_init( this->parser );
59
60 if ( strstr( server, ".conf" ) != NULL )
61 mvcp_run( this->command, server );
62
63 if ( mvcp_connect( this->command ) == mvcp_ok )
64 {
65 struct timespec t = { 1, 0 };
66 nanosleep( &t, NULL );
67 //gdk_threads_leave( );
68 dv1394app_connect( this );
69 //gdk_threads_enter( );
70 }
71 else
72 {
73 mvcp_close( this->command );
74 mvcp_parser_close( this->parser );
75 this->parser = NULL;
76 // beep( );
77 }
78 }
79
80 return this->parser != NULL;
81 }
82
83 /** Connection window - Connect button pressed.
84 */
85
86 static gboolean on_connect_pressed( GtkWidget *button, gpointer user_data )
87 {
88 dv1394app this = user_data;
89 GtkWidget *widget;
90 char *server;
91 char *port;
92
93 if ( this->parser == NULL )
94 {
95 widget = lookup_widget( this->connect, "entry_server" );
96 server = ( char * )gtk_entry_get_text( GTK_ENTRY( widget ) );
97 widget = lookup_widget( this->connect, "entry_port" );
98 port = ( char * )gtk_entry_get_text( GTK_ENTRY( widget ) );
99 instance_connect( this, server, port );
100 }
101 gtk_widget_destroy( this->connect );
102 this->guard = 1;
103 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( lookup_widget( this->window, "button_connect" ) ), TRUE );
104 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( lookup_widget( this->window, "button_disconnect" ) ), FALSE );
105 this->guard = 0;
106
107 return FALSE;
108 }
109
110 /** Connection window - Cancel button pressed.
111 */
112
113 static gboolean on_cancel_pressed( GtkWidget *button, gpointer user_data )
114 {
115 dv1394app this = user_data;
116 if ( this->guard ) return FALSE;
117 gtk_widget_destroy( this->connect );
118 return FALSE;
119 }
120
121 /** Main window - connect menu item selected.
122 */
123
124 void on_item_connect_activate( GtkMenuItem *menuitem, gpointer user_data )
125 {
126 dv1394app this = user_data;
127 GtkWidget *widget;
128
129 if ( this->guard ) return;
130 this->connect = create_window_connection( );
131
132 /* Connection set up handling */
133 widget = lookup_widget( this->connect, "button_connect" );
134 gtk_signal_connect( GTK_OBJECT( widget ), "clicked", GTK_SIGNAL_FUNC( on_connect_pressed ), this );
135 widget = lookup_widget( this->connect, "button_cancel" );
136 gtk_signal_connect( GTK_OBJECT( widget ), "clicked", GTK_SIGNAL_FUNC( on_cancel_pressed ), this );
137
138 gtk_widget_show( this->connect );
139 }
140
141 /** Main window - disconnect menu item selected.
142 */
143
144 void on_item_disconnect_activate( GtkMenuItem *menuitem, gpointer user_data )
145 {
146 dv1394app this = user_data;
147
148 if ( this->guard ) return;
149 dv1394app_disconnect( this );
150
151 this->guard = 1;
152 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( lookup_widget( this->window, "button_connect" ) ), FALSE );
153 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( lookup_widget( this->window, "button_disconnect" ) ), TRUE );
154 this->guard = 0;
155 }
156
157 /** Main window - quit menu item selected.
158 */
159
160 void on_item_quit_activate( GtkMenuItem *menuitem, gpointer user_data )
161 {
162 gtk_main_quit( );
163 }
164
165 static void playlist_open(dv1394app this, char* filename)
166 {
167 FILE* f;
168
169 if( this->selected_unit >= 0 && this->command)
170 {
171 f = fopen(filename, "rt");
172 if (f)
173 {
174 while( !feof(f) )
175 {
176 char* s;
177 char l[PATH_MAX];
178
179 /* reset line */
180 l[0] = 0;
181
182 /* load string */
183 fgets(l, sizeof(l), f);
184
185 /* remove newlines */
186 if( (s = strchr(l, '\n')) ) *s = 0;
187 if( (s = strchr(l, '\r')) ) *s = 0;
188 if( (s = strchr(l, '\t')) ) *s = 0;
189
190 /* check for empty line */
191 if(l[0])
192 mvcp_unit_append( this->command, this->selected_unit, l, -1, -1 );
193 }
194
195 fclose(f);
196 }
197 }
198
199 }
200
201 static void playlist_save(dv1394app this, char* filename)
202 {
203 int index;
204 mvcp_list_entry_t entry;
205 mvcp_list list;
206 FILE* f;
207
208 if( this->selected_unit >= 0 && this->command)
209 {
210 f = fopen(filename, "wt");
211 if (f)
212 {
213 list = mvcp_list_init( this->command, this->selected_unit);
214
215 if ( list )
216 {
217 for ( index = 0; list && index < mvcp_list_count( list ); index ++ )
218 {
219 mvcp_list_get( list, index, &entry );
220 fprintf(f, "%s\n", entry.full);
221 }
222 mvcp_list_close( list );
223 }
224
225 fclose(f);
226 }
227 }
228 }
229
230 /** Main window - playlist open menu item selected.
231 */
232
233 static void on_item_open_playlist_activate( GtkMenuItem *menuitem, gpointer user_data )
234 {
235 dv1394app this = user_data;
236 GtkWidget *dialog;
237
238 dialog = gtk_file_chooser_dialog_new ("Open File",
239 GTK_WINDOW (this->window),
240 GTK_FILE_CHOOSER_ACTION_OPEN,
241 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
242 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
243 NULL);
244
245 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog),
246 (this->playlist_folder)?this->playlist_folder:getenv("HOME"));
247
248 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
249 {
250 char *filename;
251
252 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
253 playlist_open(this, filename);
254
255 if ( this->playlist_folder )
256 g_free (this->playlist_folder);
257 this->playlist_folder = filename;
258 if ( this->playlist_folder )
259 {
260 char* e = strrchr(this->playlist_folder, '/');
261 if(e) *e = 0;
262 }
263 }
264
265 gtk_widget_destroy (dialog);
266 }
267
268 /** Main window - playlist save menu item selected.
269 */
270
271 static void on_item_save_playlist_activate( GtkMenuItem *menuitem, gpointer user_data )
272 {
273 dv1394app this = user_data;
274 GtkWidget *dialog;
275
276 dialog = gtk_file_chooser_dialog_new ("Save File",
277 GTK_WINDOW (this->window),
278 GTK_FILE_CHOOSER_ACTION_SAVE,
279 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
280 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
281 NULL);
282
283 gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
284
285 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog),
286 (this->playlist_folder)?this->playlist_folder:getenv("HOME"));
287 gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), "Untitled document");
288
289 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
290 {
291 char *filename;
292
293 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
294 playlist_save(this, filename);
295
296 if ( this->playlist_folder )
297 g_free (this->playlist_folder);
298 this->playlist_folder = filename;
299 if ( this->playlist_folder )
300 {
301 char* e = strrchr(this->playlist_folder, '/');
302 if(e) *e = 0;
303 }
304 }
305
306 gtk_widget_destroy (dialog);
307 }
308
309 static gboolean on_page_switch_pressed( GtkWidget *button, gpointer user_data )
310 {
311 dv1394app this = user_data;
312 int index = 0;
313 GtkWidget *notebook = lookup_widget( button, "notebook1" );
314
315 if ( this->guard ) return TRUE;
316 this->guard = 1;
317 for ( index = 0; index < this->page_count; index ++ )
318 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( this->page_buttons[ index ] ), FALSE );
319 for ( index = 0; index < this->page_count; index ++ )
320 {
321 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( this->page_buttons[ index ] ), FALSE );
322 if ( this->page_buttons[ index ] == button )
323 break;
324 }
325 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( this->page_buttons[ index ] ), TRUE );
326 gtk_notebook_set_current_page( GTK_NOTEBOOK( notebook ), index );
327 this->guard = 0;
328
329 return TRUE;
330 }
331
332 static gboolean on_transport_pressed( GtkWidget *button, gpointer data )
333 {
334 int index = 0;
335 dv1394app this = ( dv1394app )data;
336 mvcp dv = dv1394app_get_command( this );
337 int unit = dv1394app_get_selected_unit( this );
338
339 for ( index = 0; index < TRANSPORT_BUTTONS_COUNT; index ++ )
340 if ( this->buttons[ index ] == button )
341 break;
342
343 switch( index )
344 {
345 case 0:
346 mvcp_unit_clip_goto( dv, unit, mvcp_absolute, 0, 0 );
347 break;
348
349 case 1:
350 mvcp_unit_goto( dv, unit, 0 );
351 break;
352
353 case 2:
354 mvcp_unit_rewind( dv, unit );
355 break;
356
357 case 3:
358 mvcp_unit_step( dv, unit, -1 );
359 break;
360
361 case 4:
362 mvcp_unit_pause( dv, unit );
363 break;
364
365 case 5:
366 mvcp_unit_play( dv, unit );
367 break;
368
369 case 6:
370 mvcp_unit_stop( dv, unit );
371 break;
372
373 case 7:
374 mvcp_unit_step( dv, unit, 1 );
375 break;
376
377 case 8:
378 mvcp_unit_fast_forward( dv, unit );
379 break;
380
381 case 9:
382 mvcp_unit_clip_goto( dv, unit, mvcp_relative, 1, 0 );
383 break;
384
385 case 10:
386 mvcp_unit_clip_goto( dv, unit, mvcp_absolute, 9999, -1 );
387 break;
388
389 case 11:
390 mvcp_unit_set( dv, unit, "eof", "loop");
391 this->eof[this->selected_unit] = 0;
392 break;
393
394 case 12:
395 mvcp_unit_set( dv, unit, "eof", "pause");
396 this->eof[this->selected_unit] = 0;
397 break;
398
399 default:
400 break;
401 }
402
403 return TRUE;
404 }
405
406 static void dv1394app_register_page( dv1394app this, page item )
407 {
408 GtkWidget *toolbar = lookup_widget( this->window, "toolbar1" );
409 GtkIconSize size = gtk_toolbar_get_icon_size( GTK_TOOLBAR( toolbar ) );
410 GtkWidget *widget = lookup_widget( this->window, "notebook1" );
411 GtkWidget *bin = gtk_frame_new( NULL );
412 char *label = NULL;
413
414 this->pages[ this->page_count ] = item;
415 gtk_widget_reparent( GTK_BIN( page_get_widget( item ) )->child, bin );
416 gtk_container_add(GTK_CONTAINER( widget ), bin );
417 gtk_frame_set_label_align( GTK_FRAME( bin ), 0, 0 );
418 gtk_frame_set_shadow_type( GTK_FRAME( bin ), GTK_SHADOW_NONE );
419 gtk_widget_show( bin );
420
421 page_get_toolbar_info( item, size, &widget, &label );
422 this->page_buttons[ this->page_count ] = gtk_toolbar_append_element( GTK_TOOLBAR ( toolbar ), GTK_TOOLBAR_CHILD_TOGGLEBUTTON, NULL, label, NULL, NULL, widget, NULL, NULL);
423 gtk_label_set_use_underline( GTK_LABEL(((GtkToolbarChild*)(g_list_last( GTK_TOOLBAR( toolbar )->children)->data))->label), TRUE);
424 gtk_widget_show( widget );
425 gtk_signal_connect( GTK_OBJECT( this->page_buttons[ this->page_count ] ), "clicked", GTK_SIGNAL_FUNC( on_page_switch_pressed ), this );
426 gtk_signal_connect( GTK_OBJECT( this->page_buttons[ this->page_count ] ), "activate", GTK_SIGNAL_FUNC( on_page_switch_pressed ), this );
427
428 this->page_count ++;
429 }
430
431 static GtkAdjustment *trim_adj[3];
432 #define TRIM_ADJ_POS 0
433 #define TRIM_ADJ_IN 1
434 #define TRIM_ADJ_OUT 2
435
436 void dv1394app_show_status( dv1394app this, mvcp_status status )
437 {
438 int index = 0;
439 for ( index = 0; index < this->page_count; index ++ )
440 page_show_status( this->pages[ index ], status );
441
442 if ( status->seek_flag != this->seek_flag )
443 {
444 gtk_widget_set_sensitive( lookup_widget( dv1394app_get_widget( this ), "transport_2" ), status->seek_flag );
445 gtk_widget_set_sensitive( lookup_widget( dv1394app_get_widget( this ), "transport_3" ), status->seek_flag );
446 gtk_widget_set_sensitive( lookup_widget( dv1394app_get_widget( this ), "transport_7" ), status->seek_flag );
447 gtk_widget_set_sensitive( lookup_widget( dv1394app_get_widget( this ), "transport_8" ), status->seek_flag );
448 this->seek_flag = status->seek_flag;
449 }
450
451 if ( !this->trim_in_use )
452 {
453 int upper = status->length > 0 ? status->length - 1 : 0;
454 trim_adj[TRIM_ADJ_IN]->upper = upper;
455 trim_adj[TRIM_ADJ_IN]->value = status->in;
456 trim_adj[TRIM_ADJ_OUT]->upper = upper;
457 trim_adj[TRIM_ADJ_OUT]->value = status->out;
458 trim_adj[TRIM_ADJ_POS]->upper = upper;
459 trim_adj[TRIM_ADJ_POS]->value = status->position;
460 gtk_signal_emit_by_name( GTK_OBJECT(trim_adj[TRIM_ADJ_POS]), "value_changed" );
461 }
462
463 gtk_widget_set_sensitive( lookup_widget( dv1394app_get_widget( this ), "transport_11" ),
464 this->eof[this->selected_unit] == 'p' );
465 gtk_widget_set_sensitive( lookup_widget( dv1394app_get_widget( this ), "transport_12" ),
466 this->eof[this->selected_unit] == 'l' );
467 }
468
469 static gboolean trim_pressed( GtkWidget *button, GdkEventButton *event, gpointer user_data )
470 {
471 dv1394app this = (dv1394app)user_data;
472 mvcp_unit_pause( dv1394app_get_command( this ), this->selected_unit );
473 this->trim_in = -1;
474 this->trim_out = -1;
475 this->trim_in_use = 1;
476 return FALSE;
477 }
478
479 static gboolean trim_released( GtkWidget *button, GdkEventButton *event, gpointer user_data )
480 {
481 dv1394app this = (dv1394app)user_data;
482 this->trim_in_use = 0;
483 if ( this->trim_in != -1 )
484 mvcp_unit_set_in( dv1394app_get_command( this ), this->selected_unit, this->trim_in );
485 if ( this->trim_out != -1 )
486 mvcp_unit_set_out( dv1394app_get_command( this ), this->selected_unit, this->trim_out );
487 return TRUE;
488 }
489
490 static gboolean on_trim_value_changed_event( GtkWidget *button, gpointer user_data )
491 {
492 dv1394app this = (dv1394app)user_data;
493 if ( this->trim_in_use )
494 {
495 char *value;
496 g_object_get( G_OBJECT( button ), "user_data", &value, NULL );
497
498 if ( !strcmp( value, "position" ) )
499 {
500 mvcp_unit_goto( dv1394app_get_command( this ), this->selected_unit, trim_adj[TRIM_ADJ_POS]->value );
501 }
502 else if ( !strcmp( value, "in" ) )
503 {
504 this->trim_in = trim_adj[TRIM_ADJ_IN]->value;
505 mvcp_unit_goto( dv1394app_get_command( this ), this->selected_unit, trim_adj[TRIM_ADJ_IN]->value );
506 }
507 else if ( !strcmp( value, "out" ) )
508 {
509 this->trim_out = trim_adj[TRIM_ADJ_OUT]->value;
510 mvcp_unit_goto( dv1394app_get_command( this ), this->selected_unit, trim_adj[TRIM_ADJ_OUT]->value );
511 }
512
513 gtk_widget_queue_draw (lookup_widget(this->window, "vbox_trim") );
514 return TRUE;
515 }
516 return FALSE;
517 }
518
519 /** Initialiser for application state.
520 */
521
522 dv1394app dv1394app_init( GtkWidget *window, char *instance )
523 {
524 dv1394app this = calloc( 1, sizeof( dv1394app_t ) );
525
526 if ( this != NULL )
527 {
528 GtkWidget *widget;
529
530 this->window = window;
531
532 /* Window destroy event */
533 gtk_signal_connect( GTK_OBJECT( this->window ), "destroy", GTK_SIGNAL_FUNC( on_main_window_delete_event ), this );
534
535 /* Menu item signal handling */
536 // widget = lookup_widget( this->window, "item_connect" );
537 // gtk_signal_connect( GTK_OBJECT( widget ), "activate", GTK_SIGNAL_FUNC( on_item_connect_activate ), this );
538 widget = lookup_widget( this->window, "button_connect" );
539 gtk_signal_connect( GTK_OBJECT( widget ), "clicked", GTK_SIGNAL_FUNC( on_item_connect_activate ), this );
540 // widget = lookup_widget( this->window, "item_disconnect" );
541 // gtk_signal_connect( GTK_OBJECT( widget ), "activate", GTK_SIGNAL_FUNC( on_item_disconnect_activate ), this );
542 widget = lookup_widget( this->window, "button_disconnect" );
543 gtk_signal_connect( GTK_OBJECT( widget ), "clicked", GTK_SIGNAL_FUNC( on_item_disconnect_activate ), this );
544 // widget = lookup_widget( this->window, "item_quit" );
545 // gtk_signal_connect( GTK_OBJECT( widget ), "activate", GTK_SIGNAL_FUNC( on_item_quit_activate ), this );
546 // widget = lookup_widget( this->window, "button_quit" );
547 // gtk_signal_connect( GTK_OBJECT( widget ), "clicked", GTK_SIGNAL_FUNC( on_item_quit_activate ), this );
548 widget = lookup_widget( this->window, "button_open_playlist" );
549 gtk_signal_connect( GTK_OBJECT( widget ), "clicked", GTK_SIGNAL_FUNC( on_item_open_playlist_activate ), this );
550 widget = lookup_widget( this->window, "button_save_playlist" );
551 gtk_signal_connect( GTK_OBJECT( widget ), "clicked", GTK_SIGNAL_FUNC( on_item_save_playlist_activate ), this );
552
553
554 /* Initialise the pages. */
555 dv1394app_register_page( this, page_operate_init( this ) );
556 dv1394app_register_page( this, page_command_init( this ) );
557 this->guard = 1;
558 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( this->page_buttons[ 0 ] ), TRUE );
559 this->guard = 0;
560
561 /* Remove the empty page */
562 widget = lookup_widget( this->window, "notebook1" );
563 gtk_notebook_remove_page( GTK_NOTEBOOK( widget ), 0 );
564
565 guint keys[ ] = { GDK_0, GDK_1, GDK_2, GDK_3, GDK_4, GDK_5, GDK_6, GDK_7, GDK_8, GDK_9, GDK_A };
566 int index;
567 GtkAccelGroup *accel_group = gtk_accel_group_new( );
568
569 for ( index = 0; index < TRANSPORT_BUTTONS_COUNT; index ++ )
570 {
571 char name[ 256 ];
572 sprintf( name, "transport_%d", index );
573 this->buttons[ index ] = lookup_widget( dv1394app_get_widget( this ), name );
574 gtk_signal_connect( GTK_OBJECT( this->buttons[ index ] ), "clicked", GTK_SIGNAL_FUNC( on_transport_pressed ), this );
575 gtk_widget_add_accelerator( this->buttons[ index ], "clicked", accel_group, keys[ index ], GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE );
576 }
577
578 gtk_window_add_accel_group( GTK_WINDOW( dv1394app_get_widget( this ) ), accel_group);
579
580 trim_adj[TRIM_ADJ_POS] = GTK_ADJUSTMENT( gtk_adjustment_new( 0, 0, 1000, 1, 10, 0 ) );
581 g_object_set( G_OBJECT( trim_adj[TRIM_ADJ_POS] ), "user_data", "position", NULL );
582 trim_adj[TRIM_ADJ_IN] = GTK_ADJUSTMENT( gtk_adjustment_new( 0, 0, 1000, 1, 10, 0 ) );
583 g_object_set( G_OBJECT( trim_adj[TRIM_ADJ_IN] ), "user_data", "in", NULL );
584 trim_adj[TRIM_ADJ_OUT] = GTK_ADJUSTMENT( gtk_adjustment_new( 0, 0, 1000, 1, 10, 0 ) );
585 g_object_set( G_OBJECT( trim_adj[TRIM_ADJ_OUT] ), "user_data", "out", NULL );
586
587 int i;
588 for (i = 0; i < 3; i++)
589 gtk_signal_connect (GTK_OBJECT (trim_adj[i]), "value_changed", GTK_SIGNAL_FUNC (on_trim_value_changed_event), this );
590
591 GtkWidget *trim = gtk_enhanced_scale_new( (GtkObject**) trim_adj, 3);
592 if ( trim != NULL )
593 {
594 gtk_widget_set_name (trim, "trim");
595 GTK_WIDGET_UNSET_FLAGS( GTK_WIDGET( trim ), GTK_CAN_FOCUS );
596 gtk_widget_ref(trim);
597 gtk_object_set_data_full (GTK_OBJECT( this->window ), "trim", trim, (GtkDestroyNotify) gtk_widget_unref);
598 GtkWidget *vbox_trim = lookup_widget(this->window, "vbox_trim");
599 gtk_widget_show(trim);
600 gtk_box_pack_start(GTK_BOX (vbox_trim), trim, TRUE, TRUE, 0);
601 gtk_signal_connect( GTK_OBJECT( trim ), "button_press_event", GTK_SIGNAL_FUNC (trim_pressed), this );
602 gtk_signal_connect( GTK_OBJECT( trim ), "button_release_event", GTK_SIGNAL_FUNC (trim_released), this );
603 }
604 this->seek_flag = 1;
605
606 this->playing[0] = create_pixbuf("empty_16x16.png");
607 this->playing[1] = create_pixbuf("item_playing_16x16_(Axialis_Team).png");
608 }
609
610 if ( instance != NULL )
611 {
612 char *server = strdup( instance );
613 char *port = strchr( server, ':' );
614 if ( port != NULL )
615 *port ++ = '\0';
616 else
617 port = "5250";
618 this->guard = 1;
619 if ( instance_connect( this, server, port ) )
620 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( lookup_widget( this->window, "button_connect" ) ), TRUE );
621 else
622 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( lookup_widget( this->window, "button_disconnect" ) ), TRUE );
623 this->guard = 0;
624 free( server );
625 }
626
627
628 return this;
629 }
630
631 /** Get the app window widget.
632 */
633
634 GtkWidget *dv1394app_get_widget( dv1394app this )
635 {
636 return this->window;
637 }
638
639 /** Get the applications parser.
640 */
641
642 mvcp_parser dv1394app_get_parser( dv1394app this )
643 {
644 return this->parser;
645 }
646
647 /** Return the command parser.
648 */
649
650 mvcp dv1394app_get_command( dv1394app this )
651 {
652 return this->command;
653 }
654
655 /** Issue a connect to all pages.
656 */
657
658 void dv1394app_connect( dv1394app this )
659 {
660 int index = 0;
661 for ( index = 0; index < this->page_count; index ++ )
662 page_on_connect( this->pages[ index ] );
663 }
664
665 /** Inform all pages that the unit has changed.
666 */
667
668 void dv1394app_on_unit_change( dv1394app this, int unit )
669 {
670 int index = 0;
671 this->selected_unit = unit;
672 for ( index = 0; index < this->page_count; index ++ )
673 page_on_unit_change( this->pages[ index ], unit );
674 }
675
676 /** Return the selected unit.
677 */
678
679 int dv1394app_get_selected_unit( dv1394app this )
680 {
681 return this->selected_unit;
682 }
683
684 /** Issue a disconnect to all pages.
685 */
686
687 void dv1394app_disconnect( dv1394app this )
688 {
689 int index = 0;
690 if ( this->parser != NULL )
691 {
692 for ( index = 0; index < this->page_count; index ++ )
693 page_on_disconnect( this->pages[ index ] );
694 mvcp_close( this->command );
695 this->command = NULL;
696 mvcp_parser_close( this->parser );
697 this->parser = NULL;
698 }
699 }
700
701 /** Close application.
702 */
703
704 void dv1394app_close( dv1394app this )
705 {
706 dv1394app_disconnect( this );
707 while ( this->page_count > 0 )
708 page_close( this->pages[ -- this->page_count ] );
709 free( this );
710 }
711
712 char* frames2tc( int f, float fps, char* buf )
713 {
714 int tc[4] = { 0, 0, 0, 0 };
715 float d;
716 int t;
717
718 if ( fps && f >= 0)
719 {
720 d = f / fps;
721 t = d;
722
723 tc[0] = (d - t) * fps;
724 tc[1] = t % 60; t /= 60;
725 tc[2] = t % 60; t /= 60;
726 tc[3] = t % 24;
727 }
728
729 sprintf(buf, "%.2d:%.2d:%.2d:%.2d", tc[3], tc[2], tc[1], tc[0]);
730
731 return buf;
732 }