]> git.sesse.net Git - vlc/commitdiff
* ./include/modules_inner.h: replaced _X with __VLC_SYMBOL because _X was
authorSam Hocevar <sam@videolan.org>
Wed, 9 Jan 2002 02:01:14 +0000 (02:01 +0000)
committerSam Hocevar <sam@videolan.org>
Wed, 9 Jan 2002 02:01:14 +0000 (02:01 +0000)
    already a system macro under MacOS X.
  * ./plugins/dummy/dummy.c: fixed vlc:loop, vlc:quit, etc. entries.
  * ./plugins/glide/glide.c: activated double buffering.
  * ./plugins/mga/xmga.c: started writing an xmga plugin; doesn't work yet.
  * ./src/input/input.c: fixed the input memory leak, and the insane thread
    spawning we got with vlc:loop.
  * ./src/misc/intf_eject.c: disc ejection routine courtesy of Julien Blache,
    currently Linux-only.

31 files changed:
AUTHORS
BUGS
Makefile
configure
configure.in
include/common.h
include/input_ext-intf.h
include/intf_eject.h [new file with mode: 0644]
include/modules_inner.h
plugins/dummy/dummy.c
plugins/dummy/input_dummy.c
plugins/filter/wall.c
plugins/glide/glide.c
plugins/gtk/gnome.c
plugins/gtk/gnome.glade
plugins/gtk/gnome_callbacks.c
plugins/gtk/gnome_callbacks.h
plugins/gtk/gnome_interface.c
plugins/gtk/gtk.c
plugins/gtk/gtk.glade
plugins/gtk/gtk_callbacks.c
plugins/gtk/gtk_callbacks.h
plugins/gtk/gtk_display.c
plugins/gtk/gtk_interface.c
plugins/mga/Makefile
plugins/mga/xmga.c [new file with mode: 0644]
src/input/input.c
src/interface/interface.c
src/interface/intf_eject.c [new file with mode: 0644]
src/misc/modules.c
src/misc/modules_plugin.h

diff --git a/AUTHORS b/AUTHORS
index 6110c488869b33448bab1b067ef4fd068613df6a..f78dab6803b3dd3e8a2694f03f8104bab988a695 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -38,6 +38,10 @@ E: jobi@via.ecp.fr
 C: jobi
 D: VCD input
 
 C: jobi
 D: VCD input
 
+N: Julien Blache
+E: jb@technologeek.org
+D: Disc ejection code
+
 N: Emmanuel Blindauer
 E: manu@agat.net
 D: aRts audio output
 N: Emmanuel Blindauer
 E: manu@agat.net
 D: aRts audio output
diff --git a/BUGS b/BUGS
index 4ce2e27a7e5734bbb26dea9108b2934ca7690e8c..dd978ef1ffb8c89349c3532d40a1f2f6b8cf03a6 100644 (file)
--- a/BUGS
+++ b/BUGS
@@ -1,5 +1,5 @@
 List of known vlc bugs
 List of known vlc bugs
-$Id: BUGS,v 1.3 2002/01/05 16:09:49 sam Exp $
+$Id: BUGS,v 1.4 2002/01/09 02:01:14 sam Exp $
 
    Please try to keep this file up to date. Also, grep for FIXME in the
 source files for more and more bugs to fix.
 
    Please try to keep this file up to date. Also, grep for FIXME in the
 source files for more and more bugs to fix.
@@ -17,10 +17,7 @@ Core:
 
 Input:
 
 
 Input:
 
-  * There is a memory leak in the input because the input thread is
-  never joined for termination.
-
-  * vlc:foo targets don't work anymore.
+  -
 
 
 Audio output:
 
 
 Audio output:
@@ -37,8 +34,6 @@ Video output:
 
   * The DirectX video output plugin is broken because of vout4.
 
 
   * The DirectX video output plugin is broken because of vout4.
 
-  * The GGI video output plugin is broken because of vout4.
-
   * The BeOS video output plugin is broken because of vout4.
 
   * The QNX video output plugin is broken because of vout4.
   * The BeOS video output plugin is broken because of vout4.
 
   * The QNX video output plugin is broken because of vout4.
@@ -69,3 +64,8 @@ Gtk interface:
 
   * Saving preferences does not work at all.
 
 
   * Saving preferences does not work at all.
 
+
+Misc:
+
+  * The Jin-Roh DVD seems to segfault.
+
index 95a6b5db48a4d5d2e4c2cbc965e1079b7cc139b9..1ff8bced7c37434527786d6e740281baa2d60c9e 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -100,6 +100,7 @@ PLUGINS_TARGETS := ac3_adec/ac3_adec \
                memcpy/memcpymmxext \
                memcpy/memcpy3dn \
                mga/mga \
                memcpy/memcpymmxext \
                memcpy/memcpy3dn \
                mga/mga \
+               mga/xmga \
                motion/motion \
                motion/motionmmx \
                motion/motionmmxext \
                motion/motion \
                motion/motionmmx \
                motion/motionmmxext \
@@ -122,7 +123,7 @@ PLUGINS_TARGETS := ac3_adec/ac3_adec \
 #
 # C Objects
 # 
 #
 # C Objects
 # 
-INTERFACE := main interface intf_msg intf_playlist
+INTERFACE := main interface intf_msg intf_playlist intf_eject
 INPUT := input input_ext-dec input_ext-intf input_dec input_programs input_clock mpeg_system
 VIDEO_OUTPUT := video_output video_text vout_pictures vout_subpictures
 AUDIO_OUTPUT := audio_output aout_ext-dec aout_u8 aout_s8 aout_u16 aout_s16 aout_spdif
 INPUT := input input_ext-dec input_ext-intf input_dec input_programs input_clock mpeg_system
 VIDEO_OUTPUT := video_output video_text vout_pictures vout_subpictures
 AUDIO_OUTPUT := audio_output aout_ext-dec aout_u8 aout_s8 aout_u16 aout_s16 aout_spdif
index 0e14ce36631eb24e6cbb0f9ff2410088d04dd466..921317d8ad0d24eb3bb8934023f2bb5c76cfa106 100755 (executable)
--- a/configure
+++ b/configure
@@ -6439,7 +6439,7 @@ if test "${enable_mga+set}" = set; then
   enableval="$enable_mga"
    if test x$enable_mga = xyes
     then
   enableval="$enable_mga"
    if test x$enable_mga = xyes
     then
-      PLUGINS="${PLUGINS} mga"
+      PLUGINS="${PLUGINS} mga xmga"
     fi 
 fi
 
     fi 
 fi
 
index df82da73d1ab7ee962504000da87453c78b2f723..6d97190aeced8e7c164ee3b55f1294fdec25b589 100644 (file)
@@ -948,7 +948,7 @@ AC_ARG_ENABLE(mga,
   [  --enable-mga            Linux kernel Matrox support (default disabled)],
   [ if test x$enable_mga = xyes
     then
   [  --enable-mga            Linux kernel Matrox support (default disabled)],
   [ if test x$enable_mga = xyes
     then
-      PLUGINS="${PLUGINS} mga"
+      PLUGINS="${PLUGINS} mga xmga"
     fi ])
 
 dnl
     fi ])
 
 dnl
index 6658695817c764acfaecc46d13bfee17bb997fe9..2b537b0bbad59a964ef6d205c87a037d2b26bbaa 100644 (file)
@@ -3,7 +3,7 @@
  * Collection of useful common types and macros definitions
  *****************************************************************************
  * Copyright (C) 1998, 1999, 2000 VideoLAN
  * Collection of useful common types and macros definitions
  *****************************************************************************
  * Copyright (C) 1998, 1999, 2000 VideoLAN
- * $Id: common.h,v 1.66 2002/01/07 02:12:29 sam Exp $
+ * $Id: common.h,v 1.67 2002/01/09 02:01:14 sam Exp $
  *
  * Authors: Samuel Hocevar <sam@via.ecp.fr>
  *          Vincent Seguin <seguin@via.ecp.fr>
  *
  * Authors: Samuel Hocevar <sam@via.ecp.fr>
  *          Vincent Seguin <seguin@via.ecp.fr>
@@ -468,6 +468,7 @@ typedef struct module_symbols_s
     void ( * intf_PlaylistDestroy ) ( struct playlist_s * );
     void ( * intf_PlaylistJumpto )  ( struct playlist_s *, int );
     void ( * intf_UrlDecode )       ( char * );
     void ( * intf_PlaylistDestroy ) ( struct playlist_s * );
     void ( * intf_PlaylistJumpto )  ( struct playlist_s *, int );
     void ( * intf_UrlDecode )       ( char * );
+    int  ( * intf_Eject )           ( const char * );
 
     void    ( * msleep )         ( mtime_t );
     mtime_t ( * mdate )          ( void );
 
     void    ( * msleep )         ( mtime_t );
     mtime_t ( * mdate )          ( void );
@@ -576,6 +577,7 @@ typedef struct module_symbols_s
 
     struct module_s * ( * module_Need ) ( int, char *, struct probedata_s * );
     void ( * module_Unneed )            ( struct module_s * );
 
     struct module_s * ( * module_Need ) ( int, char *, struct probedata_s * );
     void ( * module_Unneed )            ( struct module_s * );
+
 } module_symbols_t;
 
 #ifdef PLUGIN
 } module_symbols_t;
 
 #ifdef PLUGIN
index f30e34697400878fa8ee498a41e8443f2d029528..32da2125fe2c0e79a69214010304b0493b8ac745 100644 (file)
@@ -4,7 +4,7 @@
  * control the pace of reading. 
  *****************************************************************************
  * Copyright (C) 1999, 2000 VideoLAN
  * control the pace of reading. 
  *****************************************************************************
  * Copyright (C) 1999, 2000 VideoLAN
- * $Id: input_ext-intf.h,v 1.56 2002/01/07 02:12:29 sam Exp $
+ * $Id: input_ext-intf.h,v 1.57 2002/01/09 02:01:14 sam Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *
@@ -259,7 +259,7 @@ typedef struct input_thread_s
     boolean_t               b_error;
     boolean_t               b_eof;
     vlc_thread_t            thread_id;            /* id for thread functions */
     boolean_t               b_error;
     boolean_t               b_eof;
     vlc_thread_t            thread_id;            /* id for thread functions */
-    int *                   pi_status;              /* temporary status flag */
+    int                     i_status;                         /* status flag */
 
     /* Input module */
     struct module_s *       p_input_module;
 
     /* Input module */
     struct module_s *       p_input_module;
@@ -343,7 +343,8 @@ void   input_EndBank        ( void );
 
 struct input_thread_s * input_CreateThread ( struct playlist_item_s *,
                                              int *pi_status );
 
 struct input_thread_s * input_CreateThread ( struct playlist_item_s *,
                                              int *pi_status );
-void   input_DestroyThread  ( struct input_thread_s *, int *pi_status );
+void   input_StopThread     ( struct input_thread_s *, int *pi_status );
+void   input_DestroyThread  ( struct input_thread_s * );
 
 void   input_SetStatus      ( struct input_thread_s *, int );
 void   input_Seek           ( struct input_thread_s *, off_t );
 
 void   input_SetStatus      ( struct input_thread_s *, int );
 void   input_Seek           ( struct input_thread_s *, off_t );
diff --git a/include/intf_eject.h b/include/intf_eject.h
new file mode 100644 (file)
index 0000000..71e7c1d
--- /dev/null
@@ -0,0 +1,28 @@
+/*****************************************************************************
+ * intf_eject.h: CD/DVD-ROM ejection handling functions
+ *****************************************************************************
+ * Copyright (C) 2001, 2002 VideoLAN
+ * $Id: intf_eject.h,v 1.1 2002/01/09 02:01:14 sam Exp $
+ *
+ * Author: Julien Blache <jb@technologeek.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef PLUGIN
+int intf_Eject( const char * );
+#else
+#   define intf_Eject p_symbols->intf_Eject
+#endif
index e0a25aca34f0280af4bf3c235c2ab2c6a55be107..4a9376f8487e49ba04b9ebad9ad9782bdc4979bf 100644 (file)
@@ -2,7 +2,7 @@
  * modules_inner.h : Macros used from within a module.
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
  * modules_inner.h : Macros used from within a module.
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: modules_inner.h,v 1.10 2001/12/30 07:09:54 sam Exp $
+ * $Id: modules_inner.h,v 1.11 2002/01/09 02:01:14 sam Exp $
  *
  * Authors: Samuel Hocevar <sam@zoy.org>
  *
  *
  * Authors: Samuel Hocevar <sam@zoy.org>
  *
 /* If the module is built-in, then we need to define foo_InitModule instead
  * of InitModule. Same for Activate- and DeactivateModule. */
 #ifdef BUILTIN
 /* If the module is built-in, then we need to define foo_InitModule instead
  * of InitModule. Same for Activate- and DeactivateModule. */
 #ifdef BUILTIN
-#   define _M( function )  CONCATENATE( function, MODULE_NAME )
-#   define _X( function )  CONCATENATE( function, MODULE_NAME )
-#   define DECLARE_SYMBOLS ;
-#   define STORE_SYMBOLS   ;
+#   define _M( function )          CONCATENATE( function, MODULE_NAME )
+#   define __VLC_SYMBOL( symbol )  CONCATENATE( symbol, MODULE_NAME )
+#   define DECLARE_SYMBOLS         ;
+#   define STORE_SYMBOLS           ;
 #else
 #else
-#   define _M( function )  function
-#   define _X( function )  CONCATENATE( function, MODULE_SYMBOL )
-#   define DECLARE_SYMBOLS module_symbols_t* p_symbols;
-#   define STORE_SYMBOLS   p_symbols = p_module->p_symbols;
+#   define _M( function )          function
+#   define __VLC_SYMBOL( symbol  ) CONCATENATE( symbol, MODULE_SYMBOL )
+#   define DECLARE_SYMBOLS         module_symbols_t* p_symbols;
+#   define STORE_SYMBOLS           p_symbols = p_module->p_symbols;
 #endif
 
 #define MODULE_STRING STRINGIFY( MODULE_NAME )
 #endif
 
 #define MODULE_STRING STRINGIFY( MODULE_NAME )
@@ -75,7 +75,7 @@
  * instance the module name, its shortcuts, its capabilities...
  */
 #define MODULE_INIT_START                                                     \
  * instance the module name, its shortcuts, its capabilities...
  */
 #define MODULE_INIT_START                                                     \
