]> git.sesse.net Git - vlc/blobdiff - mozilla/vlcshell.cpp
Change the podcast-urls config option to auto save.
[vlc] / mozilla / vlcshell.cpp
index 8ec4e6a3d5cdf84a22cda7a5e6618d6a04e2ccf1..6c57dda38aed12551a94266c80ec29cbed8af48c 100644 (file)
@@ -1,8 +1,8 @@
 /*****************************************************************************
- * vlcshell.c: a VideoLAN Client plugin for Mozilla
+ * vlcshell.cpp: a VLC plugin for Mozilla
  *****************************************************************************
- * Copyright (C) 2002 VideoLAN
- * $Id: vlcshell.cpp,v 1.5 2002/10/22 21:10:28 sam Exp $
+ * Copyright (C) 2002-2005 the VideoLAN team
+ * $Id$
  *
  * Authors: Samuel Hocevar <sam@zoy.org>
  *
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  *****************************************************************************/
 
 /*****************************************************************************
  * Preamble
  *****************************************************************************/
+#include "config.h"
+
 #include <stdio.h>
 #include <string.h>
-
-/* vlc stuff */
-#include <vlc/vlc.h>
+#include <stdlib.h>
 
 /* Mozilla stuff */
-#include <npapi.h>
-
-#ifdef WIN32
+#ifdef HAVE_MOZILLA_CONFIG_H
+#   include <mozilla-config.h>
+#endif
 
-#else
-    /* X11 stuff */
-#   include <X11/Xlib.h>
-#   include <X11/Intrinsic.h>
-#   include <X11/StringDefs.h>
+/* This is from mozilla java, do we really need it? */
+#if 0
+#include <jri.h>
 #endif
 
-#include "vlcpeer.h"
 #include "vlcplugin.h"
 
+/* Enable/disable debugging printf's for X11 resizing */
+#undef X11_RESIZE_DEBUG
+
+#define WINDOW_TEXT "(no video)"
+
 /*****************************************************************************
  * Unix-only declarations
 ******************************************************************************/
-#ifndef WIN32
+#ifdef XP_UNIX
+
 static void Redraw( Widget w, XtPointer closure, XEvent *event );
+static void Resize( Widget w, XtPointer closure, XEvent *event );
+
+#endif
+
+/*****************************************************************************
+ * MacOS-only declarations
+******************************************************************************/
+#ifdef XP_MACOSX
 #endif
 
 /*****************************************************************************
  * Windows-only declarations
  *****************************************************************************/
-#ifdef WIN32
-HINSTANCE g_hDllInstance = NULL;
+#ifdef XP_WIN
+
+static LRESULT CALLBACK Manage( HWND p_hwnd, UINT i_msg, WPARAM wpar, LPARAM lpar );
 
-BOOL WINAPI
-DllMain( HINSTANCE  hinstDLL,                   // handle of DLL module
-                    DWORD  fdwReason,       // reason for calling function
-                    LPVOID  lpvReserved)
-{
-        switch (fdwReason) {
-                case DLL_PROCESS_ATTACH:
-                  g_hDllInstance = hinstDLL;
-                  break;
-                case DLL_THREAD_ATTACH:
-                case DLL_PROCESS_DETACH:
-                case DLL_THREAD_DETACH:
-                break;
-        }
-        return TRUE;
-}
 #endif
 
 /******************************************************************************
@@ -86,9 +82,10 @@ char * NPP_GetMIMEDescription( void )
 
 NPError NPP_GetValue( NPP instance, NPPVariable variable, void *value )
 {
-    static nsIID nsid = VLCINTF_IID;
+
     static char psz_desc[1000];
 
+    /* plugin class variables */
     switch( variable )
     {
         case NPPVpluginNameString:
@@ -96,14 +93,13 @@ NPError NPP_GetValue( NPP instance, NPPVariable variable, void *value )
             return NPERR_NO_ERROR;
 
         case NPPVpluginDescriptionString:
-            snprintf( psz_desc, 1000-1, PLUGIN_DESCRIPTION, VLC_Version() );
-            psz_desc[1000-1] = 0;
+            snprintf( psz_desc, sizeof(psz_desc), PLUGIN_DESCRIPTION, VLC_Version() );
             *((char **)value) = psz_desc;
             return NPERR_NO_ERROR;
 
         default:
-            /* go on... */
-            break;
+            /* move on to instance variables ... */
+            ;
     }
 
     if( instance == NULL )
