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