-    int _X( InitModule ) ( module_t *p_module )                               \
+    int __VLC_SYMBOL( InitModule ) ( module_t *p_module )                     \
     {                                                                         \
         int i_shortcut = 0;                                                   \
         p_module->psz_name = MODULE_STRING;                                   \
     {                                                                         \
         int i_shortcut = 0;                                                   \
         p_module->psz_name = MODULE_STRING;                                   \
 #define MODULE_ACTIVATE_START                                                 \
     DECLARE_SYMBOLS;                                                          \
                                                                               \
 #define MODULE_ACTIVATE_START                                                 \
     DECLARE_SYMBOLS;                                                          \
                                                                               \
-    int _X( ActivateModule ) ( module_t *p_module )                           \
+    int __VLC_SYMBOL( ActivateModule ) ( module_t *p_module )                 \
     {                                                                         \
         p_module->p_functions =                                               \
           ( module_functions_t * )malloc( sizeof( module_functions_t ) );     \
     {                                                                         \
         p_module->p_functions =                                               \
           ( module_functions_t * )malloc( sizeof( module_functions_t ) );     \
  * here.
  */
 #define MODULE_DEACTIVATE_START                                               \
  * here.
  */
 #define MODULE_DEACTIVATE_START                                               \
-    int _X( DeactivateModule )( module_t *p_module )                          \
+    int __VLC_SYMBOL( DeactivateModule )( module_t *p_module )                \
     {                                                                         \
         free( p_module->p_functions );
 
     {                                                                         \
         free( p_module->p_functions );
 
index 5d23afe9faf74a10b4aff9ca64a11ef7ab6016a2..c68a96de307ea79078f5e8ea40118966fc22f17f 100644 (file)
@@ -2,7 +2,7 @@
  * dummy.c : dummy plugin for vlc
  *****************************************************************************
  * Copyright (C) 2000, 2001 VideoLAN
  * dummy.c : dummy plugin for vlc
  *****************************************************************************
  * Copyright (C) 2000, 2001 VideoLAN
- * $Id: dummy.c,v 1.13 2001/12/30 07:09:55 sam Exp $
+ * $Id: dummy.c,v 1.14 2002/01/09 02:01:14 sam Exp $
  *
  * Authors: Samuel Hocevar <sam@zoy.org>
  *
  *
  * Authors: Samuel Hocevar <sam@zoy.org>
  *
@@ -50,10 +50,11 @@ MODULE_INIT_START
     SET_DESCRIPTION( "dummy functions module" )
     /* Capability score set to 0 because we don't want to be spawned
      * unless explicitly requested to */
     SET_DESCRIPTION( "dummy functions module" )
     /* Capability score set to 0 because we don't want to be spawned
      * unless explicitly requested to */
-    ADD_CAPABILITY( INPUT, 0 )
     ADD_CAPABILITY( AOUT, 0 )
     ADD_CAPABILITY( VOUT, 0 )
     ADD_CAPABILITY( INTF, 0 )
     ADD_CAPABILITY( AOUT, 0 )
     ADD_CAPABILITY( VOUT, 0 )
     ADD_CAPABILITY( INTF, 0 )
+    /* This one is ok. */
+    ADD_CAPABILITY( INPUT, 100 )
     ADD_SHORTCUT( "dummy" )
 MODULE_INIT_STOP
 
     ADD_SHORTCUT( "dummy" )
 MODULE_INIT_STOP
 
index 7b63f261d53c14d257da958fed825abf2eec792e..392e8484696eb9cad5d52a4a5d2d9df342c12e77 100644 (file)
@@ -2,7 +2,7 @@
  * input_dummy.c: dummy input plugin, to manage "vlc:***" special options
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
  * input_dummy.c: dummy input plugin, to manage "vlc:***" special options
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: input_dummy.c,v 1.12 2002/01/04 14:01:34 sam Exp $
+ * $Id: input_dummy.c,v 1.13 2002/01/09 02:01:14 sam Exp $
  *
  * Authors: Samuel Hocevar <sam@zoy.org>
  *
  *
  * Authors: Samuel Hocevar <sam@zoy.org>
  *
@@ -89,10 +89,10 @@ static int DummyProbe( probedata_t *p_data )
     if( ( strlen(psz_name) > 4 ) && !strncasecmp( psz_name, "vlc:", 4 ) )
     {
         /* If the user specified "vlc:" then it's probably a file */
     if( ( strlen(psz_name) > 4 ) && !strncasecmp( psz_name, "vlc:", 4 ) )
     {
         /* If the user specified "vlc:" then it's probably a file */
-        return( 100 );
+        return( 1 );
     }
 
     }
 
-    return( 1 );
+    return( 0 );
 }
 
 /*****************************************************************************
 }
 
 /*****************************************************************************
@@ -153,7 +153,6 @@ static void DummyOpen( input_thread_t * p_input )
     }
 
     intf_ErrMsg( "input error: unknown command `%s'", psz_name );
     }
 
     intf_ErrMsg( "input error: unknown command `%s'", psz_name );
-
 }
 
 /*****************************************************************************
 }
 
 /*****************************************************************************
index acd562973d4f1406fd3e89096c551446a6b34185..a4d078338ce3de50f2d54338e62ae71dd204bbe6 100644 (file)
@@ -2,7 +2,7 @@
  * wall.c : Wall video plugin for vlc
  *****************************************************************************
  * Copyright (C) 2000, 2001 VideoLAN
  * wall.c : Wall video plugin for vlc
  *****************************************************************************
  * Copyright (C) 2000, 2001 VideoLAN
- * $Id: wall.c,v 1.9 2002/01/07 17:02:07 sam Exp $
+ * $Id: wall.c,v 1.10 2002/01/09 02:01:14 sam Exp $
  *
  * Authors: Samuel Hocevar <sam@zoy.org>
  *
  *
  * Authors: Samuel Hocevar <sam@zoy.org>
  *
@@ -134,8 +134,8 @@ static int vout_Create( vout_thread_t *p_vout )
         return( 1 );
     }
 
         return( 1 );
     }
 
-    p_vout->p_sys->i_col = 3;
-    p_vout->p_sys->i_row = 3;
+    p_vout->p_sys->i_col = 6;
+    p_vout->p_sys->i_row = 6;
 
     p_vout->p_sys->pp_vout = malloc( p_vout->p_sys->i_row *
                                      p_vout->p_sys->i_col *
 
     p_vout->p_sys->pp_vout = malloc( p_vout->p_sys->i_row *
                                      p_vout->p_sys->i_col *
index 1d053d54ce39f5a1996fc62e5e921bbdfdb87977..bb7a2a0312c176da7d66424b2456f9d11b0e2bff 100644 (file)
@@ -2,7 +2,7 @@
  * glide.c : 3dfx Glide plugin for vlc
  *****************************************************************************
  * Copyright (C) 2000, 2001 VideoLAN
  * glide.c : 3dfx Glide plugin for vlc
  *****************************************************************************
  * Copyright (C) 2000, 2001 VideoLAN
- * $Id: glide.c,v 1.10 2002/01/07 02:12:29 sam Exp $
+ * $Id: glide.c,v 1.11 2002/01/09 02:01:14 sam Exp $
  *
  * Authors: Samuel Hocevar <sam@zoy.org>
  *
  *
  * Authors: Samuel Hocevar <sam@zoy.org>
  *
@@ -60,7 +60,6 @@ static int  vout_Manage    ( vout_thread_t * );
 static void vout_Render    ( vout_thread_t *, picture_t * );
 static void vout_Display   ( vout_thread_t *, picture_t * );
 
 static void vout_Render    ( vout_thread_t *, picture_t * );
 static void vout_Display   ( vout_thread_t *, picture_t * );
 
-static int  NewPicture     ( vout_thread_t *, picture_t * );
 static int  OpenDisplay    ( vout_thread_t * );
 static void CloseDisplay   ( vout_thread_t * );
 
 static int  OpenDisplay    ( vout_thread_t * );
 static void CloseDisplay   ( vout_thread_t * );
 
@@ -94,9 +93,8 @@ typedef struct vout_sys_s
 {
     GrLfbInfo_t                 p_buffer_info;           /* back buffer info */
 
 {
     GrLfbInfo_t                 p_buffer_info;           /* back buffer info */
 
-    /* Dummy video memory */
-    byte_t *                    p_video;                      /* base adress */
-    size_t                      i_page_size;                    /* page size */
+    u8* pp_buffer[2];
+    int i_index;
 
 } vout_sys_t;
 
 
 } vout_sys_t;
 
@@ -167,36 +165,49 @@ int vout_Init( vout_thread_t *p_vout )
 
     I_OUTPUTPICTURES = 0;
 
 
     I_OUTPUTPICTURES = 0;
 
-    /* Try to initialize up to 1 direct buffers */
-    while( I_OUTPUTPICTURES < 1 )
-    {
-        p_pic = NULL;
-
-        /* Find an empty picture slot */
-        for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ )
-        {
-            if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
-            {
-                p_pic = p_vout->p_picture + i_index;
-                break;
-            }
-        }
+    p_pic = NULL;
 
 
-        /* Allocate the picture */
-        if( p_pic == NULL || NewPicture( p_vout, p_pic ) )
+    /* Find an empty picture slot */
+    for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ )
+    {
+        if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
         {
         {
+            p_pic = p_vout->p_picture + i_index;
             break;
         }
             break;
         }
+    }
 
 
-        p_pic->i_status = DESTROYED_PICTURE;
-        p_pic->i_type   = DIRECT_PICTURE;
+    if( p_pic == NULL )
+    {
+        return -1;
+    }
 
 
-        PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;
+    /* We know the chroma, allocate a buffer which will be used
+     * directly by the decoder */
+    p_pic->i_planes = 1;
 
 
-        I_OUTPUTPICTURES++;
-    }
+    p_pic->p->p_pixels = p_vout->p_sys->pp_buffer[p_vout->p_sys->i_index];
+    p_pic->p->i_pixel_bytes = GLIDE_BYTES_PER_PIXEL;
+    p_pic->p->i_lines = GLIDE_HEIGHT;
 
 
-    return( 0 );
+    p_pic->p->b_margin = 1;
+    p_pic->p->b_hidden = 1;
+    p_pic->p->i_visible_bytes = GLIDE_WIDTH * GLIDE_BYTES_PER_PIXEL;
+    p_pic->p->i_pitch = p_vout->p_sys->p_buffer_info.strideInBytes;
+                         /*1024 * GLIDE_BYTES_PER_PIXEL*/
+
+    p_pic->p->i_red_mask =   0xf800;
+    p_pic->p->i_green_mask = 0x07e0;
+    p_pic->p->i_blue_mask =  0x001f;
+
+    p_pic->i_status = DESTROYED_PICTURE;
+    p_pic->i_type   = DIRECT_PICTURE;
+
+    PP_OUTPUTPICTURE[ 0 ] = p_pic;
+
+    I_OUTPUTPICTURES = 1;
+
+    return 0;
 }
 
 /*****************************************************************************
 }
 
 /*****************************************************************************
@@ -286,18 +297,6 @@ static int OpenDisplay( vout_thread_t *p_vout )
     GrScreenResolution_t resolution = GR_RESOLUTION_800x600;
     GrLfbInfo_t p_front_buffer_info;                    /* front buffer info */
 
     GrScreenResolution_t resolution = GR_RESOLUTION_800x600;
     GrLfbInfo_t p_front_buffer_info;                    /* front buffer info */
 
-    p_vout->p_sys->i_page_size = GLIDE_WIDTH * GLIDE_HEIGHT
-                                  * GLIDE_BYTES_PER_PIXEL;
-
-    /* Map two framebuffers a the very beginning of the fb */
-    p_vout->p_sys->p_video = malloc( p_vout->p_sys->i_page_size * 2 );
-    if( (int)p_vout->p_sys->p_video == -1 )
-    {
-        intf_ErrMsg( "vout error: can't map video memory (%s)",
-                     strerror(errno) );
-        return( 1 );
-    }
-
     grGlideGetVersion( version );
     grGlideInit();
 
     grGlideGetVersion( version );
     grGlideInit();
 
@@ -308,8 +307,8 @@ static int OpenDisplay( vout_thread_t *p_vout )
     }
 
     grSstSelect( 0 );
     }
 
     grSstSelect( 0 );
-    if( !grSstWinOpen(0, resolution, GR_REFRESH_60Hz,
-                        GR_COLORFORMAT_ABGR, GR_ORIGIN_UPPER_LEFT, 2, 1) )
+    if( !grSstWinOpen( 0, resolution, GR_REFRESH_60Hz,
+                       GR_COLORFORMAT_ABGR, GR_ORIGIN_UPPER_LEFT, 2, 1 ) )
     {
         intf_ErrMsg( "vout error: can't open 3dfx screen" );
         return( 1 );
     {
         intf_ErrMsg( "vout error: can't open 3dfx screen" );
         return( 1 );
@@ -347,10 +346,14 @@ static int OpenDisplay( vout_thread_t *p_vout )
         grGlideShutdown();
         return( 1 );
     }
         grGlideShutdown();
         return( 1 );
     }
-    grLfbUnlock(GR_LFB_WRITE_ONLY, GR_BUFFER_BACKBUFFER );
+    grLfbUnlock( GR_LFB_WRITE_ONLY, GR_BUFFER_BACKBUFFER );
     
     grBufferClear( 0, 0, 0 );
 
     
     grBufferClear( 0, 0, 0 );
 
+    p_vout->p_sys->pp_buffer[0] = p_vout->p_sys->p_buffer_info.lfbPtr;
+    p_vout->p_sys->pp_buffer[1] = p_front_buffer_info.lfbPtr;
+    p_vout->p_sys->i_index = 0;
+
     return( 0 );
 }
 
     return( 0 );
 }
 
@@ -367,34 +370,5 @@ static void CloseDisplay( vout_thread_t *p_vout )
 
     /* shutdown Glide */
     grGlideShutdown();
 
     /* shutdown Glide */
     grGlideShutdown();
-    free( p_vout->p_sys->p_video );
-}
-
-/*****************************************************************************
- * NewPicture: allocate a picture
- *****************************************************************************
- * Returns 0 on success, -1 otherwise
- *****************************************************************************/
-static int NewPicture( vout_thread_t *p_vout, picture_t *p_pic )
-{
-    /* We know the chroma, allocate a buffer which will be used
-     * directly by the decoder */
-    p_pic->p->p_pixels = p_vout->p_sys->p_video;
-    p_pic->p->i_pixel_bytes = GLIDE_BYTES_PER_PIXEL;
-    p_pic->p->i_lines = GLIDE_HEIGHT;
-
-    p_pic->p->b_margin = 1;
-    p_pic->p->b_hidden = 1;
-    p_pic->p->i_visible_bytes = GLIDE_WIDTH * GLIDE_BYTES_PER_PIXEL;
-    p_pic->p->i_pitch = p_vout->p_sys->p_buffer_info.strideInBytes;
-                         /*1024 * GLIDE_BYTES_PER_PIXEL*/
-
-    p_pic->p->i_red_mask =   0xf800;
-    p_pic->p->i_green_mask = 0x07e0;
-    p_pic->p->i_blue_mask =  0x001f;
-
-    p_pic->i_planes = 1;
-
-    return 0;
 }
 
 }
 
index fbaac117c0735a98a01bb39044829dda6e0471e7..b03a3b5a8f66852129728ce987ca6cf72e14b540 100644 (file)
@@ -2,7 +2,7 @@
  * gnome.c : Gnome plugin for vlc
  *****************************************************************************
  * Copyright (C) 2000 VideoLAN
  * gnome.c : Gnome plugin for vlc
  *****************************************************************************
  * Copyright (C) 2000 VideoLAN
- * $Id: gnome.c,v 1.6 2002/01/07 02:12:29 sam Exp $
+ * $Id: gnome.c,v 1.7 2002/01/09 02:01:14 sam Exp $
  *
  * Authors: Samuel Hocevar <sam@zoy.org>
  *      
  *
  * Authors: Samuel Hocevar <sam@zoy.org>
  *      