@@ -111,33 +107,176 @@ NPError NPP_GetValue( NPP instance, NPPVariable variable, void *value )
         return NPERR_INVALID_INSTANCE_ERROR;
     }
 
-    VlcPlugin* p_plugin = (VlcPlugin*) instance->pdata;
+    /* plugin instance variables */
+
+    VlcPlugin* p_plugin = reinterpret_cast<VlcPlugin*>(instance->pdata);
+    if( NULL == p_plugin )
+    {
+        // plugin has not been initialized yet !
+        return NPERR_INVALID_INSTANCE_ERROR;
+    }
 
     switch( variable )
     {
-        case NPPVpluginScriptableInstance:
-            *(nsISupports**)value = p_plugin->GetPeer();
-            if( *(nsISupports**)value == NULL )
+        case NPPVpluginScriptableNPObject:
+        {
+            /* retrieve plugin root class */
+            NPClass *scriptClass = p_plugin->getScriptClass();
+            if( scriptClass )
             {
-                return NPERR_OUT_OF_MEMORY_ERROR;
+                /* create an instance and return it */
+                *(NPObject**)value = NPN_CreateObject(instance, scriptClass);
+                return NPERR_NO_ERROR;
             }
             break;
+        }
+
+        default:
+            ;
+    }
+    return NPERR_GENERIC_ERROR;
+}
 
-        case NPPVpluginScriptableIID:
-            *(nsIID**)value = (nsIID*)NPN_MemAlloc( sizeof(nsIID) );
-            if( *(nsIID**)value == NULL )
+/*
+ * there is some confusion in gecko headers regarding definition of this API
+ * NPPVariable is wrongly defined as NPNVariable, which sounds incorrect.
+ */
+
+NPError NPP_SetValue( NPP instance, NPNVariable variable, void *value )
+{
+    return NPERR_GENERIC_ERROR;
+}
+
+/******************************************************************************
+ * Mac-only API calls
+ *****************************************************************************/
+#ifdef XP_MACOSX
+int16 NPP_HandleEvent( NPP instance, void * event )
+{
+    static UInt32 lastMouseUp = 0;
+
+    if( instance == NULL )
+    {
+        return false;
+    }
+
+    VlcPlugin *p_plugin = (VlcPlugin*)instance->pdata;
+
+    if( p_plugin == NULL )
+    {
+        return false;
+    }
+
+    EventRecord *myEvent = (EventRecord*)event;
+
+    switch( myEvent->what )
+    {
+        case nullEvent:
+            return true;
+        case mouseDown:
+        {
+            if( (myEvent->when - lastMouseUp) < GetDblTime() )
             {
-                return NPERR_OUT_OF_MEMORY_ERROR;
+                /* double click */
+                libvlc_instance_t *p_vlc = p_plugin->getVLC();
+
+                if( p_vlc )
+                {
+                    if( libvlc_playlist_isplaying(p_vlc, NULL) )
+                    {
+                        libvlc_media_instance_t *p_md = libvlc_playlist_get_media_instance(p_vlc, NULL);
+                        if( p_md )
+                        {
+                            libvlc_toggle_fullscreen(p_md, NULL);
+                            libvlc_media_instance_release(p_md);
+                        }
+                    }
+                }
             }
-            **(nsIID**)value = nsid;
-            break;
-
+            return true;
+        }
+        case mouseUp:
+            lastMouseUp = myEvent->when;
+            return true;
+        case keyUp:
+        case keyDown:
+        case autoKey:
+            return true;
+        case updateEvt:
+        {
+            const NPWindow& npwindow = p_plugin->getWindow();
+            if( npwindow.window )
+            {
+                int hasVout = FALSE;
+                libvlc_instance_t *p_vlc = p_plugin->getVLC();
+
+                if( p_vlc )
+                {
+                    if( libvlc_playlist_isplaying(p_vlc, NULL) )
+                    {
+                        libvlc_media_instance_t *p_md = libvlc_playlist_get_media_instance(p_vlc, NULL);
+                        if( p_md )
+                        {
+                            hasVout = libvlc_media_instance_has_vout(p_md, NULL);
+                            if( hasVout )
+                            {
+                                libvlc_rectangle_t area;
+                                area.left = 0;
+                                area.top = 0;
+                                area.right = npwindow.width;
+                                area.bottom = npwindow.height;
+                                libvlc_video_redraw_rectangle(p_md, &area, NULL);
+                            }
+                            libvlc_media_instance_release(p_md);
+                        }
+                    }
+                }
+
+                if( ! hasVout )
+                {
+                    /* draw the beautiful "No Picture" */
+
+                    ForeColor(blackColor);
+                    PenMode( patCopy );
+
+                    /* seems that firefox forgets to set the following on occasion (reload) */
+                    SetOrigin(((NP_Port *)npwindow.window)->portx, ((NP_Port *)npwindow.window)->porty);
+
+                    Rect rect;
+                    rect.left = 0;
+                    rect.top = 0;
+                    rect.right = npwindow.width;
+                    rect.bottom = npwindow.height;
+                    PaintRect( &rect );
+
+                    ForeColor(whiteColor);
+                    MoveTo( (npwindow.width-80)/ 2  , npwindow.height / 2 );
+                    DrawText( WINDOW_TEXT , 0 , strlen(WINDOW_TEXT) );
+                }
+            }
+            return true;
+        }
+        case activateEvt:
+            return false;
+        case NPEventType_GetFocusEvent:
+        case NPEventType_LoseFocusEvent:
+            return true;
+        case NPEventType_AdjustCursorEvent:
+            return false;
+        case NPEventType_MenuCommandEvent:
+            return false;
+        case NPEventType_ClippingChangedEvent:
+            return false;
+        case NPEventType_ScrollingBeginsEvent:
+            return true;
+        case NPEventType_ScrollingEndsEvent:
+            return true;
         default:
-            return NPERR_GENERIC_ERROR;
+            ;
     }
-
-    return NPERR_NO_ERROR;
+    return false;
 }
