1 /*****************************************************************************
2 * vlcshell.c: a VideoLAN Client plugin for Mozilla
3 *****************************************************************************
4 * Copyright (C) 2002 VideoLAN
5 * $Id: vlcshell.cpp,v 1.8 2003/01/28 16:57:28 sam Exp $
7 * Authors: Samuel Hocevar <sam@zoy.org>
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.
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.
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 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
42 # include <X11/Xlib.h>
43 # include <X11/Intrinsic.h>
44 # include <X11/StringDefs.h>
48 #include "vlcplugin.h"
50 /* XXX: disable VLC */
54 # define WINDOW_TEXT "(no picture)"
56 # define WINDOW_TEXT "(no libvlc)"
59 /*****************************************************************************
60 * Unix-only declarations
61 ******************************************************************************/
63 # define VOUT_PLUGINS "xvideo,x11,dummy"
64 # define AOUT_PLUGINS "oss,dummy"
66 static void Redraw( Widget w
, XtPointer closure
, XEvent
*event
);
69 /*****************************************************************************
70 * Windows-only declarations
71 *****************************************************************************/
73 # define VOUT_PLUGINS "directx,dummy"
74 # define AOUT_PLUGINS "none" /* "directx,waveout,dummy" */
76 HINSTANCE g_hDllInstance
= NULL
;
79 DllMain( HINSTANCE hinstDLL
, // handle of DLL module
80 DWORD fdwReason
, // reason for calling function
85 case DLL_PROCESS_ATTACH
:
86 g_hDllInstance
= hinstDLL
;
88 case DLL_THREAD_ATTACH
:
89 case DLL_PROCESS_DETACH
:
90 case DLL_THREAD_DETACH
:
96 LRESULT CALLBACK
Manage( HWND
, UINT
, WPARAM
, LPARAM
);
99 /******************************************************************************
100 * UNIX-only API calls
101 *****************************************************************************/
102 char * NPP_GetMIMEDescription( void )
104 return PLUGIN_MIMETYPES
;
107 NPError
NPP_GetValue( NPP instance
, NPPVariable variable
, void *value
)
109 static nsIID nsid
= VLCINTF_IID
;
110 static char psz_desc
[1000];
114 case NPPVpluginNameString
:
115 *((char **)value
) = PLUGIN_NAME
;
116 return NPERR_NO_ERROR
;
118 case NPPVpluginDescriptionString
:
120 snprintf( psz_desc
, 1000-1, PLUGIN_DESCRIPTION
, VLC_Version() );
122 snprintf( psz_desc
, 1000-1, PLUGIN_DESCRIPTION
, "(disabled)" );
124 psz_desc
[1000-1] = 0;
125 *((char **)value
) = psz_desc
;
126 return NPERR_NO_ERROR
;
133 if( instance
== NULL
)
135 return NPERR_INVALID_INSTANCE_ERROR
;
138 VlcPlugin
* p_plugin
= (VlcPlugin
*) instance
->pdata
;
142 case NPPVpluginScriptableInstance
:
143 *(nsISupports
**)value
= p_plugin
->GetPeer();
144 if( *(nsISupports
**)value
== NULL
)
146 return NPERR_OUT_OF_MEMORY_ERROR
;
150 case NPPVpluginScriptableIID
:
151 *(nsIID
**)value
= (nsIID
*)NPN_MemAlloc( sizeof(nsIID
) );
152 if( *(nsIID
**)value
== NULL
)
154 return NPERR_OUT_OF_MEMORY_ERROR
;
156 **(nsIID
**)value
= nsid
;
160 return NPERR_GENERIC_ERROR
;
163 return NPERR_NO_ERROR
;
166 /******************************************************************************
167 * General Plug-in Calls
168 *****************************************************************************/
169 NPError
NPP_Initialize( void )
171 return NPERR_NO_ERROR
;
174 jref
NPP_GetJavaClass( void )
179 void NPP_Shutdown( void )
184 NPError
NPP_New( NPMIMEType pluginType
, NPP instance
, uint16 mode
, int16 argc
,
185 char* argn
[], char* argv
[], NPSavedData
* saved
)
195 /*, "--plugin-path", "/home/sam/videolan/vlc_MAIN/plugins"*/
199 if( instance
== NULL
)
201 return NPERR_INVALID_INSTANCE_ERROR
;
204 VlcPlugin
* p_plugin
= new VlcPlugin( instance
);
206 if( p_plugin
== NULL
)
208 return NPERR_OUT_OF_MEMORY_ERROR
;
211 instance
->pdata
= p_plugin
;
214 p_plugin
->p_hwnd
= NULL
;
215 p_plugin
->pf_wndproc
= NULL
;
219 p_plugin
->window
= 0;
220 p_plugin
->p_display
= NULL
;
223 p_plugin
->p_npwin
= NULL
;
224 p_plugin
->i_npmode
= mode
;
225 p_plugin
->i_width
= 0;
226 p_plugin
->i_height
= 0;
229 p_plugin
->i_vlc
= VLC_Create();
230 if( p_plugin
->i_vlc
< 0 )
235 return NPERR_GENERIC_ERROR
;
238 i_ret
= VLC_Init( p_plugin
->i_vlc
, sizeof(ppsz_foo
)/sizeof(char*), ppsz_foo
);
241 VLC_Destroy( p_plugin
->i_vlc
);
245 return NPERR_GENERIC_ERROR
;
248 value
.psz_string
= "dummy";
249 VLC_Set( p_plugin
->i_vlc
, "conf::intf", value
);
250 value
.psz_string
= VOUT_PLUGINS
;
251 VLC_Set( p_plugin
->i_vlc
, "conf::vout", value
);
252 value
.psz_string
= AOUT_PLUGINS
;
253 VLC_Set( p_plugin
->i_vlc
, "conf::aout", value
);
258 #endif /* USE_LIBVLC */
260 p_plugin
->b_stream
= VLC_FALSE
;
261 p_plugin
->b_autoplay
= VLC_FALSE
;
262 p_plugin
->psz_target
= NULL
;
264 for( i
= 0; i
< argc
; i
++ )
266 if( !strcmp( argn
[i
], "target" ) )
268 p_plugin
->psz_target
= argv
[i
];
270 else if( !strcmp( argn
[i
], "autoplay" ) )
272 if( !strcmp( argv
[i
], "yes" ) )
274 p_plugin
->b_autoplay
= 1;
277 else if( !strcmp( argn
[i
], "autostart" ) )
279 if( !strcmp( argv
[i
], "1" ) || !strcmp( argv
[i
], "true" ) )
281 p_plugin
->b_autoplay
= 1;
284 else if( !strcmp( argn
[i
], "filename" ) )
286 p_plugin
->psz_target
= argv
[i
];
288 else if( !strcmp( argn
[i
], "src" ) )
290 p_plugin
->psz_target
= argv
[i
];
294 else if( !strcmp( argn
[i
], "loop" ) )
296 if( !strcmp( argv
[i
], "yes" ) )
298 value
.b_bool
= VLC_TRUE
;
299 VLC_Set( p_plugin
->i_vlc
, "conf::loop", value
);
305 if( p_plugin
->psz_target
)
307 p_plugin
->psz_target
= strdup( p_plugin
->psz_target
);
310 return NPERR_NO_ERROR
;
313 NPError
NPP_Destroy( NPP instance
, NPSavedData
** save
)
315 if( instance
== NULL
)
317 return NPERR_INVALID_INSTANCE_ERROR
;
320 VlcPlugin
* p_plugin
= (VlcPlugin
*)instance
->pdata
;
322 if( p_plugin
!= NULL
)
324 if( p_plugin
->i_vlc
)
327 VLC_Stop( p_plugin
->i_vlc
);
328 VLC_Destroy( p_plugin
->i_vlc
);
333 if( p_plugin
->psz_target
)
335 free( p_plugin
->psz_target
);
336 p_plugin
->psz_target
= NULL
;
342 instance
->pdata
= NULL
;
344 return NPERR_NO_ERROR
;
347 NPError
NPP_SetWindow( NPP instance
, NPWindow
* window
)
349 if( instance
== NULL
)
351 return NPERR_INVALID_INSTANCE_ERROR
;
354 VlcPlugin
* p_plugin
= (VlcPlugin
*)instance
->pdata
;
356 /* Write the window ID for vlc */
360 /* FIXME: this cast sucks */
361 value
.i_int
= (int) (ptrdiff_t) (void *) window
->window
;
362 VLC_Set( p_plugin
->i_vlc
, "conf::x11-drawable", value
);
363 VLC_Set( p_plugin
->i_vlc
, "conf::xvideo-drawable", value
);
365 value
.i_int
= (int) (ptrdiff_t) (void *) window
->window
;
366 VLC_Set( p_plugin
->i_vlc
, "conf::directx-window", value
);
371 * Before setting window to point to the
372 * new window, you may wish to compare the new window
373 * info to the previous window (if any) to note window
378 if( !window
|| !window
->window
)
380 /* Window was destroyed. Invalidate everything. */
381 if( p_plugin
->p_npwin
)
383 SetWindowLong( p_plugin
->p_hwnd
, GWL_WNDPROC
,
384 (LONG
)p_plugin
->pf_wndproc
);
385 p_plugin
->pf_wndproc
= NULL
;
386 p_plugin
->p_hwnd
= NULL
;
389 p_plugin
->p_npwin
= window
;
390 return NPERR_NO_ERROR
;
393 if( p_plugin
->p_npwin
)
395 if( p_plugin
->p_hwnd
== (HWND
)window
->window
)
397 /* Same window, but something may have changed. First we
398 * update the plugin structure, then we redraw the window */
399 InvalidateRect( p_plugin
->p_hwnd
, NULL
, TRUE
);
400 p_plugin
->i_width
= window
->width
;
401 p_plugin
->i_height
= window
->height
;
402 p_plugin
->p_npwin
= window
;
403 UpdateWindow( p_plugin
->p_hwnd
);
404 return NPERR_NO_ERROR
;
407 /* Window has changed. Destroy the one we have, and go
408 * on as if it was a real initialization. */
409 SetWindowLong( p_plugin
->p_hwnd
, GWL_WNDPROC
,
410 (LONG
)p_plugin
->pf_wndproc
);
411 p_plugin
->pf_wndproc
= NULL
;
412 p_plugin
->p_hwnd
= NULL
;
415 p_plugin
->pf_wndproc
= (WNDPROC
)SetWindowLong( (HWND
)window
->window
,
416 GWL_WNDPROC
, (LONG
)Manage
);
417 p_plugin
->p_hwnd
= (HWND
)window
->window
;
418 SetProp( p_plugin
->p_hwnd
, "w00t", (HANDLE
)p_plugin
);
419 InvalidateRect( p_plugin
->p_hwnd
, NULL
, TRUE
);
420 UpdateWindow( p_plugin
->p_hwnd
);
424 p_plugin
->window
= (Window
) window
->window
;
425 p_plugin
->p_display
= ((NPSetWindowCallbackStruct
*)window
->ws_info
)->display
;
427 Widget w
= XtWindowToWidget( p_plugin
->p_display
, p_plugin
->window
);
428 XtAddEventHandler( w
, ExposureMask
, FALSE
,
429 (XtEventHandler
)Redraw
, p_plugin
);
430 Redraw( w
, (XtPointer
)p_plugin
, NULL
);
433 p_plugin
->p_npwin
= window
;
435 p_plugin
->i_width
= window
->width
;
436 p_plugin
->i_height
= window
->height
;
438 if( !p_plugin
->b_stream
)
440 int i_mode
= PLAYLIST_APPEND
;
442 if( p_plugin
->b_autoplay
)
444 i_mode
|= PLAYLIST_GO
;
447 if( p_plugin
->psz_target
)
450 VLC_AddTarget( p_plugin
->i_vlc
, p_plugin
->psz_target
,
451 i_mode
, PLAYLIST_END
);
453 p_plugin
->b_stream
= VLC_TRUE
;
457 return NPERR_NO_ERROR
;
460 NPError
NPP_NewStream( NPP instance
, NPMIMEType type
, NPStream
*stream
,
461 NPBool seekable
, uint16
*stype
)
463 if( instance
== NULL
)
465 return NPERR_INVALID_INSTANCE_ERROR
;
469 VlcPlugin
* p_plugin
= (VlcPlugin
*)instance
->pdata
;
472 fprintf(stderr
, "NPP_NewStream - FILE mode !!\n");
474 /* We want a *filename* ! */
478 if( !p_plugin
->b_stream
)
480 p_plugin
->psz_target
= strdup( stream
->url
);
481 p_plugin
->b_stream
= VLC_TRUE
;
485 return NPERR_NO_ERROR
;
488 int32 STREAMBUFSIZE
= 0X0FFFFFFF; /* If we are reading from a file in NPAsFile
489 * mode so we can take any size stream in our
490 * write call (since we ignore it) */
492 #define SARASS_SIZE (1024*1024)
494 int32
NPP_WriteReady( NPP instance
, NPStream
*stream
)
498 fprintf(stderr
, "NPP_WriteReady\n");
500 if (instance
!= NULL
)
502 p_plugin
= (VlcPlugin
*) instance
->pdata
;
503 /* Muahahahahahahaha */
504 return STREAMBUFSIZE
;
505 /*return SARASS_SIZE;*/
508 /* Number of bytes ready to accept in NPP_Write() */
509 return STREAMBUFSIZE
;
514 int32
NPP_Write( NPP instance
, NPStream
*stream
, int32 offset
,
515 int32 len
, void *buffer
)
517 fprintf(stderr
, "NPP_Write %i\n", (int)len
);
519 if( instance
!= NULL
)
521 /*VlcPlugin* p_plugin = (VlcPlugin*) instance->pdata;*/
524 return len
; /* The number of bytes accepted */
528 NPError
NPP_DestroyStream( NPP instance
, NPStream
*stream
, NPError reason
)
530 if( instance
== NULL
)
532 return NPERR_INVALID_INSTANCE_ERROR
;
535 return NPERR_NO_ERROR
;
539 void NPP_StreamAsFile( NPP instance
, NPStream
*stream
, const char* fname
)
541 if( instance
== NULL
)
546 fprintf(stderr
, "NPP_StreamAsFile %s\n", fname
);
549 /* VlcPlugin* p_plugin = (VlcPlugin*)instance->pdata; */
551 /* VLC_AddTarget( p_plugin->i_vlc, fname,
552 PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );*/
557 void NPP_URLNotify( NPP instance
, const char* url
,
558 NPReason reason
, void* notifyData
)
560 /***** Insert NPP_URLNotify code here *****\
561 PluginInstance* p_plugin;
562 if (instance != NULL)
563 p_plugin = (PluginInstance*) instance->pdata;
564 \*********************************************/
568 void NPP_Print( NPP instance
, NPPrint
* printInfo
)
570 if( printInfo
== NULL
)
575 if( instance
!= NULL
)
577 /***** Insert NPP_Print code here *****\
578 PluginInstance* p_plugin = (PluginInstance*) instance->pdata;
579 \**************************************/
581 if( printInfo
->mode
== NP_FULL
)
585 * If your plugin would like to take over
586 * printing completely when it is in full-screen mode,
587 * set printInfo->pluginPrinted to TRUE and print your
588 * plugin as you see fit. If your plugin wants Netscape
589 * to handle printing in this case, set
590 * printInfo->pluginPrinted to FALSE (the default) and
591 * do nothing. If you do want to handle printing
592 * yourself, printOne is true if the print button
593 * (as opposed to the print menu) was clicked.
594 * On the Macintosh, platformPrint is a THPrint; on
595 * Windows, platformPrint is a structure
596 * (defined in npapi.h) containing the printer name, port,
600 /***** Insert NPP_Print code here *****\
601 void* platformPrint =
602 printInfo->print.fullPrint.platformPrint;
604 printInfo->print.fullPrint.printOne;
605 \**************************************/
608 printInfo
->print
.fullPrint
.pluginPrinted
= FALSE
;
612 /* If not fullscreen, we must be embedded */
615 * If your plugin is embedded, or is full-screen
616 * but you returned false in pluginPrinted above, NPP_Print
617 * will be called with mode == NP_EMBED. The NPWindow
618 * in the printInfo gives the location and dimensions of
619 * the embedded plugin on the printed page. On the
620 * Macintosh, platformPrint is the printer port; on
621 * Windows, platformPrint is the handle to the printing
625 /***** Insert NPP_Print code here *****\
626 NPWindow* printWindow =
627 &(printInfo->print.embedPrint.window);
628 void* platformPrint =
629 printInfo->print.embedPrint.platformPrint;
630 \**************************************/
635 /******************************************************************************
636 * Windows-only methods
637 *****************************************************************************/
639 LRESULT CALLBACK
Manage( HWND p_hwnd
, UINT i_msg
, WPARAM wpar
, LPARAM lpar
)
641 VlcPlugin
* p_plugin
= (VlcPlugin
*) GetProp( p_hwnd
, "w00t" );
648 PAINTSTRUCT paintstruct
;
652 hdc
= BeginPaint( p_hwnd
, &paintstruct
);
654 GetClientRect( p_hwnd
, &rect
);
655 FillRect( hdc
, &rect
, (HBRUSH
)GetStockObject(WHITE_BRUSH
) );
656 TextOut( hdc
, p_plugin
->i_width
/ 2 - 40, p_plugin
->i_height
/ 2,
657 WINDOW_TEXT
, strlen(WINDOW_TEXT
) );
659 EndPaint( p_hwnd
, &paintstruct
);
664 p_plugin
->pf_wndproc( p_hwnd
, i_msg
, wpar
, lpar
);
671 /******************************************************************************
673 *****************************************************************************/
675 static void Redraw( Widget w
, XtPointer closure
, XEvent
*event
)
677 VlcPlugin
* p_plugin
= (VlcPlugin
*)closure
;
681 gcv
.foreground
= BlackPixel( p_plugin
->p_display
, 0 );
682 gc
= XCreateGC( p_plugin
->p_display
, p_plugin
->window
, GCForeground
, &gcv
);
684 XFillRectangle( p_plugin
->p_display
, p_plugin
->window
, gc
,
685 0, 0, p_plugin
->i_width
, p_plugin
->i_height
);
687 gcv
.foreground
= WhitePixel( p_plugin
->p_display
, 0 );
688 XChangeGC( p_plugin
->p_display
, gc
, GCForeground
, &gcv
);
690 XDrawString( p_plugin
->p_display
, p_plugin
->window
, gc
,
691 p_plugin
->i_width
/ 2 - 40, p_plugin
->i_height
/ 2,
692 WINDOW_TEXT
, strlen(WINDOW_TEXT
) );
694 XFreeGC( p_plugin
->p_display
, gc
);