@@ -329,53 +329,56 @@ static gint GnomeManage( gpointer p_data )
     {
         vlc_mutex_lock( &p_input_bank->pp_input[0]->stream.stream_lock );
 
     {
         vlc_mutex_lock( &p_input_bank->pp_input[0]->stream.stream_lock );
 
-        /* New input or stream map change */
-        if( p_input_bank->pp_input[0]->stream.b_changed )
+        if( !p_input_bank->pp_input[0]->b_die )
         {
         {
-            GtkModeManage( p_intf );
-            GtkSetupMenus( p_intf );
-            p_intf->p_sys->b_playing = 1;
-        }
-
-        /* Manage the slider */
-        if( p_input_bank->pp_input[0]->stream.b_seekable )
-        {
-            float           newvalue;
-            newvalue = p_intf->p_sys->p_adj->value;
-    
-#define p_area p_input_bank->pp_input[0]->stream.p_selected_area
-            /* If the user hasn't touched the slider since the last time,
-             * then the input can safely change it */
-            if( newvalue == p_intf->p_sys->f_adj_oldvalue )
+            /* New input or stream map change */
+            if( p_input_bank->pp_input[0]->stream.b_changed )
             {
             {
-                /* Update the value */
-                p_intf->p_sys->p_adj->value = p_intf->p_sys->f_adj_oldvalue =
-                    ( 100. * p_area->i_tell ) / p_area->i_size;
-    
-                gtk_signal_emit_by_name( GTK_OBJECT( p_intf->p_sys->p_adj ),
-                                         "value_changed" );
+                GtkModeManage( p_intf );
+                GtkSetupMenus( p_intf );
+                p_intf->p_sys->b_playing = 1;
             }
             }
-            /* Otherwise, send message to the input if the user has
-             * finished dragging the slider */
-            else if( p_intf->p_sys->b_slider_free )
+
+            /* Manage the slider */
+            if( p_input_bank->pp_input[0]->stream.b_seekable )
             {
             {
-                off_t i_seek = ( newvalue * p_area->i_size ) / 100;
+                float           newvalue;
+                newvalue = p_intf->p_sys->p_adj->value;
     
     
-                vlc_mutex_unlock( &p_input_bank->pp_input[0]->stream.stream_lock );
-                input_Seek( p_input_bank->pp_input[0], i_seek );
-                vlc_mutex_lock( &p_input_bank->pp_input[0]->stream.stream_lock );
+#define p_area p_input_bank->pp_input[0]->stream.p_selected_area
+                /* If the user hasn't touched the slider since the last time,
+                 * then the input can safely change it */
+                if( newvalue == p_intf->p_sys->f_adj_oldvalue )
+                {
+                    /* Update the value */
+                    p_intf->p_sys->p_adj->value = p_intf->p_sys->f_adj_oldvalue =
+                        ( 100. * p_area->i_tell ) / p_area->i_size;
     
     
-                /* Update the old value */
-                p_intf->p_sys->f_adj_oldvalue = newvalue;
-            }
+                    gtk_signal_emit_by_name( GTK_OBJECT( p_intf->p_sys->p_adj ),
+                                             "value_changed" );
+                }
+                /* Otherwise, send message to the input if the user has
+                 * finished dragging the slider */
+                else if( p_intf->p_sys->b_slider_free )
+                {
+                    off_t i_seek = ( newvalue * p_area->i_size ) / 100;
+        
+                    vlc_mutex_unlock( &p_input_bank->pp_input[0]->stream.stream_lock );
+                    input_Seek( p_input_bank->pp_input[0], i_seek );
+                    vlc_mutex_lock( &p_input_bank->pp_input[0]->stream.stream_lock );
+    
+                    /* Update the old value */
+                    p_intf->p_sys->f_adj_oldvalue = newvalue;
+                }
 #undef p_area
 #undef p_area
-        }
+            }
 
 
-        if( p_intf->p_sys->i_part !=
-            p_input_bank->pp_input[0]->stream.p_selected_area->i_part )
-        {
-            p_intf->p_sys->b_chapter_update = 1;
-            GtkSetupMenus( p_intf );
+            if( p_intf->p_sys->i_part !=
+                p_input_bank->pp_input[0]->stream.p_selected_area->i_part )
+            {
+                p_intf->p_sys->b_chapter_update = 1;
+                GtkSetupMenus( p_intf );
+            }
         }
 
         vlc_mutex_unlock( &p_input_bank->pp_input[0]->stream.stream_lock );
         }
 
         vlc_mutex_unlock( &p_input_bank->pp_input[0]->stream.stream_lock );
index 7f66367f6e320a251bcbbe80055f3d83832bf9bb..c094a3e46ac0142377d11966cba4740206dd40dd 100644 (file)
@@ -93,7 +93,6 @@
              <signal>
                <name>activate</name>
                <handler>GnomeMenubarFileOpenActivate</handler>
              <signal>
                <name>activate</name>
                <handler>GnomeMenubarFileOpenActivate</handler>
-               <data>&quot;intf_window&quot;</data>
                <last_modification_time>Sat, 19 May 2001 16:27:02 GMT</last_modification_time>
              </signal>
              <label>_Open File...</label>
                <last_modification_time>Sat, 19 May 2001 16:27:02 GMT</last_modification_time>
              </signal>
              <label>_Open File...</label>
              <signal>
                <name>activate</name>
                <handler>GnomeMenubarDiscOpenActivate</handler>
              <signal>
                <name>activate</name>
                <handler>GnomeMenubarDiscOpenActivate</handler>
-               <data>&quot;intf_window&quot;</data>
                <last_modification_time>Sat, 19 May 2001 16:27:10 GMT</last_modification_time>
              </signal>
              <label>Open _Disc...</label>
                <last_modification_time>Sat, 19 May 2001 16:27:10 GMT</last_modification_time>
              </signal>
              <label>Open _Disc...</label>
              <tooltip>Select a Network Stream</tooltip>
              <signal>
                <name>activate</name>
              <tooltip>Select a Network Stream</tooltip>
              <signal>
                <name>activate</name>
-               <handler>GnomeMenbarNetworkOpenActivate</handler>
-               <data>&quot;intf_window&quot;</data>
-               <last_modification_time>Sat, 19 May 2001 16:27:39 GMT</last_modification_time>
+               <handler>GnomeMenubarNetworkOpenActivate</handler>
+               <last_modification_time>Fri, 21 Dec 2001 13:11:28 GMT</last_modification_time>
              </signal>
              <label>_Network Stream...</label>
              <right_justify>False</right_justify>
              </signal>
              <label>_Network Stream...</label>
              <right_justify>False</right_justify>
              <right_justify>False</right_justify>
            </widget>
 
              <right_justify>False</right_justify>
            </widget>
 
+           <widget>
+             <class>GtkPixmapMenuItem</class>
+             <name>menubar_eject</name>
+             <tooltip>Eject disc</tooltip>
+             <signal>
+               <name>activate</name>
+               <handler>GnomeMenubarDiscEjectActivate</handler>
+               <last_modification_time>Fri, 21 Dec 2001 13:11:28 GMT</last_modification_time>
+             </signal>
+             <label>_Eject Disc</label>
+             <right_justify>False</right_justify>
+             <stock_icon>GNOME_STOCK_MENU_TOP</stock_icon>
+           </widget>
+
+           <widget>
+             <class>GtkMenuItem</class>
+             <name>separator15</name>
+             <right_justify>False</right_justify>
+           </widget>
+
            <widget>
              <class>GtkPixmapMenuItem</class>
              <name>menubar_exit</name>
              <signal>
                <name>activate</name>
                <handler>GnomeMenubarExitActivate</handler>
            <widget>
              <class>GtkPixmapMenuItem</class>
              <name>menubar_exit</name>
              <signal>
                <name>activate</name>
                <handler>GnomeMenubarExitActivate</handler>
-               <data>&quot;intf_window&quot;</data>
                <last_modification_time>Sat, 19 May 2001 16:27:52 GMT</last_modification_time>
              </signal>
              <stock_item>GNOMEUIINFO_MENU_EXIT_ITEM</stock_item>
                <last_modification_time>Sat, 19 May 2001 16:27:52 GMT</last_modification_time>
              </signal>
              <stock_item>GNOMEUIINFO_MENU_EXIT_ITEM</stock_item>
              <signal>
                <name>activate</name>
                <handler>GnomeMenubarWindowToggleActivate</handler>
              <signal>
                <name>activate</name>
                <handler>GnomeMenubarWindowToggleActivate</handler>
-               <data>&quot;intf_window&quot;</data>
                <last_modification_time>Sat, 19 May 2001 16:28:06 GMT</last_modification_time>
              </signal>
              <label>_Hide interface</label>
                <last_modification_time>Sat, 19 May 2001 16:28:06 GMT</last_modification_time>
              </signal>
              <label>_Hide interface</label>
              <signal>
                <name>activate</name>
                <handler>GnomeMenubarFullscreenActivate</handler>
              <signal>
                <name>activate</name>
                <handler>GnomeMenubarFullscreenActivate</handler>
-               <data>&quot;intf_window&quot;</data>
                <last_modification_time>Sat, 19 May 2001 16:28:15 GMT</last_modification_time>
              </signal>
              <label>_Fullscreen</label>
                <last_modification_time>Sat, 19 May 2001 16:28:15 GMT</last_modification_time>
              </signal>
              <label>_Fullscreen</label>
              <signal>
                <name>activate</name>
                <handler>GnomeMenubarPlaylistActivate</handler>
              <signal>
                <name>activate</name>
                <handler>GnomeMenubarPlaylistActivate</handler>
-               <data>&quot;intf_window&quot;</data>
                <last_modification_time>Sat, 19 May 2001 16:28:41 GMT</last_modification_time>
              </signal>
              <label>_Playlist...</label>
                <last_modification_time>Sat, 19 May 2001 16:28:41 GMT</last_modification_time>
              </signal>
              <label>_Playlist...</label>
              <signal>
                <name>activate</name>
                <handler>GnomeMenubarModulesActivate</handler>
              <signal>
                <name>activate</name>
                <handler>GnomeMenubarModulesActivate</handler>
-               <data>&quot;intf_window&quot;</data>
                <last_modification_time>Sat, 19 May 2001 16:28:53 GMT</last_modification_time>
              </signal>
              <label>_Modules...</label>
                <last_modification_time>Sat, 19 May 2001 16:28:53 GMT</last_modification_time>
              </signal>
              <label>_Modules...</label>
              <signal>
                <name>activate</name>
                <handler>GnomeMenubarPreferencesActivate</handler>
              <signal>
                <name>activate</name>
                <handler>GnomeMenubarPreferencesActivate</handler>
-               <data>&quot;intf_window&quot;</data>
                <last_modification_time>Sat, 19 May 2001 16:29:03 GMT</last_modification_time>
              </signal>
              <stock_item>GNOMEUIINFO_MENU_PREFERENCES_ITEM</stock_item>
                <last_modification_time>Sat, 19 May 2001 16:29:03 GMT</last_modification_time>
              </signal>
              <stock_item>GNOMEUIINFO_MENU_PREFERENCES_ITEM</stock_item>
              <signal>
                <name>activate</name>
                <handler>GnomeMenubarAboutActivate</handler>
              <signal>
                <name>activate</name>
                <handler>GnomeMenubarAboutActivate</handler>
-               <data>&quot;intf_window&quot;</data>
                <last_modification_time>Sat, 19 May 2001 16:29:19 GMT</last_modification_time>
              </signal>
              <stock_item>GNOMEUIINFO_MENU_ABOUT_ITEM</stock_item>
                <last_modification_time>Sat, 19 May 2001 16:29:19 GMT</last_modification_time>
              </signal>
              <stock_item>GNOMEUIINFO_MENU_ABOUT_ITEM</stock_item>
          <stock_pixmap>GNOME_STOCK_PIXMAP_STOP</stock_pixmap>
        </widget>
 
          <stock_pixmap>GNOME_STOCK_PIXMAP_STOP</stock_pixmap>
        </widget>
 
+       <widget>
+         <class>GtkButton</class>
+         <child_name>Toolbar:button</child_name>
+         <name>toolbar_eject</name>
+         <tooltip>Eject disc</tooltip>
+         <signal>
+           <name>button_press_event</name>
+           <handler>GtkDiscEject</handler>
+           <data>&quot;intf_window&quot;</data>
+           <last_modification_time>Fri, 21 Dec 2001 15:24:18 GMT</last_modification_time>
+         </signal>
+         <label>Eject</label>
+         <stock_pixmap>GNOME_STOCK_PIXMAP_TOP</stock_pixmap>
+       </widget>
+
        <widget>
          <class>GtkButton</class>
          <child_name>Toolbar:button</child_name>
        <widget>
          <class>GtkButton</class>
          <child_name>Toolbar:button</child_name>
index f3269278721a2614a05588e692c7b132f0196a65..56473f8dc3dd2f991eea9113777e7d4902a73ea3 100644 (file)
@@ -30,12 +30,18 @@ GnomeMenubarDiscOpenActivate           (GtkMenuItem     *menuitem,
 
 
 void
 
 
 void
-GnomeMenbarNetworkOpenActivate         (GtkMenuItem     *menuitem,
+GnomeMenubarNetworkOpenActivate         (GtkMenuItem     *menuitem,
                                         gpointer         user_data)
 {
     GtkNetworkOpenShow( GTK_WIDGET( menuitem ), NULL, "intf_window" );
 }
 
                                         gpointer         user_data)
 {
     GtkNetworkOpenShow( GTK_WIDGET( menuitem ), NULL, "intf_window" );
 }
 
+void
+GnomeMenubarDiscEjectActivate           (GtkMenuItem     *menuitem,
+                                        gpointer         user_data)
+{
+     GtkDiscEject( GTK_WIDGET( menuitem ), NULL, "intf_window" );
+}
 
 void
 GnomeMenubarExitActivate               (GtkMenuItem     *menuitem,
 
 void
 GnomeMenubarExitActivate               (GtkMenuItem     *menuitem,
@@ -259,6 +265,3 @@ GnomePopupJumpActivate                 (GtkMenuItem     *menuitem,
 {
     GtkJumpShow( GTK_WIDGET( menuitem ), NULL, "intf_popup" );
 }
 {
     GtkJumpShow( GTK_WIDGET( menuitem ), NULL, "intf_popup" );
 }
-
-
-
index c768fab7b7a7796f758c330896c473f4515b9842..bbf1089f471afd22f4dd26800b70d5a75356c42d 100644 (file)
@@ -11,7 +11,11 @@ GnomeMenubarDiscOpenActivate           (GtkMenuItem     *menuitem,
                                         gpointer         user_data);
 
 void
                                         gpointer         user_data);
 
 void
-GnomeMenbarNetworkOpenActivate         (GtkMenuItem     *menuitem,
+GnomeMenubarNetworkOpenActivate         (GtkMenuItem     *menuitem,
+                                        gpointer         user_data);
+
+void
+GnomeMenubarDiscEjectActivate         (GtkMenuItem     *menuitem,
                                         gpointer         user_data);
 
 void
                                         gpointer         user_data);
 
 void
@@ -141,3 +145,4 @@ GtkNetworkOpenBroadcast                (GtkToggleButton *togglebutton,
 void
 GtkNetworkOpenChannel                  (GtkToggleButton *togglebutton,
                                         gpointer         user_data);
 void
 GtkNetworkOpenChannel                  (GtkToggleButton *togglebutton,
                                         gpointer         user_data);
+
index c0a4dbb1331b4dd80a2008a1561365eb60139f13..22aec155ff0a54827f4fbf462ea219177d2ac9c4 100644 (file)
@@ -32,11 +32,19 @@ static GnomeUIInfo menubar_file_menu_uiinfo[] =
   {
     GNOME_APP_UI_ITEM, N_("_Network Stream..."),
     N_("Select a Network Stream"),
   {
     GNOME_APP_UI_ITEM, N_("_Network Stream..."),
     N_("Select a Network Stream"),
-    (gpointer) GnomeMenbarNetworkOpenActivate, NULL, NULL,
+    (gpointer) GnomeMenubarNetworkOpenActivate, NULL, NULL,
     GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_REFRESH,
     0, (GdkModifierType) 0, NULL
   },
   GNOMEUIINFO_SEPARATOR,
     GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_REFRESH,
     0, (GdkModifierType) 0, NULL
   },
   GNOMEUIINFO_SEPARATOR,
+  {
+    GNOME_APP_UI_ITEM, N_("_Eject Disc"),
+    N_("Eject disc"),
+    (gpointer) GnomeMenubarDiscEjectActivate, NULL, NULL,
+    GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_TOP,
+    0, (GdkModifierType) 0, NULL
+  },
+  GNOMEUIINFO_SEPARATOR,
   GNOMEUIINFO_MENU_EXIT_ITEM (GnomeMenubarExitActivate, NULL),
   GNOMEUIINFO_END
 };
   GNOMEUIINFO_MENU_EXIT_ITEM (GnomeMenubarExitActivate, NULL),
   GNOMEUIINFO_END
 };
@@ -145,6 +153,7 @@ create_intf_window (void)
   GtkWidget *toolbar_network;
   GtkWidget *toolbar_back;
   GtkWidget *toolbar_stop;
   GtkWidget *toolbar_network;
   GtkWidget *toolbar_back;
   GtkWidget *toolbar_stop;
+  GtkWidget *toolbar_eject;
   GtkWidget *toolbar_play;
   GtkWidget *toolbar_pause;
   GtkWidget *toolbar_slow;
   GtkWidget *toolbar_play;
   GtkWidget *toolbar_pause;
   GtkWidget *toolbar_slow;
@@ -220,10 +229,20 @@ create_intf_window (void)
                             (GtkDestroyNotify) gtk_widget_unref);
 
   gtk_widget_ref (menubar_file_menu_uiinfo[4].widget);
                             (GtkDestroyNotify) gtk_widget_unref);
 
   gtk_widget_ref (menubar_file_menu_uiinfo[4].widget);
-  gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_exit",
+  gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_eject",
                             menubar_file_menu_uiinfo[4].widget,
                             (GtkDestroyNotify) gtk_widget_unref);
 
                             menubar_file_menu_uiinfo[4].widget,
                             (GtkDestroyNotify) gtk_widget_unref);
 
+  gtk_widget_ref (menubar_file_menu_uiinfo[5].widget);
+  gtk_object_set_data_full (GTK_OBJECT (intf_window), "separator15",
+                            menubar_file_menu_uiinfo[5].widget,
+                            (GtkDestroyNotify) gtk_widget_unref);
+
+  gtk_widget_ref (menubar_file_menu_uiinfo[6].widget);
+  gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_exit",
+                            menubar_file_menu_uiinfo[6].widget,
+                            (GtkDestroyNotify) gtk_widget_unref);
+
   gtk_widget_ref (menubar_uiinfo[1].widget);
   gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_view",
                             menubar_uiinfo[1].widget,
   gtk_widget_ref (menubar_uiinfo[1].widget);
   gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_view",
                             menubar_uiinfo[1].widget,
@@ -390,6 +409,18 @@ create_intf_window (void)
                             (GtkDestroyNotify) gtk_widget_unref);
   gtk_widget_show (toolbar_stop);
 
                             (GtkDestroyNotify) gtk_widget_unref);
   gtk_widget_show (toolbar_stop);
 