+#endif /* XP_MACOSX */
 
 /******************************************************************************
  * General Plug-in Calls
@@ -160,157 +299,77 @@ void NPP_Shutdown( void )
 NPError NPP_New( NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc,
                  char* argn[], char* argv[], NPSavedData* saved )
 {
-    vlc_value_t value;
-    int i_ret;
-    int i;
-
-    char *ppsz_foo[] =
-    {
-        "vlc"
-        /*, "--plugin-path", "/home/sam/videolan/vlc_MAIN/plugins"*/
-    };
+    NPError status;
 
     if( instance == NULL )
     {
         return NPERR_INVALID_INSTANCE_ERROR;
     }
 
-    VlcPlugin * p_plugin = new VlcPlugin( instance );
-
-    if( p_plugin == NULL )
+    VlcPlugin * p_plugin = new VlcPlugin( instance, mode );
+    if( NULL == p_plugin )
     {
         return NPERR_OUT_OF_MEMORY_ERROR;
     }
 
-    instance->pdata = p_plugin;
-
-    p_plugin->fMode = mode;
-    p_plugin->fWindow = NULL;
-#ifdef WIN32
-
-#else
-    p_plugin->window = 0;
-#endif
-
-    p_plugin->i_vlc = VLC_Create();
-    if( p_plugin->i_vlc < 0 )
+    status = p_plugin->init(argc, argn, argv);
+    if( NPERR_NO_ERROR == status )
     {
-        p_plugin->i_vlc = 0;
-        delete p_plugin;
-        p_plugin = NULL;
-        return NPERR_GENERIC_ERROR;
-    }
-
-    i_ret = VLC_Init( p_plugin->i_vlc, sizeof(ppsz_foo)/sizeof(char*), ppsz_foo );
-    if( i_ret )
-    {
-        VLC_Destroy( p_plugin->i_vlc );
-        p_plugin->i_vlc = 0;
-        delete p_plugin;
-        p_plugin = NULL;
-        return NPERR_GENERIC_ERROR;
-    }
-
-    value.psz_string = "dummy";
-    VLC_Set( p_plugin->i_vlc, "conf::intf", value );
-#ifdef WIN32
-    value.psz_string = "directx,dummy";
-#else
-    value.psz_string = "xvideo,x11,dummy";
-#endif
-    VLC_Set( p_plugin->i_vlc, "conf::vout", value );
-#ifdef WIN32
-    value.psz_string = "none";//"directx,waveout,dummy";
-#else
-    value.psz_string = "dsp,dummy";
+        instance->pdata = reinterpret_cast<void*>(p_plugin);
+#if 0
+        NPN_SetValue(instance, NPPVpluginWindowBool, (void *)false);
+        NPN_SetValue(instance, NPPVpluginTransparentBool, (void *)false);
 #endif
