]> git.sesse.net Git - vlc/blob - mozilla/vlcplugin.c
* ./src/playlist/playlist.c: -Z flag makes playlist loop endlessly.
[vlc] / mozilla / vlcplugin.c
1 /*****************************************************************************
2  * vlcplugin.c: a VideoLAN Client plugin for Mozilla
3  *****************************************************************************
4  * Copyright (C) 2002 VideoLAN
5  * $Id: vlcplugin.c,v 1.5 2002/08/20 18:08:51 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 /* Mozilla stuff */
31 #include <plugin/npapi.h>
32
33 /* X11 stuff */
34 #include <X11/Xlib.h>
35 #include <X11/Intrinsic.h>
36 #include <X11/StringDefs.h>
37
38 /* vlc stuff */
39 #include <vlc/vlc.h>
40
41 #include "vlcplugin.h"
42
43 /*******************************************************************************
44  * Unix-only declarations
45  ******************************************************************************/
46 static void Redraw( Widget w, XtPointer closure, XEvent *event );
47
48 /*******************************************************************************
49  * UNIX-only API calls
50  ******************************************************************************/
51 char* NPP_GetMIMEDescription( void )
52 {
53     return( PLUGIN_MIMETYPES );
54 }
55
56 NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value)
57 {
58     NPError err = NPERR_NO_ERROR;
59     if (variable == NPPVpluginNameString)
60         *((char **)value) = PLUGIN_NAME;
61     else if (variable == NPPVpluginDescriptionString)
62         *((char **)value) = PLUGIN_DESCRIPTION;
63     else
64         err = NPERR_GENERIC_ERROR;
65
66     return err;
67 }
68
69 /*******************************************************************************
70  * General Plug-in Calls
71  ******************************************************************************/
72 NPError NPP_Initialize( void )
73 {
74     fprintf(stderr, "NPP_Initialize\n");
75     return NPERR_NO_ERROR;
76 }
77
78 jref NPP_GetJavaClass( void )
79 {
80     return NULL;                /* Java disabled */
81 }
82
83 void NPP_Shutdown( void )
84 {
85     /* Java disabled */
86 }
87
88 NPError NPP_New( NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc,
89                  char* argn[], char* argv[], NPSavedData* saved )
90 {
91     NPError result = NPERR_NO_ERROR;
92     PluginInstance* This;
93     int i_ret;
94     int i;
95
96     char *ppsz_foo[] =
97     {
98         "vlc"
99         /*, "--plugin-path", "/home/sam/videolan/vlc_MAIN/plugins"*/
100         , "--vout", "xvideo,x11,dummy"
101         , "--intf", "dummy"
102         , "--noaudio"
103         /*, "-v"*/
104     };
105
106     fprintf(stderr, "NPP_New\n");
107
108     if (instance == NULL)
109         return NPERR_INVALID_INSTANCE_ERROR;
110         
111     instance->pdata = NPN_MemAlloc(sizeof(PluginInstance));
112     
113     This = (PluginInstance*) instance->pdata;
114
115     if (This == NULL)
116         return NPERR_OUT_OF_MEMORY_ERROR;
117
118     {
119         /* mode is NP_EMBED, NP_FULL, or NP_BACKGROUND (see npapi.h) */
120         This->fMode = mode;
121         This->fWindow = NULL;
122
123         This->window = 0;
124     }
125
126     This->p_vlc = vlc_create_r();
127     if( This->p_vlc == NULL )
128     {
129         return NPERR_GENERIC_ERROR;
130     }
131
132     i_ret = vlc_init_r( This->p_vlc, sizeof(ppsz_foo)/sizeof(char*), ppsz_foo );
133     if( i_ret )
134     {
135         vlc_destroy_r( This->p_vlc );
136         This->p_vlc = NULL;
137         return NPERR_GENERIC_ERROR;
138     }
139
140     vlc_set_r( This->p_vlc, "vout", "xvideo,x11,dummy" );
141     vlc_set_r( This->p_vlc, "intf", "dummy" );
142     vlc_set_r( This->p_vlc, "audio", 0 );
143
144     i_ret = vlc_run_r( This->p_vlc );
145     if( i_ret )
146     {
147         vlc_destroy_r( This->p_vlc );
148         This->p_vlc = NULL;
149         return NPERR_GENERIC_ERROR;
150     }
151
152     This->b_stream = 0;
153     This->psz_target = NULL;
154
155     for( i = 0; i < argc ; i++ )
156     {
157         fprintf(stderr, "arg %i: '%s' = '%s'\n", i, argn[i], argv[i]);
158         if(!strcmp(argn[i],"target"))
159         {
160             fprintf(stderr, "target specified: %s\n", argv[i]);
161             This->psz_target = strdup( argv[i] );
162         }
163         else
164         {
165             /*vlc_set_r( This->psz_target, argn[i], argv[i] );*/
166         }
167     }
168
169     return result;
170 }
171
172 NPError NPP_Destroy( NPP instance, NPSavedData** save )
173 {
174     PluginInstance* This;
175
176     fprintf(stderr, "NPP_Destroy\n");
177
178     if (instance == NULL)
179         return NPERR_INVALID_INSTANCE_ERROR;
180
181     This = (PluginInstance*) instance->pdata;
182
183     if( This->p_vlc != NULL )
184     {
185         vlc_destroy_r( This->p_vlc );
186         This->p_vlc = NULL;
187     }
188
189     if( This->psz_target )
190     {
191         free( This->psz_target );
192         This->psz_target = NULL;
193     }
194
195     if (This != NULL) {
196         NPN_MemFree(instance->pdata);
197         instance->pdata = NULL;
198     }
199
200     return NPERR_NO_ERROR;
201 }
202
203 NPError NPP_SetWindow( NPP instance, NPWindow* window )
204 {
205     NPError result = NPERR_NO_ERROR;
206     PluginInstance* This;
207
208     fprintf(stderr, "NPP_SetWindow\n");
209
210     if (instance == NULL)
211         return NPERR_INVALID_INSTANCE_ERROR;
212
213     This = (PluginInstance*) instance->pdata;
214
215     vlc_set_r( This->p_vlc, "x11-drawable", window->window );
216     vlc_set_r( This->p_vlc, "xvideo-drawable", window->window );
217     /*
218      * PLUGIN DEVELOPERS:
219      *  Before setting window to point to the
220      *  new window, you may wish to compare the new window
221      *  info to the previous window (if any) to note window
222      *  size changes, etc.
223      */
224     
225     {
226         Widget netscape_widget;
227
228         This->window = (Window) window->window;
229         This->x = window->x;
230         This->y = window->y;
231         This->width = window->width;
232         This->height = window->height;
233         This->display = ((NPSetWindowCallbackStruct *)window->ws_info)->display;
234
235         netscape_widget = XtWindowToWidget(This->display, This->window);
236         XtAddEventHandler(netscape_widget, ExposureMask, FALSE, (XtEventHandler)Redraw, This);
237         Redraw(netscape_widget, (XtPointer)This, NULL);
238     }
239
240     This->fWindow = window;
241
242 #if 1
243     if( !This->b_stream )
244     {
245         This->b_stream = 1;
246         if( This->psz_target )
247         {
248             vlc_add_target_r( This->p_vlc, This->psz_target, PLAYLIST_APPEND, PLAYLIST_END );
249                     /* We loop, dude */
250             vlc_add_target_r( This->p_vlc, "vlc:loop", PLAYLIST_APPEND, PLAYLIST_END );
251         }
252     }
253 #endif
254
255     return result;
256 }
257
258
259 NPError NPP_NewStream( NPP instance, NPMIMEType type, NPStream *stream, 
260                        NPBool seekable, uint16 *stype )
261 {
262     PluginInstance* This;
263
264     fprintf(stderr, "NPP_NewStream - FILE mode !!\n");
265
266     if (instance == NULL)
267         return NPERR_INVALID_INSTANCE_ERROR;
268
269     This = (PluginInstance*) instance->pdata;
270
271     /* We want a *filename* ! */
272     *stype = NP_ASFILE;
273
274 #if 0
275     if( This->b_stream == 0 )
276     {
277         This->psz_target = strdup( stream->url );
278         This->b_stream = 1;
279     }
280 #endif
281
282     return NPERR_NO_ERROR;
283 }
284
285
286 /* PLUGIN DEVELOPERS:
287  *      These next 2 functions are directly relevant in a plug-in which
288  *      handles the data in a streaming manner. If you want zero bytes
289  *      because no buffer space is YET available, return 0. As long as
290  *      the stream has not been written to the plugin, Navigator will
291  *      continue trying to send bytes.  If the plugin doesn't want them,
292  *      just return some large number from NPP_WriteReady(), and
293  *      ignore them in NPP_Write().  For a NP_ASFILE stream, they are
294  *      still called but can safely be ignored using this strategy.
295  */
296
297 int32 STREAMBUFSIZE = 0X0FFFFFFF; /* If we are reading from a file in NPAsFile
298                    * mode so we can take any size stream in our
299                    * write call (since we ignore it) */
300
301 #define SARASS_SIZE (1024*1024)
302
303 int32 NPP_WriteReady( NPP instance, NPStream *stream )
304 {
305     PluginInstance* This;
306
307     fprintf(stderr, "NPP_WriteReady\n");
308
309     if (instance != NULL)
310     {
311         This = (PluginInstance*) instance->pdata;
312         /* Muahahahahahahaha */
313         return STREAMBUFSIZE;
314         /*return SARASS_SIZE;*/
315     }
316
317     /* Number of bytes ready to accept in NPP_Write() */
318     return STREAMBUFSIZE;
319     /*return 0;*/
320 }
321
322
323 int32 NPP_Write( NPP instance, NPStream *stream, int32 offset,
324                  int32 len, void *buffer )
325 {
326     fprintf(stderr, "NPP_Write %i\n", len);
327
328     if (instance != NULL)
329     {
330         /*PluginInstance* This = (PluginInstance*) instance->pdata;*/
331     }
332
333     return len;         /* The number of bytes accepted */
334 }
335
336
337 NPError NPP_DestroyStream( NPP instance, NPStream *stream, NPError reason )
338 {
339     PluginInstance* This;
340     fprintf(stderr, "NPP_DestroyStream\n");
341
342     if (instance == NULL)
343         return NPERR_INVALID_INSTANCE_ERROR;
344     This = (PluginInstance*) instance->pdata;
345
346     return NPERR_NO_ERROR;
347 }
348
349
350 void NPP_StreamAsFile( NPP instance, NPStream *stream, const char* fname )
351 {
352     PluginInstance* This;
353     fprintf(stderr, "NPP_StreamAsFile\n");
354     if (instance != NULL)
355     {
356         This = (PluginInstance*) instance->pdata;
357         vlc_add_target_r( This->p_vlc, fname, PLAYLIST_APPEND, PLAYLIST_END );
358                 /* We loop, dude */
359         vlc_add_target_r( This->p_vlc, "vlc:loop", PLAYLIST_APPEND, PLAYLIST_END );
360     }
361 }
362
363
364 void NPP_Print( NPP instance, NPPrint* printInfo )
365 {
366     fprintf(stderr, "NPP_Print\n");
367
368     if(printInfo == NULL)
369         return;
370
371     if (instance != NULL) {
372         PluginInstance* This = (PluginInstance*) instance->pdata;
373     
374         if (printInfo->mode == NP_FULL) {
375             /*
376              * PLUGIN DEVELOPERS:
377              *  If your plugin would like to take over
378              *  printing completely when it is in full-screen mode,
379              *  set printInfo->pluginPrinted to TRUE and print your
380              *  plugin as you see fit.  If your plugin wants Netscape
381              *  to handle printing in this case, set
382              *  printInfo->pluginPrinted to FALSE (the default) and
383              *  do nothing.  If you do want to handle printing
384              *  yourself, printOne is true if the print button
385              *  (as opposed to the print menu) was clicked.
386              *  On the Macintosh, platformPrint is a THPrint; on
387              *  Windows, platformPrint is a structure
388              *  (defined in npapi.h) containing the printer name, port,
389              *  etc.
390              */
391
392             void* platformPrint =
393                 printInfo->print.fullPrint.platformPrint;
394             NPBool printOne =
395                 printInfo->print.fullPrint.printOne;
396             
397             /* Do the default*/
398             printInfo->print.fullPrint.pluginPrinted = FALSE;
399         }
400         else {  /* If not fullscreen, we must be embedded */
401             /*
402              * PLUGIN DEVELOPERS:
403              *  If your plugin is embedded, or is full-screen
404              *  but you returned false in pluginPrinted above, NPP_Print
405              *  will be called with mode == NP_EMBED.  The NPWindow
406              *  in the printInfo gives the location and dimensions of
407              *  the embedded plugin on the printed page.  On the
408              *  Macintosh, platformPrint is the printer port; on
409              *  Windows, platformPrint is the handle to the printing
410              *  device context.
411              */
412
413             NPWindow* printWindow =
414                 &(printInfo->print.embedPrint.window);
415             void* platformPrint =
416                 printInfo->print.embedPrint.platformPrint;
417         }
418     }
419 }
420
421 /*******************************************************************************
422 // NPP_URLNotify:
423 // Notifies the instance of the completion of a URL request. 
424 // 
425 // NPP_URLNotify is called when Netscape completes a NPN_GetURLNotify or
426 // NPN_PostURLNotify request, to inform the plug-in that the request,
427 // identified by url, has completed for the reason specified by reason. The most
428 // common reason code is NPRES_DONE, indicating simply that the request
429 // completed normally. Other possible reason codes are NPRES_USER_BREAK,
430 // indicating that the request was halted due to a user action (for example,
431 // clicking the "Stop" button), and NPRES_NETWORK_ERR, indicating that the
432 // request could not be completed (for example, because the URL could not be
433 // found). The complete list of reason codes is found in npapi.h. 
434 // 
435 // The parameter notifyData is the same plug-in-private value passed as an
436 // argument to the corresponding NPN_GetURLNotify or NPN_PostURLNotify
437 // call, and can be used by your plug-in to uniquely identify the request. 
438  ******************************************************************************/
439 void NPP_URLNotify( NPP instance, const char* url, NPReason reason,
440                     void* notifyData )
441 {
442 }
443
444 /*******************************************************************************
445  * UNIX-only methods
446  ******************************************************************************/
447 static void Redraw( Widget w, XtPointer closure, XEvent *event )
448 {
449     PluginInstance* This = (PluginInstance*)closure;
450     GC gc;
451     XGCValues gcv;
452     const char* text = "hello d00dZ, I'm in void Redraw()";
453
454     XtVaGetValues(w, XtNbackground, &gcv.background,
455                   XtNforeground, &gcv.foreground, 0);
456     gc = XCreateGC(This->display, This->window, 
457                    GCForeground|GCBackground, &gcv);
458     XDrawRectangle(This->display, This->window, gc, 
459                    0, 0, This->width-1, This->height-1);
460     XDrawString(This->display, This->window, gc, 
461                 This->width/2 - 100, This->height/2,
462                 text, strlen(text));
463     return;
464 }
465