+  tmp_toolbar_icon = gnome_stock_pixmap_widget (intf_window, GNOME_STOCK_PIXMAP_TOP);
+  toolbar_eject = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
+                                GTK_TOOLBAR_CHILD_BUTTON,
+                                NULL,
+                                _("Eject"),
+                                _("Eject disc"), NULL,
+                                tmp_toolbar_icon, NULL, NULL);
+  gtk_widget_ref (toolbar_eject);
+  gtk_object_set_data_full (GTK_OBJECT (intf_window), "toolbar_eject", toolbar_eject,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (toolbar_eject);
+
   tmp_toolbar_icon = gnome_stock_pixmap_widget (intf_window, GNOME_STOCK_PIXMAP_FORWARD);
   toolbar_play = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
                                 GTK_TOOLBAR_CHILD_BUTTON,
   tmp_toolbar_icon = gnome_stock_pixmap_widget (intf_window, GNOME_STOCK_PIXMAP_FORWARD);
   toolbar_play = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
                                 GTK_TOOLBAR_CHILD_BUTTON,
@@ -682,6 +713,9 @@ create_intf_window (void)
   gtk_signal_connect (GTK_OBJECT (toolbar_stop), "button_press_event",
                       GTK_SIGNAL_FUNC (GtkControlStop),
                       "intf_window");
   gtk_signal_connect (GTK_OBJECT (toolbar_stop), "button_press_event",
                       GTK_SIGNAL_FUNC (GtkControlStop),
                       "intf_window");
+  gtk_signal_connect (GTK_OBJECT (toolbar_eject), "button_press_event",
+                      GTK_SIGNAL_FUNC (GtkDiscEject),
+                      "intf_window");
   gtk_signal_connect (GTK_OBJECT (toolbar_play), "button_press_event",
                       GTK_SIGNAL_FUNC (GtkControlPlay),
                       "intf_window");
   gtk_signal_connect (GTK_OBJECT (toolbar_play), "button_press_event",
                       GTK_SIGNAL_FUNC (GtkControlPlay),
                       "intf_window");
index 335ccc479920776ab6a78508ff41441458730fce..339d62f6f833c7940a6eca572d5646d5f9117873 100644 (file)
@@ -2,7 +2,7 @@
  * gtk.c : Gtk+ plugin for vlc
  *****************************************************************************
  * Copyright (C) 2000-2001 VideoLAN
  * gtk.c : Gtk+ plugin for vlc
  *****************************************************************************
  * Copyright (C) 2000-2001 VideoLAN
- * $Id: gtk.c,v 1.8 2002/01/07 02:12:29 sam Exp $
+ * $Id: gtk.c,v 1.9 2002/01/09 02:01:14 sam Exp $
  *
  * Authors: Samuel Hocevar <sam@zoy.org>
  *      
  *
  * Authors: Samuel Hocevar <sam@zoy.org>
  *      
@@ -328,61 +328,63 @@ static gint GtkManage( gpointer p_data )
     /* update the playlist */
     GtkPlayListManage( p_data );
 
     /* update the playlist */
     GtkPlayListManage( p_data );
 
-    if( p_input_bank->pp_input[0] != NULL && !p_intf->b_die )
+    if( p_input_bank->pp_input[0] != NULL )
     {
         vlc_mutex_lock( &p_input_bank->pp_input[0]->stream.stream_lock );
 
     {
         vlc_mutex_lock( &p_input_bank->pp_input[0]->stream.stream_lock );
 
-        /* New input or stream map change */
-        if( p_input_bank->pp_input[0]->stream.b_changed )
+        if( !p_input_bank->pp_input[0]->b_die )
         {
         {
-            GtkModeManage( p_intf );
-            GtkSetupMenus( p_intf );
-            p_intf->p_sys->b_playing = 1;
-        }
+            /* New input or stream map change */
+            if( p_input_bank->pp_input[0]->stream.b_changed )
+            {
+                GtkModeManage( p_intf );
+                GtkSetupMenus( p_intf );
+                p_intf->p_sys->b_playing = 1;
+            }
 
 
-        /* Manage the slider */
-        if( p_input_bank->pp_input[0]->stream.b_seekable )
-        {
-            float newvalue = p_intf->p_sys->p_adj->value;
+            /* Manage the slider */
+            if( p_input_bank->pp_input[0]->stream.b_seekable )
+            {
+                float newvalue = p_intf->p_sys->p_adj->value;
     
 #define p_area p_input_bank->pp_input[0]->stream.p_selected_area
     
 #define p_area p_input_bank->pp_input[0]->stream.p_selected_area
-            /* If the user hasn't touched the slider since the last time,
-             * then the input can safely change it */
-            if( newvalue == p_intf->p_sys->f_adj_oldvalue )
-            {
-                /* Update the value */
-                p_intf->p_sys->p_adj->value = p_intf->p_sys->f_adj_oldvalue =
-                    ( 100. * p_area->i_tell ) / p_area->i_size;
+                /* If the user hasn't touched the slider since the last time,
+                 * then the input can safely change it */
+                if( newvalue == p_intf->p_sys->f_adj_oldvalue )
+                {
+                    /* Update the value */
+                    p_intf->p_sys->p_adj->value = p_intf->p_sys->f_adj_oldvalue =
+                        ( 100. * p_area->i_tell ) / p_area->i_size;
+        
+                    gtk_signal_emit_by_name( GTK_OBJECT( p_intf->p_sys->p_adj ),
+                                             "value_changed" );
+                }
+                /* Otherwise, send message to the input if the user has
+                 * finished dragging the slider */
+                else if( p_intf->p_sys->b_slider_free )
+                {
+                    off_t i_seek = ( newvalue * p_area->i_size ) / 100;
     
     
-                gtk_signal_emit_by_name( GTK_OBJECT( p_intf->p_sys->p_adj ),
-                                         "value_changed" );
+                    /* release the lock to be able to seek */
+                    vlc_mutex_unlock( &p_input_bank->pp_input[0]->stream.stream_lock );
+                    input_Seek( p_input_bank->pp_input[0], i_seek );
+                    vlc_mutex_lock( &p_input_bank->pp_input[0]->stream.stream_lock );
+        
+                    /* Update the old value */
+                    p_intf->p_sys->f_adj_oldvalue = newvalue;
+                }
+#    undef p_area
             }
             }
-            /* Otherwise, send message to the input if the user has
-             * finished dragging the slider */
-            else if( p_intf->p_sys->b_slider_free )
-            {
-                off_t i_seek = ( newvalue * p_area->i_size ) / 100;
-
-                /* release the lock to be able to seek */
-                vlc_mutex_unlock( &p_input_bank->pp_input[0]->stream.stream_lock );
-                input_Seek( p_input_bank->pp_input[0], i_seek );
-                vlc_mutex_lock( &p_input_bank->pp_input[0]->stream.stream_lock );
     
     
-                /* Update the old value */
-                p_intf->p_sys->f_adj_oldvalue = newvalue;
+            if( p_intf->p_sys->i_part !=
+                p_input_bank->pp_input[0]->stream.p_selected_area->i_part )
+            {
+                p_intf->p_sys->b_chapter_update = 1;
+                GtkSetupMenus( p_intf );
             }
             }
-#undef p_area
-        }
-
-        if( p_intf->p_sys->i_part !=
-            p_input_bank->pp_input[0]->stream.p_selected_area->i_part )
-        {
-            p_intf->p_sys->b_chapter_update = 1;
-            GtkSetupMenus( p_intf );
         }
 
         vlc_mutex_unlock( &p_input_bank->pp_input[0]->stream.stream_lock );
         }
 
         vlc_mutex_unlock( &p_input_bank->pp_input[0]->stream.stream_lock );
-
     }
     else if( p_intf->p_sys->b_playing && !p_intf->b_die )
     {
     }
     else if( p_intf->p_sys->b_playing && !p_intf->b_die )
     {
index 871bb0bc30dae2d8b39caa143765498f4a8506da..78cc3a27b20b7b1c4acf48be1a92abcb50a82b29 100644 (file)
              <right_justify>False</right_justify>
            </widget>
 
              <right_justify>False</right_justify>
            </widget>
 
+           <widget>
+             <class>GtkMenuItem</class>
+             <name>menubar_eject</name>
+             <tooltip>Eject disc</tooltip>
+             <signal>
+               <name>activate</name>
+               <handler>GtkEjectDiscActivate</handler>
+               <data>&quot;intf_window&quot;</data>
+               <last_modification_time>Fri, 21 Dec 2001 12:51:34 GMT</last_modification_time>
+             </signal>
+             <label>_Eject Disc</label>
+             <right_justify>False</right_justify>
+           </widget>
+
+           <widget>
+             <class>GtkMenuItem</class>
+             <name>separator14</name>
+             <right_justify>False</right_justify>
+           </widget>
+
            <widget>
              <class>GtkMenuItem</class>
              <name>menubar_exit</name>
            <widget>
              <class>GtkMenuItem</class>
              <name>menubar_exit</name>
          <label>Stop</label>
        </widget>
 
          <label>Stop</label>
        </widget>
 
+       <widget>
+         <class>GtkButton</class>
+         <child_name>Toolbar:button</child_name>
+         <name>toolbar_eject</name>
+         <signal>
+           <name>button_press_event</name>
+           <handler>GtkDiscEject</handler>
+           <data>&quot;intf_window&quot;</data>
+           <last_modification_time>Fri, 21 Dec 2001 15:33:26 GMT</last_modification_time>
+         </signal>
+         <label>Eject</label>
+       </widget>
+
        <widget>
          <class>GtkButton</class>
          <child_name>Toolbar:button</child_name>
        <widget>
          <class>GtkButton</class>
          <child_name>Toolbar:button</child_name>
index 1fbeda4f806cae6500123be2fb7592fed9a1b6ce..a420a001f17133a3e9ce83d8f398b05f0a676698 100644 (file)
@@ -2,10 +2,11 @@
  * gtk_callbacks.c : Callbacks for the Gtk+ plugin.
  *****************************************************************************
  * Copyright (C) 2000, 2001 VideoLAN
  * gtk_callbacks.c : Callbacks for the Gtk+ plugin.
  *****************************************************************************
  * Copyright (C) 2000, 2001 VideoLAN
- * $Id: gtk_callbacks.c,v 1.30 2002/01/07 02:12:29 sam Exp $
+ * $Id: gtk_callbacks.c,v 1.31 2002/01/09 02:01:14 sam Exp $
  *
  * Authors: Samuel Hocevar <sam@zoy.org>
  *          Stéphane Borel <stef@via.ecp.fr>
  *
  * Authors: Samuel Hocevar <sam@zoy.org>
  *          Stéphane Borel <stef@via.ecp.fr>
+ *          Julien BLACHE <jb@technologeek.org>
  *      
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  *      
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -30,6 +31,8 @@
 
 #include <videolan/vlc.h>
 
 
 #include <videolan/vlc.h>
 
+#include <unistd.h>
+
 #include <gtk/gtk.h>
 
 #include <string.h>
 #include <gtk/gtk.h>
 
 #include <string.h>
@@ -39,6 +42,7 @@
 
 #include "interface.h"
 #include "intf_playlist.h"
 
 #include "interface.h"
 #include "intf_playlist.h"
+#include "intf_eject.h"
 
 #include "video.h"
 #include "video_output.h"
 
 #include "video.h"
 #include "video_output.h"
@@ -463,3 +467,55 @@ void GtkJumpActivate( GtkMenuItem * menuitem, gpointer user_data )
     GtkJumpShow( GTK_WIDGET( menuitem ), NULL, user_data );
 }
 
     GtkJumpShow( GTK_WIDGET( menuitem ), NULL, user_data );
 }
 
+
+/****************************************************************************
+ * Callbacks for disc ejection
+ ****************************************************************************/
+gboolean GtkDiscEject ( GtkWidget *widget, GdkEventButton *event,
+                        gpointer user_data )
+{
+  char *psz_device = NULL;
+
+  /*
+   * Get the active input
+   * Determine whether we can eject a media, ie it's a VCD or DVD
+   * If it's neither a VCD nor a DVD, then return
+   */
+
+  /*
+   * Don't really know if I must lock the stuff here, we're using it read-only
+   */
+
+  if (p_main->p_playlist->current.psz_name != NULL)
+  {
+      if (strncmp(p_main->p_playlist->current.psz_name, "dvd", 3)
+          || strncmp(p_main->p_playlist->current.psz_name, "vcd", 3))
+      {
+          /* Determine the device name by omitting the first 4 characters */
+          psz_device = strdup((p_main->p_playlist->current.psz_name + 4));
+      }
+  }
+
+  if( psz_device == NULL )
+  {
+      return TRUE;
+  }
+
+  /* If there's a stream playing, we aren't allowed to eject ! */
+  if( p_input_bank->pp_input[0] == NULL )
+  {
+      intf_WarnMsg( 4, "intf: ejecting %s", psz_device );
+
+      intf_Eject( psz_device );
+  }
+
+  free(psz_device);
+  return TRUE;
+}
+
+void GtkEjectDiscActivate ( GtkMenuItem *menuitem, gpointer user_data )
+{
+  fprintf(stderr, "DEBUG: EJECT called from MENU !\n");
+
+  GtkDiscEject( GTK_WIDGET( menuitem ), NULL, user_data );
+}
index 2d8b2da179349232333ec2a25e2dc90b2c374ac8..2dae4d205590c3d8a7d57aeb808877c2040f4213 100644 (file)
@@ -2,7 +2,7 @@
  * gtk_callbacks.h : Callbacks for the gtk plugin.
  *****************************************************************************
  * Copyright (C) 2000, 2001 VideoLAN
  * gtk_callbacks.h : Callbacks for the gtk plugin.
  *****************************************************************************
  * Copyright (C) 2000, 2001 VideoLAN
- * $Id: gtk_callbacks.h,v 1.15 2001/05/30 23:02:03 stef Exp $
+ * $Id: gtk_callbacks.h,v 1.16 2002/01/09 02:01:14 sam Exp $
  *
  * Authors: Samuel Hocevar <sam@zoy.org>
  *          Stéphane Borel <stef@via.ecp.fr>
  *
  * Authors: Samuel Hocevar <sam@zoy.org>
  *          Stéphane Borel <stef@via.ecp.fr>
@@ -70,3 +70,12 @@ void     GtkNetworkJoin         ( GtkEditable *, gpointer );
 void     GtkChannelGo           ( GtkButton *, gpointer );
 
 void     GtkNetworkOpenChannel  ( GtkToggleButton *, gpointer );
 void     GtkChannelGo           ( GtkButton *, gpointer );
 
 void     GtkNetworkOpenChannel  ( GtkToggleButton *, gpointer );
+
+void
+GtkEjectDiscActivate                   (GtkMenuItem     *menuitem,
+                                        gpointer         user_data);
+
+gboolean
+GtkDiscEject                           (GtkWidget       *widget,
+                                        GdkEventButton  *event,
+                                        gpointer         user_data);
index 26db006290fc8df4c2dfe6a782fd894fa4fcc1eb..cd1c6a4056db2ba698ec06fb34586d688f3faacf 100644 (file)
@@ -2,7 +2,7 @@
  * gtk_display.c: Gtk+ tools for main interface
  *****************************************************************************
  * Copyright (C) 1999, 2000 VideoLAN
  * gtk_display.c: Gtk+ tools for main interface
  *****************************************************************************
  * Copyright (C) 1999, 2000 VideoLAN
- * $Id: gtk_display.c,v 1.11 2002/01/07 02:12:29 sam Exp $
+ * $Id: gtk_display.c,v 1.12 2002/01/09 02:01:14 sam Exp $
  *
  * Authors: Samuel Hocevar <sam@zoy.org>
  *          Stéphane Borel <stef@via.ecp.fr>
  *
  * Authors: Samuel Hocevar <sam@zoy.org>
  *          Stéphane Borel <stef@via.ecp.fr>
@@ -225,6 +225,7 @@ gint GtkModeManage( intf_thread_t * p_intf )
 
     /* set control items */
     gtk_widget_set_sensitive( GETWIDGET(p_window, "toolbar_back"), FALSE );
 
     /* set control items */
     gtk_widget_set_sensitive( GETWIDGET(p_window, "toolbar_back"), FALSE );
+    gtk_widget_set_sensitive( GETWIDGET(p_window, "toolbar_eject"), !b_control);
     gtk_widget_set_sensitive( GETWIDGET(p_window, "toolbar_pause"), b_control );
     gtk_widget_set_sensitive( GETWIDGET(p_window, "toolbar_slow"), b_control );
     gtk_widget_set_sensitive( GETWIDGET(p_window, "toolbar_fast"), b_control );
     gtk_widget_set_sensitive( GETWIDGET(p_window, "toolbar_pause"), b_control );
     gtk_widget_set_sensitive( GETWIDGET(p_window, "toolbar_slow"), b_control );
     gtk_widget_set_sensitive( GETWIDGET(p_window, "toolbar_fast"), b_control );
index 3fd7da5b9f61c3d549e8ffbc264796f8ceaa0dc4..5c5683a822ce657e9da0c3288bc7b86fd574ebf1 100644 (file)
@@ -29,6 +29,8 @@ create_intf_window (void)
   GtkWidget *menubar_disc;
   GtkWidget *menubar_network;
   GtkWidget *separator4;
   GtkWidget *menubar_disc;
   GtkWidget *menubar_network;
   GtkWidget *separator4;
+  GtkWidget *menubar_eject;
+  GtkWidget *separator14;
   GtkWidget *menubar_exit;
   GtkWidget *menubar_view;
   GtkWidget *menubar_view_menu;
   GtkWidget *menubar_exit;
   GtkWidget *menubar_view;
   GtkWidget *menubar_view_menu;
@@ -60,6 +62,7 @@ create_intf_window (void)
   GtkWidget *toolbar_network;
   GtkWidget *toolbar_back;
   GtkWidget *toolbar_stop;
   GtkWidget *toolbar_network;
   GtkWidget *toolbar_back;
   GtkWidget *toolbar_stop;
+  GtkWidget *toolbar_eject;
   GtkWidget *toolbar_play;
   GtkWidget *toolbar_pause;
   GtkWidget *toolbar_slow;
   GtkWidget *toolbar_play;
   GtkWidget *toolbar_pause;
   GtkWidget *toolbar_slow;
@@ -196,6 +199,26 @@ create_intf_window (void)
   gtk_container_add (GTK_CONTAINER (menubar_file_menu), separator4);
   gtk_widget_set_sensitive (separator4, FALSE);
 
   gtk_container_add (GTK_CONTAINER (menubar_file_menu), separator4);
   gtk_widget_set_sensitive (separator4, FALSE);
 
+  menubar_eject = gtk_menu_item_new_with_label ("");
+  tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (menubar_eject)->child),
+                                   _("_Eject Disc"));
+  gtk_widget_add_accelerator (menubar_eject, "activate_item", menubar_file_menu_accels,
+                              tmp_key, 0, 0);
+  gtk_widget_ref (menubar_eject);
+  gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_eject", menubar_eject,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (menubar_eject);
+  gtk_container_add (GTK_CONTAINER (menubar_file_menu), menubar_eject);
+  gtk_tooltips_set_tip (tooltips, menubar_eject, _("Eject disc"), NULL);
+
+  separator14 = gtk_menu_item_new ();
+  gtk_widget_ref (separator14);
+  gtk_object_set_data_full (GTK_OBJECT (intf_window), "separator14", separator14,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (separator14);
+  gtk_container_add (GTK_CONTAINER (menubar_file_menu), separator14);
+  gtk_widget_set_sensitive (separator14, FALSE);
+
   menubar_exit = gtk_menu_item_new_with_label ("");
   tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (menubar_exit)->child),
                                    _("E_xit"));
   menubar_exit = gtk_menu_item_new_with_label ("");
   tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (menubar_exit)->child),
                                    _("E_xit"));