-    VLC_Set( p_plugin->i_vlc, "conf::aout", value );
-
-    p_plugin->b_stream = 0;
-    p_plugin->b_autoplay = 0;
-    p_plugin->psz_target = NULL;
-
-    for( i = 0; i < argc ; i++ )
-    {
-        if( !strcmp( argn[i], "target" ) )
-        {
-            p_plugin->psz_target = argv[i];
-        }
-        else if( !strcmp( argn[i], "autoplay" ) )
-        {
-            if( !strcmp( argv[i], "yes" ) )
-            {
-                p_plugin->b_autoplay = 1;
-            }
-        }
-        else if( !strcmp( argn[i], "loop" ) )
-        {
-            if( !strcmp( argv[i], "yes" ) )
-            {
-                value.b_bool = VLC_TRUE;
-                VLC_Set( p_plugin->i_vlc, "conf::loop", value );
-            }
-        }
     }
-
-    if( p_plugin->psz_target )
+    else
     {
-        p_plugin->psz_target = strdup( p_plugin->psz_target );
+        delete p_plugin;
     }
-
-    return NPERR_NO_ERROR;
+    return status;
 }
 
 NPError NPP_Destroy( NPP instance, NPSavedData** save )
 {
-    if( instance == NULL )
-    {
+    if( NULL == instance )
         return NPERR_INVALID_INSTANCE_ERROR;
-    }
 
-    VlcPlugin* p_plugin = (VlcPlugin*)instance->pdata;
+    VlcPlugin* p_plugin = reinterpret_cast<VlcPlugin*>(instance->pdata);
+    if( NULL == p_plugin )
+        return NPERR_NO_ERROR;
 
-    if( p_plugin != NULL )
-    {
-        if( p_plugin->i_vlc )
-        {
-            VLC_Stop( p_plugin->i_vlc );
-            VLC_Destroy( p_plugin->i_vlc );
-            p_plugin->i_vlc = 0;
-        }
-
-        if( p_plugin->psz_target )
-        {
-            free( p_plugin->psz_target );
-            p_plugin->psz_target = NULL;
-        }
+    instance->pdata = NULL;
 
-        delete p_plugin;
+#if XP_WIN
+    HWND win = (HWND)p_plugin->getWindow().window;
+    WNDPROC winproc = p_plugin->getWindowProc();
+    if( winproc )
+    {
+        /* reset WNDPROC */
+        SetWindowLong( win, GWL_WNDPROC, (LONG)winproc );
     }
+#endif
 
-    instance->pdata = NULL;
+    delete p_plugin;
 
     return NPERR_NO_ERROR;
 }
 
 NPError NPP_SetWindow( NPP instance, NPWindow* window )
 {
-    vlc_value_t value;
-
-    if( instance == NULL )
+    if( ! instance )
     {
         return NPERR_INVALID_INSTANCE_ERROR;
     }
 
-    VlcPlugin* p_plugin = (VlcPlugin*)instance->pdata;
+    /* NPP_SetWindow may be called before NPP_New (Opera) */
+    VlcPlugin* p_plugin = reinterpret_cast<VlcPlugin*>(instance->pdata);
+    if( ! p_plugin )
+    {
+        /* we should probably show a splash screen here */
+        return NPERR_NO_ERROR;
+    }
 
-    /* Write the window ID for vlc */
-    //value.p_address = (void*)window->window;
-    //VLC_Set( p_plugin->i_vlc, "drawable", value );
-    /* FIXME: this cast sucks */
-    value.i_int = (int) (long long) (void *) window->window;
-    VLC_Set( p_plugin->i_vlc, "conf::x11-drawable", value );
-    VLC_Set( p_plugin->i_vlc, "conf::xvideo-drawable", value );
+    libvlc_instance_t *p_vlc = p_plugin->getVLC();
 
     /*
      * PLUGIN DEVELOPERS:
@@ -320,112 +379,189 @@ NPError NPP_SetWindow( NPP instance, NPWindow* window )
      *  size changes, etc.
      */
 
-#ifdef WIN32
+    /* retrieve current window */
+    NPWindow& curwin = p_plugin->getWindow();
+
+#ifdef XP_MACOSX
+    if( window && window->window )
+    {
+        /* check if plugin has a new parent window */
+        CGrafPtr drawable = (((NP_Port*) (window->window))->port);
+        if( !curwin.window || drawable != (((NP_Port*) (curwin.window))->port) )
+        {
+            /* set/change parent window */
+            libvlc_video_set_parent(p_vlc, (libvlc_drawable_t)drawable, NULL);
+        }
+
+        /* as MacOS X video output is windowless, set viewport */
+        libvlc_rectangle_t view, clip;
+
+        /*
+        ** browser sets port origin to top-left location of plugin relative to GrafPort
+        ** window origin is set relative to document, which of little use for drawing
+        */
+        view.top     = ((NP_Port*) (window->window))->porty;
+        view.left    = ((NP_Port*) (window->window))->portx;
+        view.bottom  = window->height+view.top;
+        view.right   = window->width+view.left;
+        /* clipRect coordinates are also relative to GrafPort */
+        clip.top     = window->clipRect.top;
+        clip.left    = window->clipRect.left;
+        clip.bottom  = window->clipRect.bottom;
+        clip.right   = window->clipRect.right;
+
+        libvlc_video_set_viewport(p_vlc, &view, &clip, NULL);
+
+        /* remember new window */
+        p_plugin->setWindow(*window);
+    }
+    else if( curwin.window ) {
+        /* change/set parent */
+        libvlc_video_set_parent(p_vlc, 0, NULL);
+        curwin.window = NULL;
+    }
+#endif /* XP_MACOSX */
 
-#else
-    Widget netscape_widget;
+#ifdef XP_WIN
+    if( window && window->window )
+    {
+        /* check if plugin has a new parent window */
+        HWND drawable = (HWND) (window->window);
+        if( !curwin.window || drawable != curwin.window )
+        {
+            /* reset previous window settings */
+            HWND oldwin = (HWND)p_plugin->getWindow().window;
+            WNDPROC oldproc = p_plugin->getWindowProc();
+            if( oldproc )
+            {
+                /* reset WNDPROC */
+                SetWindowLong( oldwin, GWL_WNDPROC, (LONG)oldproc );
+            }
+            /* attach our plugin object */
+            SetWindowLongPtr((HWND)drawable, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(p_plugin));
 
-    p_plugin->window = (Window) window->window;
-    p_plugin->x = window->x;
-    p_plugin->y = window->y;
-    p_plugin->width = window->width;
-    p_plugin->height = window->height;
-    p_plugin->display = ((NPSetWindowCallbackStruct *)window->ws_info)->display;
+            /* install our WNDPROC */
+            p_plugin->setWindowProc( (WNDPROC)SetWindowLong( drawable,
+                                                           GWL_WNDPROC, (LONG)Manage ) );
 
-    netscape_widget = XtWindowToWidget(p_plugin->display, p_plugin->window);
-    XtAddEventHandler(netscape_widget, ExposureMask, FALSE, (XtEventHandler)Redraw, p_plugin);
-    Redraw(netscape_widget, (XtPointer)p_plugin, NULL);
-#endif
+            /* change window style to our liking */
+            LONG style = GetWindowLong((HWND)drawable, GWL_STYLE);
+            style |= WS_CLIPCHILDREN|WS_CLIPSIBLINGS;
+            SetWindowLong((HWND)drawable, GWL_STYLE, style);
 
-    p_plugin->fWindow = window;
+            /* change/set parent */
+            libvlc_video_set_parent(p_vlc, (libvlc_drawable_t)drawable, NULL);
 
-#if 1
-    if( !p_plugin->b_stream )
+            /* remember new window */
+            p_plugin->setWindow(*window);
+
+            /* Redraw window */
+            InvalidateRect( (HWND)drawable, NULL, TRUE );
+            UpdateWindow( (HWND)drawable );
+        }
+    }
+    else if ( curwin.window )
     {
-        int i_mode = PLAYLIST_APPEND;
+        /* reset WNDPROC */
+        HWND oldwin = (HWND)curwin.window;
+        SetWindowLong( oldwin, GWL_WNDPROC, (LONG)(p_plugin->getWindowProc()) );
+        p_plugin->setWindowProc(NULL);
+        /* change/set parent */
+        libvlc_video_set_parent(p_vlc, 0, NULL);
+        curwin.window = NULL;
+    }
+#endif /* XP_WIN */
 
-        if( p_plugin->b_autoplay )
+#ifdef XP_UNIX
+    if( window && window->window )
+    {
+        Window  drawable   = (Window) window->window;
+        if( !curwin.window || drawable != (Window)curwin.window )
         {
-            i_mode |= PLAYLIST_GO;
+            Display *p_display = ((NPSetWindowCallbackStruct *)window->ws_info)->display;
+
+            XResizeWindow( p_display, drawable, window->width, window->height );
+            Widget w = XtWindowToWidget( p_display, drawable );
+
+            XtAddEventHandler( w, ExposureMask, FALSE, (XtEventHandler)Redraw, p_plugin );
+            XtAddEventHandler( w, StructureNotifyMask, FALSE, (XtEventHandler)Resize, p_plugin );
+
+            /* set/change parent window */
+            libvlc_video_set_parent(p_vlc, (libvlc_drawable_t)drawable, NULL);
+
+            /* remember window */
+            p_plugin->setWindow(*window);
+
+            Redraw( w, (XtPointer)p_plugin, NULL );
         }
+    }
+    else if ( curwin.window )
+    {
+        /* change/set parent */
+        libvlc_video_set_parent(p_vlc, 0, NULL);
+        curwin.window = NULL;
+    }
+#endif /* XP_UNIX */
 
+    if( !p_plugin->b_stream )
+    {
         if( p_plugin->psz_target )
         {
-            VLC_AddTarget( p_plugin->i_vlc, p_plugin->psz_target,
-                           i_mode, PLAYLIST_END );
-            p_plugin->b_stream = 1;
+            if( libvlc_playlist_add( p_vlc, p_plugin->psz_target, NULL, NULL ) != -1 )
+            {
+                if( p_plugin->b_autoplay )
+                {
+                    libvlc_playlist_play(p_vlc, 0, 0, NULL, NULL);
+                }
+            }
+            p_plugin->b_stream = VLC_TRUE;
         }
     }
-#endif
-
     return NPERR_NO_ERROR;
 }
 
 NPError NPP_NewStream( NPP instance, NPMIMEType type, NPStream *stream,
                        NPBool seekable, uint16 *stype )
 {
-    if( instance == NULL )
+    if( NULL == instance  )
     {
         return NPERR_INVALID_INSTANCE_ERROR;
     }
 
-#if 0
-    VlcPlugin* p_plugin = (VlcPlugin*)instance->pdata;
-#endif
-
-    fprintf(stderr, "NPP_NewStream - FILE mode !!\n");
-
-    /* We want a *filename* ! */
-    *stype = NP_ASFILE;
-
-#if 0
-    if( p_plugin->b_stream == 0 )
+    VlcPlugin *p_plugin = reinterpret_cast<VlcPlugin *>(instance->pdata);
+    if( NULL == p_plugin )
     {
-        p_plugin->psz_target = strdup( stream->url );
-        p_plugin->b_stream = 1;
+        return NPERR_INVALID_INSTANCE_ERROR;
     }
-#endif
 
-    return NPERR_NO_ERROR;
+   /*
+   ** Firefox/Mozilla may decide to open a stream from the URL specified
+   ** in the SRC parameter of the EMBED tag and pass it to us
+   **
+   ** since VLC will open the SRC URL as well, we're not interested in
+   ** that stream. Otherwise, we'll take it and queue it up in the playlist
+   */
+    if( !p_plugin->psz_target || strcmp(stream->url, p_plugin->psz_target) )
+    {
+        /* TODO: use pipes !!!! */
+        *stype = NP_ASFILEONLY;
+        return NPERR_NO_ERROR;
+    }
+    return NPERR_GENERIC_ERROR;
 }
 
-int32 STREAMBUFSIZE = 0X0FFFFFFF; /* If we are reading from a file in NPAsFile
-                   * mode so we can take any size stream in our
-                   * write call (since we ignore it) */
-
-#define SARASS_SIZE (1024*1024)
-
 int32 NPP_WriteReady( NPP instance, NPStream *stream )
 {
-    VlcPlugin* p_plugin;
-
-    fprintf(stderr, "NPP_WriteReady\n");
-
-    if (instance != NULL)
-    {
-        p_plugin = (VlcPlugin*) instance->pdata;
-        /* Muahahahahahahaha */
-        return STREAMBUFSIZE;
-        /*return SARASS_SIZE;*/
-    }
-
-    /* Number of bytes ready to accept in NPP_Write() */
-    return STREAMBUFSIZE;
-    /*return 0;*/
+    /* TODO */
+    return 8*1024;
 }
 
 
 int32 NPP_Write( NPP instance, NPStream *stream, int32 offset,
                  int32 len, void *buffer )
 {
-    fprintf(stderr, "NPP_Write %i\n", (int)len);
-
-    if( instance != NULL )
-    {
-        /*VlcPlugin* p_plugin = (VlcPlugin*) instance->pdata;*/
-    }
-
-    return len;         /* The number of bytes accepted */
+    /* TODO */
+    return len;
 }
 
 
@@ -435,7 +571,6 @@ NPError NPP_DestroyStream( NPP instance, NPStream *stream, NPError reason )
     {
         return NPERR_INVALID_INSTANCE_ERROR;
     }
-
     return NPERR_NO_ERROR;
 }
 
