8ec4e6a3d5cdf84a22cda7a5e6618d6a04e2ccf1
[vlc.git] / mozilla / vlcshell.cpp
1 /*****************************************************************************
2  * vlcshell.c: a VideoLAN Client plugin for Mozilla
3  *****************************************************************************
4  * Copyright (C) 2002 VideoLAN
5  * $Id: vlcshell.cpp,v 1.5 2002/10/22 21:10:28 sam 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 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <stdio.h>
28 #include <string.h>
29
30 /* vlc stuff */
31 #include <vlc/vlc.h>
32
33 /* Mozilla stuff */
34 #include <npapi.h>
35
36 #ifdef WIN32
37
38 #else
39     /* X11 stuff */
40 #   include <X11/Xlib.h>
41 #   include <X11/Intrinsic.h>
42 #   include <X11/StringDefs.h>
43 #endif
44
45 #include "vlcpeer.h"
46 #include "vlcplugin.h"
47
48 /*****************************************************************************
49  * Unix-only declarations
50 ******************************************************************************/
51 #ifndef WIN32
52 static void Redraw( Widget w, XtPointer closure, XEvent *event );
53 #endif
54
55 /*****************************************************************************
56  * Windows-only declarations
57  *****************************************************************************/
58 #ifdef WIN32
59 HINSTANCE g_hDllInstance = NULL;
60
61 BOOL WINAPI
62 DllMain( HINSTANCE  hinstDLL,                   // handle of DLL module
63                     DWORD  fdwReason,       // reason for calling function
64                     LPVOID  lpvReserved)
65 {
66         switch (fdwReason) {
67                 case DLL_PROCESS_ATTACH:
68                   g_hDllInstance = hinstDLL;
69                   break;
70                 case DLL_THREAD_ATTACH:
71                 case DLL_PROCESS_DETACH:
72                 case DLL_THREAD_DETACH:
73                 break;
74         }
75         return TRUE;
76 }
77 #endif
78
79 /******************************************************************************
80  * UNIX-only API calls
81  *****************************************************************************/
82 char * NPP_GetMIMEDescription( void )
83 {
84     return PLUGIN_MIMETYPES;
85 }
86
87 NPError NPP_GetValue( NPP instance, NPPVariable variable, void *value )
88 {
89     static nsIID nsid = VLCINTF_IID;
90     static char psz_desc[1000];
91
92     switch( variable )
93     {
94         case NPPVpluginNameString:
95             *((char **)value) = PLUGIN_NAME;
96             return NPERR_NO_ERROR;
97
98         case NPPVpluginDescriptionString:
99             snprintf( psz_desc, 1000-1, PLUGIN_DESCRIPTION, VLC_Version() );
100             psz_desc[1000-1] = 0;
101             *((char **)value) = psz_desc;
102             return NPERR_NO_ERROR;
103
104         default:
105             /* go on... */
106             break;
107     }
108
109     if( instance == NULL )
110     {
111         return NPERR_INVALID_INSTANCE_ERROR;
112     }
113
114     VlcPlugin* p_plugin = (VlcPlugin*) instance->pdata;
115
116     switch( variable )
117     {
118         case NPPVpluginScriptableInstance:
119             *(nsISupports**)value = p_plugin->GetPeer();
120             if( *(nsISupports**)value == NULL )
121             {
122                 return NPERR_OUT_OF_MEMORY_ERROR;
123             }
124             break;
125
126         case NPPVpluginScriptableIID:
127             *(nsIID**)value = (nsIID*)NPN_MemAlloc( sizeof(nsIID) );
128             if( *(nsIID**)value == NULL )
129             {
130                 return NPERR_OUT_OF_MEMORY_ERROR;
131             }
132             **(nsIID**)value = nsid;
133             break;
134
135         default:
136             return NPERR_GENERIC_ERROR;
137     }
138
139     return NPERR_NO_ERROR;
140 }
141
142 /******************************************************************************
143  * General Plug-in Calls
144  *****************************************************************************/
145 NPError NPP_Initialize( void )
146 {
147     return NPERR_NO_ERROR;
148 }
149
150 jref NPP_GetJavaClass( void )
151 {
152     return NULL;
153 }
154
155 void NPP_Shutdown( void )
156 {
157     ;
158 }
159
160 NPError NPP_New( NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc,
161                  char* argn[], char* argv[], NPSavedData* saved )
162 {
163     vlc_value_t value;
164     int i_ret;
165     int i;
166
167     char *ppsz_foo[] =
168     {
169         "vlc"
170         /*, "--plugin-path", "/home/sam/videolan/vlc_MAIN/plugins"*/
171     };
172
173     if( instance == NULL )
174     {
175         return NPERR_INVALID_INSTANCE_ERROR;
176     }
177
178     VlcPlugin * p_plugin = new VlcPlugin( instance );
179
180     if( p_plugin == NULL )
181     {
182         return NPERR_OUT_OF_MEMORY_ERROR;
183     }
184
185     instance->pdata = p_plugin;
186
187     p_plugin->fMode = mode;
188     p_plugin->fWindow = NULL;
189 #ifdef WIN32
190
191 #else
192     p_plugin->window = 0;
193 #endif
194
195     p_plugin->i_vlc = VLC_Create();
196     if( p_plugin->i_vlc < 0 )
197     {
198         p_plugin->i_vlc = 0;
199         delete p_plugin;
200         p_plugin = NULL;
201         return NPERR_GENERIC_ERROR;
202     }
203
204     i_ret = VLC_Init( p_plugin->i_vlc, sizeof(ppsz_foo)/sizeof(char*), ppsz_foo );
205     if( i_ret )
206     {
207         VLC_Destroy( p_plugin->i_vlc );
208         p_plugin->i_vlc = 0;
209         delete p_plugin;
210         p_plugin = NULL;
211         return NPERR_GENERIC_ERROR;
212     }
213
214     value.psz_string = "dummy";
215     VLC_Set( p_plugin->i_vlc, "conf::intf", value );
216 #ifdef WIN32
217     value.psz_string = "directx,dummy";
218 #else
219     value.psz_string = "xvideo,x11,dummy";
220 #endif
221     VLC_Set( p_plugin->i_vlc, "conf::vout", value );
222 #ifdef WIN32
223     value.psz_string = "none";//"directx,waveout,dummy";
224 #else
225     value.psz_string = "dsp,dummy";
226 #endif
227     VLC_Set( p_plugin->i_vlc, "conf::aout", value );
228
229     p_plugin->b_stream = 0;
230     p_plugin->b_autoplay = 0;
231     p_plugin->psz_target = NULL;
232
233     for( i = 0; i < argc ; i++ )
234     {
235         if( !strcmp( argn[i], "target" ) )
236         {
237             p_plugin->psz_target = argv[i];
238         }
239         else if( !strcmp( argn[i], "autoplay" ) )
240         {
241             if( !strcmp( argv[i], "yes" ) )
242             {
243                 p_plugin->b_autoplay = 1;
244             }
245         }
246         else if( !strcmp( argn[i], "loop" ) )
247         {
248             if( !strcmp( argv[i], "yes" ) )
249             {
250                 value.b_bool = VLC_TRUE;
251                 VLC_Set( p_plugin->i_vlc, "conf::loop", value );
252             }
253         }
254     }
255
256     if( p_plugin->psz_target )
257     {
258         p_plugin->psz_target = strdup( p_plugin->psz_target );
259     }
260
261     return NPERR_NO_ERROR;
262 }
263
264 NPError NPP_Destroy( NPP instance, NPSavedData** save )
265 {
266     if( instance == NULL )
267     {
268         return NPERR_INVALID_INSTANCE_ERROR;
269     }
270
271     VlcPlugin* p_plugin = (VlcPlugin*)instance->pdata;
272
273     if( p_plugin != NULL )
274     {
275         if( p_plugin->i_vlc )
276         {
277             VLC_Stop( p_plugin->i_vlc );
278             VLC_Destroy( p_plugin->i_vlc );
279             p_plugin->i_vlc = 0;
280         }
281
282         if( p_plugin->psz_target )
283         {
284             free( p_plugin->psz_target );
285             p_plugin->psz_target = NULL;
286         }
287
288         delete p_plugin;
289     }
290
291     instance->pdata = NULL;
292
293     return NPERR_NO_ERROR;
294 }
295
296 NPError NPP_SetWindow( NPP instance, NPWindow* window )
297 {
298     vlc_value_t value;
299
300     if( instance == NULL )
301     {
302         return NPERR_INVALID_INSTANCE_ERROR;
303     }
304
305     VlcPlugin* p_plugin = (VlcPlugin*)instance->pdata;
306
307     /* Write the window ID for vlc */
308     //value.p_address = (void*)window->window;
309     //VLC_Set( p_plugin->i_vlc, "drawable", value );
310     /* FIXME: this cast sucks */
311     value.i_int = (int) (long long) (void *) window->window;
312     VLC_Set( p_plugin->i_vlc, "conf::x11-drawable", value );
313     VLC_Set( p_plugin->i_vlc, "conf::xvideo-drawable", value );
314
315     /*
316      * PLUGIN DEVELOPERS:
317      *  Before setting window to point to the
318      *  new window, you may wish to compare the new window
319      *  info to the previous window (if any) to note window
320      *  size changes, etc.
321      */
322
323 #ifdef WIN32
324
325 #else
326     Widget netscape_widget;
327
328     p_plugin->window = (Window) window->window;
329     p_plugin->x = window->x;
330     p_plugin->y = window->y;
331     p_plugin->width = window->width;
332     p_plugin->height = window->height;
333     p_plugin->display = ((NPSetWindowCallbackStruct *)window->ws_info)->display;
334
335     netscape_widget = XtWindowToWidget(p_plugin->display, p_plugin->window);
336     XtAddEventHandler(netscape_widget, ExposureMask, FALSE, (XtEventHandler)Redraw, p_plugin);
337     Redraw(netscape_widget, (XtPointer)p_plugin, NULL);
338 #endif
339
340     p_plugin->fWindow = window;
341
342 #if 1
343     if( !p_plugin->b_stream )
344     {
345         int i_mode = PLAYLIST_APPEND;
346
347         if( p_plugin->b_autoplay )
348         {
349             i_mode |= PLAYLIST_GO;
350         }
351
352         if( p_plugin->psz_target )
353         {
354             VLC_AddTarget( p_plugin->i_vlc, p_plugin->psz_target,
355                            i_mode, PLAYLIST_END );
356             p_plugin->b_stream = 1;
357         }
358     }
359 #endif
360
361     return NPERR_NO_ERROR;
362 }
363
364 NPError NPP_NewStream( NPP instance, NPMIMEType type, NPStream *stream,
365                        NPBool seekable, uint16 *stype )
366 {
367     if( instance == NULL )
368     {
369         return NPERR_INVALID_INSTANCE_ERROR;
370     }
371
372 #if 0
373     VlcPlugin* p_plugin = (VlcPlugin*)instance->pdata;
374 #endif
375
376     fprintf(stderr, "NPP_NewStream - FILE mode !!\n");
377
378     /* We want a *filename* ! */
379     *stype = NP_ASFILE;
380
381 #if 0
382     if( p_plugin->b_stream == 0 )
383     {
384         p_plugin->psz_target = strdup( stream->url );
385         p_plugin->b_stream = 1;
386     }
387 #endif
388
389     return NPERR_NO_ERROR;
390 }
391
392 int32 STREAMBUFSIZE = 0X0FFFFFFF; /* If we are reading from a file in NPAsFile
393                    * mode so we can take any size stream in our
394                    * write call (since we ignore it) */
395
396 #define SARASS_SIZE (1024*1024)
397
398 int32 NPP_WriteReady( NPP instance, NPStream *stream )
399 {
400     VlcPlugin* p_plugin;
401
402     fprintf(stderr, "NPP_WriteReady\n");
403
404     if (instance != NULL)
405     {
406         p_plugin = (VlcPlugin*) instance->pdata;
407         /* Muahahahahahahaha */
408         return STREAMBUFSIZE;
409         /*return SARASS_SIZE;*/
410     }
411
412     /* Number of bytes ready to accept in NPP_Write() */
413     return STREAMBUFSIZE;
414     /*return 0;*/
415 }
416
417
418 int32 NPP_Write( NPP instance, NPStream *stream, int32 offset,
419                  int32 len, void *buffer )
420 {
421     fprintf(stderr, "NPP_Write %i\n", (int)len);
422
423     if( instance != NULL )
424     {
425         /*VlcPlugin* p_plugin = (VlcPlugin*) instance->pdata;*/
426     }
427
428     return len;         /* The number of bytes accepted */
429 }
430
431
432 NPError NPP_DestroyStream( NPP instance, NPStream *stream, NPError reason )
433 {
434     if( instance == NULL )
435     {
436         return NPERR_INVALID_INSTANCE_ERROR;
437     }
438
439     return NPERR_NO_ERROR;
440 }
441
442
443 void NPP_StreamAsFile( NPP instance, NPStream *stream, const char* fname )
444 {
445     if( instance == NULL )
446     {
447         return;
448     }
449
450     VlcPlugin* p_plugin = (VlcPlugin*)instance->pdata;
451
452     fprintf(stderr, "NPP_StreamAsFile\n");
453     VLC_AddTarget( p_plugin->i_vlc, fname,
454                    PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
455 }
456
457 #if 0
458 void NPP_StreamAsFile( NPP instance, NPStream *stream, const char* fname )
459 {
460     fprintf(stderr,"filename : %s\n", fname);
461     ((VlcPlugin*) instance->pdata)->SetFileName(fname);
462
463     fprintf(stderr,"SetFileNeme ok. \n");
464 }
465 #endif
466
467
468 void NPP_URLNotify( NPP instance, const char* url,
469                     NPReason reason, void* notifyData )
470 {
471     /***** Insert NPP_URLNotify code here *****\
472     PluginInstance* p_plugin;
473     if (instance != NULL)
474         p_plugin = (PluginInstance*) instance->pdata;
475     \*********************************************/
476 }
477
478
479 void NPP_Print( NPP instance, NPPrint* printInfo )
480 {
481     if( printInfo == NULL )
482     {
483         return;
484     }
485
486     if( instance != NULL )
487     {
488         /***** Insert NPP_Print code here *****\
489         PluginInstance* p_plugin = (PluginInstance*) instance->pdata;
490         \**************************************/
491
492         if( printInfo->mode == NP_FULL )
493         {
494             /*
495              * PLUGIN DEVELOPERS:
496              *  If your plugin would like to take over
497              *  printing completely when it is in full-screen mode,
498              *  set printInfo->pluginPrinted to TRUE and print your
499              *  plugin as you see fit.  If your plugin wants Netscape
500              *  to handle printing in this case, set
501              *  printInfo->pluginPrinted to FALSE (the default) and
502              *  do nothing.  If you do want to handle printing
503              *  yourself, printOne is true if the print button
504              *  (as opposed to the print menu) was clicked.
505              *  On the Macintosh, platformPrint is a THPrint; on
506              *  Windows, platformPrint is a structure
507              *  (defined in npapi.h) containing the printer name, port,
508              *  etc.
509              */
510
511             /***** Insert NPP_Print code here *****\
512             void* platformPrint =
513                 printInfo->print.fullPrint.platformPrint;
514             NPBool printOne =
515                 printInfo->print.fullPrint.printOne;
516             \**************************************/
517
518             /* Do the default*/
519             printInfo->print.fullPrint.pluginPrinted = FALSE;
520         }
521         else
522         {
523             /* If not fullscreen, we must be embedded */
524             /*
525              * PLUGIN DEVELOPERS:
526              *  If your plugin is embedded, or is full-screen
527              *  but you returned false in pluginPrinted above, NPP_Print
528              *  will be called with mode == NP_EMBED.  The NPWindow
529              *  in the printInfo gives the location and dimensions of
530              *  the embedded plugin on the printed page.  On the
531              *  Macintosh, platformPrint is the printer port; on
532              *  Windows, platformPrint is the handle to the printing
533              *  device context.
534              */
535
536             /***** Insert NPP_Print code here *****\
537             NPWindow* printWindow =
538                 &(printInfo->print.embedPrint.window);
539             void* platformPrint =
540                 printInfo->print.embedPrint.platformPrint;
541             \**************************************/
542         }
543     }
544 }
545
546 /******************************************************************************
547  * UNIX-only methods
548  *****************************************************************************/
549 #ifndef WIN32
550 static void Redraw( Widget w, XtPointer closure, XEvent *event )
551 {
552     VlcPlugin* p_plugin = (VlcPlugin*)closure;
553     GC gc;
554     XGCValues gcv;
555     const char * psz_text = "(no picture)";
556
557     gcv.foreground = BlackPixel( p_plugin->display, 0 );
558     gc = XCreateGC( p_plugin->display, p_plugin->window, GCForeground, &gcv );
559
560     XFillRectangle( p_plugin->display, p_plugin->window, gc,
561                     0, 0, p_plugin->width, p_plugin->height );
562
563     gcv.foreground = WhitePixel( p_plugin->display, 0 );
564     XChangeGC( p_plugin->display, gc, GCForeground, &gcv );
565
566     XDrawString( p_plugin->display, p_plugin->window, gc,
567                  p_plugin->width / 2 - 40, p_plugin->height / 2,
568                  psz_text, strlen(psz_text) );
569
570     XFreeGC( p_plugin->display, gc );
571 }
572 #endif
573