@@ -500,6 +523,17 @@ create_intf_window (void)
                             (GtkDestroyNotify) gtk_widget_unref);
   gtk_widget_show (toolbar_stop);
 
                             (GtkDestroyNotify) gtk_widget_unref);
   gtk_widget_show (toolbar_stop);
 
+  toolbar_eject = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
+                                GTK_TOOLBAR_CHILD_BUTTON,
+                                NULL,
+                                _("Eject"),
+                                NULL, NULL,
+                                NULL, NULL, NULL);
+  gtk_widget_ref (toolbar_eject);
+  gtk_object_set_data_full (GTK_OBJECT (intf_window), "toolbar_eject", toolbar_eject,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (toolbar_eject);
+
   toolbar_play = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
                                 GTK_TOOLBAR_CHILD_BUTTON,
                                 NULL,
   toolbar_play = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
                                 GTK_TOOLBAR_CHILD_BUTTON,
                                 NULL,
@@ -776,6 +810,9 @@ create_intf_window (void)
   gtk_signal_connect (GTK_OBJECT (menubar_network), "activate",
                       GTK_SIGNAL_FUNC (GtkNetworkOpenActivate),
                       "intf_window");
   gtk_signal_connect (GTK_OBJECT (menubar_network), "activate",
                       GTK_SIGNAL_FUNC (GtkNetworkOpenActivate),
                       "intf_window");
+  gtk_signal_connect (GTK_OBJECT (menubar_eject), "activate",
+                      GTK_SIGNAL_FUNC (GtkEjectDiscActivate),
+                      "intf_window");
   gtk_signal_connect (GTK_OBJECT (menubar_exit), "activate",
                       GTK_SIGNAL_FUNC (GtkExitActivate),
                       "intf_window");
   gtk_signal_connect (GTK_OBJECT (menubar_exit), "activate",
                       GTK_SIGNAL_FUNC (GtkExitActivate),
                       "intf_window");
@@ -812,6 +849,9 @@ create_intf_window (void)
   gtk_signal_connect (GTK_OBJECT (toolbar_stop), "button_press_event",
                       GTK_SIGNAL_FUNC (GtkControlStop),
                       "intf_window");
   gtk_signal_connect (GTK_OBJECT (toolbar_stop), "button_press_event",
                       GTK_SIGNAL_FUNC (GtkControlStop),
                       "intf_window");
+  gtk_signal_connect (GTK_OBJECT (toolbar_eject), "button_press_event",
+                      GTK_SIGNAL_FUNC (GtkDiscEject),
+                      "intf_window");
   gtk_signal_connect (GTK_OBJECT (toolbar_play), "button_press_event",
                       GTK_SIGNAL_FUNC (GtkControlPlay),
                       "intf_window");
   gtk_signal_connect (GTK_OBJECT (toolbar_play), "button_press_event",
                       GTK_SIGNAL_FUNC (GtkControlPlay),
                       "intf_window");
index 630dfcad9f3e8b5f3a2d8e837d073de38ee0c6a7..5f2c872a315cd7a0891f2921c6d9b6749ec1e206 100644 (file)
@@ -1 +1,2 @@
 mga_SOURCES = mga.c
 mga_SOURCES = mga.c
+xmga_SOURCES = xmga.c
diff --git a/plugins/mga/xmga.c b/plugins/mga/xmga.c
new file mode 100644 (file)
index 0000000..5744918
--- /dev/null
@@ -0,0 +1,1208 @@
+/*****************************************************************************
+ * xmga.c : X11 MGA plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 1998-2001 VideoLAN
+ * $Id: xmga.c,v 1.1 2002/01/09 02:01:14 sam Exp $
+ *
+ * Authors: Vincent Seguin <seguin@via.ecp.fr>
+ *          Samuel Hocevar <sam@zoy.org>
+ *      
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <errno.h>                                                 /* ENOMEM */
+#include <stdlib.h>                                                /* free() */
+#include <string.h>                                            /* strerror() */
+
+#include <videolan/vlc.h>
+
+#ifdef HAVE_MACHINE_PARAM_H
+/* BSD */
+#include <machine/param.h>
+#include <sys/types.h>                                     /* typedef ushort */
+#include <sys/ipc.h>
+#endif
+
+#ifndef WIN32
+#include <netinet/in.h>                               /* BSD: struct in_addr */
+#endif
+
+#include <sys/shm.h>                                   /* shmget(), shmctl() */
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/keysym.h>
+#include <X11/extensions/XShm.h>
+#include <X11/extensions/dpms.h>
+
+#include "video.h"
+#include "video_output.h"
+
+#include "interface.h"
+#include "netutils.h"                                 /* network_ChannelJoin */
+
+#include "stream_control.h"                 /* needed by input_ext-intf.h... */
+#include "input_ext-intf.h"
+
+//#include "mga.h"
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static void vout_getfunctions( function_list_t * );
+
+static int  vout_Probe     ( probedata_t * );
+static int  vout_Create    ( vout_thread_t * );
+static void vout_Destroy   ( vout_thread_t * );
+static void vout_Render    ( vout_thread_t *, picture_t * );
+static void vout_Display   ( vout_thread_t *, picture_t * );
+static int  vout_Manage    ( vout_thread_t * );
+static int  vout_Init      ( vout_thread_t * );
+static void vout_End       ( vout_thread_t * );
+
+static int  CreateWindow   ( vout_thread_t * );
+static void DestroyWindow  ( vout_thread_t * );
+
+static int  NewPicture     ( vout_thread_t *, picture_t * );
+static void FreePicture    ( vout_thread_t *, picture_t * );
+
+static void ToggleFullScreen      ( vout_thread_t * );
+
+static void EnableXScreenSaver    ( vout_thread_t * );
+static void DisableXScreenSaver   ( vout_thread_t * );
+
+static void CreateCursor   ( vout_thread_t * );
+static void DestroyCursor  ( vout_thread_t * );
+static void ToggleCursor   ( vout_thread_t * );
+
+/*****************************************************************************
+ * Building configuration tree
+ *****************************************************************************/
+MODULE_CONFIG_START
+MODULE_CONFIG_STOP
+
+MODULE_INIT_START
+    SET_DESCRIPTION( "X11 MGA module" )
+    ADD_CAPABILITY( VOUT, 60 )
+    ADD_SHORTCUT( "xmga" )
+MODULE_INIT_STOP
+
+MODULE_ACTIVATE_START
+    vout_getfunctions( &p_module->p_functions->vout );
+MODULE_ACTIVATE_STOP
+
+MODULE_DEACTIVATE_START
+MODULE_DEACTIVATE_STOP
+
+/*****************************************************************************
+ * vout_sys_t: video output method descriptor
+ *****************************************************************************
+ * This structure is part of the video output thread descriptor.
+ * It describes the X11 and XVideo specific properties of an output thread.
+ *****************************************************************************/
+typedef struct vout_sys_s
+{
+    /* Internal settings and properties */
+    Display *           p_display;                        /* display pointer */
+
+    Visual *            p_visual;                          /* visual pointer */
+    int                 i_screen;                           /* screen number */
+    Window              window;                               /* root window */
+    GC                  gc;              /* graphic context instance handler */
+
+    boolean_t           b_shm;               /* shared memory extension flag */
+
+#ifdef MODULE_NAME_IS_xvideo
+    Window              yuv_window;   /* sub-window for displaying yuv video
+                                                                        data */
+    int                 i_xvport;
+#else
+    Colormap            colormap;               /* colormap used (8bpp only) */
+
+    int                 i_screen_depth;
+    int                 i_bytes_per_pixel;
+    int                 i_bytes_per_line;
+    int                 i_red_mask;
+    int                 i_green_mask;
+    int                 i_blue_mask;
+#endif
+
+    /* X11 generic properties */
+    Atom                wm_protocols;
+    Atom                wm_delete_window;
+
+    int                 i_width;                     /* width of main window */
+    int                 i_height;                   /* height of main window */
+
+    /* Backup of window position and size before fullscreen switch */
+    int                 i_width_backup;
+    int                 i_height_backup;
+    int                 i_xpos_backup;
+    int                 i_ypos_backup;
+
+    /* Screen saver properties */
+    int                 i_ss_timeout;                             /* timeout */
+    int                 i_ss_interval;           /* interval between changes */
+    int                 i_ss_blanking;                      /* blanking mode */
+    int                 i_ss_exposure;                      /* exposure mode */
+    BOOL                b_ss_dpms;                              /* DPMS mode */
+
+    /* Mouse pointer properties */
+    boolean_t           b_mouse_pointer_visible;
+    mtime_t             i_time_mouse_last_moved; /* used to auto-hide pointer*/
+    Cursor              blank_cursor;                   /* the hidden cursor */
+    Pixmap              cursor_pixmap;
+
+} vout_sys_t;
+
+/*****************************************************************************
+ * picture_sys_t: direct buffer method descriptor
+ *****************************************************************************
+ * This structure is part of the picture descriptor, it describes the
+ * XVideo specific properties of a direct buffer.
+ *****************************************************************************/
+typedef struct picture_sys_s
+{
+} picture_sys_t;
+
+/*****************************************************************************
+ * mwmhints_t: window manager hints
+ *****************************************************************************
+ * Fullscreen needs to be able to hide the wm decorations so we provide
+ * this structure to make it easier.
+ *****************************************************************************/
+#define MWM_HINTS_DECORATIONS   (1L << 1)
+#define PROP_MWM_HINTS_ELEMENTS 5
+typedef struct mwmhints_s
+{
+    u32 flags;
+    u32 functions;
+    u32 decorations;
+    s32 input_mode;
+    u32 status;
+} mwmhints_t;
+
+/*****************************************************************************
+ * Chroma defines
+ *****************************************************************************/
+#ifdef MODULE_NAME_IS_xvideo
+#   define MAX_DIRECTBUFFERS 5
+#else
+#   define MAX_DIRECTBUFFERS 2
+#endif
+
+/*****************************************************************************
+ * Seeking function TODO: put this in a generic location !
+ *****************************************************************************/
+static __inline__ void vout_Seek( off_t i_seek )
+{
+    off_t i_tell;
+
+    vlc_mutex_lock( &p_input_bank->lock );
+    if( p_input_bank->pp_input[0] != NULL )
+    {
+#define S p_input_bank->pp_input[0]->stream
+        i_tell = S.p_selected_area->i_tell + i_seek * (off_t)50 * S.i_mux_rate;
+
+        i_tell = ( i_tell <= 0 /*S.p_selected_area->i_start*/ )
+                   ? 0 /*S.p_selected_area->i_start*/
+                   : ( i_tell >= S.p_selected_area->i_size )
+                       ? S.p_selected_area->i_size
+                       : i_tell;
+
+        input_Seek( p_input_bank->pp_input[0], i_tell );
+#undef S
+    }
+    vlc_mutex_unlock( &p_input_bank->lock );
+}
+
+/*****************************************************************************
+ * Functions exported as capabilities. They are declared as static so that
+ * we don't pollute the namespace too much.
+ *****************************************************************************/
+static void vout_getfunctions( function_list_t * p_function_list )
+{
+    p_function_list->pf_probe = vout_Probe;
+    p_function_list->functions.vout.pf_create     = vout_Create;
+    p_function_list->functions.vout.pf_init       = vout_Init;
+    p_function_list->functions.vout.pf_end        = vout_End;
+    p_function_list->functions.vout.pf_destroy    = vout_Destroy;
+    p_function_list->functions.vout.pf_manage     = vout_Manage;
+    p_function_list->functions.vout.pf_render     = vout_Render;
+    p_function_list->functions.vout.pf_display    = vout_Display;
+}
+
+/*****************************************************************************
+ * vout_Probe: probe the video driver and return a score
+ *****************************************************************************
+ * This function tries to initialize SDL and returns a score to the
+ * plugin manager so that it can select the best plugin.
+ *****************************************************************************/
+static int vout_Probe( probedata_t *p_data )
+{
+    Display *p_display;                                   /* display pointer */
+    char    *psz_display;
+#ifdef MODULE_NAME_IS_xvideo
+    int      i_xvport, i_dummy;
+#endif
+
+    /* Open display, unsing 'vlc_display' or DISPLAY environment variable */
+    psz_display = XDisplayName( main_GetPszVariable(VOUT_DISPLAY_VAR, NULL) );
+    p_display = XOpenDisplay( psz_display );
+    if( p_display == NULL )                                         /* error */
+    {
+        intf_WarnMsg( 3, "vout: cannot open display %s", psz_display );
+        return( 0 );
+    }
+
+#ifdef MODULE_NAME_IS_xvideo
+    /* Check that there is an available XVideo port for this format */
+    i_xvport = XVideoGetPort( p_display, p_data->vout.i_chroma, &i_dummy );
+    if( i_xvport < 0 )
+    {
+        /* It failed, but it's not completely lost ! We try to open an
+         * XVideo port for a YUY2 picture */
+        i_xvport = XVideoGetPort( p_display, FOURCC_YUY2, &i_dummy );
+        if( i_xvport < 0 )
+        {
+            /* It failed, but it's not completely lost ! We try to open an
+             * XVideo port for a simple 16bpp RGB picture */
+            i_xvport = XVideoGetPort( p_display, FOURCC_RV16, &i_dummy );
+            if( i_xvport < 0 )
+            {
+                XCloseDisplay( p_display );
+                return( 0 );
+            }
+        }
+    }
+    XVideoReleasePort( p_display, i_xvport );
+#endif
+
+    /* Clean-up everyting */
+    XCloseDisplay( p_display );
+
+#ifdef MODULE_NAME_IS_xvideo 
+    return( 150 );
+#else
+    return( 50 );
+#endif
+}
+
+/*****************************************************************************
+ * vout_Create: allocate X11 video thread output method
+ *****************************************************************************
+ * This function allocate and initialize a X11 vout method. It uses some of the
+ * vout properties to choose the window size, and change them according to the
+ * actual properties of the display.
+ *****************************************************************************/
+static int vout_Create( vout_thread_t *p_vout )
+{
+    char *psz_display;
+
+    /* Allocate structure */
+    p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
+    if( p_vout->p_sys == NULL )
+    {
+        intf_ErrMsg( "vout error: %s", strerror(ENOMEM) );
+        return( 1 );
+    }
+
+    /* Open display, unsing 'vlc_display' or DISPLAY environment variable */
+    psz_display = XDisplayName( main_GetPszVariable( VOUT_DISPLAY_VAR, NULL ) );
+    p_vout->p_sys->p_display = XOpenDisplay( psz_display );
+
+    if( p_vout->p_sys->p_display == NULL )                          /* error */
+    {
+        intf_ErrMsg( "vout error: cannot open display %s", psz_display );
+        free( p_vout->p_sys );
+        return( 1 );
+    }
+    p_vout->p_sys->i_screen = DefaultScreen( p_vout->p_sys->p_display );
+
+    /* Create blank cursor (for mouse cursor autohiding) */
+    p_vout->p_sys->b_mouse_pointer_visible = 1;
+    CreateCursor( p_vout );
+
+    /* Spawn base window - this window will include the video output window,
+     * but also command buttons, subtitles and other indicators */
+    if( CreateWindow( p_vout ) )
+    {
+        intf_ErrMsg( "vout error: cannot create X11 window" );
+        DestroyCursor( p_vout );
+        XCloseDisplay( p_vout->p_sys->p_display );
+        free( p_vout->p_sys );
+        return( 1 );
+    }
+
+    /* Disable screen saver and return */
+    DisableXScreenSaver( p_vout );
+
+    return( 0 );
+}
+
+/*****************************************************************************
+ * vout_Destroy: destroy X11 video thread output method
+ *****************************************************************************
+ * Terminate an output method created by vout_CreateOutputMethod
+ *****************************************************************************/
+static void vout_Destroy( vout_thread_t *p_vout )
+{
+    /* Restore cursor if it was blanked */
+    if( !p_vout->p_sys->b_mouse_pointer_visible )
+    {
+        ToggleCursor( p_vout );
+    }
+
+    DestroyCursor( p_vout );
+    EnableXScreenSaver( p_vout );
+    DestroyWindow( p_vout );
+
+    XCloseDisplay( p_vout->p_sys->p_display );
+
+    /* Destroy structure */
+    free( p_vout->p_sys );
+}
+
+/*****************************************************************************
+ * vout_Init: initialize X11 video thread output method
+ *****************************************************************************
+ * This function create the XImages needed by the output thread. It is called
+ * at the beginning of the thread, but also each time the window is resized.
+ *****************************************************************************/
+static int vout_Init( vout_thread_t *p_vout )
+{
+    int i_index;
+    picture_t *p_pic;
+
+    I_OUTPUTPICTURES = 0;
+
+#ifdef MODULE_NAME_IS_xvideo
+    /* Initialize the output structure; we already found an XVideo port,
+     * and the corresponding chroma we will be using. Since we can
+     * arbitrary scale, stick to the coordinates and aspect. */
+    p_vout->output.i_width  = p_vout->render.i_width;
+    p_vout->output.i_height = p_vout->render.i_height;
+    p_vout->output.i_aspect = p_vout->render.i_aspect;
+
+#else
+    /* Initialize the output structure: RGB with square pixels, whatever
+     * the input format is, since it's the only format we know */
+    switch( p_vout->p_sys->i_screen_depth )
+    {
+        case 8: /* FIXME: set the palette */
+            p_vout->output.i_chroma = FOURCC_BI_RGB; break;
+        case 15:
+            p_vout->output.i_chroma = FOURCC_RV15; break;
+        case 16:
+            p_vout->output.i_chroma = FOURCC_RV16; break;
+        case 24:
+            p_vout->output.i_chroma = FOURCC_BI_BITFIELDS; break;
+        case 32:
+            p_vout->output.i_chroma = FOURCC_BI_BITFIELDS; break;
+        default:
+            intf_ErrMsg( "vout error: unknown screen depth" );
+            return( 0 );
+    }
+
+    p_vout->output.i_width = p_vout->p_sys->i_width;
+    p_vout->output.i_height = p_vout->p_sys->i_height;
+
+    /* Assume we have square pixels */
+    p_vout->output.i_aspect = p_vout->p_sys->i_width
+                               * VOUT_ASPECT_FACTOR / p_vout->p_sys->i_height;
+#endif
+
+    /* Try to initialize up to MAX_DIRECTBUFFERS direct buffers */
+    while( I_OUTPUTPICTURES < MAX_DIRECTBUFFERS )
+    {
+        p_pic = NULL;
+
+        /* Find an empty picture slot */
+        for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ )
+        {
+            if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
+            {
+                p_pic = p_vout->p_picture + i_index;
+                break;
+            }
+        }
+
+        /* Allocate the picture */
+        if( p_pic == NULL || NewPicture( p_vout, p_pic ) )
+        {
+            break;
+        }
+
+        p_pic->i_status = DESTROYED_PICTURE;
+        p_pic->i_type   = DIRECT_PICTURE;
+
+        PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;
+
+        I_OUTPUTPICTURES++;
+    }
+
+    return( 0 );
+}
+
+/*****************************************************************************
+ * vout_Render: render previously calculated output
+ *****************************************************************************/
+static void vout_Render( vout_thread_t *p_vout, picture_t *p_pic )
+{
+    ;
+}
+
+ /*****************************************************************************
+ * vout_Display: displays previously rendered output
+ *****************************************************************************
+ * This function sends the currently rendered image to X11 server.
+ * (The Xv extension takes care of "double-buffering".)
+ *****************************************************************************/
+static void vout_Display( vout_thread_t *p_vout, picture_t *p_pic )
+{
+    int i_width, i_height, i_x, i_y;
+
+    vout_PlacePicture( p_vout, p_vout->p_sys->i_width, p_vout->p_sys->i_height,
+                       &i_x, &i_y, &i_width, &i_height );
+}
+
+/*****************************************************************************
+ * vout_Manage: handle X11 events
+ *****************************************************************************
+ * This function should be called regularly by video output thread. It manages
+ * X11 events and allows window resizing. It returns a non null value on
+ * error.
+ *****************************************************************************/
+static int vout_Manage( vout_thread_t *p_vout )
+{
+    XEvent      xevent;                                         /* X11 event */
+    boolean_t   b_resized;                        /* window has been resized */
+    char        i_key;                                    /* ISO Latin-1 key */
+    KeySym      x_key_symbol;
+
+    /* Handle X11 events: ConfigureNotify events are parsed to know if the
+     * output window's size changed, MapNotify and UnmapNotify to know if the
+     * window is mapped (and if the display is useful), and ClientMessages
+     * to intercept window destruction requests */
+
+    b_resized = 0;
+    while( XCheckWindowEvent( p_vout->p_sys->p_display, p_vout->p_sys->window,
+                              StructureNotifyMask | KeyPressMask |
+                              ButtonPressMask | ButtonReleaseMask | 
+                              PointerMotionMask | Button1MotionMask , &xevent )
+           == True )
+    {
+        /* ConfigureNotify event: prepare  */
+        if( (xevent.type == ConfigureNotify)
+          && ((xevent.xconfigure.width != p_vout->p_sys->i_width)
+             || (xevent.xconfigure.height != p_vout->p_sys->i_height)) )
+        {
+            /* Update dimensions */
+            b_resized = 1;
+            p_vout->i_changes |= VOUT_SIZE_CHANGE;
+            p_vout->p_sys->i_width = xevent.xconfigure.width;
+            p_vout->p_sys->i_height = xevent.xconfigure.height;
+        }
+        /* MapNotify event: change window status and disable screen saver */
+        else if( xevent.type == MapNotify)
+        {
+            if( (p_vout != NULL) && !p_vout->b_active )
+            {
+                DisableXScreenSaver( p_vout );
+                p_vout->b_active = 1;
+            }
+        }
+        /* UnmapNotify event: change window status and enable screen saver */
+        else if( xevent.type == UnmapNotify )
+        {
+            if( (p_vout != NULL) && p_vout->b_active )
+            {
+                EnableXScreenSaver( p_vout );
+                p_vout->b_active = 0;
+            }
+        }
+        /* Keyboard event */
+        else if( xevent.type == KeyPress )
+        {
+            /* We may have keys like F1 trough F12, ESC ... */
+            x_key_symbol = XKeycodeToKeysym( p_vout->p_sys->p_display,
+                                             xevent.xkey.keycode, 0 );
+            switch( x_key_symbol )
+            {
+                 case XK_Escape:
+                     p_main->p_intf->b_die = 1;
+                     break;
+                 case XK_Menu:
+                     p_main->p_intf->b_menu_change = 1;
+                     break;
+                 case XK_Left:
+                     vout_Seek( -5 );
+                     break;
+                 case XK_Right:
+                     vout_Seek( 5 );
+                     break;
+                 case XK_Up:
+                     vout_Seek( 60 );
+                     break;
+                 case XK_Down:
+                     vout_Seek( -60 );
+                     break;
+                 case XK_Home:
+                     input_Seek( p_input_bank->pp_input[0],
+                     p_input_bank->pp_input[0]->stream.p_selected_area->i_start );
+                     break;
+                 case XK_End:
+                     input_Seek( p_input_bank->pp_input[0],
+                     p_input_bank->pp_input[0]->stream.p_selected_area->i_size );
+                     break;
+                 case XK_Page_Up:
+                     vout_Seek( 900 );
+                     break;
+                 case XK_Page_Down:
+                     vout_Seek( -900 );
+                     break;
+                 case XK_space:
+                     input_SetStatus( p_input_bank->pp_input[0],
+                                      INPUT_STATUS_PAUSE );
+                     break;
+
+                 default:
+                     /* "Normal Keys"
+                      * The reason why I use this instead of XK_0 is that 
+                      * with XLookupString, we don't have to care about
+                      * keymaps. */
+
+                    if( XLookupString( &xevent.xkey, &i_key, 1, NULL, NULL ) )
+                    {
+                        /* FIXME: handle stuff here */
+                        switch( i_key )
+                        {
+                        case 'q':
+                        case 'Q':
+                            p_main->p_intf->b_die = 1;
+                            break;
+                        case 'f':
+                        case 'F':
+                            p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
+                            break;
+
+                        case '0': network_ChannelJoin( 0 ); break;
+                        case '1': network_ChannelJoin( 1 ); break;
+                        case '2': network_ChannelJoin( 2 ); break;
+                        case '3': network_ChannelJoin( 3 ); break;
+                        case '4': network_ChannelJoin( 4 ); break;
+                        case '5': network_ChannelJoin( 5 ); break;
+                        case '6': network_ChannelJoin( 6 ); break;
+                        case '7': network_ChannelJoin( 7 ); break;
+                        case '8': network_ChannelJoin( 8 ); break;
+                        case '9': network_ChannelJoin( 9 ); break;
+
+                        default:
+                            intf_DbgMsg( "vout: unhandled key '%c' (%i)", 
+                                         (char)i_key, i_key );
+                            break;
+                        }
+                    }
+                break;
+            }
+        }
+        /* Mouse click */
+        else if( xevent.type == ButtonPress )
+        {
+            switch( ((XButtonEvent *)&xevent)->button )
+            {
+                case Button1:
+                    /* In this part we will eventually manage
+                     * clicks for DVD navigation for instance. For the
+                     * moment just pause the stream. */
+                    input_SetStatus( p_input_bank->pp_input[0],
+                                     INPUT_STATUS_PAUSE );
+                    break;
+
+                case Button4:
+                    vout_Seek( 15 );
+                    break;
+
+                case Button5:
+                    vout_Seek( -15 );
+                    break;
+            }
+        }
+        /* Mouse release */
+        else if( xevent.type == ButtonRelease )
+        {
+            switch( ((XButtonEvent *)&xevent)->button )
+            {
+                case Button3:
+                    /* FIXME: need locking ! */
+                    p_main->p_intf->b_menu_change = 1;
+                    break;
+            }
+        }
+        /* Mouse move */
+        else if( xevent.type == MotionNotify )
+        {
+            p_vout->p_sys->i_time_mouse_last_moved = mdate();
+            if( ! p_vout->p_sys->b_mouse_pointer_visible )
+            {
+                ToggleCursor( p_vout ); 
+            }
+        }
+        /* Other event */
+        else
+        {
+            intf_WarnMsg( 3, "vout: unhandled event %d received", xevent.type );
+        }
+    }
+
+    /* ClientMessage event - only WM_PROTOCOLS with WM_DELETE_WINDOW data
+     * are handled - according to the man pages, the format is always 32
+     * in this case */
+    while( XCheckTypedEvent( p_vout->p_sys->p_display,
+                             ClientMessage, &xevent ) )
+    {
+        if( (xevent.xclient.message_type == p_vout->p_sys->wm_protocols)
+            && (xevent.xclient.data.l[0] == p_vout->p_sys->wm_delete_window ) )
+        {
+            p_main->p_intf->b_die = 1;
+        }
+        else
+        {
+            intf_DbgMsg( "vout: unhandled ClientMessage received" );
+        }
+    }
+
+    /*
+     * Fullscreen Change
+     */
+    if ( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE )
+    {
+        ToggleFullScreen( p_vout );
+        p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
+
+    }
+
+    /*
+     * Size change
+     */
+    if( p_vout->i_changes & VOUT_SIZE_CHANGE )
+    {
+        int i_width, i_height, i_x, i_y;
+
+        p_vout->i_changes &= ~VOUT_SIZE_CHANGE;
+
+        intf_WarnMsg( 3, "vout: video display resized (%dx%d)",
+                      p_vout->p_sys->i_width,
+                      p_vout->p_sys->i_height );
+        vout_PlacePicture( p_vout, p_vout->p_sys->i_width,
+                           p_vout->p_sys->i_height,
+                           &i_x, &i_y, &i_width, &i_height );
+    }
+
+    /* Autohide Cursour */
+    if( mdate() - p_vout->p_sys->i_time_mouse_last_moved > 2000000 )
+    {
+        /* Hide the mouse automatically */
+        if( p_vout->p_sys->b_mouse_pointer_visible )
+        {
+            ToggleCursor( p_vout ); 
+        }
+    }
+
+    return 0;
+}
+
+/*****************************************************************************
+ * vout_End: terminate X11 video thread output method
+ *****************************************************************************
+ * Destroy the X11 XImages created by vout_Init. It is called at the end of
+ * the thread, but also each time the window is resized.
+ *****************************************************************************/
+static void vout_End( vout_thread_t *p_vout )
+{
+    int i_index;
+
+    /* Free the direct buffers we allocated */
+    for( i_index = I_OUTPUTPICTURES ; i_index ; )
+    {
+        i_index--;
+        FreePicture( p_vout, PP_OUTPUTPICTURE[ i_index ] );
+    }
+}
+
+/* following functions are local */
+
+/*****************************************************************************
+ * CreateWindow: open and set-up X11 main window
+ *****************************************************************************/
+static int CreateWindow( vout_thread_t *p_vout )
+{
+    XSizeHints              xsize_hints;
+    XSetWindowAttributes    xwindow_attributes;
+    XGCValues               xgcvalues;
+    XEvent                  xevent;
+
+    boolean_t               b_expose;
+    boolean_t               b_configure_notify;
+    boolean_t               b_map_notify;
+
+    /* Set main window's size */
+    if( p_vout->render.i_height * p_vout->render.i_aspect
+        >= p_vout->render.i_width * VOUT_ASPECT_FACTOR )
+    {
+        p_vout->p_sys->i_width = p_vout->render.i_height
+          * p_vout->render.i_aspect / VOUT_ASPECT_FACTOR;
+        p_vout->p_sys->i_height = p_vout->render.i_height;
+    }
+    else
+    {
+        p_vout->p_sys->i_width = p_vout->render.i_width;
+        p_vout->p_sys->i_height = p_vout->render.i_width
+          * VOUT_ASPECT_FACTOR / p_vout->render.i_aspect;
+    }
+
+#if 0
+    if( p_vout->p_sys->i_width <= 300 && p_vout->p_sys->i_height <= 300 )
+    {
+        p_vout->p_sys->i_width <<= 1;
+        p_vout->p_sys->i_height <<= 1;
+    }
+    else if( p_vout->p_sys->i_width <= 400
+             && p_vout->p_sys->i_height <= 400 )
+    {
+        p_vout->p_sys->i_width += p_vout->p_sys->i_width >> 1;
+        p_vout->p_sys->i_height += p_vout->p_sys->i_height >> 1;
+    }
+#endif
+
+    /* Prepare window manager hints and properties */
+    xsize_hints.base_width          = p_vout->p_sys->i_width;
+    xsize_hints.base_height         = p_vout->p_sys->i_height;
+    xsize_hints.flags               = PSize;
+    p_vout->p_sys->wm_protocols     = XInternAtom( p_vout->p_sys->p_display,
+                                                   "WM_PROTOCOLS", True );
+    p_vout->p_sys->wm_delete_window = XInternAtom( p_vout->p_sys->p_display,
+                                                   "WM_DELETE_WINDOW", True );
+
+    /* Prepare window attributes */
+    xwindow_attributes.backing_store = Always;       /* save the hidden part */
+    xwindow_attributes.background_pixel = BlackPixel(p_vout->p_sys->p_display,
+                                                     p_vout->p_sys->i_screen);
+    xwindow_attributes.event_mask = ExposureMask | StructureNotifyMask;
+    
+
+    /* Create the window and set hints - the window must receive
+     * ConfigureNotify events, and until it is displayed, Expose and
+     * MapNotify events. */
+
+    p_vout->p_sys->window =
+        XCreateWindow( p_vout->p_sys->p_display,
+                       DefaultRootWindow( p_vout->p_sys->p_display ),
+                       0, 0,
+                       p_vout->p_sys->i_width,
+                       p_vout->p_sys->i_height,
+                       0,
+                       0, InputOutput, 0,
+                       CWBackingStore | CWBackPixel | CWEventMask,
+                       &xwindow_attributes );
+
+    /* Set window manager hints and properties: size hints, command,
+     * window's name, and accepted protocols */
+    XSetWMNormalHints( p_vout->p_sys->p_display, p_vout->p_sys->window,
+                       &xsize_hints );
+    XSetCommand( p_vout->p_sys->p_display, p_vout->p_sys->window,
+                 p_main->ppsz_argv, p_main->i_argc );
+    XStoreName( p_vout->p_sys->p_display, p_vout->p_sys->window,
+                VOUT_TITLE " (XMGA output)"
+              );
+
+    if( (p_vout->p_sys->wm_protocols == None)        /* use WM_DELETE_WINDOW */
+        || (p_vout->p_sys->wm_delete_window == None)
+        || !XSetWMProtocols( p_vout->p_sys->p_display, p_vout->p_sys->window,
+                             &p_vout->p_sys->wm_delete_window, 1 ) )
+    {
+        /* WM_DELETE_WINDOW is not supported by window manager */
+        intf_Msg( "vout error: missing or bad window manager" );
+    } 
+
+    /* Creation of a graphic context that doesn't generate a GraphicsExpose
+     * event when using functions like XCopyArea */
+    xgcvalues.graphics_exposures = False;
+    p_vout->p_sys->gc = XCreateGC( p_vout->p_sys->p_display,
+                                   p_vout->p_sys->window,
+                                   GCGraphicsExposures, &xgcvalues);
+
+    /* Send orders to server, and wait until window is displayed - three
+     * events must be received: a MapNotify event, an Expose event allowing
+     * drawing in the window, and a ConfigureNotify to get the window
+     * dimensions. Once those events have been received, only ConfigureNotify
+     * events need to be received. */
+    b_expose = 0;
+    b_configure_notify = 0;
+    b_map_notify = 0;
+    XMapWindow( p_vout->p_sys->p_display, p_vout->p_sys->window);
+    do
+    {
+        XNextEvent( p_vout->p_sys->p_display, &xevent);
+        if( (xevent.type == Expose)
+            && (xevent.xexpose.window == p_vout->p_sys->window) )
+        {
+            b_expose = 1;
+        }
+        else if( (xevent.type == MapNotify)
+                 && (xevent.xmap.window == p_vout->p_sys->window) )
+        {
+            b_map_notify = 1;
+        }
+        else if( (xevent.type == ConfigureNotify)
+                 && (xevent.xconfigure.window == p_vout->p_sys->window) )
+        {
+            b_configure_notify = 1;
+            p_vout->p_sys->i_width = xevent.xconfigure.width;
+            p_vout->p_sys->i_height = xevent.xconfigure.height;
+        }
+    } while( !( b_expose && b_configure_notify && b_map_notify ) );
+
+    XSelectInput( p_vout->p_sys->p_display, p_vout->p_sys->window,
+                  StructureNotifyMask | KeyPressMask |
+                  ButtonPressMask | ButtonReleaseMask | 
+                  PointerMotionMask );
+
+    /* If the cursor was formerly blank than blank it again */
+    if( !p_vout->p_sys->b_mouse_pointer_visible )
+    {
+        ToggleCursor( p_vout );
+        ToggleCursor( p_vout );
+    }
+
+    XSync( p_vout->p_sys->p_display, False );
+
+    /* At this stage, the window is open, displayed, and ready to
+     * receive data */
+
+    return( 0 );
+}
+
+/*****************************************************************************
+ * DestroyWindow: destroy the window
+ *****************************************************************************
+ *
+ *****************************************************************************/
+static void DestroyWindow( vout_thread_t *p_vout )
+{
+    XSync( p_vout->p_sys->p_display, False );
+
+    XUnmapWindow( p_vout->p_sys->p_display, p_vout->p_sys->window );
+    XFreeGC( p_vout->p_sys->p_display, p_vout->p_sys->gc );
+    XDestroyWindow( p_vout->p_sys->p_display, p_vout->p_sys->window );
+}
+
+/*****************************************************************************
+ * NewPicture: allocate a picture
+ *****************************************************************************
+ * Returns 0 on success, -1 otherwise
+ *****************************************************************************/
+static int NewPicture( vout_thread_t *p_vout, picture_t *p_pic )
+{
+    /* We know the chroma, allocate a buffer which will be used
+     * directly by the decoder */
+    p_pic->p_sys = malloc( sizeof( picture_sys_t ) );
+
+    if( p_pic->p_sys == NULL )
+    {
+        return -1;
+    }
+
+    /* XXX */
+
+    switch( p_vout->output.i_chroma )
+    {
+        /* XXX ?? */
+
+        default:
+            /* Unknown chroma, tell the guy to get lost */
+            free( p_pic->p_sys );
+            intf_ErrMsg( "vout error: never heard of chroma 0x%.8x (%4.4s)",
+                         p_vout->output.i_chroma,
+                         (char*)&p_vout->output.i_chroma );
+            p_pic->i_planes = 0;
+            return -1;
+    }
+
+    return 0;
+}
+
+/*****************************************************************************
+ * FreePicture: destroy a picture allocated with NewPicture
+ *****************************************************************************
+ * Destroy XImage AND associated data. If using Shm, detach shared memory
+ * segment from server and process, then free it. The XDestroyImage manpage
+ * says that both the image structure _and_ the data pointed to by the
+ * image structure are freed, so no need to free p_image->data.
+ *****************************************************************************/
+static void FreePicture( vout_thread_t *p_vout, picture_t *p_pic )
+{
+
+    XSync( p_vout->p_sys->p_display, False );
+
+    free( p_pic->p_sys );
+}
+
+/*****************************************************************************
+ * ToggleFullScreen: Enable or disable full screen mode
+ *****************************************************************************
+ * This function will switch between fullscreen and window mode.
+ *
+ *****************************************************************************/
+static void ToggleFullScreen ( vout_thread_t *p_vout )
+{
+  Atom prop;
+  mwmhints_t mwmhints;
+  int i_xpos, i_ypos, i_width, i_height;
+
+  p_vout->b_fullscreen = !p_vout->b_fullscreen;
+
+  if( p_vout->b_fullscreen )
+  {
+      Window next_parent, parent, *p_dummy, dummy1;
+      unsigned int dummy2, dummy3;
+     
+      intf_WarnMsg( 3, "vout: entering fullscreen mode" );
+
+      /* Save current window coordinates so they can be restored when
+       * we exit from fullscreen mode */
+
+      /* find the real parent, which means the which is a direct child of
+       * the root window */
+      next_parent = parent = p_vout->p_sys->window;
+      while( next_parent != DefaultRootWindow( p_vout->p_sys->p_display ) )
+      {
+          parent = next_parent;
+          XQueryTree( p_vout->p_sys->p_display,
+                      parent,
+                      &dummy1,
+                      &next_parent,
+                      &p_dummy,
+                      &dummy2 );
+          XFree((void *)p_dummy);
+      }
+
+      XGetGeometry( p_vout->p_sys->p_display,
+                    p_vout->p_sys->window,
+                    &dummy1,
+                    &dummy2,
+                    &dummy3,
+                    &p_vout->p_sys->i_width_backup,
+                    &p_vout->p_sys->i_height_backup,
+                    &dummy2, &dummy3 );
+
+      XTranslateCoordinates( p_vout->p_sys->p_display,
+                             parent,
+                             DefaultRootWindow( p_vout->p_sys->p_display ),
+                             0,
+                             0,
+                             &p_vout->p_sys->i_xpos_backup,
+                             &p_vout->p_sys->i_ypos_backup,
+                             &dummy1 );
+
+      mwmhints.flags = MWM_HINTS_DECORATIONS;
+      mwmhints.decorations = 0;
+
+      i_xpos = 0;
+      i_ypos = 0;
+      i_width = DisplayWidth( p_vout->p_sys->p_display,
+                              p_vout->p_sys->i_screen );
+      i_height = DisplayHeight( p_vout->p_sys->p_display,
+                                p_vout->p_sys->i_screen );
+
+#if 0
+      /* Being a transient window allows us to really be fullscreen (display
+       * over the taskbar for instance) but then we end-up with the same
+       * result as with the brute force method */
+      XSetTransientForHint( p_vout->p_sys->p_display,
+                            p_vout->p_sys->window, None );
+#endif
+  }
+  else
+  {
+      intf_WarnMsg( 3, "vout: leaving fullscreen mode" );
+      
+      mwmhints.flags = MWM_HINTS_DECORATIONS;
+      mwmhints.decorations = 1;
+
+      i_xpos = p_vout->p_sys->i_xpos_backup;
+      i_ypos = p_vout->p_sys->i_ypos_backup;
+      i_width = p_vout->p_sys->i_width_backup;
+      i_height = p_vout->p_sys->i_height_backup;
+  }
+
+  /* To my knowledge there are two ways to create a borderless window.
+   * There's the generic way which is to tell x to bypass the window manager,
+   * but this creates problems with the focus of other applications.
+   * The other way is to use the motif property "_MOTIF_WM_HINTS" which
+   * luckily seems to be supported by most window managers.
+   */
+  prop = XInternAtom( p_vout->p_sys->p_display, "_MOTIF_WM_HINTS",
+                      False );
+  XChangeProperty( p_vout->p_sys->p_display, p_vout->p_sys->window,
+                   prop, prop, 32, PropModeReplace,
+                   (unsigned char *)&mwmhints,
+                   PROP_MWM_HINTS_ELEMENTS );
+#if 0 /* brute force way to remove decorations */
+  XSetWindowAttributes attributes;
+  attributes.override_redirect = True;
+  XChangeWindowAttributes( p_vout->p_sys->p_display,
+                           p_vout->p_sys->window,
+                           CWOverrideRedirect,
+                           &attributes);
+#endif
+
+  /* We need to unmap and remap the window if we want the window 
+   * manager to take our changes into effect */
+  XUnmapWindow( p_vout->p_sys->p_display, p_vout->p_sys->window);
+  XMapRaised( p_vout->p_sys->p_display, p_vout->p_sys->window);
+  XMoveResizeWindow( p_vout->p_sys->p_display,
+                     p_vout->p_sys->window,
+                     i_xpos,
+                     i_ypos,
+                     i_width,
+                     i_height );
+  XFlush( p_vout->p_sys->p_display );
+}
+
+/*****************************************************************************
+ * EnableXScreenSaver: enable screen saver
+ *****************************************************************************
+ * This function enables the screen saver on a display after it has been
+ * disabled by XDisableScreenSaver.
+ * FIXME: what happens if multiple vlc sessions are running at the same
+ *        time ???
+ *****************************************************************************/
+static void EnableXScreenSaver( vout_thread_t *p_vout )
+{
+    int dummy;
+
+    intf_DbgMsg( "vout: enabling screen saver" );
+    XSetScreenSaver( p_vout->p_sys->p_display, p_vout->p_sys->i_ss_timeout,
+                     p_vout->p_sys->i_ss_interval,
+                     p_vout->p_sys->i_ss_blanking,
+                     p_vout->p_sys->i_ss_exposure );
+
+    /* Restore DPMS settings */
+    if( DPMSQueryExtension( p_vout->p_sys->p_display, &dummy, &dummy ) )
+    {
+        if( p_vout->p_sys->b_ss_dpms )
+        {
+            DPMSEnable( p_vout->p_sys->p_display );
+        }
+    }
+}
+
+/*****************************************************************************
+ * DisableXScreenSaver: disable screen saver
+ *****************************************************************************
+ * See XEnableXScreenSaver
+ *****************************************************************************/
+static void DisableXScreenSaver( vout_thread_t *p_vout )
+{
+    int dummy;
+
+    /* Save screen saver informations */
+    XGetScreenSaver( p_vout->p_sys->p_display, &p_vout->p_sys->i_ss_timeout,
+                     &p_vout->p_sys->i_ss_interval,
+                     &p_vout->p_sys->i_ss_blanking,
+                     &p_vout->p_sys->i_ss_exposure );
+
+    /* Disable screen saver */
+    intf_DbgMsg( "vout: disabling screen saver" );
+    XSetScreenSaver( p_vout->p_sys->p_display, 0,
+                     p_vout->p_sys->i_ss_interval,
+                     p_vout->p_sys->i_ss_blanking,
+                     p_vout->p_sys->i_ss_exposure );
+
+    /* Disable DPMS */
+    if( DPMSQueryExtension( p_vout->p_sys->p_display, &dummy, &dummy ) )
+    {
+        CARD16 dummy;
+        /* Save DPMS current state */
+        DPMSInfo( p_vout->p_sys->p_display, &dummy,
+                  &p_vout->p_sys->b_ss_dpms );
+        intf_DbgMsg( "vout: disabling DPMS" );
+        DPMSDisable( p_vout->p_sys->p_display );
+   }
+}
+
+/*****************************************************************************
+ * CreateCursor: create a blank mouse pointer
+ *****************************************************************************/
+static void CreateCursor( vout_thread_t *p_vout )
+{
+    XColor cursor_color;
+
+    p_vout->p_sys->cursor_pixmap =
+        XCreatePixmap( p_vout->p_sys->p_display,
+                       DefaultRootWindow( p_vout->p_sys->p_display ),
+                       1, 1, 1 );
+
+    XParseColor( p_vout->p_sys->p_display,
+                 XCreateColormap( p_vout->p_sys->p_display,
+                                  DefaultRootWindow(
+                                                    p_vout->p_sys->p_display ),
+                                  DefaultVisual(
+                                                p_vout->p_sys->p_display,
+                                                p_vout->p_sys->i_screen ),
+                                  AllocNone ),
+                 "black", &cursor_color );
+
+    p_vout->p_sys->blank_cursor =
+        XCreatePixmapCursor( p_vout->p_sys->p_display,
+                             p_vout->p_sys->cursor_pixmap,
+                             p_vout->p_sys->cursor_pixmap,
+                             &cursor_color, &cursor_color, 1, 1 );
+}
+
+/*****************************************************************************
+ * DestroyCursor: destroy the blank mouse pointer
+ *****************************************************************************/
+static void DestroyCursor( vout_thread_t *p_vout )
+{
+    XFreePixmap( p_vout->p_sys->p_display, p_vout->p_sys->cursor_pixmap );
+}
+
+/*****************************************************************************
+ * ToggleCursor: hide or show the mouse pointer
+ *****************************************************************************
+ * This function hides the X pointer if it is visible by setting the pointer
+ * sprite to a blank one. To show it again, we disable the sprite.
+ *****************************************************************************/
+static void ToggleCursor( vout_thread_t *p_vout )
+{
+    if( p_vout->p_sys->b_mouse_pointer_visible )
+    {
+        XDefineCursor( p_vout->p_sys->p_display,
+                       p_vout->p_sys->window,
+                       p_vout->p_sys->blank_cursor );
+        p_vout->p_sys->b_mouse_pointer_visible = 0;
+    }
+    else
+    {
+        XUndefineCursor( p_vout->p_sys->p_display, p_vout->p_sys->window );
+        p_vout->p_sys->b_mouse_pointer_visible = 1;
+    }
+}
+
index d84a262618ca9fedef9209cae9ea40562a3248f1..207c598b04670ff48cfc7bad511229036e145089 100644 (file)
@@ -4,7 +4,7 @@
  * decoders.
  *****************************************************************************
  * Copyright (C) 1998-2001 VideoLAN
  * decoders.
  *****************************************************************************
  * Copyright (C) 1998-2001 VideoLAN
