]> git.sesse.net Git - vlc/blob - mozilla/vlcshell.cpp
90f82880a443bc3f736b6fcf9a4a5aca52250403
[vlc] / mozilla / vlcshell.cpp
1 /*****************************************************************************
2  * vlcshell.cpp: a VLC plugin for Mozilla
3  *****************************************************************************
4  * Copyright (C) 2002-2005 the VideoLAN team
5  * $Id$
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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include "config.h"
28
29 #include <stdio.h>
30 #include <string.h>
31 #include <stdlib.h>
32
33 #ifdef XP_UNIX
34 #include <X11/xpm.h>
35 #endif
36
37 /* Mozilla stuff */
38 #ifdef HAVE_MOZILLA_CONFIG_H
39 #   include <mozilla-config.h>
40 #endif
41
42 /* This is from mozilla java, do we really need it? */
43 #if 0
44 #include <jri.h>
45 #endif
46
47 #include "vlcplugin.h"
48
49 /* Enable/disable debugging printf's for X11 resizing */
50 #undef X11_RESIZE_DEBUG
51
52 #define WINDOW_TEXT "Video is loading..."
53 #define CONTROL_HEIGHT 45
54
55 /*****************************************************************************
56  * Unix-only declarations
57 ******************************************************************************/
58 #ifdef XP_UNIX
59
60 static void Redraw( Widget w, XtPointer closure, XEvent *event );
61 static void ControlHandler( Widget w, XtPointer closure, XEvent *event );
62 static void Resize( Widget w, XtPointer closure, XEvent *event );
63
64 #endif
65
66 /*****************************************************************************
67  * MacOS-only declarations
68 ******************************************************************************/
69 #ifdef XP_MACOSX
70 #endif
71
72 /*****************************************************************************
73  * Windows-only declarations
74  *****************************************************************************/
75 #ifdef XP_WIN
76
77 static LRESULT CALLBACK Manage( HWND p_hwnd, UINT i_msg, WPARAM wpar, LPARAM lpar );
78
79 #endif
80
81 /******************************************************************************
82  * UNIX-only API calls
83  *****************************************************************************/
84 char * NPP_GetMIMEDescription( void )
85 {
86     return PLUGIN_MIMETYPES;
87 }
88
89 NPError NPP_GetValue( NPP instance, NPPVariable variable, void *value )
90 {
91
92     static char psz_desc[1000];
93
94     /* plugin class variables */
95     switch( variable )
96     {
97         case NPPVpluginNameString:
98             *((char **)value) = PLUGIN_NAME;
99             return NPERR_NO_ERROR;
100
101         case NPPVpluginDescriptionString:
102             snprintf( psz_desc, sizeof(psz_desc), PLUGIN_DESCRIPTION, VLC_Version() );
103             *((char **)value) = psz_desc;
104             return NPERR_NO_ERROR;
105
106         default:
107             /* move on to instance variables ... */
108             ;
109     }
110
111     if( instance == NULL )
112     {
113         return NPERR_INVALID_INSTANCE_ERROR;
114     }
115
116     /* plugin instance variables */
117
118     VlcPlugin* p_plugin = reinterpret_cast<VlcPlugin*>(instance->pdata);
119     if( NULL == p_plugin )
120     {
121         // plugin has not been initialized yet !
122         return NPERR_INVALID_INSTANCE_ERROR;
123     }
124
125     switch( variable )
126     {
127         case NPPVpluginScriptableNPObject:
128         {
129             /* retrieve plugin root class */
130             NPClass *scriptClass = p_plugin->getScriptClass();
131             if( scriptClass )
132             {
133                 /* create an instance and return it */
134                 *(NPObject**)value = NPN_CreateObject(instance, scriptClass);
135                 return NPERR_NO_ERROR;
136             }
137             break;
138         }
139
140         default:
141             ;
142     }
143     return NPERR_GENERIC_ERROR;
144 }
145
146 /*
147  * there is some confusion in gecko headers regarding definition of this API
148  * NPPVariable is wrongly defined as NPNVariable, which sounds incorrect.
149  */
150
151 NPError NPP_SetValue( NPP instance, NPNVariable variable, void *value )
152 {
153     return NPERR_GENERIC_ERROR;
154 }
155
156 /******************************************************************************
157  * Mac-only API calls
158  *****************************************************************************/
159 #ifdef XP_MACOSX
160 int16 NPP_HandleEvent( NPP instance, void * event )
161 {
162     static UInt32 lastMouseUp = 0;
163
164     if( instance == NULL )
165     {
166         return false;
167     }
168
169     VlcPlugin *p_plugin = (VlcPlugin*)instance->pdata;
170
171     if( p_plugin == NULL )
172     {
173         return false;
174     }
175
176     EventRecord *myEvent = (EventRecord*)event;
177
178     switch( myEvent->what )
179     {
180         case nullEvent:
181             return true;
182         case mouseDown:
183         {
184             if( (myEvent->when - lastMouseUp) < GetDblTime() )
185             {
186                 /* double click */
187                 libvlc_instance_t *p_vlc = p_plugin->getVLC();
188
189                 if( p_vlc )
190                 {
191                     if( libvlc_playlist_isplaying(p_vlc, NULL) )
192                     {
193                         libvlc_media_instance_t *p_md =
194                             libvlc_playlist_get_media_instance(p_vlc, NULL);
195                         if( p_md )
196                         {
197                             libvlc_toggle_fullscreen(p_md, NULL);
198                             libvlc_media_instance_release(p_md);
199                         }
200                     }
201                 }
202             }
203             return true;
204         }
205         case mouseUp:
206             lastMouseUp = myEvent->when;
207             return true;
208         case keyUp:
209         case keyDown:
210         case autoKey:
211             return true;
212         case updateEvt:
213         {
214             const NPWindow& npwindow = p_plugin->getWindow();
215             if( npwindow.window )
216             {
217                 int hasVout = FALSE;
218                 libvlc_instance_t *p_vlc = p_plugin->getVLC();
219
220                 if( p_vlc )
221                 {
222                     if( libvlc_playlist_isplaying(p_vlc, NULL) )
223                     {
224                         libvlc_media_instance_t *p_md =
225                             libvlc_playlist_get_media_instance(p_vlc, NULL);
226                         if( p_md )
227                         {
228                             hasVout = libvlc_media_instance_has_vout(p_md, NULL);
229                             if( hasVout )
230                             {
231                                 libvlc_rectangle_t area;
232                                 area.left = 0;
233                                 area.top = 0;
234                                 area.right = npwindow.width;
235                                 area.bottom = npwindow.height;
236                                 libvlc_video_redraw_rectangle(p_md, &area, NULL);
237                             }
238                             libvlc_media_instance_release(p_md);
239                         }
240                     }
241                 }
242
243                 if( ! hasVout )
244                 {
245                     /* draw the beautiful "No Picture" */
246
247                     ForeColor(blackColor);
248                     PenMode( patCopy );
249
250                     /* seems that firefox forgets to set the following on occasion (reload) */
251                     SetOrigin(((NP_Port *)npwindow.window)->portx,
252                               ((NP_Port *)npwindow.window)->porty);
253
254                     Rect rect;
255                     rect.left = 0;
256                     rect.top = 0;
257                     rect.right = npwindow.width;
258                     rect.bottom = npwindow.height;
259                     PaintRect( &rect );
260
261                     ForeColor(whiteColor);
262                     MoveTo( (npwindow.width-80)/ 2  , npwindow.height / 2 );
263                     DrawText( WINDOW_TEXT , 0 , strlen(WINDOW_TEXT) );
264                 }
265             }
266             return true;
267         }
268         case activateEvt:
269             return false;
270         case NPEventType_GetFocusEvent:
271         case NPEventType_LoseFocusEvent:
272             return true;
273         case NPEventType_AdjustCursorEvent:
274             return false;
275         case NPEventType_MenuCommandEvent:
276             return false;
277         case NPEventType_ClippingChangedEvent:
278             return false;
279         case NPEventType_ScrollingBeginsEvent:
280             return true;
281         case NPEventType_ScrollingEndsEvent:
282             return true;
283         default:
284             ;
285     }
286     return false;
287 }
288 #endif /* XP_MACOSX */
289
290 /******************************************************************************
291  * General Plug-in Calls
292  *****************************************************************************/
293 NPError NPP_Initialize( void )
294 {
295     return NPERR_NO_ERROR;
296 }
297
298 jref NPP_GetJavaClass( void )
299 {
300     return NULL;
301 }
302
303 void NPP_Shutdown( void )
304 {
305     ;
306 }
307
308 NPError NPP_New( NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc,
309                  char* argn[], char* argv[], NPSavedData* saved )
310 {
311     NPError status;
312
313     if( instance == NULL )
314     {
315         return NPERR_INVALID_INSTANCE_ERROR;
316     }
317
318     VlcPlugin * p_plugin = new VlcPlugin( instance, mode );
319     if( NULL == p_plugin )
320     {
321         return NPERR_OUT_OF_MEMORY_ERROR;
322     }
323
324     status = p_plugin->init(argc, argn, argv);
325     if( NPERR_NO_ERROR == status )
326     {
327         instance->pdata = reinterpret_cast<void*>(p_plugin);
328 #if 0
329         NPN_SetValue(instance, NPPVpluginWindowBool, (void *)false);
330         NPN_SetValue(instance, NPPVpluginTransparentBool, (void *)false);
331 #endif
332     }
333     else
334     {
335         delete p_plugin;
336     }
337     return status;
338 }
339
340 NPError NPP_Destroy( NPP instance, NPSavedData** save )
341 {
342     if( NULL == instance )
343         return NPERR_INVALID_INSTANCE_ERROR;
344
345     VlcPlugin* p_plugin = reinterpret_cast<VlcPlugin*>(instance->pdata);
346     if( NULL == p_plugin )
347         return NPERR_NO_ERROR;
348
349     instance->pdata = NULL;
350
351 #if XP_WIN
352     HWND win = (HWND)p_plugin->getWindow().window;
353     WNDPROC winproc = p_plugin->getWindowProc();
354     if( winproc )
355     {
356         /* reset WNDPROC */
357         SetWindowLong( win, GWL_WNDPROC, (LONG)winproc );
358     }
359 #endif
360
361     delete p_plugin;
362
363     return NPERR_NO_ERROR;
364 }
365
366 NPError NPP_SetWindow( NPP instance, NPWindow* window )
367 {
368     if( ! instance )
369     {
370         return NPERR_INVALID_INSTANCE_ERROR;
371     }
372
373     /* NPP_SetWindow may be called before NPP_New (Opera) */
374     VlcPlugin* p_plugin = reinterpret_cast<VlcPlugin*>(instance->pdata);
375     if( ! p_plugin )
376     {
377         /* we should probably show a splash screen here */
378         return NPERR_NO_ERROR;
379     }
380
381     libvlc_instance_t *p_vlc = p_plugin->getVLC();
382
383     /*
384      * PLUGIN DEVELOPERS:
385      *  Before setting window to point to the
386      *  new window, you may wish to compare the new window
387      *  info to the previous window (if any) to note window
388      *  size changes, etc.
389      */
390
391     /* retrieve current window */
392     NPWindow& curwin = p_plugin->getWindow();
393
394 #ifdef XP_MACOSX
395     if( window && window->window )
396     {
397         /* check if plugin has a new parent window */
398         CGrafPtr drawable = (((NP_Port*) (window->window))->port);
399         if( !curwin.window || drawable != (((NP_Port*) (curwin.window))->port) )
400         {
401             /* set/change parent window */
402             libvlc_video_set_parent(p_vlc, (libvlc_drawable_t)drawable, NULL);
403         }
404
405         /* as MacOS X video output is windowless, set viewport */
406         libvlc_rectangle_t view, clip;
407
408         /*
409         ** browser sets port origin to top-left location of plugin relative to GrafPort
410         ** window origin is set relative to document, which of little use for drawing
411         */
412         view.top     = ((NP_Port*) (window->window))->porty;
413         view.left    = ((NP_Port*) (window->window))->portx;
414         view.bottom  = window->height+view.top;
415         view.right   = window->width+view.left;
416         /* clipRect coordinates are also relative to GrafPort */
417         clip.top     = window->clipRect.top;
418         clip.left    = window->clipRect.left;
419         clip.bottom  = window->clipRect.bottom;
420         clip.right   = window->clipRect.right;
421
422         libvlc_video_set_viewport(p_vlc, &view, &clip, NULL);
423
424         /* remember new window */
425         p_plugin->setWindow(*window);
426     }
427     else if( curwin.window ) {
428         /* change/set parent */
429         libvlc_video_set_parent(p_vlc, 0, NULL);
430         curwin.window = NULL;
431     }
432 #endif /* XP_MACOSX */
433
434 #ifdef XP_WIN
435     if( window && window->window )
436     {
437         /* check if plugin has a new parent window */
438         HWND drawable = (HWND) (window->window);
439         if( !curwin.window || drawable != curwin.window )
440         {
441             /* reset previous window settings */
442             HWND oldwin = (HWND)p_plugin->getWindow().window;
443             WNDPROC oldproc = p_plugin->getWindowProc();
444             if( oldproc )
445             {
446                 /* reset WNDPROC */
447                 SetWindowLong( oldwin, GWL_WNDPROC, (LONG)oldproc );
448             }
449             /* attach our plugin object */
450             SetWindowLongPtr((HWND)drawable, GWLP_USERDATA,
451                              reinterpret_cast<LONG_PTR>(p_plugin));
452
453             /* install our WNDPROC */
454             p_plugin->setWindowProc( (WNDPROC)SetWindowLong( drawable,
455                                              GWL_WNDPROC, (LONG)Manage ) );
456
457             /* change window style to our liking */
458             LONG style = GetWindowLong((HWND)drawable, GWL_STYLE);
459             style |= WS_CLIPCHILDREN|WS_CLIPSIBLINGS;
460             SetWindowLong((HWND)drawable, GWL_STYLE, style);
461
462             /* change/set parent */
463             libvlc_video_set_parent(p_vlc, (libvlc_drawable_t)drawable, NULL);
464
465             /* remember new window */
466             p_plugin->setWindow(*window);
467
468             /* Redraw window */
469             InvalidateRect( (HWND)drawable, NULL, TRUE );
470             UpdateWindow( (HWND)drawable );
471         }
472     }
473     else if ( curwin.window )
474     {
475         /* reset WNDPROC */
476         HWND oldwin = (HWND)curwin.window;
477         SetWindowLong( oldwin, GWL_WNDPROC, (LONG)(p_plugin->getWindowProc()) );
478         p_plugin->setWindowProc(NULL);
479         /* change/set parent */
480         libvlc_video_set_parent(p_vlc, 0, NULL);
481         curwin.window = NULL;
482     }
483 #endif /* XP_WIN */
484
485 #ifdef XP_UNIX
486     if( window && window->window )
487     {
488         Window  parent   = (Window) window->window;
489         if( !curwin.window || (parent != (Window)curwin.window) )
490         {
491             Display *p_display = ((NPSetWindowCallbackStruct *)window->ws_info)->display;
492
493             XResizeWindow( p_display, parent, window->width, window->height );
494
495             int i_blackColor = BlackPixel(p_display, DefaultScreen(p_display));
496
497             Window video = XCreateSimpleWindow( p_display, parent, 0, 0,
498                            window->width, window->height - CONTROL_HEIGHT, 0,
499                            i_blackColor, i_blackColor );
500             Window controls = XCreateSimpleWindow( p_display, parent, 0,
501                             window->height - CONTROL_HEIGHT-1, window->width,
502                             CONTROL_HEIGHT-1, 0, i_blackColor, i_blackColor );
503
504             XMapWindow( p_display, parent );
505             XMapWindow( p_display, video );
506             XMapWindow( p_display, controls );
507
508             XFlush(p_display);
509
510             Widget w = XtWindowToWidget( p_display, parent );
511
512             XtAddEventHandler( w, ExposureMask, FALSE,
513                                (XtEventHandler)Redraw, p_plugin );
514             XtAddEventHandler( w, StructureNotifyMask, FALSE,
515                                (XtEventHandler)Resize, p_plugin );
516             XtAddEventHandler( w, ButtonReleaseMask, FALSE,
517                                (XtEventHandler)ControlHandler, p_plugin );
518
519             /* callback */
520 /*
521             libvlc_media_instance_t *p_md;
522
523             libvlc_exception_t ex;
524             libvlc_exception_init(& ex );
525             p_md = libvlc_playlist_get_media_instance( p_plugin->getVLC(), &ex );
526             libvlc_exception_init( &ex );
527             libvlc_event_attach( libvlc_media_instance_event_manager( p_md, &ex ),
528                                  libvlc_MediaInstancePositionChanged, Redraw, NULL, &ex );
529 */
530
531             /* set/change parent window */
532             libvlc_video_set_parent( p_vlc, (libvlc_drawable_t) video, NULL );
533
534             /* remember window */
535             p_plugin->setWindow( *window );
536             p_plugin->setVideoWindow( video );
537             p_plugin->setControlWindow( controls );
538
539             Redraw( w, (XtPointer)p_plugin, NULL );
540         }
541     }
542     else if ( curwin.window )
543     {
544         /* change/set parent */
545         libvlc_video_set_parent(p_vlc, 0, NULL);
546         curwin.window = NULL;
547     }
548 #endif /* XP_UNIX */
549
550     if( !p_plugin->b_stream )
551     {
552         if( p_plugin->psz_target )
553         {
554             if( libvlc_playlist_add( p_vlc, p_plugin->psz_target,
555                                      NULL, NULL ) != -1 )
556             {
557                 if( p_plugin->b_autoplay )
558                 {
559                     libvlc_playlist_play(p_vlc, 0, 0, NULL, NULL);
560                 }
561             }
562             p_plugin->b_stream = VLC_TRUE;
563         }
564     }
565     return NPERR_NO_ERROR;
566 }
567
568 NPError NPP_NewStream( NPP instance, NPMIMEType type, NPStream *stream,
569                        NPBool seekable, uint16 *stype )
570 {
571     if( NULL == instance  )
572     {
573         return NPERR_INVALID_INSTANCE_ERROR;
574     }
575
576     VlcPlugin *p_plugin = reinterpret_cast<VlcPlugin *>(instance->pdata);
577     if( NULL == p_plugin )
578     {
579         return NPERR_INVALID_INSTANCE_ERROR;
580     }
581
582    /*
583    ** Firefox/Mozilla may decide to open a stream from the URL specified
584    ** in the SRC parameter of the EMBED tag and pass it to us
585    **
586    ** since VLC will open the SRC URL as well, we're not interested in
587    ** that stream. Otherwise, we'll take it and queue it up in the playlist
588    */
589     if( !p_plugin->psz_target || strcmp(stream->url, p_plugin->psz_target) )
590     {
591         /* TODO: use pipes !!!! */
592         *stype = NP_ASFILEONLY;
593         return NPERR_NO_ERROR;
594     }
595     return NPERR_GENERIC_ERROR;
596 }
597
598 int32 NPP_WriteReady( NPP instance, NPStream *stream )
599 {
600     /* TODO */
601     return 8*1024;
602 }
603
604
605 int32 NPP_Write( NPP instance, NPStream *stream, int32 offset,
606                  int32 len, void *buffer )
607 {
608     /* TODO */
609     return len;
610 }
611
612
613 NPError NPP_DestroyStream( NPP instance, NPStream *stream, NPError reason )
614 {
615     if( instance == NULL )
616     {
617         return NPERR_INVALID_INSTANCE_ERROR;
618     }
619     return NPERR_NO_ERROR;
620 }
621
622
623 void NPP_StreamAsFile( NPP instance, NPStream *stream, const char* fname )
624 {
625     if( instance == NULL )
626     {
627         return;
628     }
629
630     VlcPlugin *p_plugin = reinterpret_cast<VlcPlugin *>(instance->pdata);
631     if( NULL == p_plugin )
632     {
633         return;
634     }
635
636     if( libvlc_playlist_add( p_plugin->getVLC(), fname, stream->url, NULL ) != -1 )
637     {
638         if( p_plugin->b_autoplay )
639         {
640             libvlc_playlist_play( p_plugin->getVLC(), 0, 0, NULL, NULL);
641         }
642     }
643 }
644
645
646 void NPP_URLNotify( NPP instance, const char* url,
647                     NPReason reason, void* notifyData )
648 {
649     /***** Insert NPP_URLNotify code here *****\
650     PluginInstance* p_plugin;
651     if (instance != NULL)
652         p_plugin = (PluginInstance*) instance->pdata;
653     \*********************************************/
654 }
655
656
657 void NPP_Print( NPP instance, NPPrint* printInfo )
658 {
659     if( printInfo == NULL )
660     {
661         return;
662     }
663
664     if( instance != NULL )
665     {
666         /***** Insert NPP_Print code here *****\
667         PluginInstance* p_plugin = (PluginInstance*) instance->pdata;
668         \**************************************/
669
670         if( printInfo->mode == NP_FULL )
671         {
672             /*
673              * PLUGIN DEVELOPERS:
674              *  If your plugin would like to take over
675              *  printing completely when it is in full-screen mode,
676              *  set printInfo->pluginPrinted to TRUE and print your
677              *  plugin as you see fit.  If your plugin wants Netscape
678              *  to handle printing in this case, set
679              *  printInfo->pluginPrinted to FALSE (the default) and
680              *  do nothing.  If you do want to handle printing
681              *  yourself, printOne is true if the print button
682              *  (as opposed to the print menu) was clicked.
683              *  On the Macintosh, platformPrint is a THPrint; on
684              *  Windows, platformPrint is a structure
685              *  (defined in npapi.h) containing the printer name, port,
686              *  etc.
687              */
688
689             /***** Insert NPP_Print code here *****\
690             void* platformPrint =
691                 printInfo->print.fullPrint.platformPrint;
692             NPBool printOne =
693                 printInfo->print.fullPrint.printOne;
694             \**************************************/
695
696             /* Do the default*/
697             printInfo->print.fullPrint.pluginPrinted = FALSE;
698         }
699         else
700         {
701             /* If not fullscreen, we must be embedded */
702             /*
703              * PLUGIN DEVELOPERS:
704              *  If your plugin is embedded, or is full-screen
705              *  but you returned false in pluginPrinted above, NPP_Print
706              *  will be called with mode == NP_EMBED.  The NPWindow
707              *  in the printInfo gives the location and dimensions of
708              *  the embedded plugin on the printed page.  On the
709              *  Macintosh, platformPrint is the printer port; on
710              *  Windows, platformPrint is the handle to the printing
711              *  device context.
712              */
713
714             /***** Insert NPP_Print code here *****\
715             NPWindow* printWindow =
716                 &(printInfo->print.embedPrint.window);
717             void* platformPrint =
718                 printInfo->print.embedPrint.platformPrint;
719             \**************************************/
720         }
721     }
722 }
723
724 /******************************************************************************
725  * Windows-only methods
726  *****************************************************************************/
727 #if XP_WIN
728 static LRESULT CALLBACK Manage( HWND p_hwnd, UINT i_msg, WPARAM wpar, LPARAM lpar )
729 {
730     VlcPlugin* p_plugin = reinterpret_cast<VlcPlugin*>(GetWindowLongPtr(p_hwnd, GWLP_USERDATA));
731
732     switch( i_msg )
733     {
734         case WM_ERASEBKGND:
735             return 1L;
736
737         case WM_PAINT:
738         {
739             PAINTSTRUCT paintstruct;
740             HDC hdc;
741             RECT rect;
742
743             hdc = BeginPaint( p_hwnd, &paintstruct );
744
745             GetClientRect( p_hwnd, &rect );
746
747             FillRect( hdc, &rect, (HBRUSH)GetStockObject(BLACK_BRUSH) );
748             SetTextColor(hdc, RGB(255, 255, 255));
749             SetBkColor(hdc, RGB(0, 0, 0));
750             DrawText( hdc, WINDOW_TEXT, strlen(WINDOW_TEXT), &rect,
751                       DT_CENTER|DT_VCENTER|DT_SINGLELINE);
752
753             EndPaint( p_hwnd, &paintstruct );
754             return 0L;
755         }
756         default:
757             /* delegate to default handler */
758             return CallWindowProc(p_plugin->getWindowProc(), p_hwnd, i_msg, wpar, lpar );
759     }
760 }
761 #endif /* XP_WIN */
762
763 /******************************************************************************
764  * UNIX-only methods
765  *****************************************************************************/
766 #ifdef XP_UNIX
767 static void Redraw( Widget w, XtPointer closure, XEvent *event )
768 {
769     VlcPlugin* p_plugin = reinterpret_cast<VlcPlugin*>(closure);
770     const NPWindow& window = p_plugin->getWindow();
771     GC gc;
772     XGCValues gcv;
773
774     /* Toolbar */
775     XImage *p_playIcon = NULL;
776     XImage *p_pauseIcon = NULL;
777     XImage *p_stopIcon = NULL;
778     XImage *p_timeline = NULL;
779     XImage *p_timeKnob = NULL;
780     XImage *p_fscreen = NULL;
781     XImage *p_muteIcon = NULL;
782     XImage *p_unmuteIcon = NULL;
783
784     libvlc_media_instance_t *p_md = NULL;
785     float f_position = 0;
786     int i_playing = 0;
787     bool b_mute = false;
788
789     Window video = p_plugin->getVideoWindow();
790     Window control = p_plugin->getControlWindow();
791     Display *p_display = ((NPSetWindowCallbackStruct *)window.ws_info)->display;
792
793     gcv.foreground = BlackPixel( p_display, 0 );
794     gc = XCreateGC( p_display, video, GCForeground, &gcv );
795
796     XFillRectangle( p_display, video, gc,
797                     0, 0, window.width, window.height - CONTROL_HEIGHT );
798
799     gcv.foreground = WhitePixel( p_display, 0 );
800     XChangeGC( p_display, gc, GCForeground, &gcv );
801
802     XDrawString( p_display, video, gc,
803                  window.width / 2 - 40, (window.height - CONTROL_HEIGHT) / 2,
804                  WINDOW_TEXT, strlen(WINDOW_TEXT) );
805
806     /* RedrawToolbar */
807     gcv.foreground = BlackPixel( p_display, 0 );
808     gc = XCreateGC( p_display, control, GCForeground, &gcv );
809
810     XFillRectangle( p_display, control, gc,
811                     0, 0, window.width, CONTROL_HEIGHT );
812
813
814     gcv.foreground = WhitePixel( p_display, 0 );
815     XChangeGC( p_display, gc, GCForeground, &gcv );
816
817     /* get media instance */
818     libvlc_exception_t ex;
819     libvlc_exception_init( &ex );
820     p_md = libvlc_playlist_get_media_instance( p_plugin->getVLC(), &ex );
821     libvlc_exception_clear( &ex );
822
823     /* get isplaying */
824     libvlc_exception_init( &ex );
825     i_playing = libvlc_playlist_isplaying( p_plugin->getVLC(), &ex );
826     libvlc_exception_clear( &ex );
827
828     /* get mute info */
829     libvlc_exception_init(&ex);
830     b_mute = libvlc_audio_get_mute( p_plugin->getVLC(), &ex );
831     libvlc_exception_clear( &ex );
832
833     /* get movie position in % */
834     if( i_playing == 1 )
835     {
836         libvlc_exception_init( &ex );
837         f_position = libvlc_media_instance_get_position(p_md, &ex)*100;
838         libvlc_exception_clear( &ex );
839     }
840     libvlc_media_instance_release(p_md);
841
842     /* load icons */
843     XpmReadFileToImage( p_display, "/usr/share/vlc/mozilla/play.xpm",
844                         &p_playIcon, NULL, NULL);
845     XpmReadFileToImage( p_display, "/usr/share/vlc/mozilla/pause.xpm",
846                         &p_pauseIcon, NULL, NULL);
847     XpmReadFileToImage( p_display, "/usr/share/vlc/mozilla/stop.xpm",
848                         &p_stopIcon, NULL, NULL );
849     XpmReadFileToImage( p_display, "/usr/share/vlc/mozilla/time_line.xpm",
850                         &p_timeline, NULL, NULL);
851     XpmReadFileToImage( p_display, "/usr/share/vlc/mozilla/time_icon.xpm",
852                         &p_timeKnob, NULL, NULL);
853     XpmReadFileToImage( p_display, "/usr/share/vlc/mozilla/fullscreen.xpm",
854                         &p_fscreen, NULL, NULL);
855     XpmReadFileToImage( p_display, "/usr/share/vlc/mozilla/volume_max.xpm",
856                         &p_muteIcon, NULL, NULL);
857     XpmReadFileToImage( p_display, "/usr/share/vlc/mozilla/volume_mute.xpm",
858                         &p_unmuteIcon, NULL, NULL);
859
860 #if 1 /* DEBUG */
861     if( !p_playIcon )
862     {
863         fprintf(stderr, "Error: playImage not found\n");
864     }
865     if( !p_pauseIcon )
866     {
867         fprintf(stderr, "Error: pauseImage not found\n");
868     }
869     if( !p_stopIcon )
870     {
871         fprintf(stderr, "Error: stopImage not found\n");
872     }
873     if( !p_timeline )
874     {
875         fprintf(stderr, "Error: TimeLineImage not found\n");
876     }
877     if( !p_timeKnob )
878     {
879         fprintf(stderr, "Error: TimeIcon not found\n");
880     }
881     if( !p_fscreen )
882     {
883         fprintf(stderr, "Error: FullscreenImage not found\n");
884     }
885     if( !p_muteIcon )
886     {
887         fprintf(stderr, "Error: MuteImage not found\n");
888     }
889     if( !p_unmuteIcon )
890     {
891         fprintf(stderr, "Error: UnMuteImage not found\n");
892     }
893 #endif
894
895     /* position icons */
896     if( p_pauseIcon && (i_playing == 1) )
897     {
898         XPutImage( p_display, control, gc, p_pauseIcon, 0, 0, 4, 14,
899                    p_pauseIcon->width, p_pauseIcon->height );
900     }
901     else if( p_playIcon )
902     {
903         XPutImage( p_display, control, gc, p_playIcon, 0, 0, 4, 14,
904                    p_playIcon->width, p_playIcon->height );
905     }
906
907     if( p_stopIcon )
908         XPutImage( p_display, control, gc, p_stopIcon, 0, 0, 39, 14,
909                    p_stopIcon->width, p_stopIcon->height );
910     if( p_fscreen )
911         XPutImage( p_display, control, gc, p_fscreen, 0, 0, 67, 21,
912                    p_fscreen->width, p_fscreen->height );
913
914     if( p_unmuteIcon && b_mute )
915     {
916         XPutImage( p_display, control, gc, p_unmuteIcon, 0, 0, 94, 30,
917                  p_unmuteIcon->width, p_unmuteIcon->height );
918     }
919     else if( p_muteIcon )
920     {
921         XPutImage( p_display, control, gc, p_muteIcon, 0, 0, 94, 30,
922                    p_muteIcon->width, p_muteIcon->height );
923     }
924
925     if( p_timeline )
926         XPutImage( p_display, control, gc, p_timeline, 0, 0, 4, 4,
927                    (window.width-8), p_timeline->height );
928     if( p_timeKnob && (f_position > 0) )
929     {
930         f_position = (((float)window.width-8)/100)*f_position;
931         XPutImage( p_display, control, gc, p_timeKnob, 0, 0, (4+f_position), 2,
932                    p_timeKnob->width, p_timeKnob->height );
933     }
934
935     /* Cleanup */
936     if( p_playIcon )   XDestroyImage( p_playIcon );
937     if( p_pauseIcon )  XDestroyImage( p_pauseIcon );
938     if( p_stopIcon )   XDestroyImage( p_stopIcon );
939     if( p_timeline )   XDestroyImage( p_timeline );
940     if( p_timeKnob )   XDestroyImage( p_timeKnob );
941     if( p_fscreen )    XDestroyImage( p_fscreen );
942     if( p_muteIcon )   XDestroyImage( p_muteIcon );
943     if( p_unmuteIcon ) XDestroyImage( p_unmuteIcon );
944
945     XFreeGC( p_display, gc );
946 }
947
948 static void ControlHandler( Widget w, XtPointer closure, XEvent *event )
949 {
950     VlcPlugin* p_plugin = reinterpret_cast<VlcPlugin*>(closure);
951     const NPWindow& window = p_plugin->getWindow();
952
953     int i_height = window.height;
954     int i_width = window.width;
955     int i_xPos = event->xbutton.x;
956     int i_yPos = event->xbutton.y;
957
958     libvlc_exception_t ex;
959     libvlc_exception_init( &ex );
960     libvlc_media_instance_t *p_md =
961             libvlc_playlist_get_media_instance(p_plugin->getVLC(), &ex);
962     libvlc_exception_clear( &ex );
963
964     /* jump in the movie */
965     if( i_yPos <= (i_height-30) )
966     {
967         vlc_int64_t f_length;
968         libvlc_exception_init( &ex );
969         f_length = libvlc_media_instance_get_length( p_md, &ex ) / 100;
970         libvlc_exception_clear( &ex );
971
972         f_length = (float)f_length *
973                    ( ((float)i_xPos-4 ) / ( ((float)i_width-8)/100) );
974
975         libvlc_exception_init( &ex );
976         libvlc_media_instance_set_time( p_md, f_length, &ex );
977         libvlc_exception_clear( &ex );
978     }
979
980     /* play/pause toggle */
981     if( (i_yPos > (i_height-30)) && (i_xPos > 4) && (i_xPos <= 39) )
982     {
983         int i_playing;
984         libvlc_exception_init( &ex );
985         i_playing = libvlc_playlist_isplaying( p_plugin->getVLC(), &ex );
986         libvlc_exception_clear( &ex );
987
988         libvlc_exception_init( &ex );
989         if( i_playing == 1 )
990             libvlc_playlist_pause( p_plugin->getVLC(), &ex );
991         else
992             libvlc_playlist_play( p_plugin->getVLC(), -1, 0, NULL, &ex );
993         libvlc_exception_clear( &ex );
994     }
995
996     /* stop */
997     if( (i_yPos > (i_height-30)) && (i_xPos > 39) && (i_xPos < 67) )
998     {
999         libvlc_exception_init( &ex );
1000         libvlc_playlist_stop( p_plugin->getVLC(), &ex );
1001         libvlc_exception_clear( &ex );
1002     }
1003
1004     /* fullscreen */
1005     if( (i_yPos > (i_height-30)) && (i_xPos >= 67) && (i_xPos < 94) )
1006     {
1007         libvlc_exception_init( &ex );
1008         libvlc_set_fullscreen( p_md, 1, &ex );
1009         libvlc_exception_clear( &ex );
1010     }
1011
1012     /* mute toggle */
1013     if( (i_yPos > (i_height-30)) && (i_xPos >= 94) && (i_xPos < 109))
1014     {
1015         libvlc_exception_init( &ex );
1016         libvlc_audio_toggle_mute( p_plugin->getVLC(), &ex );
1017         libvlc_exception_clear( &ex );
1018     }
1019     libvlc_media_instance_release( p_md );
1020
1021     Redraw( w, closure, event );
1022 }
1023
1024 static void Resize ( Widget w, XtPointer closure, XEvent *event )
1025 {
1026     VlcPlugin* p_plugin = reinterpret_cast<VlcPlugin*>(closure);
1027     const NPWindow& window = p_plugin->getWindow();
1028     Window  drawable   = p_plugin->getVideoWindow();
1029     Display *p_display = ((NPSetWindowCallbackStruct *)window.ws_info)->display;
1030
1031     int i_ret;
1032     Window root_return, parent_return, * children_return;
1033     Window base_window;
1034     unsigned int i_nchildren;
1035
1036 #ifdef X11_RESIZE_DEBUG
1037     XWindowAttributes attr;
1038
1039     if( event && event->type == ConfigureNotify )
1040     {
1041         fprintf( stderr, "vlcshell::Resize() ConfigureNotify %d x %d, "
1042                  "send_event ? %s\n", event->xconfigure.width,
1043                  event->xconfigure.height,
1044                  event->xconfigure.send_event ? "TRUE" : "FALSE" );
1045     }
1046 #endif /* X11_RESIZE_DEBUG */
1047
1048     if( ! p_plugin->setSize(window.width, (window.height - CONTROL_HEIGHT)) )
1049     {
1050         /* size already set */
1051         return;
1052     }
1053
1054
1055     i_ret = XResizeWindow( p_display, drawable, window.width, (window.height - CONTROL_HEIGHT) );
1056
1057 #ifdef X11_RESIZE_DEBUG
1058     fprintf( stderr,
1059              "vlcshell::Resize() XResizeWindow(owner) returned %d\n", i_ret );
1060
1061     XGetWindowAttributes ( p_display, drawable, &attr );
1062
1063     /* X is asynchronous, so the current size reported here is not
1064        necessarily the requested size as the Resize request may not
1065        yet have been handled by the plugin host */
1066     fprintf( stderr, "vlcshell::Resize() current (owner) size %d x %d\n",
1067              attr.width, attr.height );
1068 #endif /* X11_RESIZE_DEBUG */
1069
1070     XQueryTree( p_display, drawable,
1071                 &root_return, &parent_return, &children_return,
1072                 &i_nchildren );
1073
1074     if( i_nchildren > 0 )
1075     {
1076         /* XXX: Make assumptions related to the window parenting structure in
1077            vlc/modules/video_output/x11/xcommon.c */
1078         base_window = children_return[i_nchildren - 1];
1079
1080 #ifdef X11_RESIZE_DEBUG
1081         fprintf( stderr, "vlcshell::Resize() got %d children\n", i_nchildren );
1082         fprintf( stderr, "vlcshell::Resize() got base_window %p\n",
1083                  base_window );
1084 #endif /* X11_RESIZE_DEBUG */
1085
1086         i_ret = XResizeWindow( p_display, base_window,
1087                 window.width, ( window.height - CONTROL_HEIGHT ) );
1088
1089 #ifdef X11_RESIZE_DEBUG
1090         fprintf( stderr,
1091                  "vlcshell::Resize() XResizeWindow(base) returned %d\n",
1092                  i_ret );
1093
1094         XGetWindowAttributes( p_display, base_window, &attr );
1095
1096         fprintf( stderr, "vlcshell::Resize() new size %d x %d\n",
1097                  attr.width, attr.height );
1098 #endif /* X11_RESIZE_DEBUG */
1099     }
1100 }
1101
1102 #endif /* XP_UNIX */
1103