Familiar Linux interface (non functional yet).
authorJean-Paul Saman <jpsaman@videolan.org>
Mon, 22 Jul 2002 13:49:42 +0000 (13:49 +0000)
committerJean-Paul Saman <jpsaman@videolan.org>
Mon, 22 Jul 2002 13:49:42 +0000 (13:49 +0000)
plugins/familiar/Makefile [new file with mode: 0644]
plugins/familiar/familiar.c [new file with mode: 0644]
plugins/familiar/familiar.glade [new file with mode: 0644]
plugins/familiar/familiar.h [new file with mode: 0644]
plugins/familiar/familiar_callbacks.c [new file with mode: 0644]
plugins/familiar/familiar_callbacks.h [new file with mode: 0644]
plugins/familiar/familiar_interface.c [new file with mode: 0644]
plugins/familiar/familiar_interface.h [new file with mode: 0644]
plugins/familiar/familiar_support.c [new file with mode: 0644]
plugins/familiar/familiar_support.h [new file with mode: 0644]

diff --git a/plugins/familiar/Makefile b/plugins/familiar/Makefile
new file mode 100644 (file)
index 0000000..816f76d
--- /dev/null
@@ -0,0 +1 @@
+familiar_SOURCES = familiar.c familiar_interface.c familiar_support.c familiar_callbacks.c
\ No newline at end of file
diff --git a/plugins/familiar/familiar.c b/plugins/familiar/familiar.c
new file mode 100644 (file)
index 0000000..d0446b4
--- /dev/null
@@ -0,0 +1,496 @@
+/*****************************************************************************
+ * familiar.c : familiar plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 2002 VideoLAN
+ * $Id: familiar.c,v 1.1 2002/07/22 13:49:42 jpsaman Exp $
+ *
+ * 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"
+
+/*****************************************************************************
+ * Local prototypes.
+ *****************************************************************************/
+static void intf_getfunctions ( function_list_t * p_function_list );
+static int  intf_Open         ( intf_thread_t *p_intf );
+static void intf_Close        ( intf_thread_t *p_intf );
+static void intf_Run          ( intf_thread_t *p_intf );
+
+static gint GtkManage         ( gpointer p_data );
+
+/*****************************************************************************
+ * Local variables (mutex-protected).
+ *****************************************************************************/
+static void ** pp_global_data = NULL;
+
+/*****************************************************************************
+ * Building configuration tree
+ *****************************************************************************/
+#define TOOLTIPS_TEXT N_("show tooltips")
+#define TOOLTIPS_LONGTEXT N_("Show tooltips for configuration options.")
+
+#define TOOLBAR_TEXT N_("show text on toolbar buttons")
+#define TOOLBAR_LONGTEXT N_("Show the text below icons on the toolbar.")
+
+MODULE_CONFIG_START
+ADD_CATEGORY_HINT( N_("Miscellaneous"), NULL )
+ADD_BOOL   ( "familiar-tooltips", 1, NULL /*GtkHideTooltips*/, TOOLTIPS_TEXT,
+             TOOLTIPS_LONGTEXT )
+ADD_BOOL   ( "familiar-toolbartext", 1, NULL /*GtkHideToolbarText*/, TOOLBAR_TEXT,
+             TOOLBAR_LONGTEXT )
+MODULE_CONFIG_STOP
+
+MODULE_INIT_START
+    pp_global_data = p_module->p_vlc->pp_global_data;
+    SET_DESCRIPTION( _("Familiar Linux Gtk+ interface module") )
+    ADD_CAPABILITY( INTF, 90 )
+MODULE_INIT_STOP
+
+MODULE_ACTIVATE_START
+    intf_getfunctions( &p_module->p_functions->intf );
+MODULE_ACTIVATE_STOP
+
+MODULE_DEACTIVATE_START
+MODULE_DEACTIVATE_STOP
+
+/*****************************************************************************
+ * 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;
+}
+
+/*****************************************************************************
+ * Functions exported as capabilities. They are declared as static so that
+ * we don't pollute the namespace too much.
+ *****************************************************************************/
+static void intf_getfunctions( function_list_t * p_function_list )
+{
+    p_function_list->functions.intf.pf_open  = intf_Open;
+    p_function_list->functions.intf.pf_close = intf_Close;
+    p_function_list->functions.intf.pf_run   = intf_Run;
+}
+
+/*****************************************************************************
+ * intf_Open: initialize and create window
+ *****************************************************************************/
+static int intf_Open( intf_thread_t *p_intf )
+{
+    /* 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 );
+    }
+
+    p_intf->p_sys->p_sub = msg_Subscribe( p_intf );
+
+    /* Initialize Gtk+ thread */
+    p_intf->p_sys->b_playing = 0;
+    p_intf->p_sys->b_popup_changed = 0;
+    p_intf->p_sys->b_window_changed = 0;
+    p_intf->p_sys->b_playlist_changed = 0;
+
+    p_intf->p_sys->p_input = NULL;
+    p_intf->p_sys->i_playing = -1;
+    p_intf->p_sys->b_slider_free = 1;
+
+    p_intf->p_sys->pf_callback[0] = NULL;
+
+    p_intf->p_sys->i_part = 0;
+
+    return( 0 );
+}
+
+/*****************************************************************************
+ * intf_Close: destroy interface window
+ *****************************************************************************/
+static void intf_Close( intf_thread_t *p_intf )
+{
+    if( p_intf->p_sys->p_input )
+    {
+        vlc_object_release( p_intf->p_sys->p_input );
+    }
+
+    msg_Unsubscribe( p_intf, p_intf->p_sys->p_sub );
+
+    /* Destroy structure */
+    if (p_intf->p_sys) free( p_intf->p_sys );
+}
+
+/*****************************************************************************
+ * intf_Run: Gtk+ thread
+ *****************************************************************************
+ * 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.
+ *****************************************************************************/
+static void intf_Run( intf_thread_t *p_intf )
+{
+    /* 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;
+    int    i_dummy;
+
+    /* The data types we are allowed to receive */
+    static GtkTargetEntry target_table[] =
+    {
+        { "STRING", 0, DROP_ACCEPT_STRING },
+        { "text/uri-list", 0, DROP_ACCEPT_TEXT_URI_LIST },
+        { "text/plain", 0, DROP_ACCEPT_TEXT_PLAIN }
+    };
+
+    /* Initialize Gtk+ */
+
+    /* 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 */
+    p_intf->p_sys->p_window = create_familiar();
+//    p_intf->p_sys->p_popup = create_intf_popup();
+//    p_intf->p_sys->p_playwin = create_intf_playlist();
+//    p_intf->p_sys->p_messages = create_intf_messages();
+//    p_intf->p_sys->p_tooltips = gtk_tooltips_new();
+
+    /* Set the title of the main window */
+    gtk_window_set_title( GTK_WINDOW(p_intf->p_sys->p_window),
+                          VOUT_TITLE " (Familiar interface)");
+
+    /* Accept file drops on the main window */
+    gtk_drag_dest_set( GTK_WIDGET( p_intf->p_sys->p_window ),
+                       GTK_DEST_DEFAULT_ALL, target_table,
+                       1, GDK_ACTION_COPY );
+
+    /* Accept file drops on the playlist window */
+    gtk_drag_dest_set( GTK_WIDGET( lookup_widget( p_intf->p_sys->p_playwin,
+                                   "playlist_clist") ),
+                       GTK_DEST_DEFAULT_ALL, target_table,
+                       1, GDK_ACTION_COPY );
+
+    /* Get the slider object */
+    p_intf->p_sys->p_slider_frame = GTK_FRAME( gtk_object_get_data(
+        GTK_OBJECT( p_intf->p_sys->p_window ), "progress" ) );
+
+    /* Configure the log window */
+//    p_intf->p_sys->p_messages_text = GTK_TEXT( gtk_object_get_data(
+//        GTK_OBJECT(p_intf->p_sys->p_messages ), "messages_textbox" ) );
+//    gtk_text_set_line_wrap( p_intf->p_sys->p_messages_text, TRUE);
+//    gtk_text_set_word_wrap( p_intf->p_sys->p_messages_text, FALSE);
+
+    /* Get the interface labels */
+#define P_LABEL( name ) GTK_LABEL( gtk_object_get_data( \
+                         GTK_OBJECT( p_intf->p_sys->p_window ), name ) )
+    p_intf->p_sys->p_label_title = P_LABEL( "title_label" );
+    p_intf->p_sys->p_label_chapter = P_LABEL( "chapter_label" );
+#undef P_LABEL
+
+    /* Connect the date display to the slider */
+#define P_SLIDER GTK_RANGE( gtk_object_get_data( \
+                         GTK_OBJECT( p_intf->p_sys->p_window ), "slider" ) )
+    p_intf->p_sys->p_adj = gtk_range_get_adjustment( P_SLIDER );
+
+    gtk_signal_connect ( GTK_OBJECT( p_intf->p_sys->p_adj ), "value_changed",
+                         GTK_SIGNAL_FUNC( GtkDisplayDate ), NULL );
+    p_intf->p_sys->f_adj_oldvalue = 0;
+#undef P_SLIDER
+
+    /* We don't create these ones yet because we perhaps won't need them */
+    p_intf->p_sys->p_about = NULL;
+    p_intf->p_sys->p_modules = NULL;
+    p_intf->p_sys->p_open = NULL;
+    p_intf->p_sys->p_jump = NULL;
+
+    /* Hide tooltips if the option is set */
+    if( !config_GetInt( p_intf, "gtk-tooltips" ) )
+    {
+        gtk_tooltips_disable( p_intf->p_sys->p_tooltips );
+    }
+
+    /* 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 );
+
+    gtk_object_set_data( GTK_OBJECT(p_intf->p_sys->p_popup),
+                         "p_intf", p_intf );
+
+    gtk_object_set_data( GTK_OBJECT( p_intf->p_sys->p_playwin ),
+                         "p_intf", p_intf );
+
+    gtk_object_set_data( GTK_OBJECT( p_intf->p_sys->p_messages ),
+                         "p_intf", p_intf );
+
+    gtk_object_set_data( GTK_OBJECT(p_intf->p_sys->p_adj),
+                         "p_intf", p_intf );
+
+    /* Show the control window */
+    gtk_widget_show( p_intf->p_sys->p_window );
+
+    /* Sleep to avoid using all CPU - since some interfaces needs to access
+     * keyboard events, a 100ms delay is a good compromise */
+    i_dummy = gtk_timeout_add( INTF_IDLE_SLEEP / 1000, GtkManage, p_intf );
+
+    /* Enter Gtk mode */
+    gtk_main();
+
+    /* Remove the timeout */
+    gtk_timeout_remove( i_dummy );
+
+    /* Destroy the Tooltips structure */
+    gtk_object_destroy( GTK_OBJECT(p_intf->p_sys->p_tooltips) );
+
+    /* Launch stored callbacks */
+    for( i_dummy = 0;
+         i_dummy < MAX_ATEXIT && p_intf->p_sys->pf_callback[i_dummy] != NULL;
+         i_dummy++ )
+    {
+        p_intf->p_sys->pf_callback[i_dummy]();
+    }
+}
+
+/* following functions are local */
+
+/*****************************************************************************
+ * GtkManage: manage main thread messages
+ *****************************************************************************
+ * In this function, called approx. 10 times a second, we check what the
+ * main program wanted to tell us.
+ *****************************************************************************/
+static gint GtkManage( gpointer p_data )
+{
+#define p_intf ((intf_thread_t *)p_data)
+    int i_start, i_stop;
+
+    vlc_mutex_lock( &p_intf->change_lock );
+
+    /* If the "display popup" flag has changed */
+    if( p_intf->b_menu_change )
+    {
+        if( !GTK_IS_WIDGET( p_intf->p_sys->p_popup ) )
+        {
+            p_intf->p_sys->p_popup = create_intf_popup();
+            gtk_object_set_data( GTK_OBJECT( p_intf->p_sys->p_popup ),
+                                 "p_intf", p_intf );
+        }
+        gtk_menu_popup( GTK_MENU( p_intf->p_sys->p_popup ),
+                        NULL, NULL, NULL, NULL, 0, GDK_CURRENT_TIME );
+        p_intf->b_menu_change = 0;
+    }
+
+    /* Update the log window */
+    vlc_mutex_lock( p_intf->p_sys->p_sub->p_lock );
+    i_stop = *p_intf->p_sys->p_sub->pi_stop;
+    vlc_mutex_unlock( p_intf->p_sys->p_sub->p_lock );
+
+    if( p_intf->p_sys->p_sub->i_start != i_stop )
+    {
+        static GdkColor white  = { 0, 0xffff, 0xffff, 0xffff };
+        static GdkColor gray   = { 0, 0xaaaa, 0xaaaa, 0xaaaa };
+        static GdkColor yellow = { 0, 0xffff, 0xffff, 0x6666 };
+        static GdkColor red    = { 0, 0xffff, 0x6666, 0x6666 };
+
+        static const char * ppsz_type[4] = { ": ", " error: ", " warning: ",
+                                             " debug: " };
+        static GdkColor *   pp_color[4] = { &white, &red, &yellow, &gray };
+
+        for( i_start = p_intf->p_sys->p_sub->i_start;
+             i_start != i_stop;
+             i_start = (i_start+1) % VLC_MSG_QSIZE )
+        {
+            /* Append all messages to log window */
+            gtk_text_insert( p_intf->p_sys->p_messages_text, NULL, &gray,
+             NULL, p_intf->p_sys->p_sub->p_msg[i_start].psz_module, -1 );
+
+            gtk_text_insert( p_intf->p_sys->p_messages_text, NULL, &gray,
+                NULL, ppsz_type[p_intf->p_sys->p_sub->p_msg[i_start].i_type],
+                -1 );
+
+            gtk_text_insert( p_intf->p_sys->p_messages_text, NULL,
+                pp_color[p_intf->p_sys->p_sub->p_msg[i_start].i_type], NULL,
+                p_intf->p_sys->p_sub->p_msg[i_start].psz_msg, -1 );
+
+            gtk_text_insert( p_intf->p_sys->p_messages_text, NULL, &gray,
+                NULL, "\n", -1 );
+        }
+
+        vlc_mutex_lock( p_intf->p_sys->p_sub->p_lock );
+        p_intf->p_sys->p_sub->i_start = i_start;
+        vlc_mutex_unlock( p_intf->p_sys->p_sub->p_lock );
+
+        gtk_text_set_point( p_intf->p_sys->p_messages_text,
+                    gtk_text_get_length( p_intf->p_sys->p_messages_text ) );
+    }
+
+    /* Update the playlist */
+    GtkPlayListManage( p_data );
+
+    /* Update the input */
+    if( p_intf->p_sys->p_input == NULL )
+    {
+        p_intf->p_sys->p_input = vlc_object_find( p_intf, VLC_OBJECT_INPUT,
+                                                          FIND_ANYWHERE );
+    }
+    else if( p_intf->p_sys->p_input->b_dead )
+    {
+        vlc_object_release( p_intf->p_sys->p_input );
+        p_intf->p_sys->p_input = NULL;
+    }
+
+    if( p_intf->p_sys->p_input )
+    {
+        input_thread_t *p_input = p_intf->p_sys->p_input;
+
+        vlc_mutex_lock( &p_input->stream.stream_lock );
+
+        if( !p_input->b_die )
+        {
+            /* New input or stream map change */
+            if( p_input->stream.b_changed )
+            {
+                GtkModeManage( p_intf );
+                GtkSetupMenus( p_intf );
+                p_intf->p_sys->b_playing = 1;
+            }
+
+            /* Manage the slider */
+            if( p_input->stream.b_seekable && p_intf->p_sys->b_playing )
+            {
+                float newvalue = p_intf->p_sys->p_adj->value;
+
+#define p_area p_input->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;
+
+                    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;
+
+                    /* release the lock to be able to seek */
+                    vlc_mutex_unlock( &p_input->stream.stream_lock );
+                    input_Seek( p_input, i_seek, INPUT_SEEK_SET );
+                    vlc_mutex_lock( &p_input->stream.stream_lock );
+
+                    /* Update the old value */
+                    p_intf->p_sys->f_adj_oldvalue = newvalue;
+                }
+#undef p_area
+            }
+
+            if( p_intf->p_sys->i_part !=
+                p_input->stream.p_selected_area->i_part )
+            {
+                p_intf->p_sys->b_chapter_update = 1;
+                GtkSetupMenus( p_intf );
+            }
+        }
+
+        vlc_mutex_unlock( &p_input->stream.stream_lock );
+    }
+    else if( p_intf->p_sys->b_playing && !p_intf->b_die )
+    {
+        GtkModeManage( p_intf );
+        p_intf->p_sys->b_playing = 0;
+    }
+
+    if( p_intf->b_die )
+    {
+        vlc_mutex_unlock( &p_intf->change_lock );
+
+        /* Prepare to die, young Skywalker */
+        gtk_main_quit();
+
+        /* Just in case */
+        return( FALSE );
+    }
+
+    vlc_mutex_unlock( &p_intf->change_lock );
+
+    return( TRUE );
+
+#undef p_intf
+}
diff --git a/plugins/familiar/familiar.glade b/plugins/familiar/familiar.glade
new file mode 100644 (file)
index 0000000..1272aa4
--- /dev/null
@@ -0,0 +1,288 @@
+<?xml version="1.0"?>
+<GTK-Interface>
+
+<project>
+  <name>Familiar</name>
+  <program_name>familiar</program_name>
+  <directory></directory>
+  <source_directory>src</source_directory>
+  <pixmaps_directory>share</pixmaps_directory>
+  <language>C</language>
+  <gnome_support>False</gnome_support>
+  <gettext_support>True</gettext_support>
+  <main_source_file>familiar_interface.c</main_source_file>
+  <main_header_file>familiar_interface.h</main_header_file>
+  <handler_source_file>familiar_callbacks.c</handler_source_file>
+  <handler_header_file>familiar_callbacks.h</handler_header_file>
+  <support_source_file>familiar_support.c</support_source_file>
+  <support_header_file>familiar_support.h</support_header_file>
+</project>
+
+<widget>
+  <class>GtkWindow</class>
+  <name>familiar</name>
+  <width>240</width>
+  <height>320</height>
+  <title>vlc (familiar)</title>
+  <type>GTK_WINDOW_TOPLEVEL</type>
+  <position>GTK_WIN_POS_NONE</position>
+  <modal>False</modal>
+  <allow_shrink>False</allow_shrink>
+  <allow_grow>False</allow_grow>
+  <auto_shrink>False</auto_shrink>
+
+  <widget>
+    <class>GtkVBox</class>
+    <name>vbox</name>
+    <homogeneous>False</homogeneous>
+    <spacing>0</spacing>
+
+    <widget>
+      <class>GtkToolbar</class>
+      <name>toolbar</name>
+      <width>112</width>
+      <height>16</height>
+      <orientation>GTK_ORIENTATION_HORIZONTAL</orientation>
+      <type>GTK_TOOLBAR_ICONS</type>
+      <space_size>5</space_size>
+      <space_style>GTK_TOOLBAR_SPACE_EMPTY</space_style>
+      <relief>GTK_RELIEF_NORMAL</relief>
+      <tooltips>True</tooltips>
+      <child>
+       <padding>0</padding>
+       <expand>False</expand>
+       <fill>True</fill>
+      </child>
+
+      <widget>
+       <class>GtkPixmap</class>
+       <name>xpm_open</name>
+       <can_focus>True</can_focus>
+       <signal>
+         <name>button_press_event</name>
+         <handler>on_xpm_open_button_press_event</handler>
+         <last_modification_time>Mon, 22 Jul 2002 13:18:11 GMT</last_modification_time>
+       </signal>
+       <filename>familiar-openb16x16.xpm</filename>
+       <xalign>0.5</xalign>
+       <yalign>0.5</yalign>
+       <xpad>0</xpad>
+       <ypad>0</ypad>
+       <build_insensitive>True</build_insensitive>
+      </widget>
+
+      <widget>
+       <class>GtkPixmap</class>
+       <name>xpm_preferences</name>
+       <can_focus>True</can_focus>
+       <signal>
+         <name>button_press_event</name>
+         <handler>on_xpm_preferences_button_press_event</handler>
+         <last_modification_time>Mon, 22 Jul 2002 13:17:55 GMT</last_modification_time>
+       </signal>
+       <filename>familiar-preferencesb16x16.xpm</filename>
+       <xalign>0.5</xalign>
+       <yalign>0.5</yalign>
+       <xpad>0</xpad>
+       <ypad>0</ypad>
+       <build_insensitive>True</build_insensitive>
+      </widget>
+
+      <widget>
+       <class>GtkPixmap</class>
+       <name>xpm_rewind</name>
+       <can_focus>True</can_focus>
+       <signal>
+         <name>button_press_event</name>
+         <handler>on_xpm_rewind_button_press_event</handler>
+         <last_modification_time>Mon, 22 Jul 2002 13:18:17 GMT</last_modification_time>
+       </signal>
+       <filename>familiar-rewindb16x16.xpm</filename>
+       <xalign>0.5</xalign>
+       <yalign>0.5</yalign>
+       <xpad>0</xpad>
+       <ypad>0</ypad>
+       <build_insensitive>True</build_insensitive>
+       <child>
+         <new_group>True</new_group>
+       </child>
+      </widget>
+
+      <widget>
+       <class>GtkPixmap</class>
+       <name>xpm_pause</name>
+       <can_focus>True</can_focus>
+       <signal>
+         <name>button_press_event</name>
+         <handler>on_xpm_pause_button_press_event</handler>
+         <last_modification_time>Mon, 22 Jul 2002 13:18:29 GMT</last_modification_time>
+       </signal>
+       <filename>familiar-pauseb16x16.xpm</filename>
+       <xalign>0.5</xalign>
+       <yalign>0.5</yalign>
+       <xpad>0</xpad>
+       <ypad>0</ypad>
+       <build_insensitive>True</build_insensitive>
+      </widget>
+
+      <widget>
+       <class>GtkPixmap</class>
+       <name>xpm_play</name>
+       <can_focus>True</can_focus>
+       <signal>
+         <name>button_press_event</name>
+         <handler>on_xpm_play_button_press_event</handler>
+         <last_modification_time>Mon, 22 Jul 2002 13:18:36 GMT</last_modification_time>
+       </signal>
+       <filename>familiar-playb16x16.xpm</filename>
+       <xalign>0.5</xalign>
+       <yalign>0.5</yalign>
+       <xpad>0</xpad>
+       <ypad>0</ypad>
+       <build_insensitive>True</build_insensitive>
+      </widget>
+
+      <widget>
+       <class>GtkPixmap</class>
+       <name>xpm_stop</name>
+       <can_focus>True</can_focus>
+       <signal>
+         <name>button_press_event</name>
+         <handler>on_xpm_stop_button_press_event</handler>
+         <last_modification_time>Mon, 22 Jul 2002 13:18:43 GMT</last_modification_time>
+       </signal>
+       <filename>familiar-stopb16x16.xpm</filename>
+       <xalign>0.5</xalign>
+       <yalign>0.5</yalign>
+       <xpad>0</xpad>
+       <ypad>0</ypad>
+       <build_insensitive>True</build_insensitive>
+      </widget>
+
+      <widget>
+       <class>GtkPixmap</class>
+       <name>xpm_forward</name>
+       <can_focus>True</can_focus>
+       <signal>
+         <name>button_press_event</name>
+         <handler>on_xpm_forward_button_press_event</handler>
+         <last_modification_time>Mon, 22 Jul 2002 13:18:55 GMT</last_modification_time>
+       </signal>
+       <filename>familiar-forwardb16x16.xpm</filename>
+       <xalign>0.5</xalign>
+       <yalign>0.5</yalign>
+       <xpad>0</xpad>
+       <ypad>0</ypad>
+       <build_insensitive>True</build_insensitive>
+      </widget>
+    </widget>
+
+    <widget>
+      <class>GtkProgressBar</class>
+      <name>progress</name>
+      <value>0</value>
+      <lower>0</lower>
+      <upper>100</upper>
+      <bar_style>GTK_PROGRESS_CONTINUOUS</bar_style>
+      <orientation>GTK_PROGRESS_LEFT_TO_RIGHT</orientation>
+      <activity_mode>True</activity_mode>
+      <show_text>False</show_text>
+      <format>%P %%</format>
+      <text_xalign>0.5</text_xalign>
+      <text_yalign>0.5</text_yalign>
+      <child>
+       <padding>0</padding>
+       <expand>False</expand>
+       <fill>False</fill>
+      </child>
+    </widget>
+
+    <widget>
+      <class>GtkNotebook</class>
+      <name>notebook</name>
+      <can_focus>True</can_focus>
+      <show_tabs>True</show_tabs>
+      <show_border>True</show_border>
+      <tab_pos>GTK_POS_TOP</tab_pos>
+      <scrollable>False</scrollable>
+      <tab_hborder>2</tab_hborder>
+      <tab_vborder>2</tab_vborder>
+      <popup_enable>False</popup_enable>
+      <child>
+       <padding>0</padding>
+       <expand>True</expand>
+       <fill>True</fill>
+      </child>
+
+      <widget>
+       <class>Placeholder</class>
+      </widget>
+
+      <widget>
+       <class>GtkLabel</class>
+       <child_name>Notebook:tab</child_name>
+       <name>media</name>
+       <label>Media</label>
+       <justify>GTK_JUSTIFY_CENTER</justify>
+       <wrap>False</wrap>
+       <xalign>0.5</xalign>
+       <yalign>0.5</yalign>
+       <xpad>0</xpad>
+       <ypad>0</ypad>
+      </widget>
+
+      <widget>
+       <class>Placeholder</class>
+      </widget>
+
+      <widget>
+       <class>GtkLabel</class>
+       <child_name>Notebook:tab</child_name>
+       <name>preference</name>
+       <label>Preference</label>
+       <justify>GTK_JUSTIFY_CENTER</justify>
+       <wrap>False</wrap>
+       <xalign>0.5</xalign>
+       <yalign>0.5</yalign>
+       <xpad>0</xpad>
+       <ypad>0</ypad>
+      </widget>
+
+      <widget>
+       <class>Placeholder</class>
+      </widget>
+
+      <widget>
+       <class>GtkLabel</class>
+       <child_name>Notebook:tab</child_name>
+       <name>help</name>
+       <label>Help</label>
+       <justify>GTK_JUSTIFY_CENTER</justify>
+       <wrap>False</wrap>
+       <xalign>0.5</xalign>
+       <yalign>0.5</yalign>
+       <xpad>0</xpad>
+       <ypad>0</ypad>
+      </widget>
+
+      <widget>
+       <class>Placeholder</class>
+      </widget>
+
+      <widget>
+       <class>GtkLabel</class>
+       <child_name>Notebook:tab</child_name>
+       <name>about</name>
+       <label>About</label>
+       <justify>GTK_JUSTIFY_CENTER</justify>
+       <wrap>False</wrap>
+       <xalign>0.5</xalign>
+       <yalign>0.5</yalign>
+       <xpad>0</xpad>
+       <ypad>0</ypad>
+      </widget>
+    </widget>
+  </widget>
+</widget>
+
+</GTK-Interface>
diff --git a/plugins/familiar/familiar.h b/plugins/familiar/familiar.h
new file mode 100644 (file)
index 0000000..d919b55
--- /dev/null
@@ -0,0 +1,101 @@
+/*****************************************************************************
+ * familiar.h: private Gtk+ interface description
+ *****************************************************************************
+ * Copyright (C) 1999, 2000 VideoLAN
+ * $Id: familiar.h,v 1.1 2002/07/22 13:49:42 jpsaman Exp $
+ *
+ * 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.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Drag'n'drop stuff
+ *****************************************************************************/
+#define DROP_ACCEPT_TEXT_URI_LIST  0
+#define DROP_ACCEPT_TEXT_PLAIN     1
+#define DROP_ACCEPT_STRING         2
+
+#define MAX_ATEXIT                 10
+
+/*****************************************************************************
+ * intf_sys_t: description and status of Gtk+ interface
+ *****************************************************************************/
+struct intf_sys_t
+{
+    /* special actions */
+    vlc_bool_t          b_playing;
+    vlc_bool_t          b_popup_changed;                   /* display menu ? */
+    vlc_bool_t          b_window_changed;        /* window display toggled ? */
+    vlc_bool_t          b_playlist_changed;    /* playlist display toggled ? */
+    vlc_bool_t          b_slider_free;                      /* slider status */
+
+    /* menus handlers */
+    vlc_bool_t          b_program_update;   /* do we need to update programs
+                                                                        menu */
+    vlc_bool_t          b_title_update;  /* do we need to update title menus */
+    vlc_bool_t          b_chapter_update;            /* do we need to update
+                                                               chapter menus */
+    vlc_bool_t          b_audio_update;  /* do we need to update audio menus */
+    vlc_bool_t          b_spu_update;      /* do we need to update spu menus */
+
+    /* windows and widgets */
+    GtkWidget *         p_window;                             /* main window */
+    GtkWidget *         p_popup;                               /* popup menu */
+    GtkWidget *         p_playwin;                               /* playlist */
+    GtkWidget *         p_modules;                         /* module manager */
+    GtkWidget *         p_about;                             /* about window */
+    GtkWidget *         p_open;                          /* multiopen window */
+    GtkWidget *         p_jump;                               /* jump window */
+
+    GtkTooltips *       p_tooltips;                              /* tooltips */
+
+    /* The input thread */
+    input_thread_t *    p_input;
+
+    /* The slider */
+    GtkFrame *          p_slider_frame;
+    GtkAdjustment *     p_adj;                   /* slider adjustment object */
+    float               f_adj_oldvalue;                    /* previous value */
+
+    /* The messages window */
+    GtkWidget *         p_messages;                       /* messages window */
+    GtkText *           p_messages_text;                   /* messages frame */
+    msg_subscription_t* p_sub;                  /* message bank subscription */
+
+    /* Playlist management */
+    int                 i_playing;                 /* playlist selected item */
+
+    /* The window labels for DVD mode */
+    GtkLabel *          p_label_title;
+    GtkLabel *          p_label_chapter;
+    gint                i_part;                           /* current chapter */
+
+    /* XXX: Ugly kludge, see gtk.c */
+    void             ( *pf_callback[MAX_ATEXIT] ) ( void );
+};
+
+/*****************************************************************************
+ * Prototypes
+ *****************************************************************************/
+gint GtkModeManage   ( intf_thread_t * p_intf );
+void GtkDisplayDate  ( GtkAdjustment *p_adj );
+
+/*****************************************************************************
+ * Useful macro
+ ****************************************************************************/
+#define  GtkGetIntf( widget ) __GtkGetIntf( GTK_WIDGET( widget ) )
+void * __GtkGetIntf( GtkWidget * );
+
diff --git a/plugins/familiar/familiar_callbacks.c b/plugins/familiar/familiar_callbacks.c
new file mode 100644 (file)
index 0000000..39581e4
--- /dev/null
@@ -0,0 +1,79 @@
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <gtk/gtk.h>
+
+#include "familiar_callbacks.h"
+#include "familiar_interface.h"
+#include "familiar_support.h"
+
+gboolean
+on_xpm_open_button_press_event         (GtkWidget       *widget,
+                                        GdkEventButton  *event,
+                                        gpointer         user_data)
+{
+
+  return FALSE;
+}
+
+
+gboolean
+on_xpm_preferences_button_press_event  (GtkWidget       *widget,
+                                        GdkEventButton  *event,
+                                        gpointer         user_data)
+{
+
+  return FALSE;
+}
+
+
+gboolean
+on_xpm_rewind_button_press_event       (GtkWidget       *widget,
+                                        GdkEventButton  *event,
+                                        gpointer         user_data)
+{
+
+  return FALSE;
+}
+
+
+gboolean
+on_xpm_pause_button_press_event        (GtkWidget       *widget,
+                                        GdkEventButton  *event,
+                                        gpointer         user_data)
+{
+
+  return FALSE;
+}
+
+
+gboolean
+on_xpm_play_button_press_event         (GtkWidget       *widget,
+                                        GdkEventButton  *event,
+                                        gpointer         user_data)
+{
+
+  return FALSE;
+}
+
+
+gboolean
+on_xpm_stop_button_press_event         (GtkWidget       *widget,
+                                        GdkEventButton  *event,
+                                        gpointer         user_data)
+{
+
+  return FALSE;
+}
+
+
+gboolean
+on_xpm_forward_button_press_event      (GtkWidget       *widget,
+                                        GdkEventButton  *event,
+                                        gpointer         user_data)
+{
+
+  return FALSE;
+}
+
diff --git a/plugins/familiar/familiar_callbacks.h b/plugins/familiar/familiar_callbacks.h
new file mode 100644 (file)
index 0000000..29c6eab
--- /dev/null
@@ -0,0 +1,36 @@
+#include <gtk/gtk.h>
+
+gboolean
+on_xpm_open_button_press_event         (GtkWidget       *widget,
+                                        GdkEventButton  *event,
+                                        gpointer         user_data);
+
+gboolean
+on_xpm_preferences_button_press_event  (GtkWidget       *widget,
+                                        GdkEventButton  *event,
+                                        gpointer         user_data);
+
+gboolean
+on_xpm_rewind_button_press_event       (GtkWidget       *widget,
+                                        GdkEventButton  *event,
+                                        gpointer         user_data);
+
+gboolean
+on_xpm_pause_button_press_event        (GtkWidget       *widget,
+                                        GdkEventButton  *event,
+                                        gpointer         user_data);
+
+gboolean
+on_xpm_play_button_press_event         (GtkWidget       *widget,
+                                        GdkEventButton  *event,
+                                        gpointer         user_data);
+
+gboolean
+on_xpm_stop_button_press_event         (GtkWidget       *widget,
+                                        GdkEventButton  *event,
+                                        gpointer         user_data);
+
+gboolean
+on_xpm_forward_button_press_event      (GtkWidget       *widget,
+                                        GdkEventButton  *event,
+                                        gpointer         user_data);
diff --git a/plugins/familiar/familiar_interface.c b/plugins/familiar/familiar_interface.c
new file mode 100644 (file)
index 0000000..d52fdda
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ * DO NOT EDIT THIS FILE - it is generated by Glade.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtk.h>
+
+#include "familiar_callbacks.h"
+#include "familiar_interface.h"
+#include "familiar_support.h"
+
+GtkWidget*
+create_familiar (void)
+{
+  GtkWidget *familiar;
+  GtkWidget *vbox;
+  GtkWidget *toolbar;
+  GtkWidget *xpm_open;
+  GtkWidget *xpm_preferences;
+  GtkWidget *xpm_rewind;
+  GtkWidget *xpm_pause;
+  GtkWidget *xpm_play;
+  GtkWidget *xpm_stop;
+  GtkWidget *xpm_forward;
+  GtkWidget *progress;
+  GtkWidget *notebook;
+  GtkWidget *empty_notebook_page;
+  GtkWidget *media;
+  GtkWidget *preference;
+  GtkWidget *help;
+  GtkWidget *about;
+
+  familiar = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+  gtk_object_set_data (GTK_OBJECT (familiar), "familiar", familiar);
+  gtk_widget_set_usize (familiar, 240, 320);
+  gtk_window_set_title (GTK_WINDOW (familiar), _("vlc (familiar)"));
+  gtk_window_set_policy (GTK_WINDOW (familiar), FALSE, FALSE, FALSE);
+
+  vbox = gtk_vbox_new (FALSE, 0);
+  gtk_widget_ref (vbox);
+  gtk_object_set_data_full (GTK_OBJECT (familiar), "vbox", vbox,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (vbox);
+  gtk_container_add (GTK_CONTAINER (familiar), vbox);
+
+  toolbar = gtk_toolbar_new (GTK_ORIENTATION_HORIZONTAL, GTK_TOOLBAR_ICONS);
+  gtk_widget_ref (toolbar);
+  gtk_object_set_data_full (GTK_OBJECT (familiar), "toolbar", toolbar,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (toolbar);
+  gtk_box_pack_start (GTK_BOX (vbox), toolbar, FALSE, TRUE, 0);
+  gtk_widget_set_usize (toolbar, 112, 16);
+
+  xpm_open = create_pixmap (familiar, "familiar-openb16x16.xpm");
+  gtk_widget_ref (xpm_open);
+  gtk_object_set_data_full (GTK_OBJECT (familiar), "xpm_open", xpm_open,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (xpm_open);
+  gtk_toolbar_append_widget (GTK_TOOLBAR (toolbar), xpm_open, NULL, NULL);
+  GTK_WIDGET_SET_FLAGS (xpm_open, GTK_CAN_FOCUS);
+
+  xpm_preferences = create_pixmap (familiar, "familiar-preferencesb16x16.xpm");
+  gtk_widget_ref (xpm_preferences);
+  gtk_object_set_data_full (GTK_OBJECT (familiar), "xpm_preferences", xpm_preferences,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (xpm_preferences);
+  gtk_toolbar_append_widget (GTK_TOOLBAR (toolbar), xpm_preferences, NULL, NULL);
+  GTK_WIDGET_SET_FLAGS (xpm_preferences, GTK_CAN_FOCUS);
+
+  xpm_rewind = create_pixmap (familiar, "familiar-rewindb16x16.xpm");
+  gtk_widget_ref (xpm_rewind);
+  gtk_object_set_data_full (GTK_OBJECT (familiar), "xpm_rewind", xpm_rewind,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (xpm_rewind);
+  gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
+
+  gtk_toolbar_append_widget (GTK_TOOLBAR (toolbar), xpm_rewind, NULL, NULL);
+  GTK_WIDGET_SET_FLAGS (xpm_rewind, GTK_CAN_FOCUS);
+
+  xpm_pause = create_pixmap (familiar, "familiar-pauseb16x16.xpm");
+  gtk_widget_ref (xpm_pause);
+  gtk_object_set_data_full (GTK_OBJECT (familiar), "xpm_pause", xpm_pause,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (xpm_pause);
+  gtk_toolbar_append_widget (GTK_TOOLBAR (toolbar), xpm_pause, NULL, NULL);
+  GTK_WIDGET_SET_FLAGS (xpm_pause, GTK_CAN_FOCUS);
+
+  xpm_play = create_pixmap (familiar, "familiar-playb16x16.xpm");
+  gtk_widget_ref (xpm_play);
+  gtk_object_set_data_full (GTK_OBJECT (familiar), "xpm_play", xpm_play,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (xpm_play);
+  gtk_toolbar_append_widget (GTK_TOOLBAR (toolbar), xpm_play, NULL, NULL);
+  GTK_WIDGET_SET_FLAGS (xpm_play, GTK_CAN_FOCUS);
+
+  xpm_stop = create_pixmap (familiar, "familiar-stopb16x16.xpm");
+  gtk_widget_ref (xpm_stop);
+  gtk_object_set_data_full (GTK_OBJECT (familiar), "xpm_stop", xpm_stop,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (xpm_stop);
+  gtk_toolbar_append_widget (GTK_TOOLBAR (toolbar), xpm_stop, NULL, NULL);
+  GTK_WIDGET_SET_FLAGS (xpm_stop, GTK_CAN_FOCUS);
+
+  xpm_forward = create_pixmap (familiar, "familiar-forwardb16x16.xpm");
+  gtk_widget_ref (xpm_forward);
+  gtk_object_set_data_full (GTK_OBJECT (familiar), "xpm_forward", xpm_forward,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (xpm_forward);
+  gtk_toolbar_append_widget (GTK_TOOLBAR (toolbar), xpm_forward, NULL, NULL);
+  GTK_WIDGET_SET_FLAGS (xpm_forward, GTK_CAN_FOCUS);
+
+  progress = gtk_progress_bar_new ();
+  gtk_widget_ref (progress);
+  gtk_object_set_data_full (GTK_OBJECT (familiar), "progress", progress,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (progress);
+  gtk_box_pack_start (GTK_BOX (vbox), progress, FALSE, FALSE, 0);
+  gtk_progress_set_activity_mode (GTK_PROGRESS (progress), TRUE);
+
+  notebook = gtk_notebook_new ();
+  gtk_widget_ref (notebook);
+  gtk_object_set_data_full (GTK_OBJECT (familiar), "notebook", notebook,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (notebook);
+  gtk_box_pack_start (GTK_BOX (vbox), notebook, TRUE, TRUE, 0);
+
+  empty_notebook_page = gtk_vbox_new (FALSE, 0);
+  gtk_widget_show (empty_notebook_page);
+  gtk_container_add (GTK_CONTAINER (notebook), empty_notebook_page);
+
+  media = gtk_label_new (_("Media"));
+  gtk_widget_ref (media);
+  gtk_object_set_data_full (GTK_OBJECT (familiar), "media", media,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (media);
+  gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), 0), media);
+
+  empty_notebook_page = gtk_vbox_new (FALSE, 0);
+  gtk_widget_show (empty_notebook_page);
+  gtk_container_add (GTK_CONTAINER (notebook), empty_notebook_page);
+
+  preference = gtk_label_new (_("Preference"));
+  gtk_widget_ref (preference);
+  gtk_object_set_data_full (GTK_OBJECT (familiar), "preference", preference,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (preference);
+  gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), 1), preference);
+
+  empty_notebook_page = gtk_vbox_new (FALSE, 0);
+  gtk_widget_show (empty_notebook_page);
+  gtk_container_add (GTK_CONTAINER (notebook), empty_notebook_page);
+
+  help = gtk_label_new (_("Help"));
+  gtk_widget_ref (help);
+  gtk_object_set_data_full (GTK_OBJECT (familiar), "help", help,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (help);
+  gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), 2), help);
+
+  empty_notebook_page = gtk_vbox_new (FALSE, 0);
+  gtk_widget_show (empty_notebook_page);
+  gtk_container_add (GTK_CONTAINER (notebook), empty_notebook_page);
+
+  about = gtk_label_new (_("About"));
+  gtk_widget_ref (about);
+  gtk_object_set_data_full (GTK_OBJECT (familiar), "about", about,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (about);
+  gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), 3), about);
+
+  gtk_signal_connect (GTK_OBJECT (xpm_open), "button_press_event",
+                      GTK_SIGNAL_FUNC (on_xpm_open_button_press_event),
+                      NULL);
+  gtk_signal_connect (GTK_OBJECT (xpm_preferences), "button_press_event",
+                      GTK_SIGNAL_FUNC (on_xpm_preferences_button_press_event),
+                      NULL);
+  gtk_signal_connect (GTK_OBJECT (xpm_rewind), "button_press_event",
+                      GTK_SIGNAL_FUNC (on_xpm_rewind_button_press_event),
+                      NULL);
+  gtk_signal_connect (GTK_OBJECT (xpm_pause), "button_press_event",
+                      GTK_SIGNAL_FUNC (on_xpm_pause_button_press_event),
+                      NULL);
+  gtk_signal_connect (GTK_OBJECT (xpm_play), "button_press_event",
+                      GTK_SIGNAL_FUNC (on_xpm_play_button_press_event),
+                      NULL);
+  gtk_signal_connect (GTK_OBJECT (xpm_stop), "button_press_event",
+                      GTK_SIGNAL_FUNC (on_xpm_stop_button_press_event),
+                      NULL);
+  gtk_signal_connect (GTK_OBJECT (xpm_forward), "button_press_event",
+                      GTK_SIGNAL_FUNC (on_xpm_forward_button_press_event),
+                      NULL);
+
+  return familiar;
+}
+
diff --git a/plugins/familiar/familiar_interface.h b/plugins/familiar/familiar_interface.h
new file mode 100644 (file)
index 0000000..27a3bcf
--- /dev/null
@@ -0,0 +1,5 @@
+/*
+ * DO NOT EDIT THIS FILE - it is generated by Glade.
+ */
+
+GtkWidget* create_familiar (void);
diff --git a/plugins/familiar/familiar_support.c b/plugins/familiar/familiar_support.c
new file mode 100644 (file)
index 0000000..3fa4cb4
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * DO NOT EDIT THIS FILE - it is generated by Glade.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <gtk/gtk.h>
+
+#include "familiar_support.h"
+
+/* This is an internally used function to check if a pixmap file exists. */
+static gchar* check_file_exists        (const gchar     *directory,
+                                        const gchar     *filename);
+
+/* This is an internally used function to create pixmaps. */
+static GtkWidget* create_dummy_pixmap  (GtkWidget       *widget);
+
+GtkWidget*
+lookup_widget                          (GtkWidget       *widget,
+                                        const gchar     *widget_name)
+{
+  GtkWidget *parent, *found_widget;
+
+  for (;;)
+    {
+      if (GTK_IS_MENU (widget))
+        parent = gtk_menu_get_attach_widget (GTK_MENU (widget));
+      else
+        parent = widget->parent;
+      if (parent == NULL)
+        break;
+      widget = parent;
+    }
+
+  found_widget = (GtkWidget*) gtk_object_get_data (GTK_OBJECT (widget),
+                                                   widget_name);
+  if (!found_widget)
+    g_warning ("Widget not found: %s", widget_name);
+  return found_widget;
+}
+
+/* This is a dummy pixmap we use when a pixmap can't be found. */
+static char *dummy_pixmap_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"1 1 1 1",
+"  c None",
+/* pixels */
+" "
+};
+
+/* This is an internally used function to create pixmaps. */
+static GtkWidget*
+create_dummy_pixmap                    (GtkWidget       *widget)
+{
+  GdkColormap *colormap;
+  GdkPixmap *gdkpixmap;
+  GdkBitmap *mask;
+  GtkWidget *pixmap;
+
+  colormap = gtk_widget_get_colormap (widget);
+  gdkpixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL, colormap, &mask,
+                                                     NULL, dummy_pixmap_xpm);
+  if (gdkpixmap == NULL)
+    g_error ("Couldn't create replacement pixmap.");
+  pixmap = gtk_pixmap_new (gdkpixmap, mask);
+  gdk_pixmap_unref (gdkpixmap);
+  gdk_bitmap_unref (mask);
+  return pixmap;
+}
+
+static GList *pixmaps_directories = NULL;
+
+/* Use this function to set the directory containing installed pixmaps. */
+void
+add_pixmap_directory                   (const gchar     *directory)
+{
+  pixmaps_directories = g_list_prepend (pixmaps_directories,
+                                        g_strdup (directory));
+}
+
+/* This is an internally used function to create pixmaps. */
+GtkWidget*
+create_pixmap                          (GtkWidget       *widget,
+                                        const gchar     *filename)
+{
+  gchar *found_filename = NULL;
+  GdkColormap *colormap;
+  GdkPixmap *gdkpixmap;
+  GdkBitmap *mask;
+  GtkWidget *pixmap;
+  GList *elem;
+
+  if (!filename || !filename[0])
+      return create_dummy_pixmap (widget);
+
+  /* We first try any pixmaps directories set by the application. */
+  elem = pixmaps_directories;
+  while (elem)
+    {
+      found_filename = check_file_exists ((gchar*)elem->data, filename);
+      if (found_filename)
+        break;
+      elem = elem->next;
+    }
+
+  /* If we haven't found the pixmap, try the source directory. */
+  if (!found_filename)
+    {
+      found_filename = check_file_exists ("../share", filename);
+    }
+
+  if (!found_filename)
+    {
+      g_warning (_("Couldn't find pixmap file: %s"), filename);
+      return create_dummy_pixmap (widget);
+    }
+
+  colormap = gtk_widget_get_colormap (widget);
+  gdkpixmap = gdk_pixmap_colormap_create_from_xpm (NULL, colormap, &mask,
+                                                   NULL, found_filename);
+  if (gdkpixmap == NULL)
+    {
+      g_warning (_("Error loading pixmap file: %s"), found_filename);
+      g_free (found_filename);
+      return create_dummy_pixmap (widget);
+    }
+  g_free (found_filename);
+  pixmap = gtk_pixmap_new (gdkpixmap, mask);
+  gdk_pixmap_unref (gdkpixmap);
+  gdk_bitmap_unref (mask);
+  return pixmap;
+}
+
+/* This is an internally used function to check if a pixmap file exists. */
+static gchar*
+check_file_exists                      (const gchar     *directory,
+                                        const gchar     *filename)
+{
+  gchar *full_filename;
+  struct stat s;
+  gint status;
+
+  full_filename = (gchar*) g_malloc (strlen (directory) + 1
+                                     + strlen (filename) + 1);
+  strcpy (full_filename, directory);
+  strcat (full_filename, G_DIR_SEPARATOR_S);
+  strcat (full_filename, filename);
+
+  status = stat (full_filename, &s);
+  if (status == 0 && S_ISREG (s.st_mode))
+    return full_filename;
+  g_free (full_filename);
+  return NULL;
+}
+
diff --git a/plugins/familiar/familiar_support.h b/plugins/familiar/familiar_support.h
new file mode 100644 (file)
index 0000000..931bc5a
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * DO NOT EDIT THIS FILE - it is generated by Glade.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <gtk/gtk.h>
+
+/*
+ * Standard gettext macros.
+ */
+#ifdef ENABLE_NLS
+#  include <libintl.h>
+#  undef _
+#  define _(String) dgettext (PACKAGE, String)
+#  ifdef gettext_noop
+#    define N_(String) gettext_noop (String)
+#  else
+#    define N_(String) (String)
+#  endif
+#else
+#  define textdomain(String) (String)
+#  define gettext(String) (String)
+#  define dgettext(Domain,Message) (Message)
+#  define dcgettext(Domain,Message,Type) (Message)
+#  define bindtextdomain(Domain,Directory) (Domain)
+#  define _(String) (String)
+#  define N_(String) (String)
+#endif
+
+
+/*
+ * Public Functions.
+ */
+
+/*
+ * This function returns a widget in a component created by Glade.
+ * Call it with the toplevel widget in the component (i.e. a window/dialog),
+ * or alternatively any widget in the component, and the name of the widget
+ * you want returned.
+ */
+GtkWidget*  lookup_widget              (GtkWidget       *widget,
+                                        const gchar     *widget_name);
+
+/* get_widget() is deprecated. Use lookup_widget instead. */
+#define get_widget lookup_widget
+
+/* Use this function to set the directory containing installed pixmaps. */
+void        add_pixmap_directory       (const gchar     *directory);
+
+
+/*
+ * Private Functions.
+ */
+
+/* This is used to create the pixmaps in the interface. */
+GtkWidget*  create_pixmap              (GtkWidget       *widget,
+                                        const gchar     *filename);
+