- * $Id: input.c,v 1.168 2002/01/07 02:12:29 sam Exp $
+ * $Id: input.c,v 1.169 2002/01/09 02:01:14 sam Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *
@@ -113,11 +113,15 @@ void input_InitBank ( void )
  *****************************************************************************/
 void input_EndBank ( void )
 {
  *****************************************************************************/
 void input_EndBank ( void )
 {
+    int i_input;
+
     /* Ask all remaining video outputs to die */
     /* Ask all remaining video outputs to die */
-    while( p_input_bank->i_count )
+    for( i_input = 0; i_input < p_input_bank->i_count; i_input++ )
     {
     {
+        input_StopThread(
+                p_input_bank->pp_input[ i_input ], NULL );
         input_DestroyThread(
         input_DestroyThread(
-                p_input_bank->pp_input[ --p_input_bank->i_count ], NULL );
+                p_input_bank->pp_input[ i_input ] );
     }
 
     vlc_mutex_destroy( &p_input_bank->lock );
     }
 
     vlc_mutex_destroy( &p_input_bank->lock );
@@ -134,7 +138,6 @@ void input_EndBank ( void )
 input_thread_t *input_CreateThread ( playlist_item_t *p_item, int *pi_status )
 {
     input_thread_t *    p_input;                        /* thread descriptor */
 input_thread_t *input_CreateThread ( playlist_item_t *p_item, int *pi_status )
 {
     input_thread_t *    p_input;                        /* thread descriptor */
-    int                 i_status;                           /* thread status */
 
     /* Allocate descriptor */
     p_input = (input_thread_t *)malloc( sizeof(input_thread_t) );
 
     /* Allocate descriptor */
     p_input = (input_thread_t *)malloc( sizeof(input_thread_t) );
@@ -146,16 +149,15 @@ input_thread_t *input_CreateThread ( playlist_item_t *p_item, int *pi_status )
     }
 
     /* Initialize thread properties */
     }
 
     /* Initialize thread properties */
-    p_input->b_die              = 0;
-    p_input->b_error            = 0;
-    p_input->b_eof              = 0;
+    p_input->b_die      = 0;
+    p_input->b_error    = 0;
+    p_input->b_eof      = 0;
 
     /* Set target */
 
     /* Set target */
-    p_input->p_source           = p_item->psz_name;
+    p_input->p_source   = p_item->psz_name;
 
 
-    /* I have never understood that stuff --Meuuh */
-    p_input->pi_status          = (pi_status != NULL) ? pi_status : &i_status;
-    *p_input->pi_status         = THREAD_CREATE;
+    /* Set status */
+    p_input->i_status   = THREAD_CREATE;
 
     /* Initialize stream description */
     p_input->stream.i_es_number = 0;
 
     /* Initialize stream description */
     p_input->stream.i_es_number = 0;
@@ -196,6 +198,7 @@ input_thread_t *input_CreateThread ( playlist_item_t *p_item, int *pi_status )
         return( NULL );
     }
 
         return( NULL );
     }
 
