- the resurected mozilla plugin for Safari/Firefox on MacOS X
[vlc.git] / 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 /* XXX: disable VLC here */
25 #define USE_LIBVLC 1
26
27 /*****************************************************************************
28  * Preamble
29  *****************************************************************************/
30 #include "config.h"
31
32 #include <stdio.h>
33 #include <string.h>
34 #include <stdlib.h>
35
36 /* vlc stuff */
37 #ifdef USE_LIBVLC
38 #   include <vlc/vlc.h>
39 #endif
40
41 /* Mozilla stuff */
42 #ifdef HAVE_MOZILLA_CONFIG_H
43 #   include <mozilla-config.h>
44 #endif
45 #include <nsISupports.h>
46 #include <nsMemory.h>
47 #include <npapi.h>
48 #include <npruntime.h>
49
50 /* This is from mozilla java, do we really need it? */
51 #if 0
52 #include <jri.h>
53 #endif
54
55 #include "vlcplugin.h"
56 #include "vlcruntime.h"
57
58 #if USE_LIBVLC
59 #   define WINDOW_TEXT "(no picture)"
60 #else
61 #   define WINDOW_TEXT "(no libvlc)"
62 #endif
63
64 /* Enable/disable debugging printf's for X11 resizing */
65 #undef X11_RESIZE_DEBUG
66
67 /*****************************************************************************
68  * Unix-only declarations
69 ******************************************************************************/
70 #ifdef XP_UNIX
71 #   define VOUT_PLUGINS "xvideo,x11,dummy"
72 #   define AOUT_PLUGINS "esd,arts,alsa,oss,dummy"
73
74 static unsigned int i_previous_height = 100000;
75 static unsigned int i_previous_width = 100000;
76
77 static void Redraw( Widget w, XtPointer closure, XEvent *event );
78 static void Resize( Widget w, XtPointer closure, XEvent *event );
79 #endif
80
81 /*****************************************************************************
82  * MacOS-only declarations
83 ******************************************************************************/
84 #ifdef XP_MACOSX
85 #   define VOUT_PLUGINS "macosx,dummy"
86 #   define AOUT_PLUGINS "auhal,macosx,dummy"
87
88 #endif
89
90 /*****************************************************************************
91  * Windows-only declarations
92  *****************************************************************************/
93 #ifdef XP_WIN
94 #   define VOUT_PLUGINS "directx,wingdi,dummy"
95 #   define AOUT_PLUGINS "directx,waveout,dummy"
96
97 #if defined(XP_WIN) && !USE_LIBVLC
98 LRESULT CALLBACK Manage( HWND, UINT, WPARAM, LPARAM );
99 #endif
100 #endif
101
102 /******************************************************************************
103  * UNIX-only API calls
104  *****************************************************************************/
105 char * NPP_GetMIMEDescription( void )
106 {
107     return PLUGIN_MIMETYPES;
108 }
109
110 NPError NPP_GetValue( NPP instance, NPPVariable variable, void *value )
111 {
112
113     static nsIID nsid = VLCINTF_IID;
114     static char psz_desc[1000];
115
116     switch( variable )
117     {
118         case NPPVpluginNameString:
119             *((char **)value) = PLUGIN_NAME;
120             return NPERR_NO_ERROR;
121
122         case NPPVpluginDescriptionString:
123 #if USE_LIBVLC
124             snprintf( psz_desc, 1000-1, PLUGIN_DESCRIPTION, VLC_Version() );
125 #else /* USE_LIBVLC */
126             snprintf( psz_desc, 1000-1, PLUGIN_DESCRIPTION, "(disabled)" );
127 #endif /* USE_LIBVLC */
128             psz_desc[1000-1] = 0;
129             *((char **)value) = psz_desc;
130             return NPERR_NO_ERROR;
131
132         default:
133             /* go on... */
134             break;
135     }
136
137     if( instance == NULL )
138     {
139         return NPERR_INVALID_INSTANCE_ERROR;
140     }
141
142     VlcPlugin* p_plugin = (VlcPlugin*) instance->pdata;
143
144     switch( variable )
145     {
146         case NPPVpluginScriptableInstance:
147             *(nsISupports**)value = p_plugin->GetPeer();
148             if( *(nsISupports**)value == NULL )
149             {
150                 return NPERR_OUT_OF_MEMORY_ERROR;
151             }
152             break;
153
154         case NPPVpluginScriptableIID:
155             *(nsIID**)value = (nsIID*)NPN_MemAlloc( sizeof(nsIID) );
156             if( *(nsIID**)value == NULL )
157             {
158                 return NPERR_OUT_OF_MEMORY_ERROR;
159             }
160             **(nsIID**)value = nsid;
161             break;
162
163         case NPPVpluginScriptableNPObject:
164             static VlcRuntimeClass<VlcRuntimeRootObject> *rootClass = new VlcRuntimeClass<VlcRuntimeRootObject>;
165             *(NPObject**)value = NPN_CreateObject(instance, rootClass);
166             if( *(NPObject**)value == NULL )
167             {
168                 return NPERR_OUT_OF_MEMORY_ERROR;
169             }
170             break;
171
172         default:
173             return NPERR_GENERIC_ERROR;
174     }
175
176     return NPERR_NO_ERROR;
177 }
178
179 /******************************************************************************
180  * Mac-only API calls
181  *****************************************************************************/
182 #ifdef XP_MACOSX
183 int16 NPP_HandleEvent( NPP instance, void * event )
184 {
185     if( instance == NULL )
186     {
187         return false;
188     }
189
190     VlcPlugin *p_plugin = (VlcPlugin*)instance->pdata;
191     EventRecord *myEvent = (EventRecord*)event;
192
193     switch( myEvent->what )
194     {
195         case nullEvent:
196             break;
197         case mouseDown:
198         case mouseUp:
199             return true;
200         case keyUp:
201         case keyDown:
202         case autoKey:
203             return true;
204         case updateEvt:
205         {
206             NPWindow *npwindow = p_plugin->window;
207             NP_Port *npport = (NP_Port *)(npwindow->window);
208
209             SetPort( npport->port );
210             //SetOrigin( npport->portx , npport->porty);
211
212             /* draw the beautiful "No Picture" */
213
214             ForeColor(blackColor);
215             PenMode( patCopy );
216
217             Rect rect;
218             rect.left = 0;
219             rect.top = 0;
220             rect.right = npwindow->width;
221             rect.bottom = npwindow->height;
222             PaintRect( &rect );
223
224             ForeColor(whiteColor);
225             char *text = strdup( WINDOW_TEXT );
226             MoveTo( (npwindow->width-80)/ 2  , npwindow->height / 2 );
227             DrawText( text , 0 , strlen(text) );
228             free(text);
229
230             return true;
231         }
232         case activateEvt:
233             return false;
234         case NPEventType_GetFocusEvent:
235         case NPEventType_LoseFocusEvent:
236             return true;
237         case NPEventType_AdjustCursorEvent:
238             return false;
239         case NPEventType_ScrollingBeginsEvent:
240         case NPEventType_ScrollingEndsEvent:
241             return true;
242         default:
243             ;
244     }
245     return false;
246 }
247 #endif /* XP_MACOSX */
248
249 /******************************************************************************
250  * General Plug-in Calls
251  *****************************************************************************/
252 NPError NPP_Initialize( void )
253 {
254     return NPERR_NO_ERROR;
255 }
256
257 jref NPP_GetJavaClass( void )
258 {
259     return NULL;
260 }
261
262 void NPP_Shutdown( void )
263 {
264     ;
265 }
266
267 NPError NPP_New( NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc,
268                  char* argn[], char* argv[], NPSavedData* saved )
269 {
270     int i;
271
272 #if USE_LIBVLC
273     vlc_value_t value;
274     int i_ret;
275
276 #endif /* USE_LIBVLC */
277
278     if( instance == NULL )
279     {
280         return NPERR_INVALID_INSTANCE_ERROR;
281     }
282
283     VlcPlugin * p_plugin = new VlcPlugin( instance );
284
285     if( p_plugin == NULL )
286     {
287         return NPERR_OUT_OF_MEMORY_ERROR;
288     }
289
290     instance->pdata = p_plugin;
291
292 #ifdef XP_WIN
293     p_plugin->p_hwnd = NULL;
294     p_plugin->pf_wndproc = NULL;
295 #endif /* XP_WIN */
296
297 #ifdef XP_UNIX
298     p_plugin->window = 0;
299     p_plugin->p_display = NULL;
300 #endif /* XP_UNIX */
301
302     p_plugin->p_npwin = NULL;
303     p_plugin->i_npmode = mode;
304     p_plugin->i_width = 0;
305     p_plugin->i_height = 0;
306
307 #if USE_LIBVLC
308     p_plugin->i_vlc = VLC_Create();
309     if( p_plugin->i_vlc < 0 )
310     {
311         p_plugin->i_vlc = 0;
312         delete p_plugin;
313         p_plugin = NULL;
314         return NPERR_GENERIC_ERROR;
315     }
316
317     {
318 #ifdef XP_MACOSX
319         char *ppsz_argv[] =
320         {
321             "vlc",
322             "-vvvv",
323             "--plugin-path",
324             "/Library/Internet Plug-Ins/VLC Plugin.plugin/"
325             "Contents/MacOS/modules"
326         };
327
328 #elif defined(XP_WIN)
329         char *ppsz_argv[] = { NULL, "-vv" };
330         HKEY h_key;
331         DWORD i_type, i_data = MAX_PATH + 1;
332         char p_data[MAX_PATH + 1];
333         if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, "Software\\VideoLAN\\VLC",
334                           0, KEY_READ, &h_key ) == ERROR_SUCCESS )
335         {
336              if( RegQueryValueEx( h_key, "InstallDir", 0, &i_type,
337                                   (LPBYTE)p_data, &i_data ) == ERROR_SUCCESS )
338              {
339                  if( i_type == REG_SZ )
340                  {
341                      strcat( p_data, "\\vlc" );
342                      ppsz_argv[0] = p_data;
343                  }
344              }
345              RegCloseKey( h_key );
346         }
347
348         if( !ppsz_argv[0] ) ppsz_argv[0] = "vlc";
349
350 #else /* XP_MACOSX */
351         char *ppsz_argv[] =
352         {
353             "vlc"
354             "-vvvv"
355             /*, "--plugin-path", ""*/
356         };
357
358 #endif /* XP_MACOSX */
359
360         /* HACK: special case for loop, to have it set before playlist startup
361          */
362         for( i = 0; i < argc ; i++ )
363         {
364             if( !strcmp( argn[i], "loop" ) )
365             {
366                 if( !strcmp( argv[i], "1" ) || !strcmp( argv[i], "yes" ) )
367                 {
368                     value.b_bool = VLC_TRUE;
369                     VLC_VariableSet( p_plugin->i_vlc, "conf::loop", value );
370                 }
371             }
372         }
373
374         i_ret = VLC_Init( p_plugin->i_vlc, sizeof(ppsz_argv)/sizeof(char*),
375                           ppsz_argv );
376
377     }
378
379     if( i_ret )
380     {
381         VLC_Destroy( p_plugin->i_vlc );
382         p_plugin->i_vlc = 0;
383         delete p_plugin;
384         p_plugin = NULL;
385         return NPERR_GENERIC_ERROR;
386     }
387
388     value.psz_string = "dummy";
389     VLC_VariableSet( p_plugin->i_vlc, "conf::intf", value );
390     value.psz_string = VOUT_PLUGINS;
391     VLC_VariableSet( p_plugin->i_vlc, "conf::vout", value );
392     value.psz_string = AOUT_PLUGINS;
393     VLC_VariableSet( p_plugin->i_vlc, "conf::aout", value );
394
395 #else /* USE_LIBVLC */
396     p_plugin->i_vlc = 1;
397
398 #endif /* USE_LIBVLC */
399
400     p_plugin->b_stream = VLC_FALSE;
401     p_plugin->b_autoplay = VLC_FALSE;
402     p_plugin->psz_target = NULL;
403
404     for( i = 0; i < argc ; i++ )
405     {
406         if( !strcmp( argn[i], "target" ) )
407         {
408             p_plugin->psz_target = argv[i];
409         }
410         else if( !strcmp( argn[i], "autoplay" ) )
411         {
412             if( !strcmp( argv[i], "1" ) || !strcmp( argv[i], "yes" ) )
413             {
414                 p_plugin->b_autoplay = 1;
415             }
416         }
417         else if( !strcmp( argn[i], "autostart" ) )
418         {
419             if( !strcmp( argv[i], "1" ) || !strcmp( argv[i], "true" ) )
420             {
421                 p_plugin->b_autoplay = 1;
422             }
423         }
424         else if( !strcmp( argn[i], "filename" ) )
425         {
426             p_plugin->psz_target = argv[i];
427         }
428         else if( !strcmp( argn[i], "src" ) )
429         {
430             p_plugin->psz_target = argv[i];
431         }
432
433 #if USE_LIBVLC
434         else if( !strcmp( argn[i], "fullscreen" ) )
435         {
436             if( !strcmp( argv[i], "1" ) || !strcmp( argv[i], "yes" ) )
437             {
438                 value.b_bool = VLC_TRUE;
439                 VLC_VariableSet( p_plugin->i_vlc, "conf::fullscreen", value );
440             }
441         }
442         else if( !strcmp( argn[i], "mute" ) )
443         {
444             if( !strcmp( argv[i], "1" ) || !strcmp( argv[i], "yes" ) )
445             {
446                 VLC_VolumeMute( p_plugin->i_vlc );
447             }
448         }
449 #endif /* USE_LIBVLC */
450     }
451
452     if( p_plugin->psz_target )
453     {
454         p_plugin->psz_target = strdup( p_plugin->psz_target );
455     }
456
457     return NPERR_NO_ERROR;
458 }
459
460 #ifdef XP_WIN
461 /* This is really ugly but there is a deadlock when stopping a stream
462  * (in VLC_CleanUp()) because the video output is a child of the drawable but
463  * is in a different thread. */
464 static void HackStopVout( VlcPlugin* p_plugin )
465 {
466     MSG msg;
467     HWND hwnd;
468     vlc_value_t value;
469
470     VLC_VariableGet( p_plugin->i_vlc, "drawable", &value );
471
472     hwnd = FindWindowEx( (HWND)value.i_int, 0, 0, 0 );
473     if( !hwnd ) return;
474
475     PostMessage( hwnd, WM_CLOSE, 0, 0 );
476
477     do
478     {
479         while( PeekMessage( &msg, (HWND)value.i_int, 0, 0, PM_REMOVE ) )
480         {
481             TranslateMessage(&msg);
482             DispatchMessage(&msg);
483         }
484         if( FindWindowEx( (HWND)value.i_int, 0, 0, 0 ) ) Sleep( 10 );
485     }
486     while( (hwnd = FindWindowEx( (HWND)value.i_int, 0, 0, 0 )) );
487 }
488 #endif /* XP_WIN */
489
490 NPError NPP_Destroy( NPP instance, NPSavedData** save )
491 {
492     if( instance == NULL )
493     {
494         return NPERR_INVALID_INSTANCE_ERROR;
495     }
496
497     VlcPlugin* p_plugin = (VlcPlugin*)instance->pdata;
498
499     if( p_plugin != NULL )
500     {
501         if( p_plugin->i_vlc )
502         {
503 #if USE_LIBVLC
504 #   ifdef XP_WIN
505             HackStopVout( p_plugin );
506 #   endif /* XP_WIN */
507             VLC_CleanUp( p_plugin->i_vlc );
508             VLC_Destroy( p_plugin->i_vlc );
509 #endif /* USE_LIBVLC */
510             p_plugin->i_vlc = 0;
511         }
512
513         if( p_plugin->psz_target )
514         {
515             free( p_plugin->psz_target );
516             p_plugin->psz_target = NULL;
517         }
518
519         delete p_plugin;
520     }
521
522     instance->pdata = NULL;
523
524     return NPERR_NO_ERROR;
525 }
526
527 NPError NPP_SetWindow( NPP instance, NPWindow* window )
528 {
529     vlc_value_t value;
530 #ifdef XP_MACOSX
531     vlc_value_t valuex;
532     vlc_value_t valuey;
533     vlc_value_t valuew;
534     vlc_value_t valueh;
535     vlc_value_t valuet;
536     vlc_value_t valuel;
537     vlc_value_t valueb;
538     vlc_value_t valuer;
539     vlc_value_t valueportx;
540     vlc_value_t valueporty;
541     vlc_value_t valueredraw;
542 #endif /* XP_MACOSX */
543
544     if( instance == NULL )
545     {
546         return NPERR_INVALID_INSTANCE_ERROR;
547     }
548
549     VlcPlugin* p_plugin = (VlcPlugin*)instance->pdata;
550
551     /* Write the window ID for vlc */
552 #if USE_LIBVLC
553
554 #ifdef XP_MACOSX
555     value.i_int = (int)(((NP_Port*) (window->window))->port);
556     VLC_VariableSet( p_plugin->i_vlc, "drawable", value );
557
558     valueportx.i_int = ((NP_Port*) (window->window))->portx;
559     valueporty.i_int = ((NP_Port*) (window->window))->porty;
560     VLC_VariableSet( p_plugin->i_vlc, "drawableportx", valueportx );
561     VLC_VariableSet( p_plugin->i_vlc, "drawableporty", valueporty );
562
563     valuex.i_int = window->x;
564     valuey.i_int = window->y;
565     valuew.i_int = window->width;
566     valueh.i_int = window->height;
567     valuet.i_int = window->clipRect.top;
568     valuel.i_int = window->clipRect.left;
569     valueb.i_int = window->clipRect.bottom;
570     valuer.i_int = window->clipRect.right;
571
572     VLC_VariableSet( p_plugin->i_vlc, "drawablet", valuet );
573     VLC_VariableSet( p_plugin->i_vlc, "drawablel", valuel );
574     VLC_VariableSet( p_plugin->i_vlc, "drawableb", valueb );
575     VLC_VariableSet( p_plugin->i_vlc, "drawabler", valuer );
576     VLC_VariableSet( p_plugin->i_vlc, "drawablex", valuex );
577     VLC_VariableSet( p_plugin->i_vlc, "drawabley", valuey );
578     VLC_VariableSet( p_plugin->i_vlc, "drawablew", valuew );
579     VLC_VariableSet( p_plugin->i_vlc, "drawableh", valueh );
580
581     p_plugin->window = window;
582
583     valueredraw.i_int = 1;
584     VLC_VariableSet( p_plugin->i_vlc, "drawableredraw", valueredraw );
585
586 #else /* XP_MACOSX */
587     /* FIXME: this cast sucks */
588     value.i_int = (int) (ptrdiff_t) (void *) window->window;
589     VLC_VariableSet( p_plugin->i_vlc, "drawable", value );
590
591 #endif /* XP_MACOSX */
592
593 #endif /* USE_LIBVLC */
594
595     /*
596      * PLUGIN DEVELOPERS:
597      *  Before setting window to point to the
598      *  new window, you may wish to compare the new window
599      *  info to the previous window (if any) to note window
600      *  size changes, etc.
601      */
602
603 #ifdef XP_WIN
604     if( !window || !window->window )
605     {
606         /* Window was destroyed. Invalidate everything. */
607         if( p_plugin->p_npwin )
608         {
609 #if !USE_LIBVLC
610             SetWindowLong( p_plugin->p_hwnd, GWL_WNDPROC,
611                            (LONG)p_plugin->pf_wndproc );
612 #endif /* !USE_LIBVLC */
613             p_plugin->pf_wndproc = NULL;
614             p_plugin->p_hwnd = NULL;
615         }
616
617         p_plugin->p_npwin = window;
618         return NPERR_NO_ERROR;
619     }
620
621     if( p_plugin->p_npwin )
622     {
623         if( p_plugin->p_hwnd == (HWND)window->window )
624         {
625             /* Same window, but something may have changed. First we
626              * update the plugin structure, then we redraw the window */
627             p_plugin->i_width = window->width;
628             p_plugin->i_height = window->height;
629             p_plugin->p_npwin = window;
630 #if !USE_LIBVLC
631             InvalidateRect( p_plugin->p_hwnd, NULL, TRUE );
632             UpdateWindow( p_plugin->p_hwnd );
633 #endif /* !USE_LIBVLC */
634             return NPERR_NO_ERROR;
635         }
636
637         /* Window has changed. Destroy the one we have, and go
638          * on as if it was a real initialization. */
639 #if !USE_LIBVLC
640         SetWindowLong( p_plugin->p_hwnd, GWL_WNDPROC,
641                        (LONG)p_plugin->pf_wndproc );
642 #endif /* !USE_LIBVLC */
643         p_plugin->pf_wndproc = NULL;
644         p_plugin->p_hwnd = NULL;
645     }
646
647 #if !USE_LIBVLC
648     p_plugin->pf_wndproc = (WNDPROC)SetWindowLong( (HWND)window->window,
649                                                    GWL_WNDPROC, (LONG)Manage );
650 #endif /* !USE_LIBVLC */
651
652     p_plugin->p_hwnd = (HWND)window->window;
653     SetProp( p_plugin->p_hwnd, "w00t", (HANDLE)p_plugin );
654     InvalidateRect( p_plugin->p_hwnd, NULL, TRUE );
655     UpdateWindow( p_plugin->p_hwnd );
656 #endif /* XP_WIN */
657
658     p_plugin->i_width = window->width;
659     p_plugin->i_height = window->height;
660     p_plugin->p_npwin = window;
661
662 #ifdef XP_UNIX
663     p_plugin->window = (Window) window->window;
664     p_plugin->p_display =
665         ((NPSetWindowCallbackStruct *)window->ws_info)->display;
666
667     XResizeWindow( p_plugin->p_display, p_plugin->window,
668                    p_plugin->i_width, p_plugin->i_height );
669     Widget w = XtWindowToWidget( p_plugin->p_display, p_plugin->window );
670
671     XtAddEventHandler( w, ExposureMask, FALSE,
672                        (XtEventHandler)Redraw, p_plugin );
673     XtAddEventHandler( w, StructureNotifyMask, FALSE,
674                        (XtEventHandler)Resize, p_plugin );
675     Redraw( w, (XtPointer)p_plugin, NULL );
676 #endif /* XP_UNIX */
677
678     if( !p_plugin->b_stream )
679     {
680         int i_mode = PLAYLIST_APPEND;
681
682         if( p_plugin->b_autoplay )
683         {
684             i_mode |= PLAYLIST_GO;
685         }
686
687         if( p_plugin->psz_target )
688         {
689 #if USE_LIBVLC
690             VLC_AddTarget( p_plugin->i_vlc, p_plugin->psz_target,
691                            0, 0, PLAYLIST_INSERT, 0 );
692 #endif
693             p_plugin->b_stream = VLC_TRUE;
694         }
695     }
696
697     return NPERR_NO_ERROR;
698 }
699
700 NPError NPP_NewStream( NPP instance, NPMIMEType type, NPStream *stream,
701                        NPBool seekable, uint16 *stype )
702 {
703     if( instance == NULL )
704     {
705         return NPERR_INVALID_INSTANCE_ERROR;
706     }
707
708 #if 0
709     VlcPlugin* p_plugin = (VlcPlugin*)instance->pdata;
710 #endif
711
712     /* fprintf(stderr, "NPP_NewStream - FILE mode !!\n"); */
713
714     /* We want a *filename* ! */
715     *stype = NP_ASFILE;
716
717 #if 0
718     if( !p_plugin->b_stream )
719     {
720         p_plugin->psz_target = strdup( stream->url );
721         p_plugin->b_stream = VLC_TRUE;
722     }
723 #endif
724
725     return NPERR_NO_ERROR;
726 }
727
728 int32 STREAMBUFSIZE = 0X0FFFFFFF; /* If we are reading from a file in NPAsFile
729                    * mode so we can take any size stream in our
730                    * write call (since we ignore it) */
731
732 #define SARASS_SIZE (1024*1024)
733
734 int32 NPP_WriteReady( NPP instance, NPStream *stream )
735 {
736     VlcPlugin* p_plugin;
737
738     /* fprintf(stderr, "NPP_WriteReady\n"); */
739
740     if (instance != NULL)
741     {
742         p_plugin = (VlcPlugin*) instance->pdata;
743         /* Muahahahahahahaha */
744         return STREAMBUFSIZE;
745         /*return SARASS_SIZE;*/
746     }
747
748     /* Number of bytes ready to accept in NPP_Write() */
749     return STREAMBUFSIZE;
750     /*return 0;*/
751 }
752
753
754 int32 NPP_Write( NPP instance, NPStream *stream, int32 offset,
755                  int32 len, void *buffer )
756 {
757     /* fprintf(stderr, "NPP_Write %i\n", (int)len); */
758
759     if( instance != NULL )
760     {
761         /*VlcPlugin* p_plugin = (VlcPlugin*) instance->pdata;*/
762     }
763
764     return len;         /* The number of bytes accepted */
765 }
766
767
768 NPError NPP_DestroyStream( NPP instance, NPStream *stream, NPError reason )
769 {
770     if( instance == NULL )
771     {
772         return NPERR_INVALID_INSTANCE_ERROR;
773     }
774
775     return NPERR_NO_ERROR;
776 }
777
778
779 void NPP_StreamAsFile( NPP instance, NPStream *stream, const char* fname )
780 {
781     if( instance == NULL )
782     {
783         return;
784     }
785
786     /* fprintf(stderr, "NPP_StreamAsFile %s\n", fname); */
787
788 #if USE_LIBVLC
789     VlcPlugin* p_plugin = (VlcPlugin*)instance->pdata;
790
791     VLC_AddTarget( p_plugin->i_vlc, fname, 0, 0,
792                    PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
793 #endif /* USE_LIBVLC */
794 }
795
796
797 void NPP_URLNotify( NPP instance, const char* url,
798                     NPReason reason, void* notifyData )
799 {
800     /***** Insert NPP_URLNotify code here *****\
801     PluginInstance* p_plugin;
802     if (instance != NULL)
803         p_plugin = (PluginInstance*) instance->pdata;
804     \*********************************************/
805 }
806
807
808 void NPP_Print( NPP instance, NPPrint* printInfo )
809 {
810     if( printInfo == NULL )
811     {
812         return;
813     }
814
815     if( instance != NULL )
816     {
817         /***** Insert NPP_Print code here *****\
818         PluginInstance* p_plugin = (PluginInstance*) instance->pdata;
819         \**************************************/
820
821         if( printInfo->mode == NP_FULL )
822         {
823             /*
824              * PLUGIN DEVELOPERS:
825              *  If your plugin would like to take over
826              *  printing completely when it is in full-screen mode,
827              *  set printInfo->pluginPrinted to TRUE and print your
828              *  plugin as you see fit.  If your plugin wants Netscape
829              *  to handle printing in this case, set
830              *  printInfo->pluginPrinted to FALSE (the default) and
831              *  do nothing.  If you do want to handle printing
832              *  yourself, printOne is true if the print button
833              *  (as opposed to the print menu) was clicked.
834              *  On the Macintosh, platformPrint is a THPrint; on
835              *  Windows, platformPrint is a structure
836              *  (defined in npapi.h) containing the printer name, port,
837              *  etc.
838              */
839
840             /***** Insert NPP_Print code here *****\
841             void* platformPrint =
842                 printInfo->print.fullPrint.platformPrint;
843             NPBool printOne =
844                 printInfo->print.fullPrint.printOne;
845             \**************************************/
846
847             /* Do the default*/
848             printInfo->print.fullPrint.pluginPrinted = FALSE;
849         }
850         else
851         {
852             /* If not fullscreen, we must be embedded */
853             /*
854              * PLUGIN DEVELOPERS:
855              *  If your plugin is embedded, or is full-screen
856              *  but you returned false in pluginPrinted above, NPP_Print
857              *  will be called with mode == NP_EMBED.  The NPWindow
858              *  in the printInfo gives the location and dimensions of
859              *  the embedded plugin on the printed page.  On the
860              *  Macintosh, platformPrint is the printer port; on
861              *  Windows, platformPrint is the handle to the printing
862              *  device context.
863              */
864
865             /***** Insert NPP_Print code here *****\
866             NPWindow* printWindow =
867                 &(printInfo->print.embedPrint.window);
868             void* platformPrint =
869                 printInfo->print.embedPrint.platformPrint;
870             \**************************************/
871         }
872     }
873 }
874
875 /******************************************************************************
876  * Windows-only methods
877  *****************************************************************************/
878 #if defined(XP_WIN) && !USE_LIBVLC
879 LRESULT CALLBACK Manage( HWND p_hwnd, UINT i_msg, WPARAM wpar, LPARAM lpar )
880 {
881     VlcPlugin* p_plugin = (VlcPlugin*) GetProp( p_hwnd, "w00t" );
882
883     switch( i_msg )
884     {
885         case WM_PAINT:
886         {
887             PAINTSTRUCT paintstruct;
888             HDC hdc;
889             RECT rect;
890
891             hdc = BeginPaint( p_hwnd, &paintstruct );
892
893             GetClientRect( p_hwnd, &rect );
894             FillRect( hdc, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH) );
895             TextOut( hdc, p_plugin->i_width / 2 - 40, p_plugin->i_height / 2,
896                      WINDOW_TEXT, strlen(WINDOW_TEXT) );
897
898             EndPaint( p_hwnd, &paintstruct );
899             break;
900         }
901         default:
902             p_plugin->pf_wndproc( p_hwnd, i_msg, wpar, lpar );
903             break;
904     }
905     return 0;
906 }
907 #endif /* XP_WIN */
908
909 /******************************************************************************
910  * UNIX-only methods
911  *****************************************************************************/
912 #ifdef XP_UNIX
913 static void Redraw( Widget w, XtPointer closure, XEvent *event )
914 {
915     VlcPlugin* p_plugin = (VlcPlugin*)closure;
916     GC gc;
917     XGCValues gcv;
918
919     gcv.foreground = BlackPixel( p_plugin->p_display, 0 );
920     gc = XCreateGC( p_plugin->p_display, p_plugin->window, GCForeground, &gcv );
921
922     XFillRectangle( p_plugin->p_display, p_plugin->window, gc,
923                     0, 0, p_plugin->i_width, p_plugin->i_height );
924
925     gcv.foreground = WhitePixel( p_plugin->p_display, 0 );
926     XChangeGC( p_plugin->p_display, gc, GCForeground, &gcv );
927
928     XDrawString( p_plugin->p_display, p_plugin->window, gc,
929                  p_plugin->i_width / 2 - 40, p_plugin->i_height / 2,
930                  WINDOW_TEXT, strlen(WINDOW_TEXT) );
931
932     XFreeGC( p_plugin->p_display, gc );
933 }
934
935 static void Resize ( Widget w, XtPointer closure, XEvent *event )
936 {
937     VlcPlugin* p_plugin = (VlcPlugin*)closure;
938     int i_ret;
939     Window root_return, parent_return, * children_return;
940     Window base_window;
941     unsigned int i_nchildren;
942
943 #ifdef X11_RESIZE_DEBUG
944     XWindowAttributes attr;
945
946     if( event && event->type == ConfigureNotify )
947     {
948         fprintf( stderr, "vlcshell::Resize() ConfigureNotify %d x %d, "
949                  "send_event ? %s\n", event->xconfigure.width,
950                  event->xconfigure.height,
951                  event->xconfigure.send_event ? "TRUE" : "FALSE" );
952     }
953 #endif /* X11_RESIZE_DEBUG */
954
955     if( p_plugin->i_height == i_previous_height &&
956         p_plugin->i_width == i_previous_width )
957     {
958         return;
959     }
960     i_previous_height = p_plugin->i_height;
961     i_previous_width  = p_plugin->i_width;
962
963
964     i_ret = XResizeWindow( p_plugin->p_display, p_plugin->window,
965             p_plugin->i_width, p_plugin->i_height );
966
967 #ifdef X11_RESIZE_DEBUG
968     fprintf( stderr,
969              "vlcshell::Resize() XResizeWindow(owner) returned %d\n", i_ret );
970
971     XGetWindowAttributes ( p_plugin->p_display, p_plugin->window, &attr );
972
973     /* X is asynchronous, so the current size reported here is not
974        necessarily the requested size as the Resize request may not
975        yet have been handled by the plugin host */
976     fprintf( stderr, "vlcshell::Resize() current (owner) size %d x %d\n",
977              attr.width, attr.height );
978 #endif /* X11_RESIZE_DEBUG */
979
980     XQueryTree( p_plugin->p_display, p_plugin->window,
981                 &root_return, &parent_return, &children_return,
982                 &i_nchildren );
983
984     if( i_nchildren > 0 )
985     {
986         /* XXX: Make assumptions related to the window parenting structure in
987            vlc/modules/video_output/x11/xcommon.c */
988         base_window = children_return[i_nchildren - 1];
989
990 #ifdef X11_RESIZE_DEBUG
991         fprintf( stderr, "vlcshell::Resize() got %d children\n", i_nchildren );
992         fprintf( stderr, "vlcshell::Resize() got base_window %p\n",
993                  base_window );
994 #endif /* X11_RESIZE_DEBUG */
995
996         i_ret = XResizeWindow( p_plugin->p_display, base_window,
997                 p_plugin->i_width, p_plugin->i_height );
998
999 #ifdef X11_RESIZE_DEBUG
1000         fprintf( stderr,
1001                  "vlcshell::Resize() XResizeWindow(base) returned %d\n",
1002                  i_ret );
1003
1004         XGetWindowAttributes( p_plugin->p_display, base_window, &attr );
1005
1006         fprintf( stderr, "vlcshell::Resize() new size %d x %d\n",
1007                  attr.width, attr.height );
1008 #endif /* X11_RESIZE_DEBUG */
1009     }
1010 }
1011
1012 #endif /* XP_UNIX */
1013