Changes to the libvlc API:
[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.4 2002/10/11 22:32:56 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         , "--vout", "xvideo,x11,dummy"
172         , "--aout", "dsp"
173         , "--intf", "dummy"
174         /*, "--noaudio"*/
175     };
176
177     if( instance == NULL )
178     {
179         return NPERR_INVALID_INSTANCE_ERROR;
180     }
181
182     VlcPlugin * p_plugin = new VlcPlugin( instance );
183
184     if( p_plugin == NULL )
185     {
186         return NPERR_OUT_OF_MEMORY_ERROR;
187     }
188
189     instance->pdata = p_plugin;
190
191     p_plugin->fMode = mode;
192     p_plugin->fWindow = NULL;
193     p_plugin->window = 0;
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 = "xvideo,x11,dummy";
215     VLC_Set( p_plugin->i_vlc, "conf::vout", value );
216     value.psz_string = "dummy";
217     VLC_Set( p_plugin->i_vlc, "conf::intf", value );
218
219     p_plugin->b_stream = 0;
220     p_plugin->b_autoplay = 0;
221     p_plugin->psz_target = NULL;
222
223     for( i = 0; i < argc ; i++ )
224     {
225         if( !strcmp( argn[i], "target" ) )
226         {
227             p_plugin->psz_target = argv[i];
228         }
229         else if( !strcmp( argn[i], "autoplay" ) )
230         {
231             if( !strcmp( argv[i], "yes" ) )
232             {
233                 p_plugin->b_autoplay = 1;
234             }
235         }
236         else if( !strcmp( argn[i], "loop" ) )
237         {
238             if( !strcmp( argv[i], "yes" ) )
239             {
240                 value.b_bool = VLC_TRUE;
241                 VLC_Set( p_plugin->i_vlc, "conf::loop", value );
242             }
243         }
244     }
245
246     if( p_plugin->psz_target )
247     {
248         p_plugin->psz_target = strdup( p_plugin->psz_target );
249     }
250
251     return NPERR_NO_ERROR;
252 }
253
254 NPError NPP_Destroy( NPP instance, NPSavedData** save )
255 {
256     if( instance == NULL )
257     {
258         return NPERR_INVALID_INSTANCE_ERROR;
259     }
260
261     VlcPlugin* p_plugin = (VlcPlugin*)instance->pdata;
262
263     if( p_plugin != NULL )
264     {
265         if( p_plugin->i_vlc )
266         {
267             VLC_Stop( p_plugin->i_vlc );
268             VLC_Destroy( p_plugin->i_vlc );
269             p_plugin->i_vlc = 0;
270         }
271
272         if( p_plugin->psz_target )
273         {
274             free( p_plugin->psz_target );
275             p_plugin->psz_target = NULL;
276         }
277
278         delete p_plugin;
279     }
280
281     instance->pdata = NULL;
282
283     return NPERR_NO_ERROR;
284 }
285
286 NPError NPP_SetWindow( NPP instance, NPWindow* window )
287 {
288     vlc_value_t value;
289
290     if( instance == NULL )
291     {
292         return NPERR_INVALID_INSTANCE_ERROR;
293     }
294
295     VlcPlugin* p_plugin = (VlcPlugin*)instance->pdata;
296
297     /* Write the window ID for vlc */
298     value.p_address = (void*)window->window;
299     VLC_Set( p_plugin->i_vlc, "drawable", value );
300
301     /*
302      * PLUGIN DEVELOPERS:
303      *  Before setting window to point to the
304      *  new window, you may wish to compare the new window
305      *  info to the previous window (if any) to note window
306      *  size changes, etc.
307      */
308
309     Widget netscape_widget;
310
311     p_plugin->window = (Window) window->window;
312     p_plugin->x = window->x;
313     p_plugin->y = window->y;
314     p_plugin->width = window->width;
315     p_plugin->height = window->height;
316     p_plugin->display = ((NPSetWindowCallbackStruct *)window->ws_info)->display;
317
318     netscape_widget = XtWindowToWidget(p_plugin->display, p_plugin->window);
319     XtAddEventHandler(netscape_widget, ExposureMask, FALSE, (XtEventHandler)Redraw, p_plugin);
320     Redraw(netscape_widget, (XtPointer)p_plugin, NULL);
321
322     p_plugin->fWindow = window;
323
324 #if 1
325     if( !p_plugin->b_stream )
326     {
327         int i_mode = PLAYLIST_APPEND;
328
329         if( p_plugin->b_autoplay )
330         {
331             i_mode |= PLAYLIST_GO;
332         }
333
334         if( p_plugin->psz_target )
335         {
336             VLC_AddTarget( p_plugin->i_vlc, p_plugin->psz_target,
337                            i_mode, PLAYLIST_END );
338             p_plugin->b_stream = 1;
339         }
340     }
341 #endif
342
343     return NPERR_NO_ERROR;
344 }
345
346 NPError NPP_NewStream( NPP instance, NPMIMEType type, NPStream *stream,
347                        NPBool seekable, uint16 *stype )
348 {
349     if( instance == NULL )
350     {
351         return NPERR_INVALID_INSTANCE_ERROR;
352     }
353
354 #if 0
355     VlcPlugin* p_plugin = (VlcPlugin*)instance->pdata;
356 #endif
357
358     fprintf(stderr, "NPP_NewStream - FILE mode !!\n");
359
360     /* We want a *filename* ! */
361     *stype = NP_ASFILE;
362
363 #if 0
364     if( p_plugin->b_stream == 0 )
365     {
366         p_plugin->psz_target = strdup( stream->url );
367         p_plugin->b_stream = 1;
368     }
369 #endif
370
371     return NPERR_NO_ERROR;
372 }
373
374 int32 STREAMBUFSIZE = 0X0FFFFFFF; /* If we are reading from a file in NPAsFile
375                    * mode so we can take any size stream in our
376                    * write call (since we ignore it) */
377
378 #define SARASS_SIZE (1024*1024)
379
380 int32 NPP_WriteReady( NPP instance, NPStream *stream )
381 {
382     VlcPlugin* p_plugin;
383
384     fprintf(stderr, "NPP_WriteReady\n");
385
386     if (instance != NULL)
387     {
388         p_plugin = (VlcPlugin*) instance->pdata;
389         /* Muahahahahahahaha */
390         return STREAMBUFSIZE;
391         /*return SARASS_SIZE;*/
392     }
393
394     /* Number of bytes ready to accept in NPP_Write() */
395     return STREAMBUFSIZE;
396     /*return 0;*/
397 }
398
399
400 int32 NPP_Write( NPP instance, NPStream *stream, int32 offset,
401                  int32 len, void *buffer )
402 {
403     fprintf(stderr, "NPP_Write %i\n", len);
404
405     if( instance != NULL )
406     {
407         /*VlcPlugin* p_plugin = (VlcPlugin*) instance->pdata;*/
408     }
409
410     return len;         /* The number of bytes accepted */
411 }
412
413
414 NPError NPP_DestroyStream( NPP instance, NPStream *stream, NPError reason )
415 {
416     if( instance == NULL )
417     {
418         return NPERR_INVALID_INSTANCE_ERROR;
419     }
420
421     return NPERR_NO_ERROR;
422 }
423
424
425 void NPP_StreamAsFile( NPP instance, NPStream *stream, const char* fname )
426 {
427     if( instance == NULL )
428     {
429         return;
430     }
431
432     VlcPlugin* p_plugin = (VlcPlugin*)instance->pdata;
433
434     fprintf(stderr, "NPP_StreamAsFile\n");
435     VLC_AddTarget( p_plugin->i_vlc, fname,
436                    PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
437 }
438
439 #if 0
440 void NPP_StreamAsFile( NPP instance, NPStream *stream, const char* fname )
441 {
442     fprintf(stderr,"filename : %s\n", fname);
443     ((VlcPlugin*) instance->pdata)->SetFileName(fname);
444
445     fprintf(stderr,"SetFileNeme ok. \n");
446 }
447 #endif
448
449
450 void NPP_URLNotify( NPP instance, const char* url,
451                     NPReason reason, void* notifyData )
452 {
453     /***** Insert NPP_URLNotify code here *****\
454     PluginInstance* p_plugin;
455     if (instance != NULL)
456         p_plugin = (PluginInstance*) instance->pdata;
457     \*********************************************/
458 }
459
460
461 void NPP_Print( NPP instance, NPPrint* printInfo )
462 {
463     if( printInfo == NULL )
464     {
465         return;
466     }
467
468     if( instance != NULL )
469     {
470         /***** Insert NPP_Print code here *****\
471         PluginInstance* p_plugin = (PluginInstance*) instance->pdata;
472         \**************************************/
473
474         if( printInfo->mode == NP_FULL )
475         {
476             /*
477              * PLUGIN DEVELOPERS:
478              *  If your plugin would like to take over
479              *  printing completely when it is in full-screen mode,
480              *  set printInfo->pluginPrinted to TRUE and print your
481              *  plugin as you see fit.  If your plugin wants Netscape
482              *  to handle printing in this case, set
483              *  printInfo->pluginPrinted to FALSE (the default) and
484              *  do nothing.  If you do want to handle printing
485              *  yourself, printOne is true if the print button
486              *  (as opposed to the print menu) was clicked.
487              *  On the Macintosh, platformPrint is a THPrint; on
488              *  Windows, platformPrint is a structure
489              *  (defined in npapi.h) containing the printer name, port,
490              *  etc.
491              */
492
493             /***** Insert NPP_Print code here *****\
494             void* platformPrint =
495                 printInfo->print.fullPrint.platformPrint;
496             NPBool printOne =
497                 printInfo->print.fullPrint.printOne;
498             \**************************************/
499
500             /* Do the default*/
501             printInfo->print.fullPrint.pluginPrinted = FALSE;
502         }
503         else
504         {
505             /* If not fullscreen, we must be embedded */
506             /*
507              * PLUGIN DEVELOPERS:
508              *  If your plugin is embedded, or is full-screen
509              *  but you returned false in pluginPrinted above, NPP_Print
510              *  will be called with mode == NP_EMBED.  The NPWindow
511              *  in the printInfo gives the location and dimensions of
512              *  the embedded plugin on the printed page.  On the
513              *  Macintosh, platformPrint is the printer port; on
514              *  Windows, platformPrint is the handle to the printing
515              *  device context.
516              */
517
518             /***** Insert NPP_Print code here *****\
519             NPWindow* printWindow =
520                 &(printInfo->print.embedPrint.window);
521             void* platformPrint =
522                 printInfo->print.embedPrint.platformPrint;
523             \**************************************/
524         }
525     }
526 }
527
528 /******************************************************************************
529  * UNIX-only methods
530  *****************************************************************************/
531 #ifndef WIN32
532 static void Redraw( Widget w, XtPointer closure, XEvent *event )
533 {
534     VlcPlugin* p_plugin = (VlcPlugin*)closure;
535     GC gc;
536     XGCValues gcv;
537     const char * psz_text = "(no picture)";
538
539     gcv.foreground = BlackPixel( p_plugin->display, 0 );
540     gc = XCreateGC( p_plugin->display, p_plugin->window, GCForeground, &gcv );
541
542     XFillRectangle( p_plugin->display, p_plugin->window, gc,
543                     0, 0, p_plugin->width, p_plugin->height );
544
545     gcv.foreground = WhitePixel( p_plugin->display, 0 );
546     XChangeGC( p_plugin->display, gc, GCForeground, &gcv );
547
548     XDrawString( p_plugin->display, p_plugin->window, gc,
549                  p_plugin->width / 2 - 40, p_plugin->height / 2,
550                  psz_text, strlen(psz_text) );
551
552     XFreeGC( p_plugin->display, gc );
553 }
554 #endif
555