@@ -447,22 +582,20 @@ void NPP_StreamAsFile( NPP instance, NPStream *stream, const char* fname )
         return;
     }
 
-    VlcPlugin* p_plugin = (VlcPlugin*)instance->pdata;
-
-    fprintf(stderr, "NPP_StreamAsFile\n");
-    VLC_AddTarget( p_plugin->i_vlc, fname,
-                   PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
-}
-
-#if 0
-void NPP_StreamAsFile( NPP instance, NPStream *stream, const char* fname )
-{
-    fprintf(stderr,"filename : %s\n", fname);
-    ((VlcPlugin*) instance->pdata)->SetFileName(fname);
+    VlcPlugin *p_plugin = reinterpret_cast<VlcPlugin *>(instance->pdata);
+    if( NULL == p_plugin )
+    {
+        return;
+    }
 
-    fprintf(stderr,"SetFileNeme ok. \n");
+    if( libvlc_playlist_add( p_plugin->getVLC(), fname, stream->url, NULL ) != -1 )
+    {
+        if( p_plugin->b_autoplay )
+        {
+            libvlc_playlist_play( p_plugin->getVLC(), 0, 0, NULL, NULL);
+        }
+    }
 }
-#endif
 
 
 void NPP_URLNotify( NPP instance, const char* url,
@@ -543,31 +676,151 @@ void NPP_Print( NPP instance, NPPrint* printInfo )
     }
 }
 
