* mozilla plugin on MacOSX. Not fully implemented yet.
[vlc.git] / mozilla / vlcshell.cpp
1 /*****************************************************************************
2  * vlcshell.cpp: a VLC plugin for Mozilla
3  *****************************************************************************
4  * Copyright (C) 2002 VideoLAN
5  * $Id: vlcshell.cpp,v 1.16 2003/08/14 12:38:03 garf Exp $
6  *
7  * Authors: Samuel Hocevar <sam@zoy.org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 /* XXX: disable VLC here */
25 #define USE_LIBVLC 1
26
27 /*****************************************************************************
28  * Preamble
29  *****************************************************************************/
30 #include <stdio.h>
31 #include <string.h>
32 #include <stdlib.h>
33
34 /* vlc stuff */
35 #ifdef USE_LIBVLC
36 #   include <vlc/vlc.h>
37 #endif
38
39 /* Mozilla stuff */
40 #include <nsISupports.h>
41 #include <nsMemory.h>
42 #include <npapi.h>
43
44 #ifdef XP_WIN
45     /* Windows stuff */
46 #endif
47
48 #ifdef XP_MACOSX
49     /* Mac OS X stuff */
50 #   include <QuickDraw.h>
51 #endif
52
53 #include "vlcpeer.h"
54 #include "vlcplugin.h"
55
56 #if USE_LIBVLC
57 #   define WINDOW_TEXT "(no picture)"
58 #else
59 #   define WINDOW_TEXT "(no libvlc)"
60 #endif
61
62 /* No, I really don't want to use XP_UNIX stuff on MacOSX */
63 #ifdef XP_MACOSX
64 #undef XP_UNIX
65 #endif
66
67 #ifdef XP_UNIX
68     /* X11 stuff */
69 #   include <X11/Xlib.h>
70 #   include <X11/Intrinsic.h>
71 #   include <X11/StringDefs.h>
72 #endif
73
74 /*****************************************************************************
75  * Unix-only declarations
76 ******************************************************************************/
77 #ifdef XP_UNIX
78 #   define VOUT_PLUGINS "xvideo,x11,dummy"
79 #   define AOUT_PLUGINS "oss,dummy"
80
81 static void Redraw( Widget w, XtPointer closure, XEvent *event );
82 #endif
83
84 /*****************************************************************************
85  * MacOS-only declarations
86 ******************************************************************************/
87 #ifdef XP_MACOSX
88 #   define VOUT_PLUGINS "macosx"
89 #   define AOUT_PLUGINS "macosx"
90
91 #endif
92
93 /*****************************************************************************
94  * Windows-only declarations
95  *****************************************************************************/
96 #ifdef XP_WIN
97 #   define VOUT_PLUGINS "directx,dummy"
98 #   define AOUT_PLUGINS "none" /* "directx,waveout,dummy" */
99
100 HINSTANCE g_hDllInstance = NULL;
101
102 BOOL WINAPI
103 DllMain( HINSTANCE  hinstDLL,                   // handle of DLL module
104                     DWORD  fdwReason,       // reason for calling function
105                     LPVOID  lpvReserved)
106 {
107     switch (fdwReason)
108     {
109         case DLL_PROCESS_ATTACH:
110             g_hDllInstance = hinstDLL;
111             break;
112         case DLL_THREAD_ATTACH:
113         case DLL_PROCESS_DETACH:
114         case DLL_THREAD_DETACH:
115             break;
116     }
117     return TRUE;
118 }
119
120 LRESULT CALLBACK Manage( HWND, UINT, WPARAM, LPARAM );
121 #endif
122
123 /******************************************************************************
124  * UNIX-only API calls
125  *****************************************************************************/
126 char * NPP_GetMIMEDescription( void )
127 {
128     return PLUGIN_MIMETYPES;
129 }
130
131 NPError NPP_GetValue( NPP instance, NPPVariable variable, void *value )
132 {
133     static nsIID nsid = VLCINTF_IID;
134     static char psz_desc[1000];
135
136     switch( variable )
137     {
138         case NPPVpluginNameString:
139             *((char **)value) = PLUGIN_NAME;
140             return NPERR_NO_ERROR;
141
142         case NPPVpluginDescriptionString:
143 #if USE_LIBVLC
144             snprintf( psz_desc, 1000-1, PLUGIN_DESCRIPTION, VLC_Version() );
145 #else
146             snprintf( psz_desc, 1000-1, PLUGIN_DESCRIPTION, "(disabled)" );
147 #endif
148             psz_desc[1000-1] = 0;
149             *((char **)value) = psz_desc;
150             return NPERR_NO_ERROR;
151
152         default:
153             /* go on... */
154             break;
155     }
156
157     if( instance == NULL )
158     {
159         return NPERR_INVALID_INSTANCE_ERROR;
160     }
161
162     VlcPlugin* p_plugin = (VlcPlugin*) instance->pdata;
163
164     switch( variable )
165     {
166         case NPPVpluginScriptableInstance:
167             *(nsISupports**)value = p_plugin->GetPeer();
168             if( *(nsISupports**)value == NULL )
169             {
170                 return NPERR_OUT_OF_MEMORY_ERROR;
171             }
172             break;
173
174         case NPPVpluginScriptableIID:
175             *(nsIID**)value = (nsIID*)NPN_MemAlloc( sizeof(nsIID) );
176             if( *(nsIID**)value == NULL )
177             {
178                 return NPERR_OUT_OF_MEMORY_ERROR;
179             }
180             **(nsIID**)value = nsid;
181             break;
182
183         default:
184             return NPERR_GENERIC_ERROR;
185     }
186
187     return NPERR_NO_ERROR;
188 }
189
190 /******************************************************************************
191  * Mac-only API calls
192  *****************************************************************************/
193 #ifdef XP_MACOSX
194 int16 NPP_HandleEvent( NPP instance, void * event )
195 {
196     VlcPlugin *p_plugin = (VlcPlugin*)instance->pdata;
197     vlc_value_t value;
198
199     if( instance == NULL )
200     {
201         return false;
202     }
203
204     EventRecord *pouetEvent = (EventRecord*)event;
205
206     if (pouetEvent->what == 6)
207     {
208         value.i_int = 1;
209         VLC_Set( p_plugin->i_vlc, "drawableredraw", value );
210
211         return true;
212     }
213
214     Boolean eventHandled = false;
215
216     return eventHandled;
217 }
218 #endif
219
220 /******************************************************************************
221  * General Plug-in Calls
222  *****************************************************************************/
223 NPError NPP_Initialize( void )
224 {
225     return NPERR_NO_ERROR;
226 }
227
228 jref NPP_GetJavaClass( void )
229 {
230     return NULL;
231 }
232
233 void NPP_Shutdown( void )
234 {
235     ;
236 }
237
238 NPError NPP_New( NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc,
239                  char* argn[], char* argv[], NPSavedData* saved )
240 {
241     int i;
242 #if USE_LIBVLC
243     vlc_value_t value;
244     int i_ret;
245
246     char *ppsz_foo[] =
247     {
248         "vlc"
249         /*, "--plugin-path", "/home/sam/videolan/vlc_MAIN/plugins"*/
250     };
251 #endif
252
253     if( instance == NULL )
254     {
255         return NPERR_INVALID_INSTANCE_ERROR;
256     }
257
258     VlcPlugin * p_plugin = new VlcPlugin( instance );
259
260     if( p_plugin == NULL )
261     {
262         return NPERR_OUT_OF_MEMORY_ERROR;
263     }
264
265     instance->pdata = p_plugin;
266
267 #ifdef XP_WIN
268     p_plugin->p_hwnd = NULL;
269     p_plugin->pf_wndproc = NULL;
270 #endif
271
272 #ifdef XP_UNIX
273     p_plugin->window = 0;
274     p_plugin->p_display = NULL;
275 #endif
276
277     p_plugin->p_npwin = NULL;
278     p_plugin->i_npmode = mode;
279     p_plugin->i_width = 0;
280     p_plugin->i_height = 0;
281
282 #if USE_LIBVLC
283     p_plugin->i_vlc = VLC_Create();
284     if( p_plugin->i_vlc < 0 )
285     {
286         p_plugin->i_vlc = 0;
287         delete p_plugin;
288         p_plugin = NULL;
289         return NPERR_GENERIC_ERROR;
290     }
291
292     i_ret = VLC_Init( p_plugin->i_vlc, sizeof(ppsz_foo)/sizeof(char*), ppsz_foo );
293     if( i_ret )
294     {
295         VLC_Destroy( p_plugin->i_vlc );
296         p_plugin->i_vlc = 0;
297         delete p_plugin;
298         p_plugin = NULL;
299         return NPERR_GENERIC_ERROR;
300     }
301
302     value.psz_string = "dummy";
303     VLC_Set( p_plugin->i_vlc, "conf::intf", value );
304     value.psz_string = VOUT_PLUGINS;
305     VLC_Set( p_plugin->i_vlc, "conf::vout", value );
306     value.psz_string = AOUT_PLUGINS;
307     VLC_Set( p_plugin->i_vlc, "conf::aout", value );
308
309 #else
310     p_plugin->i_vlc = 1;
311
312 #endif /* USE_LIBVLC */
313
314     p_plugin->b_stream = VLC_FALSE;
315     p_plugin->b_autoplay = VLC_FALSE;
316     p_plugin->psz_target = NULL;
317
318     for( i = 0; i < argc ; i++ )
319     {
320         if( !strcmp( argn[i], "target" ) )
321         {
322             p_plugin->psz_target = argv[i];
323         }
324         else if( !strcmp( argn[i], "autoplay" ) )
325         {
326             if( !strcmp( argv[i], "yes" ) )
327             {
328                 p_plugin->b_autoplay = 1;
329             }
330         }
331         else if( !strcmp( argn[i], "autostart" ) )
332         {
333             if( !strcmp( argv[i], "1" ) || !strcmp( argv[i], "true" ) )
334             {
335                 p_plugin->b_autoplay = 1;
336             }
337         }
338         else if( !strcmp( argn[i], "filename" ) )
339         {
340             p_plugin->psz_target = argv[i];
341         }
342         else if( !strcmp( argn[i], "src" ) )
343         {
344             p_plugin->psz_target = argv[i];
345         }
346
347 #if USE_LIBVLC
348         else if( !strcmp( argn[i], "loop" ) )
349         {
350             if( !strcmp( argv[i], "yes" ) )
351             {
352                 value.b_bool = VLC_TRUE;
353                 VLC_Set( p_plugin->i_vlc, "conf::loop", value );
354             }
355         }
356 #endif
357     }
358
359     if( p_plugin->psz_target )
360     {
361         p_plugin->psz_target = strdup( p_plugin->psz_target );
362     }
363
364     return NPERR_NO_ERROR;
365 }
366
367 NPError NPP_Destroy( NPP instance, NPSavedData** save )
368 {
369     if( instance == NULL )
370     {
371         return NPERR_INVALID_INSTANCE_ERROR;
372     }
373
374     VlcPlugin* p_plugin = (VlcPlugin*)instance->pdata;
375
376     if( p_plugin != NULL )
377     {
378         if( p_plugin->i_vlc )
379         {
380 #if USE_LIBVLC
381             VLC_Stop( p_plugin->i_vlc );
382             VLC_Destroy( p_plugin->i_vlc );
383 #endif
384             p_plugin->i_vlc = 0;
385         }
386
387         if( p_plugin->psz_target )
388         {
389             free( p_plugin->psz_target );
390             p_plugin->psz_target = NULL;
391         }
392
393         delete p_plugin;
394     }
395
396     instance->pdata = NULL;
397
398     return NPERR_NO_ERROR;
399 }
400
401 NPError NPP_SetWindow( NPP instance, NPWindow* window )
402 {
403 #ifdef XP_MACOSX
404     vlc_value_t value;
405     vlc_value_t valuex;
406     vlc_value_t valuey;
407     vlc_value_t valuew;
408     vlc_value_t valueh;
409     vlc_value_t valuet;
410     vlc_value_t valuel;
411     vlc_value_t valueb;
412     vlc_value_t valuer;
413     vlc_value_t valueportx;
414     vlc_value_t valueporty;
415 #endif
416
417     if( instance == NULL )
418     {
419         return NPERR_INVALID_INSTANCE_ERROR;
420     }
421
422     VlcPlugin* p_plugin = (VlcPlugin*)instance->pdata;
423
424     /* Write the window ID for vlc */
425 #if USE_LIBVLC
426
427 #ifdef XP_MACOSX
428     value.i_int = ((NP_Port*) (window->window))->port;
429     VLC_Set( p_plugin->i_vlc, "drawable", value );
430
431     valueportx.i_int = ((NP_Port*) (window->window))->portx;
432     valueporty.i_int = ((NP_Port*) (window->window))->porty;
433     VLC_Set( p_plugin->i_vlc, "drawableportx", valueportx );
434     VLC_Set( p_plugin->i_vlc, "drawableporty", valueporty );
435
436     valuex.i_int = window->x;
437     valuey.i_int = window->y;
438     valuew.i_int = window->width;
439     valueh.i_int = window->height;
440     valuet.i_int = window->clipRect.top;
441     valuel.i_int = window->clipRect.left;
442     valueb.i_int = window->clipRect.bottom;
443     valuer.i_int = window->clipRect.right;
444
445     VLC_Set( p_plugin->i_vlc, "drawablet", valuet );
446     VLC_Set( p_plugin->i_vlc, "drawablel", valuel );
447     VLC_Set( p_plugin->i_vlc, "drawableb", valueb );
448     VLC_Set( p_plugin->i_vlc, "drawabler", valuer );
449     VLC_Set( p_plugin->i_vlc, "drawablex", valuex );
450     VLC_Set( p_plugin->i_vlc, "drawabley", valuey );
451     VLC_Set( p_plugin->i_vlc, "drawablew", valuew );
452     VLC_Set( p_plugin->i_vlc, "drawableh", valueh );
453
454     p_plugin->window = window;
455
456 #else
457     /* FIXME: this cast sucks */
458     value.i_int = (int) (ptrdiff_t) (void *) window->window;
459     VLC_Set( p_plugin->i_vlc, "drawable", value );
460 #endif
461
462 #endif
463
464     /*
465      * PLUGIN DEVELOPERS:
466      *  Before setting window to point to the
467      *  new window, you may wish to compare the new window
468      *  info to the previous window (if any) to note window
469      *  size changes, etc.
470      */
471
472 #ifdef XP_WIN
473     if( !window || !window->window )
474     {
475         /* Window was destroyed. Invalidate everything. */
476         if( p_plugin->p_npwin )
477         {
478             SetWindowLong( p_plugin->p_hwnd, GWL_WNDPROC,
479                            (LONG)p_plugin->pf_wndproc );
480             p_plugin->pf_wndproc = NULL;
481             p_plugin->p_hwnd = NULL;
482         }
483
484         p_plugin->p_npwin = window;
485         return NPERR_NO_ERROR;
486     }
487
488     if( p_plugin->p_npwin )
489     {
490         if( p_plugin->p_hwnd == (HWND)window->window )
491         {
492             /* Same window, but something may have changed. First we
493              * update the plugin structure, then we redraw the window */
494             InvalidateRect( p_plugin->p_hwnd, NULL, TRUE );
495             p_plugin->i_width = window->width;
496             p_plugin->i_height = window->height;
497             p_plugin->p_npwin = window;
498             UpdateWindow( p_plugin->p_hwnd );
499             return NPERR_NO_ERROR;
500         }
501
502         /* Window has changed. Destroy the one we have, and go
503          * on as if it was a real initialization. */
504         SetWindowLong( p_plugin->p_hwnd, GWL_WNDPROC,
505                        (LONG)p_plugin->pf_wndproc );
506         p_plugin->pf_wndproc = NULL;
507         p_plugin->p_hwnd = NULL;
508     }
509
510     p_plugin->pf_wndproc = (WNDPROC)SetWindowLong( (HWND)window->window,
511                                                    GWL_WNDPROC, (LONG)Manage );
512     p_plugin->p_hwnd = (HWND)window->window;
513     SetProp( p_plugin->p_hwnd, "w00t", (HANDLE)p_plugin );
514     InvalidateRect( p_plugin->p_hwnd, NULL, TRUE );
515     UpdateWindow( p_plugin->p_hwnd );
516 #endif
517
518 #ifdef XP_UNIX
519     p_plugin->window = (Window) window->window;
520     p_plugin->p_display = ((NPSetWindowCallbackStruct *)window->ws_info)->display;
521
522     Widget w = XtWindowToWidget( p_plugin->p_display, p_plugin->window );
523     XtAddEventHandler( w, ExposureMask, FALSE,
524                        (XtEventHandler)Redraw, p_plugin );
525     Redraw( w, (XtPointer)p_plugin, NULL );
526 #endif
527
528     p_plugin->p_npwin = window;
529
530     p_plugin->i_width = window->width;
531     p_plugin->i_height = window->height;
532
533     if( !p_plugin->b_stream )
534     {
535         int i_mode = PLAYLIST_APPEND;
536
537         if( p_plugin->b_autoplay )
538         {
539             i_mode |= PLAYLIST_GO;
540         }
541
542         if( p_plugin->psz_target )
543         {
544 #if USE_LIBVLC
545             VLC_AddTarget( p_plugin->i_vlc, p_plugin->psz_target,
546                            0, 0, i_mode, PLAYLIST_END );
547 #endif
548             p_plugin->b_stream = VLC_TRUE;
549         }
550     }
551
552     return NPERR_NO_ERROR;
553 }
554
555 NPError NPP_NewStream( NPP instance, NPMIMEType type, NPStream *stream,
556                        NPBool seekable, uint16 *stype )
557 {
558     if( instance == NULL )
559     {
560         return NPERR_INVALID_INSTANCE_ERROR;
561     }
562
563 #if 0
564     VlcPlugin* p_plugin = (VlcPlugin*)instance->pdata;
565 #endif
566
567     /* fprintf(stderr, "NPP_NewStream - FILE mode !!\n"); */
568
569     /* We want a *filename* ! */
570     *stype = NP_ASFILE;
571
572 #if 0
573     if( !p_plugin->b_stream )
574     {
575         p_plugin->psz_target = strdup( stream->url );
576         p_plugin->b_stream = VLC_TRUE;
577     }
578 #endif
579
580     return NPERR_NO_ERROR;
581 }
582
583 int32 STREAMBUFSIZE = 0X0FFFFFFF; /* If we are reading from a file in NPAsFile
584                    * mode so we can take any size stream in our
585                    * write call (since we ignore it) */
586
587 #define SARASS_SIZE (1024*1024)
588
589 int32 NPP_WriteReady( NPP instance, NPStream *stream )
590 {
591     VlcPlugin* p_plugin;
592
593     /* fprintf(stderr, "NPP_WriteReady\n"); */
594
595     if (instance != NULL)
596     {
597         p_plugin = (VlcPlugin*) instance->pdata;
598         /* Muahahahahahahaha */
599         return STREAMBUFSIZE;
600         /*return SARASS_SIZE;*/
601     }
602
603     /* Number of bytes ready to accept in NPP_Write() */
604     return STREAMBUFSIZE;
605     /*return 0;*/
606 }
607
608
609 int32 NPP_Write( NPP instance, NPStream *stream, int32 offset,
610                  int32 len, void *buffer )
611 {
612     /* fprintf(stderr, "NPP_Write %i\n", (int)len); */
613
614     if( instance != NULL )
615     {
616         /*VlcPlugin* p_plugin = (VlcPlugin*) instance->pdata;*/
617     }
618
619     return len;         /* The number of bytes accepted */
620 }
621
622
623 NPError NPP_DestroyStream( NPP instance, NPStream *stream, NPError reason )
624 {
625     if( instance == NULL )
626     {
627         return NPERR_INVALID_INSTANCE_ERROR;
628     }
629
630     return NPERR_NO_ERROR;
631 }
632
633
634 void NPP_StreamAsFile( NPP instance, NPStream *stream, const char* fname )
635 {
636     if( instance == NULL )
637     {
638         return;
639     }
640
641     /* fprintf(stderr, "NPP_StreamAsFile %s\n", fname); */
642
643 #if USE_LIBVLC
644     VlcPlugin* p_plugin = (VlcPlugin*)instance->pdata;
645
646     VLC_AddTarget( p_plugin->i_vlc, fname, 0, 0,
647                    PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
648 #endif
649 }
650
651
652 void NPP_URLNotify( NPP instance, const char* url,
653                     NPReason reason, void* notifyData )
654 {
655     /***** Insert NPP_URLNotify code here *****\
656     PluginInstance* p_plugin;
657     if (instance != NULL)
658         p_plugin = (PluginInstance*) instance->pdata;
659     \*********************************************/
660 }
661
662
663 void NPP_Print( NPP instance, NPPrint* printInfo )
664 {
665     if( printInfo == NULL )
666     {
667         return;
668     }
669
670     if( instance != NULL )
671     {
672         /***** Insert NPP_Print code here *****\
673         PluginInstance* p_plugin = (PluginInstance*) instance->pdata;
674         \**************************************/
675
676         if( printInfo->mode == NP_FULL )
677         {
678             /*
679              * PLUGIN DEVELOPERS:
680              *  If your plugin would like to take over
681              *  printing completely when it is in full-screen mode,
682              *  set printInfo->pluginPrinted to TRUE and print your
683              *  plugin as you see fit.  If your plugin wants Netscape
684              *  to handle printing in this case, set
685              *  printInfo->pluginPrinted to FALSE (the default) and
686              *  do nothing.  If you do want to handle printing
687              *  yourself, printOne is true if the print button
688              *  (as opposed to the print menu) was clicked.
689              *  On the Macintosh, platformPrint is a THPrint; on
690              *  Windows, platformPrint is a structure
691              *  (defined in npapi.h) containing the printer name, port,
692              *  etc.
693              */
694
695             /***** Insert NPP_Print code here *****\
696             void* platformPrint =
697                 printInfo->print.fullPrint.platformPrint;
698             NPBool printOne =
699                 printInfo->print.fullPrint.printOne;
700             \**************************************/
701
702             /* Do the default*/
703             printInfo->print.fullPrint.pluginPrinted = FALSE;
704         }
705         else
706         {
707             /* If not fullscreen, we must be embedded */
708             /*
709              * PLUGIN DEVELOPERS:
710              *  If your plugin is embedded, or is full-screen
711              *  but you returned false in pluginPrinted above, NPP_Print
712              *  will be called with mode == NP_EMBED.  The NPWindow
713              *  in the printInfo gives the location and dimensions of
714              *  the embedded plugin on the printed page.  On the
715              *  Macintosh, platformPrint is the printer port; on
716              *  Windows, platformPrint is the handle to the printing
717              *  device context.
718              */
719
720             /***** Insert NPP_Print code here *****\
721             NPWindow* printWindow =
722                 &(printInfo->print.embedPrint.window);
723             void* platformPrint =
724                 printInfo->print.embedPrint.platformPrint;
725             \**************************************/
726         }
727     }
728 }
729
730 /******************************************************************************
731  * Windows-only methods
732  *****************************************************************************/
733 #ifdef XP_WIN
734 LRESULT CALLBACK Manage( HWND p_hwnd, UINT i_msg, WPARAM wpar, LPARAM lpar )
735 {
736     VlcPlugin* p_plugin = (VlcPlugin*) GetProp( p_hwnd, "w00t" );
737
738     switch( i_msg )
739     {
740 #if !USE_LIBVLC
741         case WM_PAINT:
742         {
743             PAINTSTRUCT paintstruct;
744             HDC hdc;
745             RECT rect;
746
747             hdc = BeginPaint( p_hwnd, &paintstruct );
748
749             GetClientRect( p_hwnd, &rect );
750             FillRect( hdc, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH) );
751             TextOut( hdc, p_plugin->i_width / 2 - 40, p_plugin->i_height / 2,
752                      WINDOW_TEXT, strlen(WINDOW_TEXT) );
753
754             EndPaint( p_hwnd, &paintstruct );
755             break;
756         }
757 #endif
758         default:
759             p_plugin->pf_wndproc( p_hwnd, i_msg, wpar, lpar );
760             break;
761     }
762     return 0;
763 }
764 #endif
765
766 /******************************************************************************
767  * UNIX-only methods
768  *****************************************************************************/
769 #ifdef XP_UNIX
770 static void Redraw( Widget w, XtPointer closure, XEvent *event )
771 {
772     VlcPlugin* p_plugin = (VlcPlugin*)closure;
773     GC gc;
774     XGCValues gcv;
775
776     gcv.foreground = BlackPixel( p_plugin->p_display, 0 );
777     gc = XCreateGC( p_plugin->p_display, p_plugin->window, GCForeground, &gcv );
778
779     XFillRectangle( p_plugin->p_display, p_plugin->window, gc,
780                     0, 0, p_plugin->i_width, p_plugin->i_height );
781
782     gcv.foreground = WhitePixel( p_plugin->p_display, 0 );
783     XChangeGC( p_plugin->p_display, gc, GCForeground, &gcv );
784
785     XDrawString( p_plugin->p_display, p_plugin->window, gc,
786                  p_plugin->i_width / 2 - 40, p_plugin->i_height / 2,
787                  WINDOW_TEXT, strlen(WINDOW_TEXT) );
788
789     XFreeGC( p_plugin->p_display, gc );
790 }
791 #endif
792