+#if 0
     /* If status is NULL, wait until the thread is created */
     if( pi_status == NULL )
     {
     /* If status is NULL, wait until the thread is created */
     if( pi_status == NULL )
     {
@@ -204,36 +207,30 @@ input_thread_t *input_CreateThread ( playlist_item_t *p_item, int *pi_status )
             msleep( THREAD_SLEEP );
         } while( (i_status != THREAD_READY) && (i_status != THREAD_ERROR)
                 && (i_status != THREAD_FATAL) );
             msleep( THREAD_SLEEP );
         } while( (i_status != THREAD_READY) && (i_status != THREAD_ERROR)
                 && (i_status != THREAD_FATAL) );
-        if( i_status != THREAD_READY )
-        {
-            return( NULL );
-        }
     }
     }
+#endif
+
     return( p_input );
 }
 
 /*****************************************************************************
     return( p_input );
 }
 
 /*****************************************************************************
- * input_DestroyThread: mark an input thread as zombie
+ * input_StopThread: mark an input thread as zombie
  *****************************************************************************
  * This function should not return until the thread is effectively cancelled.
  *****************************************************************************/
  *****************************************************************************
  * This function should not return until the thread is effectively cancelled.
  *****************************************************************************/
-void input_DestroyThread( input_thread_t *p_input, int *pi_status )
+void input_StopThread( input_thread_t *p_input, int *pi_status )
 {
 {
-    int         i_status;                                   /* thread status */
-
-    /* Set status */
-    p_input->pi_status = (pi_status != NULL) ? pi_status : &i_status;
-    *p_input->pi_status = THREAD_DESTROY;
+    /* Make the thread exit from a possible vlc_cond_wait() */
+    vlc_mutex_lock( &p_input->stream.stream_lock );
 
     /* Request thread destruction */
     p_input->b_die = 1;
 
 
     /* Request thread destruction */
     p_input->b_die = 1;
 
-    /* Make the thread exit from a possible vlc_cond_wait() */
-    vlc_mutex_lock( &p_input->stream.stream_lock );
     vlc_cond_signal( &p_input->stream.stream_wait );
     vlc_mutex_unlock( &p_input->stream.stream_lock );
 
     /* If status is NULL, wait until thread has been destroyed */
     vlc_cond_signal( &p_input->stream.stream_wait );
     vlc_mutex_unlock( &p_input->stream.stream_lock );
 
     /* If status is NULL, wait until thread has been destroyed */
+#if 0
     if( pi_status == NULL )
     {
         do
     if( pi_status == NULL )
     {
         do
@@ -242,6 +239,25 @@ void input_DestroyThread( input_thread_t *p_input, int *pi_status )
         } while ( (i_status != THREAD_OVER) && (i_status != THREAD_ERROR)
                   && (i_status != THREAD_FATAL) );
     }
         } while ( (i_status != THREAD_OVER) && (i_status != THREAD_ERROR)
                   && (i_status != THREAD_FATAL) );
     }