+/******************************************************************************
+ * Windows-only methods
+ *****************************************************************************/
+#if XP_WIN
+static LRESULT CALLBACK Manage( HWND p_hwnd, UINT i_msg, WPARAM wpar, LPARAM lpar )
+{
+    VlcPlugin* p_plugin = reinterpret_cast<VlcPlugin*>(GetWindowLongPtr(p_hwnd, GWLP_USERDATA));
+
+    switch( i_msg )
+    {
+        case WM_ERASEBKGND:
+            return 1L;
+
+        case WM_PAINT:
+        {
+            PAINTSTRUCT paintstruct;
+            HDC hdc;
+            RECT rect;
+
+            hdc = BeginPaint( p_hwnd, &paintstruct );
+
+            GetClientRect( p_hwnd, &rect );
+
+            FillRect( hdc, &rect, (HBRUSH)GetStockObject(BLACK_BRUSH) );
+            SetTextColor(hdc, RGB(255, 255, 255));
+            SetBkColor(hdc, RGB(0, 0, 0));
+            DrawText( hdc, WINDOW_TEXT, strlen(WINDOW_TEXT), &rect, DT_CENTER|DT_VCENTER|DT_SINGLELINE); 
+
+            EndPaint( p_hwnd, &paintstruct );
+            return 0L;
+        }
+        default:
+            /* delegate to default handler */
+            return CallWindowProc(p_plugin->getWindowProc(), p_hwnd, i_msg, wpar, lpar );
+    }
+}
+#endif /* XP_WIN */
+
 /******************************************************************************
  * UNIX-only methods
  *****************************************************************************/
