📄 gtv.c
字号:
/* * 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 100static 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -