2 * This file is part of MPlayer.
4 * MPlayer is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * MPlayer is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #include <sys/types.h>
26 #include "wm/wsxdnd.h"
27 #include "interface.h"
28 #include "skin/skin.h"
30 #include "mplayer/gtk/eq.h"
31 #include "mplayer/widgets.h"
32 #include "mplayer/gmplayer.h"
33 #include "mplayer/play.h"
35 #include "access_mpcontext.h"
40 #include "libvo/x11_common.h"
41 #include "libvo/video_out.h"
42 #include "libvo/font_load.h"
43 #include "libvo/sub.h"
44 #include "input/input.h"
45 #include "libao2/audio_out.h"
48 #include "libaf/equalizer.h"
49 #include "libass/ass.h"
50 #include "libass/ass_mp.h"
52 extern af_cfg_t af_cfg
;
58 #include "stream/stream.h"
59 #include "libmpdemux/demuxer.h"
60 #include "libmpdemux/stheader.h"
61 #include "libmpcodecs/dec_video.h"
64 #include "stream/stream_dvd.h"
67 int vcd_seek_to_track(void *vcd
, int track
);
73 guiInterface_t guiIntfStruct
;
76 char * gstrcat( char ** dest
,const char * src
)
80 if ( !src
) return NULL
;
84 tmp
=malloc( strlen( *dest
) + strlen( src
) + 1 );
86 if ( tmp
) /* TODO: advanced error handling */
88 strcpy( tmp
,*dest
); strcat( tmp
,src
); free( *dest
);
92 { tmp
=malloc( strlen( src
) + 1 ); strcpy( tmp
,src
); }
97 int gstrcmp( const char * a
,const char * b
)
99 if ( !a
&& !b
) return 0;
100 if ( !a
|| !b
) return -1;
101 return strcmp( a
,b
);
104 int gstrncmp( const char * a
,const char * b
,int size
)
106 if ( !a
&& !b
) return 0;
107 if ( !a
|| !b
) return -1;
108 return strncmp( a
,b
,size
);
111 char * gstrdup( const char * str
)
113 if ( !str
) return NULL
;
114 return strdup( str
);
117 char * gstrchr( char * str
,int c
)
119 if ( !str
) return NULL
;
120 return strchr( str
,c
);
123 void gfree( void ** p
)
125 if ( *p
== NULL
) return;
129 void gset( char ** str
, const char * what
)
131 if ( *str
) { if ( !strstr( *str
,what
) ) { gstrcat( str
,"," ); gstrcat( str
,what
); }}
132 else gstrcat( str
,what
);
136 * \brief this actually creates a new list containing only one element...
138 void gaddlist( char *** list
,const char * entry
)
144 for ( i
=0;(*list
)[i
];i
++ ) free( (*list
)[i
] );
148 (*list
)=malloc( 2 * sizeof(char **) );
149 (*list
)[0]=gstrdup( entry
);
154 * \brief this replaces a string starting with search by replace.
155 * If not found, replace is appended.
157 void greplace(char ***list
, const char *search
, const char *replace
)
160 int len
= (search
) ? strlen(search
) : 0;
163 for (i
= 0; (*list
)[i
]; i
++) {
164 if (search
&& (strncmp((*list
)[i
], search
, len
) == 0)) {
166 (*list
)[i
] = gstrdup(replace
);
170 *list
= realloc(*list
, (i
+ 2) * sizeof(char *));
173 *list
= malloc(2 * sizeof(char *));
175 (*list
)[i
] = gstrdup(replace
);
176 (*list
)[i
+ 1] = NULL
;
183 memset( &guiIntfStruct
,0,sizeof( guiIntfStruct
) );
184 guiIntfStruct
.Balance
=50.0f
;
185 guiIntfStruct
.StreamType
=-1;
187 memset( >kEquChannels
,0,sizeof( gtkEquChannels
) );
189 if ( !gtkDXR3Device
) gtkDXR3Device
=strdup( "/dev/em8300-0" );
191 if ( stream_cache_size
> 0 ) { gtkCacheOn
=1; gtkCacheSize
=stream_cache_size
; }
192 else if ( stream_cache_size
== 0 ) gtkCacheOn
= 0;
193 if ( autosync
&& autosync
!= gtkAutoSync
) { gtkAutoSyncOn
=1; gtkAutoSync
=autosync
; }
196 gtkASS
.enabled
= ass_enabled
;
197 gtkASS
.use_margins
= ass_use_margins
;
198 gtkASS
.top_margin
= ass_top_margin
;
199 gtkASS
.bottom_margin
= ass_bottom_margin
;
204 wsXInit( (void *)mDisplay
);
206 skinDirInHome
=get_path("skins");
207 skinDirInHome_obsolete
=get_path("Skin");
208 skinMPlayerDir
=MPLAYER_DATADIR
"/skins";
209 skinMPlayerDir_obsolete
=MPLAYER_DATADIR
"/Skin";
210 mp_msg( MSGT_GPLAYER
,MSGL_V
,"SKIN dir 1: '%s'\n",skinDirInHome
);
211 mp_msg( MSGT_GPLAYER
,MSGL_V
,"SKIN dir 1 (obsolete): '%s'\n",skinDirInHome_obsolete
);
212 mp_msg( MSGT_GPLAYER
,MSGL_V
,"SKIN dir 2: '%s'\n",skinMPlayerDir
);
213 mp_msg( MSGT_GPLAYER
,MSGL_V
,"SKIN dir 2 (obsolete): '%s'\n",skinMPlayerDir_obsolete
);
214 if ( !skinName
) skinName
=strdup( "default" );
215 i
= skinRead( skinName
);
216 if ((i
== -1) && strcmp(skinName
,"default"))
218 mp_msg( MSGT_GPLAYER
,MSGL_WARN
,MSGTR_SKIN_SKINCFG_SelectedSkinNotFound
, skinName
);
219 skinName
=strdup( "default" );
220 i
= skinRead( skinName
);
223 case -1: mp_msg( MSGT_GPLAYER
,MSGL_ERR
,MSGTR_SKIN_SKINCFG_SkinNotFound
,skinName
); exit( 0 );
224 case -2: mp_msg( MSGT_GPLAYER
,MSGL_ERR
,MSGTR_SKIN_SKINCFG_SkinCfgReadError
,skinName
); exit( 0 );
226 // --- initialize windows
227 if ( ( mplDrawBuffer
= malloc( appMPlayer
.main
.Bitmap
.ImageSize
) ) == NULL
)
229 fprintf( stderr
,MSGTR_NEMDB
);
235 appMPlayer
.main
.x
= gui_main_pos_x
;
236 appMPlayer
.main
.y
= gui_main_pos_y
;
237 appMPlayer
.sub
.x
= gui_sub_pos_x
;
238 appMPlayer
.sub
.y
= gui_sub_pos_y
;
243 appMPlayer
.subWindow
.Parent
=WinID
;
247 if (guiWinID
>=0) appMPlayer
.mainWindow
.Parent
=guiWinID
;
249 wsCreateWindow( &appMPlayer
.subWindow
,
250 appMPlayer
.sub
.x
,appMPlayer
.sub
.y
,appMPlayer
.sub
.width
,appMPlayer
.sub
.height
,
251 wsNoBorder
,wsShowMouseCursor
|wsHandleMouseButton
|wsHandleMouseMove
,wsShowFrame
|wsHideWindow
,"MPlayer - Video" );
253 wsDestroyImage( &appMPlayer
.subWindow
);
254 wsCreateImage( &appMPlayer
.subWindow
,appMPlayer
.sub
.Bitmap
.Width
,appMPlayer
.sub
.Bitmap
.Height
);
255 wsXDNDMakeAwareness(&appMPlayer
.subWindow
);
260 vo_setwindow( appMPlayer
.subWindow
.WindowID
, appMPlayer
.subWindow
.wGC
);
262 // i=wsHideFrame|wsMaxSize|wsHideWindow;
263 // if ( appMPlayer.mainDecoration ) i=wsShowFrame|wsMaxSize|wsHideWindow;
264 i
=wsShowFrame
|wsMaxSize
|wsHideWindow
;
265 wsCreateWindow( &appMPlayer
.mainWindow
,
266 appMPlayer
.main
.x
,appMPlayer
.main
.y
,appMPlayer
.main
.width
,appMPlayer
.main
.height
,
267 wsNoBorder
,wsShowMouseCursor
|wsHandleMouseButton
|wsHandleMouseMove
,i
,"MPlayer" );
269 wsSetShape( &appMPlayer
.mainWindow
,appMPlayer
.main
.Mask
.Image
);
270 wsXDNDMakeAwareness(&appMPlayer
.mainWindow
);
273 mp_msg( MSGT_GPLAYER
,MSGL_DBG2
,"[main] depth on screen: %d\n",wsDepthOnScreen
);
274 mp_msg( MSGT_GPLAYER
,MSGL_DBG2
,"[main] parent: 0x%x\n",(int)appMPlayer
.mainWindow
.WindowID
);
275 mp_msg( MSGT_GPLAYER
,MSGL_DBG2
,"[main] sub: 0x%x\n",(int)appMPlayer
.subWindow
.WindowID
);
278 appMPlayer
.mainWindow
.ReDraw
=(void *)mplMainDraw
;
279 appMPlayer
.mainWindow
.MouseHandler
=mplMainMouseHandle
;
280 appMPlayer
.mainWindow
.KeyHandler
=mplMainKeyHandle
;
281 appMPlayer
.mainWindow
.DandDHandler
=mplDandDHandler
;
283 appMPlayer
.subWindow
.ReDraw
=(void *)mplSubDraw
;
284 appMPlayer
.subWindow
.MouseHandler
=mplSubMouseHandle
;
285 appMPlayer
.subWindow
.KeyHandler
=mplMainKeyHandle
;
286 appMPlayer
.subWindow
.DandDHandler
=mplDandDHandler
;
288 wsSetBackgroundRGB( &appMPlayer
.subWindow
,appMPlayer
.sub
.R
,appMPlayer
.sub
.G
,appMPlayer
.sub
.B
);
289 wsClearWindow( appMPlayer
.subWindow
);
290 if ( appMPlayer
.sub
.Bitmap
.Image
) wsConvert( &appMPlayer
.subWindow
,appMPlayer
.sub
.Bitmap
.Image
,appMPlayer
.sub
.Bitmap
.ImageSize
);
292 btnModify( evSetVolume
,guiIntfStruct
.Volume
);
293 btnModify( evSetBalance
,guiIntfStruct
.Balance
);
294 btnModify( evSetMoviePosition
,guiIntfStruct
.Position
);
296 wsSetIcon( wsDisplay
,appMPlayer
.mainWindow
.WindowID
,guiIcon
,guiIconMask
);
297 wsSetIcon( wsDisplay
,appMPlayer
.subWindow
.WindowID
,guiIcon
,guiIconMask
);
299 guiIntfStruct
.Playing
=0;
301 if ( !appMPlayer
.mainDecoration
) wsWindowDecoration( &appMPlayer
.mainWindow
,0 );
303 wsVisibleWindow( &appMPlayer
.mainWindow
,wsShowWindow
);
305 wsVisibleWindow( &appMPlayer
.subWindow
,wsShowWindow
);
309 do { XNextEvent( wsDisplay
,&xev
); } while ( xev
.type
!= MapNotify
|| xev
.xmap
.event
!= appMPlayer
.subWindow
.WindowID
);
310 appMPlayer
.subWindow
.Mapped
=wsMapped
;
313 if ( !fullscreen
) fullscreen
=gtkLoadFullscreen
;
317 btnModify( evFullScreen
,btnPressed
);
320 if ( !fullscreen
) fullscreen
=gtkLoadFullscreen
;
321 if ( gtkShowVideoWindow
)
323 wsVisibleWindow( &appMPlayer
.subWindow
,wsShowWindow
);
326 do { XNextEvent( wsDisplay
,&xev
); } while ( xev
.type
!= MapNotify
|| xev
.xmap
.event
!= appMPlayer
.subWindow
.WindowID
);
327 appMPlayer
.subWindow
.Mapped
=wsMapped
;
333 btnModify( evFullScreen
,btnPressed
);
340 wsVisibleWindow( &appMPlayer
.subWindow
,wsShowWindow
);
343 do { XNextEvent( wsDisplay
,&xev
); } while ( xev
.type
!= MapNotify
|| xev
.xmap
.event
!= appMPlayer
.subWindow
.WindowID
);
344 appMPlayer
.subWindow
.Mapped
=wsMapped
;
346 wsVisibleWindow( &appMPlayer
.subWindow
, wsShowWindow
);
349 btnModify( evFullScreen
,btnPressed
);
356 if ( filename
) mplSetFileName( NULL
,filename
,STREAMTYPE_FILE
);
357 if ( plCurrent
&& !filename
) mplSetFileName( plCurrent
->path
,plCurrent
->name
,STREAMTYPE_FILE
);
358 if ( subdata
) guiSetFilename( guiIntfStruct
.Subtitlename
, subdata
->filename
);
365 mp_msg( MSGT_GPLAYER
,MSGL_V
,"[GUI] done.\n" );
369 gui_main_pos_x
=appMPlayer
.mainWindow
.X
; gui_main_pos_y
=appMPlayer
.mainWindow
.Y
;
370 gui_sub_pos_x
=appMPlayer
.subWindow
.X
; gui_sub_pos_y
=appMPlayer
.subWindow
.Y
;
374 ass_enabled
= gtkASS
.enabled
;
375 ass_use_margins
= gtkASS
.use_margins
;
376 ass_top_margin
= gtkASS
.top_margin
;
377 ass_bottom_margin
= gtkASS
.bottom_margin
;
397 extern int stream_dump_type
;
398 extern int vcd_track
;
399 extern m_obj_settings_t
* vf_settings
;
401 void guiLoadFont( void )
403 #ifdef CONFIG_FREETYPE
404 load_font_ft(vo_image_width
, vo_image_height
, &vo_font
, font_name
, osd_font_scale_factor
);
409 if ( vo_font
->name
) free( vo_font
->name
);
410 if ( vo_font
->fpath
) free( vo_font
->fpath
);
412 if ( vo_font
->pic_a
[i
] )
414 if ( vo_font
->pic_a
[i
]->bmp
) free( vo_font
->pic_a
[i
]->bmp
);
415 if ( vo_font
->pic_a
[i
]->pal
) free( vo_font
->pic_a
[i
]->pal
);
418 if ( vo_font
->pic_b
[i
] )
420 if ( vo_font
->pic_b
[i
]->bmp
) free( vo_font
->pic_b
[i
]->bmp
);
421 if ( vo_font
->pic_b
[i
]->pal
) free( vo_font
->pic_b
[i
]->pal
);
423 free( vo_font
); vo_font
=NULL
;
427 vo_font
=read_font_desc( font_name
,font_factor
,0 );
428 if ( !vo_font
) mp_msg( MSGT_CPLAYER
,MSGL_ERR
,MSGTR_CantLoadFont
,font_name
);
432 font_name
=gstrdup( get_path( "font/font.desc" ) );
433 vo_font
=read_font_desc( font_name
,font_factor
,0 );
436 gfree( (void **)&font_name
); font_name
=gstrdup(MPLAYER_DATADIR
"/font/font.desc" );
437 vo_font
=read_font_desc( font_name
,font_factor
,0 );
443 extern mp_osd_obj_t
* vo_osd_list
;
445 extern char **sub_name
;
447 void guiLoadSubtitle( char * name
)
449 if ( guiIntfStruct
.Playing
== 0 )
451 guiIntfStruct
.SubtitleChanged
=1; //what is this for? (mw)
456 mp_msg( MSGT_GPLAYER
,MSGL_INFO
,MSGTR_DeletingSubtitles
);
463 mp_osd_obj_t
* osd
= vo_osd_list
;
466 if ( osd
->type
== OSDTYPE_SUBTITLE
) break;
469 if ( osd
&& osd
->flags
&OSDFLAG_VISIBLE
)
471 len
=osd
->stride
* ( osd
->bbox
.y2
- osd
->bbox
.y1
);
472 memset( osd
->bitmap_buffer
,0,len
);
473 memset( osd
->alpha_buffer
,0,len
);
479 mp_msg( MSGT_GPLAYER
,MSGL_INFO
,MSGTR_LoadingSubtitles
,name
);
480 subdata
=sub_read_file( name
, guiIntfStruct
.FPS
);
481 if ( !subdata
) mp_msg( MSGT_GPLAYER
,MSGL_ERR
,MSGTR_CantLoadSub
,name
);
482 sub_name
= (malloc(2 * sizeof(char*))); //when mplayer will be restarted
483 sub_name
[0] = strdup(name
); //sub_name[0] will be read
486 update_set_of_subtitles();
490 static void add_vf( char * str
)
492 mp_msg( MSGT_GPLAYER
,MSGL_STATUS
,MSGTR_AddingVideoFilter
,str
);
496 while ( vf_settings
[i
].name
) if ( !gstrcmp( vf_settings
[i
++].name
,str
) ) { i
=-1; break; }
498 { vf_settings
=realloc( vf_settings
,( i
+ 2 ) * sizeof( m_obj_settings_t
) ); vf_settings
[i
].name
=strdup( str
);vf_settings
[i
].attribs
= NULL
; vf_settings
[i
+1].name
=NULL
; }
499 } else { vf_settings
=malloc( 2 * sizeof( m_obj_settings_t
) ); vf_settings
[0].name
=strdup( str
);vf_settings
[0].attribs
= NULL
; vf_settings
[1].name
=NULL
; }
502 static void remove_vf( char * str
)
506 if ( !vf_settings
) return;
508 mp_msg( MSGT_GPLAYER
,MSGL_STATUS
,MSGTR_RemovingVideoFilter
,str
);
510 while ( vf_settings
[n
++].name
); n
--;
514 while ( vf_settings
[i
].name
) if ( !gstrcmp( vf_settings
[i
++].name
,str
) ) { m
=i
- 1; break; }
518 if ( n
== 1 ) { free( vf_settings
[0].name
);free( vf_settings
[0].attribs
); free( vf_settings
); vf_settings
=NULL
; }
519 else { free( vf_settings
[i
].name
);free( vf_settings
[i
].attribs
); memcpy( &vf_settings
[i
],&vf_settings
[i
+ 1],( n
- i
) * sizeof( m_obj_settings_t
) ); }
524 int guiGetEvent( int type
,char * arg
)
526 const ao_functions_t
*audio_out
= NULL
;
527 const vo_functions_t
*video_out
= NULL
;
528 mixer_t
*mixer
= NULL
;
530 stream_t
* stream
= (stream_t
*) arg
;
531 #ifdef CONFIG_DVDREAD
532 dvd_priv_t
* dvdp
= (dvd_priv_t
*) arg
;
535 if (guiIntfStruct
.mpcontext
) {
536 audio_out
= mpctx_get_audio_out(guiIntfStruct
.mpcontext
);
537 video_out
= mpctx_get_video_out(guiIntfStruct
.mpcontext
);
538 mixer
= mpctx_get_mixer(guiIntfStruct
.mpcontext
);
544 guiIntfStruct
.event_struct
=(void *)arg
;
545 wsEvents( wsDisplay
,(XEvent
*)arg
,NULL
);
552 guiIntfStruct
.Playing
=1;
553 // if ( !gtkShowVideoWindow ) wsVisibleWindow( &appMPlayer.subWindow,wsHideWindow );
556 guiIntfStruct
.Playing
=0;
557 // if ( !gtkShowVideoWindow ) wsVisibleWindow( &appMPlayer.subWindow,wsHideWindow );
559 case guiSetPause
: guiIntfStruct
.Playing
=2; break;
567 if ( arg
) guiSetFilename( guiIntfStruct
.Filename
,arg
);
569 case guiSetAudioOnly
:
570 guiIntfStruct
.AudioOnly
=(int)arg
;
571 if ( (int)arg
) { guiIntfStruct
.NoWindow
=True
; wsVisibleWindow( &appMPlayer
.subWindow
,wsHideWindow
); }
572 else wsVisibleWindow( &appMPlayer
.subWindow
,wsShowWindow
);
575 guiIntfStruct
.mpcontext
=(void *)arg
;
577 guiIntfStruct
.demuxer
=(void *)arg
;
580 guiIntfStruct
.afilter
=(void *)arg
;
584 if ( !appMPlayer
.subWindow
.isFullScreen
)
586 wsResizeWindow( &appMPlayer
.subWindow
,vo_dwidth
,vo_dheight
);
587 wsMoveWindow( &appMPlayer
.subWindow
,True
,appMPlayer
.sub
.x
,appMPlayer
.sub
.y
);
589 guiIntfStruct
.MovieWidth
=vo_dwidth
;
590 guiIntfStruct
.MovieHeight
=vo_dheight
;
592 wsMoveWindow( &appMPlayer
.mainWindow
,0,0, vo_dheight
);
595 #ifdef CONFIG_DVDREAD
597 guiIntfStruct
.DVD
.titles
=dvdp
->vmg_file
->tt_srpt
->nr_of_srpts
;
598 guiIntfStruct
.DVD
.chapters
=dvdp
->vmg_file
->tt_srpt
->title
[dvd_title
].nr_of_ptts
;
599 guiIntfStruct
.DVD
.angles
=dvdp
->vmg_file
->tt_srpt
->title
[dvd_title
].nr_of_angles
;
600 guiIntfStruct
.DVD
.nr_of_audio_channels
=dvdp
->nr_of_channels
;
601 memcpy( guiIntfStruct
.DVD
.audio_streams
,dvdp
->audio_streams
,sizeof( dvdp
->audio_streams
) );
602 guiIntfStruct
.DVD
.nr_of_subtitles
=dvdp
->nr_of_subtitles
;
603 memcpy( guiIntfStruct
.DVD
.subtitles
,dvdp
->subtitles
,sizeof( dvdp
->subtitles
) );
604 guiIntfStruct
.DVD
.current_title
=dvd_title
+ 1;
605 guiIntfStruct
.DVD
.current_chapter
=dvd_chapter
+ 1;
606 guiIntfStruct
.DVD
.current_angle
=dvd_angle
+ 1;
607 guiIntfStruct
.Track
=dvd_title
+ 1;
611 guiIntfStruct
.StreamType
=stream
->type
;
612 switch( stream
->type
)
614 #ifdef CONFIG_DVDREAD
616 guiGetEvent( guiSetDVD
,(char *)stream
->priv
);
626 guiIntfStruct
.VCDTracks
=0;
629 for ( i
=1;i
< 100;i
++ )
630 if ( vcd_seek_to_track( stream
->priv
,i
) < 0 ) break;
631 vcd_seek_to_track( stream
->priv
,vcd_track
);
632 guiIntfStruct
.VCDTracks
=--i
;
640 mp_msg( MSGT_GPLAYER
,MSGL_V
,"cmd: %d\n",(int)arg
);
644 mplEventHandling( evExit
,0 );
646 case MP_CMD_VO_FULLSCREEN
:
647 mplEventHandling( evFullScreen
,0 );
650 mplEventHandling( guiCMDArray
[ (int)arg
- MP_CMD_GUI_EVENTS
- 1 ],0 );
654 mplEventHandling( evRedraw
,0 );
660 mixer_getvolume( mixer
,&l
,&r
);
661 guiIntfStruct
.Volume
=(r
>l
?r
:l
);
662 if ( r
!= l
) guiIntfStruct
.Balance
=( ( r
- l
) + 100 ) * 0.5f
;
663 else guiIntfStruct
.Balance
=50.0f
;
664 btnModify( evSetVolume
,guiIntfStruct
.Volume
);
665 btnModify( evSetBalance
,guiIntfStruct
.Balance
);
668 case guiSetFileFormat
:
669 guiIntfStruct
.FileFormat
=(int)arg
;
673 guiIntfStruct
.sh_video
=arg
;
676 sh_video_t
* sh
= (sh_video_t
*)arg
;
677 guiIntfStruct
.FPS
=sh
->fps
;
680 if ( guiIntfStruct
.NoWindow
) wsVisibleWindow( &appMPlayer
.subWindow
,wsHideWindow
);
682 if ( guiIntfStruct
.StreamType
== STREAMTYPE_STREAM
) btnSet( evSetMoviePosition
,btnDisabled
);
683 else btnSet( evSetMoviePosition
,btnReleased
);
689 mixer_getvolume( mixer
,&l
,&r
);
690 guiIntfStruct
.Volume
=(r
>l
?r
:l
);
691 if ( r
!= l
) guiIntfStruct
.Balance
=( ( r
- l
) + 100 ) * 0.5f
;
692 else guiIntfStruct
.Balance
=50.0f
;
693 btnModify( evSetVolume
,guiIntfStruct
.Volume
);
694 btnModify( evSetBalance
,guiIntfStruct
.Balance
);
697 if ( gtkEnableAudioEqualizer
)
704 eq
.channel
=i
; eq
.band
=j
; eq
.gain
=gtkEquChannels
[i
][j
];
705 gtkSet( gtkSetEqualizer
,0,&eq
);
710 if ( video_driver_list
&& !gstrcmp( video_driver_list
[0],"dxr3" ) && guiIntfStruct
.FileFormat
!= DEMUXER_TYPE_MPEG_PS
711 #ifdef CONFIG_LIBAVCODEC
716 gtkMessageBox( GTK_MB_FATAL
,MSGTR_NEEDLAVC
);
717 guiIntfStruct
.Playing
=0;
723 // if ( guiIntfStruct.Playing == 1 && guiIntfStruct.FilenameChanged )
724 if ( guiIntfStruct
.FilenameChanged
)
730 stream_cache_size
=-1;
736 guiIntfStruct
.demuxer
=NULL
;
737 guiIntfStruct
.sh_video
=NULL
;
738 wsPostRedisplay( &appMPlayer
.subWindow
);
740 case guiSetParameters
:
741 guiGetEvent( guiSetDefaults
,NULL
);
742 switch ( guiIntfStruct
.StreamType
)
744 case STREAMTYPE_PLAYLIST
:
750 sprintf( tmp
,"vcd://%d",guiIntfStruct
.Track
+ 1 );
751 guiSetFilename( guiIntfStruct
.Filename
,tmp
);
755 #ifdef CONFIG_DVDREAD
759 sprintf( tmp
,"dvd://%d",guiIntfStruct
.Title
);
760 guiSetFilename( guiIntfStruct
.Filename
,tmp
);
762 dvd_chapter
=guiIntfStruct
.Chapter
;
763 dvd_angle
=guiIntfStruct
.Angle
;
767 //if ( guiIntfStruct.StreamType != STREAMTYPE_PLAYLIST ) // Does not make problems anymore!
769 if ( guiIntfStruct
.Filename
) filename
=gstrdup( guiIntfStruct
.Filename
);
770 else if ( filename
) guiSetFilename( guiIntfStruct
.Filename
,filename
);
774 if ( !video_driver_list
)
777 while ( video_out_drivers
[i
++] )
778 if ( video_out_drivers
[i
- 1]->control( VOCTRL_GUISUPPORT
,NULL
) == VO_TRUE
)
780 gaddlist( &video_driver_list
,(char *)video_out_drivers
[i
- 1]->info
->short_name
);
785 if ( !video_driver_list
&& !video_driver_list
[0] ) { gtkMessageBox( GTK_MB_FATAL
,MSGTR_IDFGCVD
); exit_player( "gui init" ); }
789 guiIntfStruct
.NoWindow
=False
;
790 while ( video_out_drivers
[i
++] )
791 if ( video_out_drivers
[i
- 1]->control( VOCTRL_GUISUPPORT
,NULL
) == VO_TRUE
)
793 if ( ( video_driver_list
&& !gstrcmp( video_driver_list
[0],(char *)video_out_drivers
[i
- 1]->info
->short_name
) )&&( video_out_drivers
[i
- 1]->control( VOCTRL_GUI_NOWINDOW
,NULL
) == VO_TRUE
) )
794 { guiIntfStruct
.NoWindow
=True
; break; }
799 #ifdef CONFIG_LIBAVCODEC
802 if ( video_driver_list
&& !gstrcmp( video_driver_list
[0],"dxr3" ) )
804 if ( ( guiIntfStruct
.StreamType
!= STREAMTYPE_DVD
)&&( guiIntfStruct
.StreamType
!= STREAMTYPE_VCD
) )
806 #ifdef CONFIG_LIBAVCODEC
807 if ( gtkVfLAVC
) add_vf( "lavc" );
813 if ( gtkVfPP
) add_vf( "pp" );
814 else remove_vf( "pp" );
817 // if ( ao_plugin_cfg.plugin_list ) { free( ao_plugin_cfg.plugin_list ); ao_plugin_cfg.plugin_list=NULL; }
819 greplace(&af_cfg
.list
, "volnorm", "volnorm");
820 if (gtkEnableAudioEqualizer
)
821 greplace(&af_cfg
.list
, "equalizer", "equalizer");
822 if ( gtkAOExtraStereo
)
824 char *name
= malloc(12 + 20 + 1);
825 snprintf(name
, 12 + 20, "extrastereo=%f", gtkAOExtraStereoMul
);
827 greplace(&af_cfg
.list
, "extrastereo", name
);
830 #ifdef CONFIG_OSS_AUDIO
831 if ( audio_driver_list
&& !gstrncmp( audio_driver_list
[0],"oss",3 ) )
834 mixer_device
= gtkAOOSSMixer
;
835 mixer_channel
= gtkAOOSSMixerChannel
;
836 if (gtkAOOSSDevice
) {
837 tmp
= calloc( 1,strlen( gtkAOOSSDevice
) + 7 );
838 sprintf( tmp
,"oss:%s",gtkAOOSSDevice
);
841 gaddlist( &audio_driver_list
,tmp
);
846 if ( audio_driver_list
&& !gstrncmp( audio_driver_list
[0],"alsa",4 ) )
849 mixer_device
= gtkAOALSAMixer
;
850 mixer_channel
= gtkAOALSAMixerChannel
;
851 if (gtkAOALSADevice
) {
852 tmp
= calloc( 1,strlen( gtkAOALSADevice
) + 14 );
853 sprintf( tmp
,"alsa:device=%s",gtkAOALSADevice
);
855 tmp
= strdup("alsa");
856 gaddlist( &audio_driver_list
,tmp
);
861 if ( audio_driver_list
&& !gstrncmp( audio_driver_list
[0],"sdl",3 ) )
864 if (gtkAOSDLDriver
) {
865 tmp
= calloc( 1,strlen( gtkAOSDLDriver
) + 10 );
866 sprintf( tmp
,"sdl:%s",gtkAOSDLDriver
);
869 gaddlist( &audio_driver_list
,tmp
);
874 if ( audio_driver_list
&& !gstrncmp( audio_driver_list
[0],"esd",3 ) )
877 if (gtkAOESDDevice
) {
878 tmp
= calloc( 1,strlen( gtkAOESDDevice
) + 10 );
879 sprintf( tmp
,"esd:%s",gtkAOESDDevice
);
882 gaddlist( &audio_driver_list
,tmp
);
887 //subdata->filename=gstrdup( guiIntfStruct.Subtitlename );
889 if ( gtkSubDumpMPSub
) stream_dump_type
=4;
890 if ( gtkSubDumpSrt
) stream_dump_type
=6;
891 gtkSubDumpMPSub
=gtkSubDumpSrt
=0;
895 if ( gtkCacheOn
) stream_cache_size
=gtkCacheSize
;
896 if ( gtkAutoSyncOn
) autosync
=gtkAutoSync
;
898 if ( guiIntfStruct
.AudioFile
) audio_stream
=gstrdup( guiIntfStruct
.AudioFile
);
899 else if ( guiIntfStruct
.FilenameChanged
) gfree( (void**)&audio_stream
);
902 guiIntfStruct
.DiskChanged
=0;
903 guiIntfStruct
.FilenameChanged
=0;
904 guiIntfStruct
.NewPlay
=0;
907 ass_enabled
= gtkASS
.enabled
;
908 ass_use_margins
= gtkASS
.use_margins
;
909 ass_top_margin
= gtkASS
.top_margin
;
910 ass_bottom_margin
= gtkASS
.bottom_margin
;
918 void guiEventHandling( void )
920 if ( !guiIntfStruct
.Playing
|| guiIntfStruct
.NoWindow
) wsHandleEvents();
926 float gtkEquChannels
[6][10];
928 plItem
* plCurrent
= NULL
;
929 plItem
* plList
= NULL
;
930 plItem
* plLastPlayed
= NULL
;
932 URLItem
*URLList
= NULL
;
934 char *fsHistory
[fsPersistant_MaxPos
] = { NULL
,NULL
,NULL
,NULL
,NULL
};
936 #if defined( MP_DEBUG ) && 0
939 plItem
* next
= plList
;
940 printf( "--- list ---\n" );
941 while( next
|| next
->next
)
943 printf( "item: %s/%s\n",next
->path
,next
->name
);
944 if ( next
->next
) next
=next
->next
; else break;
946 printf( "--- end of list ---\n" );
952 void * gtkSet( int cmd
,float fparam
, void * vparam
)
954 equalizer_t
* eq
= (equalizer_t
*)vparam
;
955 plItem
* item
= (plItem
*)vparam
;
957 URLItem
* url_item
= (URLItem
*)vparam
;
962 // --- handle playlist
963 case gtkAddPlItem
: // add item to playlist
966 plItem
* next
= plList
;
967 while ( next
->next
) { /*printf( "%s\n",next->name );*/ next
=next
->next
; }
968 next
->next
=item
; item
->prev
=next
;
969 } else { item
->prev
=item
->next
=NULL
; plCurrent
=plList
=item
; }
972 case gtkInsertPlItem
: // add item into playlist after current
975 plItem
* curr
= plCurrent
;
976 item
->next
=curr
->next
;
978 item
->next
->prev
=item
;
981 plCurrent
=plCurrent
->next
;
985 return gtkSet(gtkAddPlItem
,0,(void*)item
);
987 case gtkGetNextPlItem
: // get current item from playlist
988 if ( plCurrent
&& plCurrent
->next
)
990 plCurrent
=plCurrent
->next
;
991 /*if ( !plCurrent && plList )
993 plItem * next = plList;
994 while ( next->next ) { if ( !next->next ) break; next=next->next; }
1000 case gtkGetPrevPlItem
:
1001 if ( plCurrent
&& plCurrent
->prev
)
1003 plCurrent
=plCurrent
->prev
;
1004 //if ( !plCurrent && plList ) plCurrent=plList;
1008 case gtkSetCurrPlItem
: // set current item
1011 case gtkGetCurrPlItem
: // get current item
1013 case gtkDelCurrPlItem
: // delete current item
1015 plItem
* curr
= plCurrent
;
1020 curr
->prev
->next
=curr
->next
;
1022 curr
->next
->prev
=curr
->prev
;
1025 plCurrent
=curr
->next
;
1027 if ( curr
->path
) free( curr
->path
);
1028 if ( curr
->name
) free( curr
->name
);
1031 mplCurr(); // Instead of using mplNext && mplPrev
1034 case gtkDelPl
: // delete list
1036 plItem
* curr
= plList
;
1038 if ( !plList
) return NULL
;
1041 if ( curr
->path
) free( curr
->path
);
1042 if ( curr
->name
) free( curr
->name
);
1047 while ( curr
->next
)
1050 if ( curr
->path
) free( curr
->path
);
1051 if ( curr
->name
) free( curr
->name
);
1056 plList
=NULL
; plCurrent
=NULL
;
1063 URLItem
* next_url
= URLList
;
1065 while ( next_url
->next
)
1067 if ( !gstrcmp( next_url
->url
,url_item
->url
) )
1072 next_url
=next_url
->next
;
1074 if ( ( !is_added
)&&( gstrcmp( next_url
->url
,url_item
->url
) ) ) next_url
->next
=url_item
;
1075 } else { url_item
->next
=NULL
; URLList
=url_item
; }
1078 #ifndef CONFIG_FREETYPE
1079 case gtkSetFontFactor
:
1084 case gtkSetFontOutLine
:
1085 subtitle_font_thickness
=( 8.0f
/ 100.0f
) * fparam
;
1088 case gtkSetFontBlur
:
1089 subtitle_font_radius
=( 8.0f
/ 100.0f
) * fparam
;
1092 case gtkSetFontTextScale
:
1093 text_font_scale_factor
=fparam
;
1096 case gtkSetFontOSDScale
:
1097 osd_font_scale_factor
=fparam
;
1100 case gtkSetFontEncoding
:
1101 gfree( (void **)&subtitle_font_encoding
);
1102 subtitle_font_encoding
=gstrdup( (char *)vparam
);
1105 case gtkSetFontAutoScale
:
1106 subtitle_autoscale
=(int)fparam
;
1111 case gtkSetSubEncoding
:
1112 gfree( (void **)&sub_cp
);
1113 sub_cp
=gstrdup( (char *)vparam
);
1117 case gtkClearStruct
:
1118 if ( (unsigned int)vparam
& guiFilenames
)
1120 gfree( (void **)&guiIntfStruct
.Filename
);
1121 gfree( (void **)&guiIntfStruct
.Subtitlename
);
1122 gfree( (void **)&guiIntfStruct
.AudioFile
);
1123 gtkSet( gtkDelPl
,0,NULL
);
1125 #ifdef CONFIG_DVDREAD
1126 if ( (unsigned int)vparam
& guiDVD
) memset( &guiIntfStruct
.DVD
,0,sizeof( guiDVDStruct
) );
1129 if ( (unsigned int)vparam
& guiVCD
) guiIntfStruct
.VCDTracks
=0;
1132 case gtkSetExtraStereo
:
1133 gtkAOExtraStereoMul
=fparam
;
1134 if (guiIntfStruct
.afilter
)
1135 af_control_any_rev(guiIntfStruct
.afilter
,
1136 AF_CONTROL_ES_MUL
| AF_CONTROL_SET
, >kAOExtraStereoMul
);
1141 mp_cmd
=calloc( 1,sizeof( *mp_cmd
) );
1142 mp_cmd
->id
=MP_CMD_PANSCAN
; mp_cmd
->name
=strdup( "panscan" );
1143 mp_cmd
->args
[0].v
.f
=fparam
; mp_cmd
->args
[1].v
.i
=1;
1144 mp_input_queue_cmd( mp_cmd
);
1148 auto_quality
=(int)fparam
;
1150 // --- set equalizers
1151 case gtkSetContrast
:
1152 if ( guiIntfStruct
.sh_video
) set_video_colors( guiIntfStruct
.sh_video
,"contrast",(int)fparam
);
1154 case gtkSetBrightness
:
1155 if ( guiIntfStruct
.sh_video
) set_video_colors( guiIntfStruct
.sh_video
,"brightness",(int)fparam
);
1158 if ( guiIntfStruct
.sh_video
) set_video_colors( guiIntfStruct
.sh_video
,"hue",(int)fparam
);
1160 case gtkSetSaturation
:
1161 if ( guiIntfStruct
.sh_video
) set_video_colors( guiIntfStruct
.sh_video
,"saturation",(int)fparam
);
1163 case gtkSetEqualizer
:
1165 af_control_ext_t tmp
;
1168 gtkEquChannels
[eq
->channel
][eq
->band
]=eq
->gain
;
1169 tmp
.ch
= eq
->channel
;
1170 tmp
.arg
= gtkEquChannels
[eq
->channel
];
1171 if (guiIntfStruct
.afilter
)
1172 af_control_any_rev(guiIntfStruct
.afilter
,
1173 AF_CONTROL_EQUALIZER_GAIN
| AF_CONTROL_SET
, &tmp
);
1178 memset( gtkEquChannels
,0,sizeof( gtkEquChannels
) );
1179 if (guiIntfStruct
.afilter
)
1183 tmp
.arg
= gtkEquChannels
[i
];
1184 af_control_any_rev(guiIntfStruct
.afilter
,
1185 AF_CONTROL_EQUALIZER_GAIN
| AF_CONTROL_SET
, &tmp
);
1194 #define mp_basename(s) (strrchr(s,'/')==NULL?(char*)s:(strrchr(s,'/')+1))
1196 #include "playtree.h"
1198 //This function adds/inserts one file into the gui playlist
1200 int import_file_into_gui(char* temp
, int insert
)
1202 char *filename
, *pathname
;
1205 filename
= strdup(mp_basename(temp
));
1206 pathname
= strdup(temp
);
1207 if (strlen(pathname
)-strlen(filename
)>0)
1208 pathname
[strlen(pathname
)-strlen(filename
)-1]='\0'; // We have some path so remove / at end
1210 pathname
[strlen(pathname
)-strlen(filename
)]='\0';
1211 mp_msg(MSGT_PLAYTREE
,MSGL_V
, "Adding filename %s && pathname %s\n",filename
,pathname
); //FIXME: Change to MSGL_DBG2 ?
1212 item
=calloc( 1,sizeof( plItem
) );
1215 item
->name
=filename
;
1216 item
->path
=pathname
;
1218 gtkSet( gtkInsertPlItem
,0,(void*)item
); // Inserts the item after current, and makes current=item
1220 gtkSet( gtkAddPlItem
,0,(void*)item
);
1225 // This function imports the initial playtree (based on cmd-line files) into the gui playlist
1227 // - overwriting gui pl (enqueue=0)
1228 // - appending it to gui pl (enqueue=1)
1230 int import_initial_playtree_into_gui(play_tree_t
* my_playtree
, m_config_t
* config
, int enqueue
)
1232 play_tree_iter_t
* my_pt_iter
=NULL
;
1235 if (!enqueue
) // Delete playlist before "appending"
1236 gtkSet(gtkDelPl
,0,0);
1238 if((my_pt_iter
=pt_iter_create(&my_playtree
,config
)))
1240 while ((filename
=pt_iter_get_next_file(my_pt_iter
))!=NULL
)
1242 if (import_file_into_gui(filename
, 0)) // Add it to end of list
1247 mplCurr(); // Update filename
1251 filename
=guiIntfStruct
.Filename
; // Backward compatibility; if file is specified on commandline,
1252 // gmplayer does directly start in Play-Mode.
1259 // This function imports and inserts an playtree, that is created "on the fly", for example by
1260 // parsing some MOV-Reference-File; or by loading an playlist with "File Open"
1262 // The file which contained the playlist is thereby replaced with it's contents.
1264 int import_playtree_playlist_into_gui(play_tree_t
* my_playtree
, m_config_t
* config
)
1266 play_tree_iter_t
* my_pt_iter
=NULL
;
1268 plItem
* save
=(plItem
*)gtkSet( gtkGetCurrPlItem
, 0, 0); // Save current item
1270 if((my_pt_iter
=pt_iter_create(&my_playtree
,config
)))
1272 while ((filename
=pt_iter_get_next_file(my_pt_iter
))!=NULL
)
1274 if (import_file_into_gui(filename
, 1)) // insert it into the list and set plCurrent=new item
1277 pt_iter_destroy(&my_pt_iter
);
1281 gtkSet(gtkSetCurrPlItem
, 0, (void*)save
);
1283 gtkSet(gtkSetCurrPlItem
, 0, (void*)plList
); // go to head, if plList was empty before
1286 gtkSet(gtkDelCurrPlItem
, 0, 0);
1288 mplCurr(); // Update filename
1294 // wrapper function for mp_msg to display a message box for errors and warnings.
1296 void guiMessageBox(int level
, char * str
) {
1299 gtkMessageBox(GTK_MB_FATAL
|GTK_MB_SIMPLE
, str
);
1302 gtkMessageBox(GTK_MB_ERROR
|GTK_MB_SIMPLE
, str
);
1305 // WARNING! Do NOT enable this! There are too many non-critical messages with
1306 // MSGL_WARN, for example: broken SPU packets, codec's bit error messages,
1307 // etc etc, they should not raise up a new window every time.
1309 gtkMessageBox(GTK_MB_WARNING
|GTK_MB_SIMPLE
, str
);