-#ifndef WIN32
+#ifdef XP_UNIX
 static void Redraw( Widget w, XtPointer closure, XEvent *event )
 {
-    VlcPlugin* p_plugin = (VlcPlugin*)closure;
+    VlcPlugin* p_plugin = reinterpret_cast<VlcPlugin*>(closure);
+    const NPWindow& window = p_plugin->getWindow();
     GC gc;
     XGCValues gcv;
-    const char * psz_text = "(no picture)";
 
-    gcv.foreground = BlackPixel( p_plugin->display, 0 );
-    gc = XCreateGC( p_plugin->display, p_plugin->window, GCForeground, &gcv );
+    Window  drawable   = (Window) window.window;
+    Display *p_display = ((NPSetWindowCallbackStruct *)window.ws_info)->display;
+
+    gcv.foreground = BlackPixel( p_display, 0 );
+    gc = XCreateGC( p_display, drawable, GCForeground, &gcv );
 
-    XFillRectangle( p_plugin->display, p_plugin->window, gc,
-                    0, 0, p_plugin->width, p_plugin->height );
+    XFillRectangle( p_display, drawable, gc,
+                    0, 0, window.width, window.height );
 
-    gcv.foreground = WhitePixel( p_plugin->display, 0 );
-    XChangeGC( p_plugin->display, gc, GCForeground, &gcv );
+    gcv.foreground = WhitePixel( p_display, 0 );
+    XChangeGC( p_display, gc, GCForeground, &gcv );
 
-    XDrawString( p_plugin->display, p_plugin->window, gc,
-                 p_plugin->width / 2 - 40, p_plugin->height / 2,
-                 psz_text, strlen(psz_text) );
+    XDrawString( p_display, drawable, gc,
+                 window.width / 2 - 40, window.height / 2,
+                 WINDOW_TEXT, strlen(WINDOW_TEXT) );
 
-    XFreeGC( p_plugin->display, gc );
+    XFreeGC( p_display, gc );
 }
