/* * gtv - a Gtk+ based SMPEG player * (c) Michael Vance, 1999 * briareos@lokigames.com * * TODO * - SMPEG returns an incorrect current_frame after a * call to SMPEG_renderFinal(). * - SMPEG loops audio incorrectly when audio stream is * shorter than a video stream, etc. */ #include "gtv.h" #include "SDL_syswm.h" #define TIMER_TIMEOUT 100 static GtkWidget* create_gtv_window( void ); static void gtv_connect( gpointer, gchar*, gchar*, GtkSignalFunc ); static void gtv_set_frame( gpointer, int ); static void gtv_set_fps( gpointer, float ); static void gtv_set_trackbar( gpointer, int ); static void gtv_set_sensitive( gpointer, gchar*, gboolean ); static void gtv_clear_screen( gpointer ); static void gtv_fix_toggle_state( gpointer ); static void gtv_double( GtkWidget*, gpointer ); static void gtv_loop( GtkWidget*, gpointer ); static void gtv_audio( GtkWidget*, gpointer ); static void gtv_filter( GtkWidget*, gpointer ); static void gtv_open( GtkWidget*, gpointer ); static void gtv_open_file( gchar*, gpointer ); static void gtv_close( GtkWidget*, gpointer ); static void gtv_info( GtkWidget*, gpointer ); static void gtv_quit( GtkWidget*, gpointer ); static void gtv_about( GtkWidget*, gpointer ); static void gtv_play( GtkWidget*, gpointer ); static void gtv_pause( GtkWidget*, gpointer ); static void gtv_stop( GtkWidget*, gpointer ); static void gtv_step( GtkWidget*, gpointer ); static void gtv_to_end( GtkWidget*, gpointer ); static void gtv_seek( GtkAdjustment*, gpointer ); static void gtv_drag_data_received(GtkWidget * widget, GdkDragContext * context, gint x, gint y, GtkSelectionData * selection_data, guint info, guint time); static int gtv_trackbar_dragging; static gchar * gtv_default_directory = 0; static void gtv_fix_toggle_state( gpointer raw ) { SMPEG* mpeg = NULL; assert( raw ); mpeg = (SMPEG*) gtk_object_get_data( GTK_OBJECT( raw ), "mpeg" ); /* If no mpeg is loaded, pop all the buttons. */ if( !mpeg ) { GtkWidget* twotimes = NULL; GtkWidget* loop = NULL; GtkWidget* audio = NULL; GtkWidget* filter = NULL; twotimes = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( raw ), "twotimes" ) ); loop = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( raw ), "loop" ) ); audio = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( raw ), "audio" ) ); filter = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( raw ), "filter" ) ); #if 1 /* Sam 5/31/2000 - Default to doubled video and audio on */ gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( twotimes ), FALSE ); gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( loop ), FALSE ); gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( audio ), TRUE ); gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( filter ), FALSE ); #else gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( twotimes ), FALSE ); gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( loop ), FALSE ); gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( audio ), FALSE ); gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( filter ), FALSE ); #endif } } static void gtv_set_sensitive( gpointer raw, gchar* name, gboolean sensitive ) { GtkWidget* item = NULL; assert( raw ); assert( name ); item = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( raw ), name ) ); assert( item ); gtk_widget_set_sensitive( item, sensitive ); } static void gtv_set_buttons_sensitive( gpointer raw, gboolean sensitive ) { SMPEG_Info* info = NULL; /* HACK If no MPEG is loaded, info has been memset()'ed to 0. */ info = (SMPEG_Info*) gtk_object_get_data( GTK_OBJECT( raw ), "info" ); gtv_set_sensitive( raw, "play", sensitive ); gtv_set_sensitive( raw, "pause", sensitive ); gtv_set_sensitive( raw, "stop", sensitive ); gtv_set_sensitive( raw, "step", sensitive && info->has_video ); gtv_set_sensitive( raw, "to_end", sensitive && info->has_video ); gtv_set_sensitive( raw, "loop", sensitive ); gtv_set_sensitive( raw, "close", sensitive ); gtv_set_sensitive( raw, "file_info", sensitive ); gtv_set_sensitive( raw, "twotimes", sensitive && info->has_video ); gtv_set_sensitive( raw, "audio", sensitive && info->has_audio && info->has_video); gtv_set_sensitive( raw, "filter", sensitive && info->has_video ); gtv_fix_toggle_state( raw ); } static void gtv_dialog_cleanup( gpointer raw ) { GtkWidget* dialog = NULL; dialog = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( raw ), "dialog" ) ); gtk_grab_remove( dialog ); gtk_widget_destroy( dialog ); gtk_object_set_data( GTK_OBJECT( raw ), "dialog", NULL ); } static void gtv_dialog_cancel( GtkWidget* item, gpointer raw ) { gtv_dialog_cleanup( raw ); } static void gtv_open_ok( GtkWidget* item, gpointer raw ) { GtkWidget* file_sel = NULL; gchar* filename = NULL; /* HACK HACK HACK */ file_sel = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( raw ), "dialog" ) ); filename = gtk_file_selection_get_filename( GTK_FILE_SELECTION( file_sel ) ); if( filename ) { gtv_open_file( filename, raw ); if( strrchr( filename, '/') ) { if( gtv_default_directory ) free( gtv_default_directory ); gtv_default_directory = (gchar *) malloc( (strlen(filename) + 1) * sizeof(gchar) ); strcpy( gtv_default_directory, filename); *(strrchr( gtv_default_directory, '/' ) + 1) = 0; } } gtv_dialog_cleanup( raw ); } static void gtv_open( GtkWidget* item, gpointer raw ) { GtkWidget* file_sel = NULL; file_sel = gtk_file_selection_new( "Select an MPEG" ); gtk_signal_connect( GTK_OBJECT( GTK_FILE_SELECTION( file_sel )->ok_button ), "clicked", GTK_SIGNAL_FUNC( gtv_open_ok ), raw ); gtk_signal_connect( GTK_OBJECT( GTK_FILE_SELECTION( file_sel )->cancel_button ), "clicked", GTK_SIGNAL_FUNC( gtv_dialog_cancel ), raw ); if( gtv_default_directory ) gtk_file_selection_complete( GTK_FILE_SELECTION( file_sel ), gtv_default_directory ); gtk_file_selection_hide_fileop_buttons( GTK_FILE_SELECTION( file_sel ) ); /* HACK HACK HACK */ gtk_object_set_data( GTK_OBJECT( raw ), "dialog", file_sel ); gtk_grab_add( file_sel ); gtk_widget_show( file_sel ); } static void gtv_center_window(SDL_Surface *screen) { SDL_SysWMinfo info; SDL_VERSION(&info.version); if ( SDL_GetWMInfo(&info) > 0 ) { int x, y; int w, h; #ifdef unix if ( info.subsystem == SDL_SYSWM_X11 ) { info.info.x11.lock_func(); w = DisplayWidth(info.info.x11.display, DefaultScreen(info.info.x11.display)); h = DisplayHeight(info.info.x11.display, DefaultScreen(info.info.x11.display)); x = (w - screen->w)/2; y = (h - screen->h)/2; XMoveWindow(info.info.x11.display, info.info.x11.wmwindow, x, y); info.info.x11.unlock_func(); } #else #ifdef WIN32 /* FIXME: implement centering code for Windows */ #else #warning Need to implement these functions for other systems #endif // WIN32 #endif // unix } } static void gtv_open_file( gchar* name, gpointer raw ) { SMPEG_Info* info = NULL; SMPEG* mpeg = NULL; gchar buffer[FILENAME_BUFFER_SIZE]; assert( name ); assert( raw ); gtv_close( NULL, raw ); if( SDL_Init( SDL_INIT_AUDIO | SDL_INIT_VIDEO ) < 0 ) { fprintf( stderr, "gtv: couldn't initialize SDL: %s\n", SDL_GetError( ) ); exit( 1 ); } info = (SMPEG_Info*) gtk_object_get_data( GTK_OBJECT( raw ), "info" ); assert( info ); mpeg = SMPEG_new( name, info, 1 ); if( SMPEG_error( mpeg ) ) { fprintf( stderr, "gtv: %s\n", SMPEG_error( mpeg ) ); SMPEG_delete( mpeg ); gtk_object_set_data( GTK_OBJECT( raw ), "mpeg", NULL ); return; } gtk_object_set_data( GTK_OBJECT( raw ), "mpeg", mpeg ); strncpy( (char*) gtk_object_get_data( GTK_OBJECT( raw ), "filename_buffer" ), name, FILENAME_BUFFER_SIZE ); gtv_set_frame( raw, 0 ); gtv_set_fps( raw, 0.0 ); g_snprintf( buffer, FILENAME_BUFFER_SIZE, "gtv - %s", name ); gtk_window_set_title( GTK_WINDOW( raw ), buffer ); if( info->has_video ) { SDL_Surface* sdl_screen = NULL; const SDL_VideoInfo *video_info; int video_bpp; /* Get the "native" video mode */ video_info = SDL_GetVideoInfo(); switch (video_info->vfmt->BitsPerPixel) { case 16: case 32: video_bpp = video_info->vfmt->BitsPerPixel; break; default: video_bpp = 16; break; } #ifdef linux putenv("SDL_VIDEO_CENTERED=1"); #endif sdl_screen = SDL_SetVideoMode( info->width , info->height , video_bpp, SDL_ASYNCBLIT); SDL_WM_SetCaption(name, "gtv movie"); gtv_center_window(sdl_screen); SMPEG_setdisplay( mpeg, sdl_screen, NULL, NULL ); gtk_object_set_data( GTK_OBJECT( raw ), "sdl_screen", sdl_screen ); gtv_double( NULL, raw ); } gtv_loop( NULL, raw ); gtv_audio( NULL, raw ); gtv_filter( NULL, raw ); gtv_set_buttons_sensitive( raw, TRUE ); } static void gtv_close( GtkWidget* item, gpointer raw ) { SMPEG* mpeg = NULL; SMPEG_Info* info = NULL; assert( raw != NULL ); gtv_stop( NULL, raw ); mpeg = (SMPEG*) gtk_object_get_data( GTK_OBJECT( raw ), "mpeg" ); if( mpeg ) { SDL_Surface* sdl_screen = NULL; SMPEG_delete( mpeg ); gtk_object_set_data( GTK_OBJECT( raw ), "mpeg", NULL ); info = (SMPEG_Info*) gtk_object_get_data( GTK_OBJECT( raw ), "info" ); memset( info, 0, sizeof( SMPEG_Info ) ); sdl_screen = (SDL_Surface*) gtk_object_get_data( GTK_OBJECT( raw ), "sdl_screen" ); SDL_FreeSurface( sdl_screen ); gtk_object_set_data( GTK_OBJECT( raw ), "sdl_screen", NULL ); SDL_Quit( ); } /* Reset title. */ gtk_window_set_title( GTK_WINDOW( raw ), "gtv" ); gtv_set_frame( raw, 0 ); gtv_set_fps( raw, 0.0 ); gtv_set_buttons_sensitive( raw, FALSE ); } static GtkWidget* create_file_info_dialog( void ) { GtkWidget *file_info_dialog; GtkWidget *dialog_vbox1; GtkWidget *vbox2; GtkWidget *label5; GtkWidget *scrolledwindow1; GtkWidget *viewport1; GtkWidget *text; GtkWidget *dialog_action_area1; GtkWidget *ok; file_info_dialog = gtk_dialog_new (); gtk_object_set_data (GTK_OBJECT (file_info_dialog), "file_info_dialog", file_info_dialog); gtk_window_set_title (GTK_WINDOW (file_info_dialog), "File Info"); gtk_window_set_default_size (GTK_WINDOW (file_info_dialog), 256, 192); dialog_vbox1 = GTK_DIALOG (file_info_dialog)->vbox; gtk_object_set_data (GTK_OBJECT (file_info_dialog), "dialog_vbox1", dialog_vbox1); gtk_widget_show (dialog_vbox1); vbox2 = gtk_vbox_new (FALSE, 5); gtk_widget_ref (vbox2); gtk_object_set_data_full (GTK_OBJECT (file_info_dialog), "vbox2", vbox2, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (vbox2); gtk_box_pack_start (GTK_BOX (dialog_vbox1), vbox2, TRUE, TRUE, 0); gtk_container_set_border_width (GTK_CONTAINER (vbox2), 5); label5 = gtk_label_new ("File info:"); gtk_widget_ref (label5); gtk_object_set_data_full (GTK_OBJECT (file_info_dialog), "label5", label5, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (label5); gtk_box_pack_start (GTK_BOX (vbox2), label5, FALSE, FALSE, 0); gtk_misc_set_alignment (GTK_MISC (label5), 0, 0.5); scrolledwindow1 = gtk_scrolled_window_new (NULL, NULL); gtk_widget_ref (scrolledwindow1); gtk_object_set_data_full (GTK_OBJECT (file_info_dialog), "scrolledwindow1", scrolledwindow1, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (scrolledwindow1); gtk_box_pack_start (GTK_BOX (vbox2), scrolledwindow1, TRUE, TRUE, 0); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow1), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); viewport1 = gtk_viewport_new (NULL, NULL); gtk_widget_ref (viewport1); gtk_object_set_data_full (GTK_OBJECT (file_info_dialog), "viewport1", viewport1, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (viewport1); gtk_container_add (GTK_CONTAINER (scrolledwindow1), viewport1); text = gtk_text_new (NULL, NULL); gtk_widget_ref (text); gtk_object_set_data_full (GTK_OBJECT (file_info_dialog), "text", text, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (text); gtk_container_add (GTK_CONTAINER (viewport1), text); dialog_action_area1 = GTK_DIALOG (file_info_dialog)->action_area; gtk_object_set_data (GTK_OBJECT (file_info_dialog), "dialog_action_area1", dialog_action_area1); gtk_widget_show (dialog_action_area1); gtk_container_set_border_width (GTK_CONTAINER (dialog_action_area1), 10); ok = gtk_button_new_with_label (" OK "); gtk_widget_ref (ok); gtk_object_set_data_full (GTK_OBJECT (file_info_dialog), "ok", ok, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (ok); gtk_box_pack_start (GTK_BOX (dialog_action_area1), ok, FALSE, FALSE, 0); return file_info_dialog; } static void gtv_info( GtkWidget* item, gpointer raw ) { GtkWidget* dialog = NULL; GtkWidget* ok = NULL; gchar buffer[1024]; gint ignored = 0; GtkWidget* text = NULL; SMPEG_Info* info = NULL; int hh,mm,ss; dialog = create_file_info_dialog( ); ok = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( dialog ), "ok" ) ); gtk_signal_connect( GTK_OBJECT( ok ), "clicked", GTK_SIGNAL_FUNC( gtv_dialog_cancel ), raw ); /* HACK HACK HACK */ gtk_object_set_data( GTK_OBJECT( raw ), "dialog", dialog ); /* Actually stuff some data in there. */ info = (SMPEG_Info*) gtk_object_get_data( GTK_OBJECT( raw ), "info" ); hh = info->total_time / 3600; mm = (info->total_time - hh * 3600)/60; ss = ((int)info->total_time % 60); g_snprintf( buffer, 1024, "Filename: %s\nStream: %s\nVideo: %dx%d resolution\nAudio: %s\nSize: %d\nTime %d:%02d:%02d\n", (gchar*) gtk_object_get_data( GTK_OBJECT( raw ), "filename_buffer" ), ( info->has_audio && info->has_video ) ? "system" : ( info->has_video ? "video" : ( info->has_audio ? "audio" : "not MPEG" ) ), info->width, info->height, ( info->has_audio ? info->audio_string : "none" ), info->total_size , hh,mm,ss); text = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( dialog ), "text" ) ); gtk_editable_insert_text( GTK_EDITABLE( text ), buffer, strlen( buffer ), &ignored ); gtk_grab_add( dialog ); gtk_widget_show( dialog ); } static GtkWidget* create_about_dialog( void ) { GtkWidget *about_dialog; GtkWidget *dialog_vbox2; GtkWidget *scrolledwindow2; GtkWidget *viewport2; GtkWidget *text; GtkWidget *dialog_action_area2; GtkWidget *ok; about_dialog = gtk_dialog_new (); gtk_object_set_data (GTK_OBJECT (about_dialog), "about_dialog", about_dialog); gtk_window_set_title (GTK_WINDOW (about_dialog), "About gtv"); gtk_window_set_default_size (GTK_WINDOW (about_dialog), 384, 256); gtk_window_set_policy (GTK_WINDOW (about_dialog), TRUE, TRUE, FALSE); dialog_vbox2 = GTK_DIALOG (about_dialog)->vbox; gtk_object_set_data (GTK_OBJECT (about_dialog), "dialog_vbox2", dialog_vbox2); gtk_widget_show (dialog_vbox2); scrolledwindow2 = gtk_scrolled_window_new (NULL, NULL); gtk_widget_ref (scrolledwindow2); gtk_object_set_data_full (GTK_OBJECT (about_dialog), "scrolledwindow2", scrolledwindow2, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (scrolledwindow2); gtk_box_pack_start (GTK_BOX (dialog_vbox2), scrolledwindow2, TRUE, TRUE, 0); gtk_container_set_border_width (GTK_CONTAINER (scrolledwindow2), 5); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow2), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); viewport2 = gtk_viewport_new (NULL, NULL); gtk_widget_ref (viewport2); gtk_object_set_data_full (GTK_OBJECT (about_dialog), "viewport2", viewport2, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (viewport2); gtk_container_add (GTK_CONTAINER (scrolledwindow2), viewport2); text = gtk_text_new (NULL, NULL); gtk_widget_ref (text); gtk_object_set_data_full (GTK_OBJECT (about_dialog), "text", text, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (text); gtk_container_add (GTK_CONTAINER (viewport2), text); dialog_action_area2 = GTK_DIALOG (about_dialog)->action_area; gtk_object_set_data (GTK_OBJECT (about_dialog), "dialog_action_area2", dialog_action_area2); gtk_widget_show (dialog_action_area2); gtk_container_set_border_width (GTK_CONTAINER (dialog_action_area2), 10); ok = gtk_button_new_with_label (" OK "); gtk_widget_ref (ok); gtk_object_set_data_full (GTK_OBJECT (about_dialog), "ok", ok, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (ok); gtk_box_pack_start (GTK_BOX (dialog_action_area2), ok, FALSE, FALSE, 0); return about_dialog; } static void gtv_about( GtkWidget* item, gpointer raw ) { static const char* msg = "gtv - Gtk+ MPEG Player\n" \ "(c) Michael Vance, 1999\n" \ " briareos@lokigames.com\n" \ "\n" \ "Built using:\n" \ "SMPEG - http://www.lokigames.com/development\n" \ "Gtk+ - http://www.gtk.org\n" \ "Glade - http://glade.pn.org\n" \ "\n" \ "Distributed under the GPL.\n"; GtkWidget* dialog = NULL; GtkWidget* ok = NULL; GtkWidget* text = NULL; gint ignored = 0; dialog = create_about_dialog( ); ok = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( dialog ), "ok" ) ); gtk_signal_connect( GTK_OBJECT( ok ), "clicked", GTK_SIGNAL_FUNC( gtv_dialog_cancel ), raw ); text = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( dialog ), "text" ) ); gtk_editable_insert_text( GTK_EDITABLE( text ), msg, strlen( msg ), &ignored ); /* HACK HACK HACK */ gtk_object_set_data( GTK_OBJECT( raw ), "dialog", dialog ); gtk_grab_add( dialog ); gtk_widget_show( dialog ); } static void gtv_rewind( gpointer raw ) { SMPEG* mpeg = NULL; assert( raw ); mpeg = (SMPEG*) gtk_object_get_data( GTK_OBJECT( raw ), "mpeg" ); if( mpeg ) { SMPEG_Info* info = NULL; SMPEG_rewind( mpeg ); gtv_clear_screen( raw ); info = (SMPEG_Info*) gtk_object_get_data( GTK_OBJECT( raw ), "info" ); SMPEG_getinfo( mpeg, info ); gtv_set_frame( raw, info->current_frame ); } } static void gtv_double( GtkWidget* item, gpointer raw ) { SMPEG* mpeg = NULL; SDL_Surface* sdl_screen = NULL; SMPEG_Info* info = NULL; int stopped=0; int width,height; assert( raw ); mpeg = (SMPEG*) gtk_object_get_data( GTK_OBJECT( raw ), "mpeg" ); sdl_screen = (SDL_Surface*) gtk_object_get_data( GTK_OBJECT( raw ), "sdl_screen" ); if( mpeg && sdl_screen ) { GtkWidget* twotimes = NULL; gboolean active = FALSE; twotimes = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( raw ), "twotimes" ) ); active = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( twotimes ) ); info = (SMPEG_Info*) gtk_object_get_data( GTK_OBJECT( raw ), "info" ); assert( info ); if (SMPEG_status(mpeg)==SMPEG_PLAYING) { SMPEG_pause(mpeg); stopped=1; } if( active ) { width = info->width * 2; height = info->height * 2; } else { width = info->width; height = info->height; } sdl_screen = SDL_SetVideoMode(width, height, sdl_screen->format->BitsPerPixel,sdl_screen->flags); gtv_center_window(sdl_screen); SMPEG_setdisplay( mpeg, sdl_screen, NULL, NULL ); gtk_object_set_data( GTK_OBJECT( raw ), "sdl_screen", sdl_screen ); SMPEG_scaleXY( mpeg, sdl_screen->w, sdl_screen->h ); gtv_center_window(sdl_screen); if (stopped) SMPEG_pause(mpeg); } } static void gtv_loop( GtkWidget* item, gpointer raw ) { SMPEG* mpeg = NULL; assert( raw ); mpeg = (SMPEG*) gtk_object_get_data( GTK_OBJECT( raw ), "mpeg" ); if( mpeg ) { GtkWidget* loop = NULL; gboolean active = FALSE; loop = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( raw ), "loop" ) ); active = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( loop ) ); SMPEG_loop( mpeg, active ); } } static void gtv_audio( GtkWidget* item, gpointer raw ) { SMPEG* mpeg = NULL; assert( raw ); mpeg = (SMPEG*) gtk_object_get_data( GTK_OBJECT( raw ), "mpeg" ); if( mpeg ) { GtkWidget* audio = NULL; gboolean active = FALSE; SMPEG_Info* info = NULL; audio = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( raw ), "audio" ) ); info = (SMPEG_Info*) gtk_object_get_data( GTK_OBJECT( raw ), "info" ); active = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( audio ) ); SMPEG_enableaudio( mpeg, active && info->has_audio ); } } static void gtv_filter( GtkWidget* item, gpointer raw ) { SMPEG* mpeg = NULL; SMPEG_Info* info = NULL; assert( raw ); mpeg = (SMPEG*) gtk_object_get_data( GTK_OBJECT( raw ), "mpeg" ); info = (SMPEG_Info*) gtk_object_get_data( GTK_OBJECT( raw ), "info" ); if( mpeg && info->has_video ) { GtkWidget* filter = NULL; gboolean active = FALSE; filter = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( raw ), "filter" ) ); active = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( filter ) ); if(active) { SMPEG_Filter * filter; /* Activate the bilinear filter */ filter = SMPEGfilter_bilinear(); filter = SMPEG_filter( mpeg, filter ); filter->destroy(filter); } else { SMPEG_Filter * filter; /* Reset to default (null) filter */ filter = SMPEGfilter_null(); filter = SMPEG_filter( mpeg, filter ); filter->destroy(filter); } } } static void gtv_play( GtkWidget* item, gpointer raw ) { SMPEG* mpeg = NULL; assert( raw ); mpeg = (SMPEG*) gtk_object_get_data( GTK_OBJECT( raw ), "mpeg" ); if( mpeg ) { // gtv_rewind( raw ); SMPEG_play( mpeg ); } } static void gtv_pause( GtkWidget* item, gpointer raw ) { SMPEG* mpeg = NULL; assert( raw ); mpeg = (SMPEG*) gtk_object_get_data( GTK_OBJECT( raw ), "mpeg" ); if( mpeg ) { SMPEG_pause( mpeg ); } } static void gtv_stop( GtkWidget* item, gpointer raw ) { SMPEG* mpeg = NULL; SMPEG_Info* info = NULL; assert( raw ); mpeg = (SMPEG*) gtk_object_get_data( GTK_OBJECT( raw ), "mpeg" ); info = (SMPEG_Info*) gtk_object_get_data( GTK_OBJECT( raw ), "info" ); if( mpeg ) { SMPEG_stop( mpeg ); gtv_rewind( raw ); SMPEG_getinfo( mpeg, info ); gtv_set_trackbar( raw, info->current_offset ); } } static void gtv_step( GtkWidget* item, gpointer raw ) { SMPEG* mpeg = NULL; SMPEG_Info* info = NULL; assert( raw ); mpeg = (SMPEG*) gtk_object_get_data( GTK_OBJECT( raw ), "mpeg" ); info = (SMPEG_Info*) gtk_object_get_data( GTK_OBJECT( raw ), "info" ); if( mpeg && info && info->has_video && ( SMPEG_status( mpeg ) != SMPEG_PLAYING ) ) { int next_frame = 0; GtkWidget* twotimes = NULL; gboolean active = FALSE; SDL_Surface* sdl_screen = NULL; SMPEG_getinfo( mpeg, info ); next_frame = info->current_frame + 1; twotimes = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( raw ), "twotimes" ) ); active = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( twotimes ) ); sdl_screen = (SDL_Surface*) gtk_object_get_data( GTK_OBJECT( raw ), "sdl_screen" ); SMPEG_renderFrame( mpeg, next_frame ); SMPEG_getinfo( mpeg, info ); if( info->current_frame != next_frame ) { GtkWidget *looping; /* Sam 5/31/2000 - Only loop if the looping toggle is set */ looping = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(raw), "loop")); if ( ! gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(looping)) ) { return; } gtv_rewind( raw ); gtv_step( NULL, raw ); } gtv_set_frame( raw, info->current_frame ); } } static void gtv_to_end( GtkWidget* item, gpointer raw ) { SMPEG* mpeg = NULL; SMPEG_Info* info = NULL; assert( raw ); mpeg = (SMPEG*) gtk_object_get_data( GTK_OBJECT( raw ), "mpeg" ); info = (SMPEG_Info*) gtk_object_get_data( GTK_OBJECT( raw ), "info" ); if( mpeg && info->has_video ) { GtkWidget* twotimes = NULL; gboolean active = FALSE; SDL_Surface* sdl_screen = NULL; SMPEG_stop( mpeg ); twotimes = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( raw ), "twotimes" ) ); active = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( twotimes ) ); sdl_screen = (SDL_Surface*) gtk_object_get_data( GTK_OBJECT( raw ), "sdl_screen" ); if( active ) { SMPEG_renderFinal( mpeg, sdl_screen, 0, 0 ); } else { SMPEG_renderFinal( mpeg, sdl_screen, ( sdl_screen->w - info->width ) / 2, ( sdl_screen->h - info->height ) / 2 ); } SMPEG_getinfo( mpeg, info ); gtv_set_frame( raw, info->current_frame ); } } static void gtv_seek( GtkAdjustment* adjust, gpointer raw ) { SMPEG* mpeg = NULL; SMPEG_Info* info = NULL; assert( raw ); if(gtv_trackbar_dragging) return; mpeg = (SMPEG*) gtk_object_get_data( GTK_OBJECT( raw ), "mpeg" ); info = (SMPEG_Info*) gtk_object_get_data( GTK_OBJECT( raw ), "info" ); if( mpeg && info && info->total_size ) { /* In case file is growing while we're playing */ SMPEG_getinfo( mpeg, info ); SMPEG_seek(mpeg, (int)((info->total_size*adjust->value)/100)); SMPEG_getinfo( mpeg, info ); gtv_set_frame( raw, info->current_frame ); } } static void gtv_trackbar_drag_on(GtkWidget *widget, gpointer raw) { gtv_trackbar_dragging = 1; } static void gtv_trackbar_drag_off(GtkWidget *widget, gpointer raw) { gtv_trackbar_dragging = 0; } static void gtv_set_frame( gpointer raw, int value ) { GtkWidget* frame = NULL; gchar buffer[32]; assert( raw ); assert( value >= 0 ); frame = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( raw ), "frame" ) ); g_snprintf( buffer, 32, "%d", value ); gtk_label_set_text( GTK_LABEL( frame ), buffer ); } static void gtv_set_fps( gpointer raw, float value ) { GtkWidget* fps = NULL; gchar buffer[32]; assert( raw ); assert( value >= 0.0 ); fps = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( raw ), "fps" ) ); g_snprintf( buffer, 32, "%2.2f", value ); gtk_label_set_text( GTK_LABEL( fps ), buffer ); } static void gtv_set_trackbar( gpointer raw, int value ) { SMPEG* mpeg = NULL; SMPEG_Info* info = NULL; GtkWidget* scale = NULL; GtkAdjustment* seek = NULL; assert( raw ); assert( value >= 0 ); if(gtv_trackbar_dragging) return; mpeg = (SMPEG*) gtk_object_get_data( GTK_OBJECT( raw ), "mpeg" ); info = (SMPEG_Info*) gtk_object_get_data( GTK_OBJECT( raw ), "info" ); if( mpeg && info && info->total_size ) { scale = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( raw ), "scale" ) ); seek = gtk_range_get_adjustment ( GTK_RANGE( scale ) ); seek->value = 100. * value / info->total_size; gtk_range_set_adjustment ( GTK_RANGE( scale ), seek ); gtk_range_slider_update ( GTK_RANGE( scale ) ); gtk_range_clear_background ( GTK_RANGE( scale ) ); gtk_range_draw_background ( GTK_RANGE( scale ) ); } } /* Drag-N-Drop support, contributed by */ static void gtv_drag_data_received(GtkWidget * widget, GdkDragContext * context, gint x, gint y, GtkSelectionData * selection_data, guint info, guint time) { gchar *temp, *string; string = (gchar *)selection_data->data; /* remove newline at end of line, and the file:// url header at the begining, copied this code from the xmms source */ temp = strchr(string, '\n'); if (temp) { if (*(temp - 1) == '\r') *(temp - 1) = '\0'; *temp = '\0'; } if (!strncmp(string, "file:", 5)) string = string + 5; gtv_open_file(string, widget); gtv_play(NULL, widget); } static gint gtv_timer( gpointer raw ) { SMPEG* mpeg = NULL; SMPEG_Info* info = NULL; mpeg = (SMPEG*) gtk_object_get_data( GTK_OBJECT( raw ), "mpeg" ); info = (SMPEG_Info*) gtk_object_get_data( GTK_OBJECT( raw ), "info" ); if( mpeg && info ) { if( SMPEG_status( mpeg ) == SMPEG_PLAYING ) { SMPEG_getinfo( mpeg, info ); gtv_set_frame( raw, info->current_frame ); gtv_set_fps( raw, info->current_fps ); gtv_set_trackbar( raw, info->current_offset ); } } return 1; } static void gtv_clear_screen( gpointer raw ) { SDL_Surface* sdl_screen = NULL; sdl_screen = (SDL_Surface*) gtk_object_get_data( GTK_OBJECT( raw ), "sdl_screen" ); if( sdl_screen ) { SDL_FillRect( sdl_screen, NULL, SDL_MapRGB( sdl_screen->format, 0, 0, 0 ) ); SDL_UpdateRect( sdl_screen, 0, 0, 0, 0 ); } } static void gtv_quit( GtkWidget* item, gpointer raw ) { gtv_close( NULL, raw ); gtk_exit( 0 ); } static void gtv_connect( gpointer raw, gchar* name, gchar* signal, GtkSignalFunc func ) { GtkObject* item = NULL; assert( raw ); item = GTK_OBJECT( gtk_object_get_data( GTK_OBJECT( raw ), name ) ); assert( item ); gtk_signal_connect(item, signal, func, raw ); } int main( int argc, char* argv[] ) { static GtkTargetEntry drop_types[] = { { "text/plain", 0, 1 } }; /* These are always on the stack until program exit. */ SMPEG_Info info; gchar filename_buffer[FILENAME_BUFFER_SIZE]; GtkWidget* window = NULL; memset( &info, 0, sizeof( info ) ); memset( &filename_buffer, 0, sizeof( gchar ) * FILENAME_BUFFER_SIZE ); gtk_set_locale(); gtk_init( &argc, &argv ); window = create_gtv_window( ); gtk_drag_dest_set(window, GTK_DEST_DEFAULT_ALL, drop_types, 1, GDK_ACTION_COPY); gtk_signal_connect( GTK_OBJECT( window ), "drag_data_received", GTK_SIGNAL_FUNC( gtv_drag_data_received ), window ); gtk_signal_connect( GTK_OBJECT( window ), "destroy", GTK_SIGNAL_FUNC( gtv_quit ), window ); gtk_object_set_data( GTK_OBJECT( window ), "info", &info ); gtk_object_set_data( GTK_OBJECT( window ), "mpeg", NULL ); gtk_object_set_data( GTK_OBJECT( window ), "sdl_screen", NULL ); gtk_object_set_data( GTK_OBJECT( window ), "filename_buffer", filename_buffer ); gtk_widget_show( window ); gtv_connect( window, "open", "activate", GTK_SIGNAL_FUNC( gtv_open ) ); gtv_connect( window, "close", "activate", GTK_SIGNAL_FUNC( gtv_close ) ); gtv_connect( window, "file_info", "activate", GTK_SIGNAL_FUNC( gtv_info ) ); gtv_connect( window, "quit", "activate", GTK_SIGNAL_FUNC( gtv_quit ) ); gtv_connect( window, "about", "activate", GTK_SIGNAL_FUNC( gtv_about ) ); gtv_connect( window, "play", "clicked", GTK_SIGNAL_FUNC( gtv_play ) ); gtv_connect( window, "pause", "clicked", GTK_SIGNAL_FUNC( gtv_pause ) ); gtv_connect( window, "stop", "clicked", GTK_SIGNAL_FUNC( gtv_stop ) ); gtv_connect( window, "step", "clicked", GTK_SIGNAL_FUNC( gtv_step ) ); gtv_connect( window, "to_end", "clicked", GTK_SIGNAL_FUNC( gtv_to_end ) ); gtv_connect( window, "twotimes", "toggled", GTK_SIGNAL_FUNC( gtv_double ) ); gtv_connect( window, "loop", "toggled", GTK_SIGNAL_FUNC( gtv_loop ) ); gtv_connect( window, "audio", "toggled", GTK_SIGNAL_FUNC( gtv_audio ) ); gtv_connect( window, "filter", "toggled", GTK_SIGNAL_FUNC( gtv_filter ) ); gtv_connect( window, "seek", "value_changed", GTK_SIGNAL_FUNC( gtv_seek ) ); gtv_connect( window, "scale", "button_press_event", GTK_SIGNAL_FUNC( gtv_trackbar_drag_on ) ); gtv_connect( window, "scale", "button_release_event", GTK_SIGNAL_FUNC( gtv_trackbar_drag_off ) ); /* gtk_idle_add_priority( G_PRIORITY_LOW, gtv_timer, window );*/ gtk_timeout_add( TIMER_TIMEOUT, gtv_timer, window ); gtv_set_frame( window, 0 ); gtv_set_fps( window, 0.0 ); gtv_set_buttons_sensitive( window, FALSE ); if( argc > 1 ) { gtv_open_file( argv[1], window ); } gtk_main( ); return 0; } static GtkWidget* create_gtv_window( void ) { GtkWidget *gtv_window; GtkWidget *vbox1; GtkWidget *menubar1; GtkWidget *file; GtkWidget *file_menu; GtkAccelGroup *file_menu_accels; GtkWidget *open; GtkWidget *close; GtkWidget *separator1; GtkWidget *file_info; GtkWidget *separator2; GtkWidget *quit; GtkWidget *help; GtkWidget *help_menu; GtkAccelGroup *help_menu_accels; GtkWidget *about; GtkWidget *table1; GtkObject *seek; GtkWidget *scale; GtkWidget *play; GtkWidget *pause; GtkWidget *stop; GtkWidget *step; GtkWidget *to_end; GtkWidget *twotimes; GtkWidget *loop; GtkWidget *audio; GtkWidget *filter; GtkWidget *label3; GtkWidget *fps; GtkWidget *label2; GtkWidget *frame; GtkAccelGroup *accel_group; accel_group = gtk_accel_group_new (); gtv_window = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_object_set_data (GTK_OBJECT (gtv_window), "gtv_window", gtv_window); gtk_window_set_title (GTK_WINDOW (gtv_window), "gtv"); gtk_widget_set_uposition (GTK_WIDGET (gtv_window), 0, 0); vbox1 = gtk_vbox_new (FALSE, 0); gtk_widget_ref (vbox1); gtk_object_set_data_full (GTK_OBJECT (gtv_window), "vbox1", vbox1, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (vbox1); gtk_container_add (GTK_CONTAINER (gtv_window), vbox1); menubar1 = gtk_menu_bar_new (); gtk_widget_ref (menubar1); gtk_object_set_data_full (GTK_OBJECT (gtv_window), "menubar1", menubar1, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (menubar1); gtk_box_pack_start (GTK_BOX (vbox1), menubar1, FALSE, FALSE, 0); file = gtk_menu_item_new_with_label ("File"); gtk_widget_ref (file); gtk_object_set_data_full (GTK_OBJECT (gtv_window), "file", file, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (file); gtk_container_add (GTK_CONTAINER (menubar1), file); file_menu = gtk_menu_new (); gtk_widget_ref (file_menu); gtk_object_set_data_full (GTK_OBJECT (gtv_window), "file_menu", file_menu, (GtkDestroyNotify) gtk_widget_unref); gtk_menu_item_set_submenu (GTK_MENU_ITEM (file), file_menu); file_menu_accels = gtk_menu_ensure_uline_accel_group (GTK_MENU (file_menu)); open = gtk_menu_item_new_with_label ("Open"); gtk_widget_ref (open); gtk_object_set_data_full (GTK_OBJECT (gtv_window), "open", open, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (open); gtk_container_add (GTK_CONTAINER (file_menu), open); gtk_widget_add_accelerator (open, "activate", accel_group, GDK_O, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); close = gtk_menu_item_new_with_label ("Close"); gtk_widget_ref (close); gtk_object_set_data_full (GTK_OBJECT (gtv_window), "close", close, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (close); gtk_container_add (GTK_CONTAINER (file_menu), close); gtk_widget_add_accelerator (close, "activate", accel_group, GDK_W, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); separator1 = gtk_menu_item_new (); gtk_widget_ref (separator1); gtk_object_set_data_full (GTK_OBJECT (gtv_window), "separator1", separator1, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (separator1); gtk_container_add (GTK_CONTAINER (file_menu), separator1); gtk_widget_set_sensitive (separator1, FALSE); file_info = gtk_menu_item_new_with_label ("Info"); gtk_widget_ref (file_info); gtk_object_set_data_full (GTK_OBJECT (gtv_window), "file_info", file_info, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (file_info); gtk_container_add (GTK_CONTAINER (file_menu), file_info); gtk_widget_add_accelerator (file_info, "activate", accel_group, GDK_I, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); separator2 = gtk_menu_item_new (); gtk_widget_ref (separator2); gtk_object_set_data_full (GTK_OBJECT (gtv_window), "separator2", separator2, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (separator2); gtk_container_add (GTK_CONTAINER (file_menu), separator2); gtk_widget_set_sensitive (separator2, FALSE); quit = gtk_menu_item_new_with_label ("Quit"); gtk_widget_ref (quit); gtk_object_set_data_full (GTK_OBJECT (gtv_window), "quit", quit, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (quit); gtk_container_add (GTK_CONTAINER (file_menu), quit); gtk_widget_add_accelerator (quit, "activate", accel_group, GDK_Q, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); help = gtk_menu_item_new_with_label ("Help"); gtk_widget_ref (help); gtk_object_set_data_full (GTK_OBJECT (gtv_window), "help", help, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (help); gtk_container_add (GTK_CONTAINER (menubar1), help); gtk_menu_item_right_justify (GTK_MENU_ITEM (help)); help_menu = gtk_menu_new (); gtk_widget_ref (help_menu); gtk_object_set_data_full (GTK_OBJECT (gtv_window), "help_menu", help_menu, (GtkDestroyNotify) gtk_widget_unref); gtk_menu_item_set_submenu (GTK_MENU_ITEM (help), help_menu); help_menu_accels = gtk_menu_ensure_uline_accel_group (GTK_MENU (help_menu)); about = gtk_menu_item_new_with_label ("About"); gtk_widget_ref (about); gtk_object_set_data_full (GTK_OBJECT (gtv_window), "about", about, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (about); gtk_container_add (GTK_CONTAINER (help_menu), about); gtk_widget_add_accelerator (about, "activate", accel_group, GDK_F1, 0, GTK_ACCEL_VISIBLE); table1 = gtk_table_new (4, 5, FALSE); gtk_widget_ref (table1); gtk_object_set_data_full (GTK_OBJECT (gtv_window), "table1", table1, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (table1); gtk_box_pack_start (GTK_BOX (vbox1), table1, TRUE, TRUE, 0); gtk_container_set_border_width (GTK_CONTAINER (table1), 5); gtk_table_set_row_spacings (GTK_TABLE (table1), 5); gtk_table_set_col_spacings (GTK_TABLE (table1), 5); seek = gtk_adjustment_new(0.0, 0.0, 100.0, 1.0, 0.0, 0.0); gtk_object_set_data_full (GTK_OBJECT (gtv_window), "seek", seek, (GtkDestroyNotify) (0)); scale = gtk_hscale_new(GTK_ADJUSTMENT(seek)); gtv_trackbar_dragging = 0; gtk_widget_ref (scale); gtk_object_set_data_full (GTK_OBJECT (gtv_window), "scale", scale, (GtkDestroyNotify) gtk_widget_unref); gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED); gtk_widget_show (scale); gtk_table_attach (GTK_TABLE (table1), scale, 0, 5, 3, 4, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); play = gtk_button_new_with_label (" Play "); gtk_widget_ref (play); gtk_object_set_data_full (GTK_OBJECT (gtv_window), "play", play, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (play); gtk_table_attach (GTK_TABLE (table1), play, 0, 1, 1, 2, (GtkAttachOptions) (0), (GtkAttachOptions) (0), 0, 0); pause = gtk_button_new_with_label (" Pause "); gtk_widget_ref (pause); gtk_object_set_data_full (GTK_OBJECT (gtv_window), "pause", pause, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (pause); gtk_table_attach (GTK_TABLE (table1), pause, 1, 2, 1, 2, (GtkAttachOptions) (0), (GtkAttachOptions) (0), 0, 0); stop = gtk_button_new_with_label (" Stop "); gtk_widget_ref (stop); gtk_object_set_data_full (GTK_OBJECT (gtv_window), "stop", stop, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (stop); gtk_table_attach (GTK_TABLE (table1), stop, 2, 3, 1, 2, (GtkAttachOptions) (0), (GtkAttachOptions) (0), 0, 0); step = gtk_button_new_with_label (" Step "); gtk_widget_ref (step); gtk_object_set_data_full (GTK_OBJECT (gtv_window), "step", step, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (step); gtk_table_attach (GTK_TABLE (table1), step, 3, 4, 1, 2, (GtkAttachOptions) (0), (GtkAttachOptions) (0), 0, 0); to_end = gtk_button_new_with_label (" To End "); gtk_widget_ref (to_end); gtk_object_set_data_full (GTK_OBJECT (gtv_window), "to_end", to_end, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (to_end); gtk_table_attach (GTK_TABLE (table1), to_end, 4, 5, 1, 2, (GtkAttachOptions) (0), (GtkAttachOptions) (0), 0, 0); twotimes = gtk_check_button_new_with_label ("Double"); gtk_widget_ref (twotimes); gtk_object_set_data_full (GTK_OBJECT (gtv_window), "twotimes", twotimes, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (twotimes); gtk_table_attach (GTK_TABLE (table1), twotimes, 0, 1, 2, 3, (GtkAttachOptions) (0), (GtkAttachOptions) (0), 0, 0); loop = gtk_check_button_new_with_label ("Loop"); gtk_widget_ref (loop); gtk_object_set_data_full (GTK_OBJECT (gtv_window), "loop", loop, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (loop); gtk_table_attach (GTK_TABLE (table1), loop, 1, 2, 2, 3, (GtkAttachOptions) (0), (GtkAttachOptions) (0), 0, 0); audio = gtk_check_button_new_with_label ("Audio"); gtk_widget_ref (audio); gtk_object_set_data_full (GTK_OBJECT (gtv_window), "audio", audio, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (audio); gtk_table_attach (GTK_TABLE (table1), audio, 2, 3, 2, 3, (GtkAttachOptions) (0), (GtkAttachOptions) (0), 0, 0); filter = gtk_check_button_new_with_label ("Filter"); gtk_widget_ref (filter); gtk_object_set_data_full (GTK_OBJECT (gtv_window), "filter", filter, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (filter); gtk_table_attach (GTK_TABLE (table1), filter, 3, 4, 2, 3, (GtkAttachOptions) (0), (GtkAttachOptions) (0), 0, 0); label3 = gtk_label_new ("Current frame:"); gtk_widget_ref (label3); gtk_object_set_data_full (GTK_OBJECT (gtv_window), "label3", label3, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (label3); gtk_table_attach (GTK_TABLE (table1), label3, 0, 2, 0, 1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_misc_set_alignment (GTK_MISC (label3), 1, 0.5); fps = gtk_label_new (""); gtk_widget_ref (fps); gtk_object_set_data_full (GTK_OBJECT (gtv_window), "fps", fps, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (fps); gtk_table_attach (GTK_TABLE (table1), fps, 3, 4, 0, 1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_misc_set_alignment (GTK_MISC (fps), 1, 0.5); label2 = gtk_label_new ("fps"); gtk_widget_ref (label2); gtk_object_set_data_full (GTK_OBJECT (gtv_window), "label2", label2, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (label2); gtk_table_attach (GTK_TABLE (table1), label2, 4, 5, 0, 1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_misc_set_alignment (GTK_MISC (label2), 0, 0.5); frame = gtk_label_new (""); gtk_widget_ref (frame); gtk_object_set_data_full (GTK_OBJECT (gtv_window), "frame", frame, (GtkDestroyNotify) gtk_widget_unref); gtk_widget_show (frame); gtk_table_attach (GTK_TABLE (table1), frame, 2, 3, 0, 1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_misc_set_alignment (GTK_MISC (frame), 0, 0.5); gtk_window_add_accel_group (GTK_WINDOW (gtv_window), accel_group); return gtv_window; }