familiar.c 7.07 KB
Newer Older
1 2 3 4
/*****************************************************************************
 * familiar.c : familiar plugin for vlc
 *****************************************************************************
 * Copyright (C) 2002 VideoLAN
5
 * $Id: familiar.c,v 1.7 2002/07/31 20:56:51 sam Exp $
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
 *
 * Authors: Jean-Paul Saman <jpsaman@wxs.nl>
 *
 * 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 <stdlib.h>                                      /* malloc(), free() */
#include <errno.h>                                                 /* ENOMEM */
#include <string.h>                                            /* strerror() */
#include <stdio.h>

#include <vlc/vlc.h>
#include <vlc/intf.h>

#include <gtk/gtk.h>

#include "familiar_callbacks.h"
#include "familiar_interface.h"
#include "familiar_support.h"
#include "familiar.h"

42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
/*****************************************************************************
 * Local variables (mutex-protected).
 *****************************************************************************/
static void ** pp_global_data = NULL;

/*****************************************************************************
 * g_atexit: kludge to avoid the Gtk+ thread to segfault at exit
 *****************************************************************************
 * gtk_init() makes several calls to g_atexit() which calls atexit() to
 * register tidying callbacks to be called at program exit. Since the Gtk+
 * plugin is likely to be unloaded at program exit, we have to export this
 * symbol to intercept the g_atexit() calls. Talk about crude hack.
 *****************************************************************************/
void g_atexit( GVoidFunc func )
{
    intf_thread_t *p_intf;

    int i_dummy;

    if( pp_global_data == NULL )
    {
        atexit( func );
        return;
    }

    p_intf = (intf_thread_t *)*pp_global_data;
    if( p_intf == NULL )
    {
        return;
    }

    for( i_dummy = 0;
         i_dummy < MAX_ATEXIT && p_intf->p_sys->pf_callback[i_dummy] != NULL;
         i_dummy++ )
    {
        ;
    }

    if( i_dummy >= MAX_ATEXIT - 1 )
    {
        msg_Err( p_intf, "too many atexit() callbacks to register" );
        return;
    }

    p_intf->p_sys->pf_callback[i_dummy]     = func;
    p_intf->p_sys->pf_callback[i_dummy + 1] = NULL;
}

90 91 92
/*****************************************************************************
 * Local prototypes.
 *****************************************************************************/
93 94
static int  Open         ( vlc_object_t * );
static void Close        ( vlc_object_t * );             
95

96
static void Run          ( intf_thread_t * );                  
97 98

/*****************************************************************************
99
 * Module descriptor
100
 *****************************************************************************/
101 102 103 104 105
vlc_module_begin();
    set_description( _("Familiar Linux Gtk+ interface module") );
    set_capability( "interface", 70 );
    set_callbacks( Open, Close );
vlc_module_end();
106 107

/*****************************************************************************
108
 * Open: initialize and create window
109
 *****************************************************************************/
110 111 112 113
static int Open( vlc_object_t *p_this )
{   
    intf_thread_t *p_intf = (intf_thread_t *)p_this;

114 115 116 117 118 119 120 121 122 123 124
    /* Allocate instance and initialize some members */
    p_intf->p_sys = malloc( sizeof( intf_sys_t ) );
    if( p_intf->p_sys == NULL )
    {
        msg_Err( p_intf, "out of memory" );
        return( 1 );
    }

    /* Initialize Gtk+ thread */
    p_intf->p_sys->p_input = NULL;

125 126
    p_intf->pf_run = Run;

127 128 129 130
    return( 0 );
}

/*****************************************************************************
131
 * Close: destroy interface window
132
 *****************************************************************************/
133 134 135 136
static void Close( vlc_object_t *p_this )
{   
    intf_thread_t *p_intf = (intf_thread_t *)p_this;

137 138 139 140 141 142 143 144 145 146
    if( p_intf->p_sys->p_input )
    {
        vlc_object_release( p_intf->p_sys->p_input );
    }

    /* Destroy structure */
    if (p_intf->p_sys) free( p_intf->p_sys );
}

/*****************************************************************************
147
 * Run: Gtk+ thread
148 149 150 151 152 153
 *****************************************************************************
 * this part of the interface is in a separate thread so that we can call
 * gtk_main() from within it without annoying the rest of the program.
 * XXX: the approach may look kludgy, and probably is, but I could not find
 * a better way to dynamically load a Gtk+ interface at runtime.
 *****************************************************************************/
154
static void Run( intf_thread_t *p_intf )
155 156 157 158 159 160
{
    /* gtk_init needs to know the command line. We don't care, so we
     * give it an empty one */
    char  *p_args[] = { "" };
    char **pp_args  = p_args;
    int    i_args   = 1;
161
    int    i_dummy  = 0;
162 163

    /* Initialize Gtk+ */
164
    gtk_set_locale ();
165 166 167 168 169 170 171 172 173

    /* gtk_init will register stuff with g_atexit, so we need to take
     * the global lock if we want to be able to intercept the calls */
    vlc_mutex_lock( p_intf->p_vlc->p_global_lock );
    *p_intf->p_vlc->pp_global_data = p_intf;
    gtk_init( &i_args, &pp_args );
    vlc_mutex_unlock( p_intf->p_vlc->p_global_lock );

    /* Create some useful widgets that will certainly be used */
174
// FIXME: magic path
175
    add_pixmap_directory("share");
176
    p_intf->p_sys->p_window = create_familiar();
177 178 179 180
    if (p_intf->p_sys->p_window == NULL)
    {
        msg_Err( p_intf, "unable to create familiar interface" );
    }
181 182 183

    /* Set the title of the main window */
    gtk_window_set_title( GTK_WINDOW(p_intf->p_sys->p_window),
184
                          VOUT_TITLE " (Familiar Linux interface)");
185

Jean-Paul Saman's avatar
Jean-Paul Saman committed
186 187 188 189 190
    /* Get the slider object */
    p_intf->p_sys->p_notebook = GTK_NOTEBOOK( gtk_object_get_data(
        GTK_OBJECT( p_intf->p_sys->p_window ), "notebook" ) );
//    gtk_widget_hide( GTK_WIDGET(p_intf->p_sys->p_notebook) );

191 192 193 194 195 196 197 198 199 200 201 202 203
    /* Store p_intf to keep an eye on it */
    gtk_object_set_data( GTK_OBJECT(p_intf->p_sys->p_window),
                         "p_intf", p_intf );
    /* Show the control window */
    gtk_widget_show( p_intf->p_sys->p_window );

    /* Enter Gtk mode */
    gtk_main();

    /* Remove the timeout */
    gtk_timeout_remove( i_dummy );
}