-#endif
+
+static void Resize ( Widget w, XtPointer closure, XEvent *event )
+{
+    VlcPlugin* p_plugin = reinterpret_cast<VlcPlugin*>(closure);
+    const NPWindow& window = p_plugin->getWindow();
+    Window  drawable   = (Window) window.window;
+    Display *p_display = ((NPSetWindowCallbackStruct *)window.ws_info)->display;
+
+    int i_ret;
+    Window root_return, parent_return, * children_return;
+    Window base_window;
+    unsigned int i_nchildren;
+
+#ifdef X11_RESIZE_DEBUG
+    XWindowAttributes attr;
+
+    if( event && event->type == ConfigureNotify )
+    {
+        fprintf( stderr, "vlcshell::Resize() ConfigureNotify %d x %d, "
+                 "send_event ? %s\n", event->xconfigure.width,
+                 event->xconfigure.height,
+                 event->xconfigure.send_event ? "TRUE" : "FALSE" );
+    }
+#endif /* X11_RESIZE_DEBUG */
+
+    if( ! p_plugin->setSize(window.width, window.height) )
+    {
+        /* size already set */
+        return;
+    }
+
+
+    i_ret = XResizeWindow( p_display, drawable, window.width, window.height );
+
+#ifdef X11_RESIZE_DEBUG
+    fprintf( stderr,
+             "vlcshell::Resize() XResizeWindow(owner) returned %d\n", i_ret );
+
+    XGetWindowAttributes ( p_display, drawable, &attr );
+
+    /* X is asynchronous, so the current size reported here is not
+       necessarily the requested size as the Resize request may not
+       yet have been handled by the plugin host */
+    fprintf( stderr, "vlcshell::Resize() current (owner) size %d x %d\n",
+             attr.width, attr.height );
+#endif /* X11_RESIZE_DEBUG */
+
+    XQueryTree( p_display, drawable,
+                &root_return, &parent_return, &children_return,
+                &i_nchildren );
+
+    if( i_nchildren > 0 )
+    {
+        /* XXX: Make assumptions related to the window parenting structure in
+           vlc/modules/video_output/x11/xcommon.c */
+        base_window = children_return[i_nchildren - 1];
+
+#ifdef X11_RESIZE_DEBUG
+        fprintf( stderr, "vlcshell::Resize() got %d children\n", i_nchildren );
+        fprintf( stderr, "vlcshell::Resize() got base_window %p\n",
+                 base_window );
+#endif /* X11_RESIZE_DEBUG */
+
+        i_ret = XResizeWindow( p_display, base_window,
+                window.width, window.height );
+
+#ifdef X11_RESIZE_DEBUG
+        fprintf( stderr,
+                 "vlcshell::Resize() XResizeWindow(base) returned %d\n",
+                 i_ret );
+
+        XGetWindowAttributes( p_display, base_window, &attr );
+
+        fprintf( stderr, "vlcshell::Resize() new size %d x %d\n",
+                 attr.width, attr.height );
+#endif /* X11_RESIZE_DEBUG */
+    }
+}
+
+#endif /* XP_UNIX */