+#endif
+}
+
+/*****************************************************************************
+ * input_DestroyThread: mark an input thread as zombie
+ *****************************************************************************
+ * This function should not return until the thread is effectively cancelled.
+ *****************************************************************************/
+void input_DestroyThread( input_thread_t *p_input )
+{
+    /* Join the thread */
+    vlc_thread_join( p_input->thread_id );
+
+    /* Destroy Mutex locks */
+    vlc_mutex_destroy( &p_input->stream.control.control_lock );
+    vlc_mutex_destroy( &p_input->stream.stream_lock );
+    
+    /* Free input structure */
+    free( p_input );
 }
 
 /*****************************************************************************
 }
 
 /*****************************************************************************
@@ -254,13 +270,15 @@ static void RunThread( input_thread_t *p_input )
     if( InitThread( p_input ) )
     {
         /* If we failed, wait before we are killed, and exit */
     if( InitThread( p_input ) )
     {
         /* If we failed, wait before we are killed, and exit */
-        *p_input->pi_status = THREAD_ERROR;
+        p_input->i_status = THREAD_ERROR;
         p_input->b_error = 1;
         ErrorThread( p_input );
         DestroyThread( p_input );
         return;
     }
 
         p_input->b_error = 1;
         ErrorThread( p_input );
         DestroyThread( p_input );
         return;
     }
 
+    p_input->i_status = THREAD_READY;
+
     /* initialization is complete */
     vlc_mutex_lock( &p_input->stream.stream_lock );
     p_input->stream.b_changed = 1;
     /* initialization is complete */
     vlc_mutex_lock( &p_input->stream.stream_lock );
     p_input->stream.b_changed = 1;
@@ -507,8 +525,6 @@ static int InitThread( input_thread_t * p_input )
         return( -1 );
     }
 
         return( -1 );
     }
 
-    *p_input->pi_status = THREAD_READY;
-
     return( 0 );
 }
 
     return( 0 );
 }
 
@@ -531,11 +547,8 @@ static void ErrorThread( input_thread_t *p_input )
  *****************************************************************************/
 static void EndThread( input_thread_t * p_input )
 {
  *****************************************************************************/
 static void EndThread( input_thread_t * p_input )
 {
-    int *       pi_status;                                  /* thread status */
-
     /* Store status */
     /* Store status */
-    pi_status = p_input->pi_status;
-    *pi_status = THREAD_END;
+    p_input->i_status = THREAD_END;
 
     if( p_main->b_stats )
     {
 
     if( p_main->b_stats )
     {
@@ -605,20 +618,8 @@ static void CloseThread( input_thread_t * p_input )
  *****************************************************************************/
 static void DestroyThread( input_thread_t * p_input )
 {
  *****************************************************************************/
 static void DestroyThread( input_thread_t * p_input )
 {
-    int *       pi_status;                                  /* thread status */
-
-    /* Store status */
-    pi_status = p_input->pi_status;
-
-    /* Destroy Mutex locks */
-    vlc_mutex_destroy( &p_input->stream.control.control_lock );
-    vlc_mutex_destroy( &p_input->stream.stream_lock );
-    
-    /* Free input structure */
-    free( p_input );
-
     /* Update status */
     /* Update status */
-    *pi_status = THREAD_OVER;
+    p_input->i_status = THREAD_OVER;
 }
 
 /*****************************************************************************
 }
 
 /*****************************************************************************
index d36ba3b27b44d31371b3e998592c556ed0396688..dc78d91f749e0a23b2c8f9d2324aac018f30a9a3 100644 (file)
@@ -4,7 +4,7 @@
  * interface, such as command line.
  *****************************************************************************
  * Copyright (C) 1998-2001 VideoLAN
  * interface, such as command line.
  *****************************************************************************
  * Copyright (C) 1998-2001 VideoLAN
- * $Id: interface.c,v 1.86 2002/01/07 02:12:30 sam Exp $
+ * $Id: interface.c,v 1.87 2002/01/09 02:01:14 sam Exp $
  *
  * Authors: Vincent Seguin <seguin@via.ecp.fr>
  *
  *
  * Authors: Vincent Seguin <seguin@via.ecp.fr>
  *
@@ -128,18 +128,33 @@ static void intf_Manage( intf_thread_t *p_intf )
 
     vlc_mutex_lock( &p_input_bank->lock );
 
 
     vlc_mutex_lock( &p_input_bank->lock );
 
-    if( p_input_bank->i_count 
-         && ( p_input_bank->pp_input[0]->b_error
-               || p_input_bank->pp_input[0]->b_eof ) )
+    if( p_input_bank->i_count )
     {
     {
-        intf_WarnMsg( 3, "intf: input thread destroyed" );
-        input_DestroyThread( p_input_bank->pp_input[0], NULL );
-        p_input_bank->pp_input[0] = NULL;
-        p_input_bank->i_count--;
-    }
+        int i_input;
+        input_thread_t *p_input;
+
+        for( i_input = 0; i_input < p_input_bank->i_count; i_input++ )
+        {
+            p_input = p_input_bank->pp_input[i_input];
+            
+            if( p_input->i_status == THREAD_OVER )
+            {
+                /* XXX: completely stupid ! */
+                input_DestroyThread( p_input );
+                p_input_bank->pp_input[i_input] = NULL;
+                p_input_bank->i_count--;
+            }
+            else if( ( p_input->i_status == THREAD_READY
+                        || p_input->i_status == THREAD_ERROR )
+                     && ( p_input->b_error || p_input->b_eof ) )
+            {
+                input_StopThread( p_input, NULL );
+            }
 
 
+        }
+    }
     /* If no stream is being played, try to find one */
     /* If no stream is being played, try to find one */
-    if( !p_input_bank->i_count && !p_intf->b_die )
+    else
     {
 //        vlc_mutex_lock( &p_main->p_playlist->change_lock );
 
     {
 //        vlc_mutex_lock( &p_main->p_playlist->change_lock );
 
@@ -155,14 +170,20 @@ static void intf_Manage( intf_thread_t *p_intf )
             }
             else
             {
             }
             else
             {
+                input_thread_t *p_input;
+
                 p_main->p_playlist->b_stopped = 0;
                 p_main->p_playlist->i_mode = PLAYLIST_FORWARD + 
                     main_GetIntVariable( PLAYLIST_LOOP_VAR,
                                          PLAYLIST_LOOP_DEFAULT );
                 intf_WarnMsg( 3, "intf: creating new input thread" );
                 p_main->p_playlist->b_stopped = 0;
                 p_main->p_playlist->i_mode = PLAYLIST_FORWARD + 
                     main_GetIntVariable( PLAYLIST_LOOP_VAR,
                                          PLAYLIST_LOOP_DEFAULT );
                 intf_WarnMsg( 3, "intf: creating new input thread" );
-                p_input_bank->pp_input[0] =
-                    input_CreateThread( &p_main->p_playlist->current, NULL );
-                p_input_bank->i_count++;
+                p_input = input_CreateThread( &p_main->p_playlist->current,
+                                              NULL );
+                if( p_input != NULL )
+                {
+                    p_input_bank->pp_input[ p_input_bank->i_count ] = p_input;
+                    p_input_bank->i_count++;
+                }
             }
         }
         else
             }
         }
         else
diff --git a/src/interface/intf_eject.c b/src/interface/intf_eject.c
new file mode 100644 (file)
index 0000000..8111436
--- /dev/null
@@ -0,0 +1,182 @@
+/*****************************************************************************
+ * intf_eject.c: CD/DVD-ROM ejection handling functions
+ *****************************************************************************
+ * Copyright (C) 2001, 2002 VideoLAN
+ * $Id: intf_eject.c,v 1.1 2002/01/09 02:01:14 sam Exp $
+ *
+ * Author: Julien Blache <jb@technologeek.org> for the Linux part
+ *               with code taken from the Linux "eject" command
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <videolan/vlc.h>
+
+#ifdef SYS_LINUX
+
+/* This code could be extended to support CD/DVD-ROM chargers */
+#   include <linux/version.h>
+    /* handy macro found in 2.1 kernels, but not in older ones */
+#   ifndef KERNEL_VERSION
+#       define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
+#   endif
+
+#   include <sys/types.h>
+#   include <sys/stat.h>
+#   include <sys/ioctl.h>
+#   include <fcntl.h>
+
+#   include <sys/ioctl.h>
+#   include <linux/cdrom.h>
+#   if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
+#       include <linux/ucdrom.h>
+#   endif
+
+#   include <sys/mount.h>
+#   include <scsi/scsi.h>
+#   include <scsi/sg.h>
+#   include <scsi/scsi_ioctl.h>
+
+#endif
+
+static int EjectCdrom( int i_fd );
+static int EjectScsi ( int i_fd );
+
+/*
+ * Eject using CDROMEJECT ioctl. Return 0 if successful
+ */
+static int EjectCdrom( int i_fd )
+{
+    int i_status;
+  
+    i_status = ioctl( i_fd, CDROMEJECT );
+  
+    return i_status;
+}
+
+
+/*
+ * Eject using SCSI commands. Return 0 if successful
+ */
+static int EjectScsi( int i_fd )
+{
+    int i_status;
+
+    struct sdata
+    {
+        int  inlen;
+        int  outlen;
+        char cmd[256];
+    } scsi_cmd;
+
+    scsi_cmd.inlen  = 0;
+    scsi_cmd.outlen = 0;
+    scsi_cmd.cmd[0] = ALLOW_MEDIUM_REMOVAL;
+    scsi_cmd.cmd[1] = 0;
+    scsi_cmd.cmd[2] = 0;
+    scsi_cmd.cmd[3] = 0;
+    scsi_cmd.cmd[4] = 0;
+    scsi_cmd.cmd[5] = 0;
+    i_status = ioctl( i_fd, SCSI_IOCTL_SEND_COMMAND, (void *)&scsi_cmd );
+    if( i_status != 0 )
+    {
+        return 1;
+    }
+
+    scsi_cmd.inlen  = 0;
+    scsi_cmd.outlen = 0;
+    scsi_cmd.cmd[0] = START_STOP;
+    scsi_cmd.cmd[1] = 0;
+    scsi_cmd.cmd[2] = 0;
+    scsi_cmd.cmd[3] = 0;
+    scsi_cmd.cmd[4] = 1;
+    scsi_cmd.cmd[5] = 0;
+    i_status = ioctl( i_fd, SCSI_IOCTL_SEND_COMMAND, (void *)&scsi_cmd );
+    if( i_status != 0 )
+    {
+        return 1;
+    }
+  
+    scsi_cmd.inlen  = 0;
+    scsi_cmd.outlen = 0;
+    scsi_cmd.cmd[0] = START_STOP;
+    scsi_cmd.cmd[1] = 0;
+    scsi_cmd.cmd[2] = 0;
+    scsi_cmd.cmd[3] = 0;
+    scsi_cmd.cmd[4] = 2;
+    scsi_cmd.cmd[5] = 0;
+    i_status = ioctl( i_fd, SCSI_IOCTL_SEND_COMMAND, (void *)&scsi_cmd );
+    if( i_status != 0 )
+    {
+        return 1;
+    }
+  
+    /* Force kernel to reread partition table when new disc inserted */
+    i_status = ioctl( i_fd, BLKRRPART );
+  
+    return i_status;
+}
+
+/*
+ * returns 0 on success
+ * returns 1 on failure
+ * returns -1 if not implemented
+ *
+ * Modify eject_disc() prototype as needed for portability
+ */
+
+int intf_Eject( const char *psz_device )
+{
+  int i_ret;
+
+#ifdef SYS_LINUX
+  int i_fd = 0;
+
+   i_fd = open( psz_device, O_RDONLY | O_NONBLOCK );
+   
+   if( i_fd == -1 )
+   {
+       intf_ErrMsg( "intf error: couldn't open device %s", psz_device );
+       return 1;
+   }
+
+   if( EjectCdrom(i_fd) == 0 )
+   {
+       i_ret = 0;
+   }
+   else if( EjectScsi(i_fd) == 0 )
+   {
+       i_ret = 0;
+   }
+   else
+   {
+       intf_ErrMsg( "intf error: couldn't eject %s", psz_device );
+       i_ret = 1;
+   }
+
+   close( i_fd );
+
+#else
+   i_ret = -1;
+
+#endif
+   return i_ret;
+}
+
index 4fc8c56f5891673e807afa0d9f3c90d0935ccfe6..d617f2675e89b7b78ff22d861620f1ed9a699cff 100644 (file)
@@ -2,7 +2,7 @@
  * modules.c : Built-in and plugin modules management functions
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
  * modules.c : Built-in and plugin modules management functions
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: modules.c,v 1.46 2001/12/30 07:09:56 sam Exp $
+ * $Id: modules.c,v 1.47 2002/01/09 02:01:14 sam Exp $
  *
  * Authors: Samuel Hocevar <sam@zoy.org>
  *          Ethan C. Baldridge <BaldridgeE@cadmus.com>
  *
  * Authors: Samuel Hocevar <sam@zoy.org>
  *          Ethan C. Baldridge <BaldridgeE@cadmus.com>
@@ -54,6 +54,7 @@
 
 #include "interface.h"
 #include "intf_playlist.h"
 
 #include "interface.h"
 #include "intf_playlist.h"
+#include "intf_eject.h"
 
 #include "stream_control.h"
 #include "input_ext-intf.h"
 
 #include "stream_control.h"
 #include "input_ext-intf.h"
index da0f2211138e874d0de78beef84ea762955d40bb..0535ca08830d4a2c4fb8c8b832bbee5fcfd27008 100644 (file)
@@ -2,7 +2,7 @@
  * modules_plugin.h : Plugin management functions used by the core application.
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
  * modules_plugin.h : Plugin management functions used by the core application.
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: modules_plugin.h,v 1.3 2002/01/07 02:12:30 sam Exp $
+ * $Id: modules_plugin.h,v 1.4 2002/01/09 02:01:14 sam Exp $
  *
  * Authors: Samuel Hocevar <sam@zoy.org>
  *
  *
  * Authors: Samuel Hocevar <sam@zoy.org>
  *
@@ -174,6 +174,7 @@ module_error( void )
     (p_symbols)->intf_PlaylistDestroy = intf_PlaylistDestroy; \
     (p_symbols)->intf_PlaylistJumpto = intf_PlaylistJumpto; \
     (p_symbols)->intf_UrlDecode = intf_UrlDecode; \
     (p_symbols)->intf_PlaylistDestroy = intf_PlaylistDestroy; \
     (p_symbols)->intf_PlaylistJumpto = intf_PlaylistJumpto; \
     (p_symbols)->intf_UrlDecode = intf_UrlDecode; \
+    (p_symbols)->intf_Eject = intf_Eject; \
     (p_symbols)->msleep = msleep; \
     (p_symbols)->mdate = mdate; \
     (p_symbols)->network_ChannelCreate = network_ChannelCreate; \
     (p_symbols)->msleep = msleep; \
     (p_symbols)->mdate = mdate; \
     (p_symbols)->network_ChannelCreate = network_ChannelCreate; \