vlcshell.cpp 15.5 KB
Newer Older
1
/*****************************************************************************
2
 * vlcshell.cpp: a VLC plugin for Mozilla
3
 *****************************************************************************
Jean-Paul Saman's avatar
Jean-Paul Saman committed
4
 * Copyright (C) 2002-2009 the VideoLAN team
5
 * $Id$
6 7
 *
 * Authors: Samuel Hocevar <sam@zoy.org>
8
 *          Jean-Paul Saman <jpsaman@videolan.org>
9 10 11 12 13 14 15 16 17 18 19 20 21
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
Antoine Cellerier's avatar
Antoine Cellerier committed
22
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 24 25 26 27
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/
28 29 30 31 32

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

33 34
#include <stdio.h>
#include <string.h>
35
#include <stdlib.h>
36

37
#include "vlcplugin.h"
38
#include "vlcshell.h"
39

40 41 42 43

/******************************************************************************
 * UNIX-only API calls
 *****************************************************************************/
44
NPP_GET_MIME_CONST char * NPP_GetMIMEDescription( void )
45
{
46
    return mimetype;
47 48 49 50
}

NPError NPP_GetValue( NPP instance, NPPVariable variable, void *value )
{
51
    static char psz_name[] = PLUGIN_NAME;
Sam Hocevar's avatar
Sam Hocevar committed
52
    static char psz_desc[1000];
53

54
    /* plugin class variables */
55 56 57
    switch( variable )
    {
        case NPPVpluginNameString:
58
            *((char **)value) = psz_name;
59 60 61
            return NPERR_NO_ERROR;

        case NPPVpluginDescriptionString:
62
            snprintf( psz_desc, sizeof(psz_desc), PLUGIN_DESCRIPTION,
63
                      libvlc_get_version() );
Sam Hocevar's avatar
Sam Hocevar committed
64
            *((char **)value) = psz_desc;
65
            return NPERR_NO_ERROR;
Sam Hocevar's avatar
Sam Hocevar committed
66

67 68 69 70 71 72
#if defined(XP_UNIX)
        case NPPVpluginNeedsXEmbed:
            *((bool *)value) = true;
            return NPERR_NO_ERROR;
#endif

Sam Hocevar's avatar
Sam Hocevar committed
73
        default:
74
            /* move on to instance variables ... */
75
            ;
76 77 78 79 80 81 82
    }

    if( instance == NULL )
    {
        return NPERR_INVALID_INSTANCE_ERROR;
    }

83
    /* plugin instance variables */
84

85
    VlcPluginBase *p_plugin = reinterpret_cast<VlcPluginBase *>(instance->pdata);
86
    if( NULL == p_plugin )
87
    {
88
        /* plugin has not been initialized yet ! */
89 90
        return NPERR_INVALID_INSTANCE_ERROR;
    }
91

92 93
    switch( variable )
    {
94
        case NPPVpluginScriptableNPObject:
95
        {
96 97 98
            /* retrieve plugin root class */
            NPClass *scriptClass = p_plugin->getScriptClass();
            if( scriptClass )
99
            {
100 101 102
                /* create an instance and return it */
                *(NPObject**)value = NPN_CreateObject(instance, scriptClass);
                return NPERR_NO_ERROR;
103 104
            }
            break;
105
        }
106

107
        default:
108
            ;
109
    }
110
    return NPERR_GENERIC_ERROR;
111 112
}

113 114 115 116 117 118 119 120 121 122
/*
 * 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;
}

123 124 125
/******************************************************************************
 * Mac-only API calls
 *****************************************************************************/
126
#ifdef XP_MACOSX
David Menestrina's avatar
David Menestrina committed
127
int16_t NPP_HandleEvent( NPP instance, void * event )
128
{
129
    static UInt32 lastMouseUp = 0;
130 131 132 133 134
    if( instance == NULL )
    {
        return false;
    }

135
    VlcPluginBase *p_plugin = reinterpret_cast<VlcPluginBase *>(instance->pdata);
136 137 138 139 140
    if( p_plugin == NULL )
    {
        return false;
    }

141
#ifndef __x86_64__
142
    EventRecord *myEvent = (EventRecord*)event;
143

144
    switch( myEvent->what )
145
    {
146
        case nullEvent:
147
            return true;
148
        case mouseDown:
149 150 151 152
        {
            if( (myEvent->when - lastMouseUp) < GetDblTime() )
            {
                /* double click */
153
                p_plugin->toggle_fullscreen();
154 155 156
            }
            return true;
        }
157
        case mouseUp:
158
            lastMouseUp = myEvent->when;
159 160 161 162 163 164 165
            return true;
        case keyUp:
        case keyDown:
        case autoKey:
            return true;
        case updateEvt:
        {
166 167
            const NPWindow& npwindow = p_plugin->getWindow();
            if( npwindow.window )
168
            {
Jean-Paul Saman's avatar
Jean-Paul Saman committed
169
                bool hasVout = false;
170

171
                if( p_plugin->playlist_isplaying() )
172
                {
173 174
                    hasVout = p_plugin->player_has_vout();
#if 0
175
                    if( hasVout )
176
                    {
177 178 179 180 181
                        libvlc_rectangle_t area;
                        area.left = 0;
                        area.top = 0;
                        area.right = npwindow.width;
                        area.bottom = npwindow.height;
182
                        libvlc_video_redraw_rectangle(p_plugin->getMD(), &area, NULL);
183
                    }
184 185 186
#else
#warning disabled code
#endif
187
                }
188

189 190
                if( ! hasVout )
                {
191
                    /* draw the text from p_plugin->psz_text */
192 193
                    ForeColor(blackColor);
                    PenMode( patCopy );
194

195 196
                    /* seems that firefox forgets to set the following
                     * on occasion (reload) */
197 198
                    SetOrigin(((NP_Port *)npwindow.window)->portx,
                              ((NP_Port *)npwindow.window)->porty);
199

200 201 202 203 204 205
                    Rect rect;
                    rect.left = 0;
                    rect.top = 0;
                    rect.right = npwindow.width;
                    rect.bottom = npwindow.height;
                    PaintRect( &rect );
206

207 208
                    ForeColor(whiteColor);
                    MoveTo( (npwindow.width-80)/ 2  , npwindow.height / 2 );
209 210
                    if( p_plugin->psz_text )
                        DrawText( p_plugin->psz_text, 0, strlen(p_plugin->psz_text) );
211
                }
212
            }
213 214 215 216 217 218 219 220 221
            return true;
        }
        case activateEvt:
            return false;
        case NPEventType_GetFocusEvent:
        case NPEventType_LoseFocusEvent:
            return true;
        case NPEventType_AdjustCursorEvent:
            return false;
222 223 224 225 226
        case NPEventType_MenuCommandEvent:
            return false;
        case NPEventType_ClippingChangedEvent:
            return false;
        case NPEventType_ScrollingBeginsEvent:
227
            return true;
228
        case NPEventType_ScrollingEndsEvent:
229 230 231 232
            return true;
        default:
            ;
    }
233
#endif // __x86_64__
234
    return false;
235
}
236
#endif /* XP_MACOSX */
237

238 239 240 241 242
/******************************************************************************
 * General Plug-in Calls
 *****************************************************************************/
NPError NPP_Initialize( void )
{
243 244 245 246 247 248 249 250 251 252 253
#ifdef XP_UNIX
    NPError err = NPERR_NO_ERROR;
    bool supportsXEmbed = false;

    err = NPN_GetValue( NULL, NPNVSupportsXEmbedBool,
                        (void *)&supportsXEmbed );

    if ( err != NPERR_NO_ERROR || supportsXEmbed != true )
        return NPERR_INCOMPATIBLE_VERSION_ERROR;
#endif

254 255 256
    return NPERR_NO_ERROR;
}

257
#ifdef OJI
258 259 260 261
jref NPP_GetJavaClass( void )
{
    return NULL;
}
262
#endif
263 264 265 266 267 268

void NPP_Shutdown( void )
{
    ;
}

269
NPError NPP_New( NPMIMEType pluginType, NPP instance,
270
                 NPuint16_t mode, NPint16_t argc,
271 272
                 char* argn[], char* argv[], NPSavedData* saved )
{
273
    NPError status;
274 275 276 277 278 279

    if( instance == NULL )
    {
        return NPERR_INVALID_INSTANCE_ERROR;
    }

280
    VlcPluginBase *p_plugin = new VlcPlugin( instance, mode );
281
    if( NULL == p_plugin )
282 283 284 285
    {
        return NPERR_OUT_OF_MEMORY_ERROR;
    }

286
    status = p_plugin->init(argc, argn, argv);
287 288
    if( NPERR_NO_ERROR == status )
    {
289
        instance->pdata = reinterpret_cast<void*>(p_plugin);
290
    }
291 292
    else
    {
293 294
        delete p_plugin;
    }
295
    return status;
296 297
}

298 299
NPError NPP_Destroy( NPP instance, NPSavedData** save )
{
300
    if( NULL == instance )
301 302
        return NPERR_INVALID_INSTANCE_ERROR;

303
    VlcPluginBase *p_plugin = reinterpret_cast<VlcPluginBase *>(instance->pdata);
304 305 306 307
    if( NULL == p_plugin )
        return NPERR_NO_ERROR;

    instance->pdata = NULL;
308

309 310
    if( p_plugin->playlist_isplaying() )
        p_plugin->playlist_stop();
311

312
    delete p_plugin;
313 314 315 316 317 318

    return NPERR_NO_ERROR;
}

NPError NPP_SetWindow( NPP instance, NPWindow* window )
{
319
    if( ! instance )
320 321 322 323
    {
        return NPERR_INVALID_INSTANCE_ERROR;
    }

324
    /* NPP_SetWindow may be called before NPP_New (Opera) */
325
    VlcPluginBase *p_plugin = reinterpret_cast<VlcPluginBase *>(instance->pdata);
326
    if( NULL == p_plugin )
327 328 329 330
    {
        /* we should probably show a splash screen here */
        return NPERR_NO_ERROR;
    }
Jean-Paul Saman's avatar
Jean-Paul Saman committed
331

332
    libvlc_instance_t *p_vlc = p_plugin->getVLC();
333

334 335 336 337 338 339 340 341
    /*
     * PLUGIN DEVELOPERS:
     *  Before setting window to point to the
     *  new window, you may wish to compare the new window
     *  info to the previous window (if any) to note window
     *  size changes, etc.
     */

342
    /* retrieve current window */
343
    NPWindow& curr_window = p_plugin->getWindow();
344

345 346 347
    if (window && window->window) {
        if (!curr_window.window) {
            /* we've just been created */
348
            p_plugin->setWindow(*window);
349 350 351 352 353
            p_plugin->create_windows();
            p_plugin->resize_windows();
        } else {
            if (window->window == curr_window.window) {
                /* resize / move notification */
354
                p_plugin->setWindow(*window);
355 356
                p_plugin->resize_windows();
            } else {
357
                /* plugin parent window was changed, notify plugin about it */
358 359 360 361
                p_plugin->destroy_windows();
                p_plugin->setWindow(*window);
                p_plugin->create_windows();
                p_plugin->resize_windows();
362
            }
363
        }
364
    } else {
365 366
        /* NOTE: on Windows, Opera does not call NPP_SetWindow
         * on window destruction. */
367 368 369 370
        if (curr_window.window) {
            /* we've been destroyed */
            p_plugin->destroy_windows();
        }
371
    }
372

373 374
    /* now display toolbar if asked through parameters */
    if( p_plugin->b_toolbar )
375
    {
376
        p_plugin->set_toolbar_visible(true);
377
    }
378

379 380 381 382 383

    if( !p_plugin->b_stream )
    {
        if( p_plugin->psz_target )
        {
384
            if( p_plugin->playlist_add( p_plugin->psz_target ) != -1 )
385 386 387
            {
                if( p_plugin->b_autoplay )
                {
388
                    p_plugin->playlist_play();
389 390
                }
            }
391
            p_plugin->b_stream = true;
392 393 394 395 396 397
        }
    }
    return NPERR_NO_ERROR;
}

NPError NPP_NewStream( NPP instance, NPMIMEType type, NPStream *stream,
398
                       NPBool seekable, NPuint16_t *stype )
399
{
400
    if( NULL == instance  )
401 402 403 404
    {
        return NPERR_INVALID_INSTANCE_ERROR;
    }

405
    VlcPluginBase *p_plugin = reinterpret_cast<VlcPluginBase *>(instance->pdata);
406 407 408 409
    if( NULL == p_plugin )
    {
        return NPERR_INVALID_INSTANCE_ERROR;
    }
410

411 412 413 414 415 416 417 418
   /*
   ** 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) )
419
    {
420 421 422
        /* TODO: use pipes !!!! */
        *stype = NP_ASFILEONLY;
        return NPERR_NO_ERROR;
423
    }
424
    return NPERR_GENERIC_ERROR;
425 426
}

427
NPint32_t NPP_WriteReady( NPP instance, NPStream *stream )
428
{
429 430
    /* TODO */
    return 8*1024;
431 432
}

433
NPint32_t NPP_Write( NPP instance, NPStream *stream, NPint32_t offset,
434
                 NPint32_t len, void *buffer )
435
{
436 437
    /* TODO */
    return len;
438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455
}

NPError NPP_DestroyStream( NPP instance, NPStream *stream, NPError reason )
{
    if( instance == NULL )
    {
        return NPERR_INVALID_INSTANCE_ERROR;
    }
    return NPERR_NO_ERROR;
}

void NPP_StreamAsFile( NPP instance, NPStream *stream, const char* fname )
{
    if( instance == NULL )
    {
        return;
    }

456
    VlcPluginBase *p_plugin = reinterpret_cast<VlcPluginBase *>(instance->pdata);
457 458 459 460
    if( NULL == p_plugin )
    {
        return;
    }
461

462
    if( p_plugin->playlist_add( stream->url ) != -1 )
463 464 465
    {
        if( p_plugin->b_autoplay )
        {
466
            p_plugin->playlist_play();
467 468
        }
    }
469
}
470 471 472 473 474 475 476 477 478 479 480 481 482

void NPP_URLNotify( NPP instance, const char* url,
                    NPReason reason, void* notifyData )
{
    /***** Insert NPP_URLNotify code here *****\
    PluginInstance* p_plugin;
    if (instance != NULL)
        p_plugin = (PluginInstance*) instance->pdata;
    \*********************************************/
}

void NPP_Print( NPP instance, NPPrint* printInfo )
{
483 484
    if( printInfo == NULL )
    {
485
        return;
486
    }
487

488 489 490
    if( instance != NULL )
    {
        /***** Insert NPP_Print code here *****\
491
        PluginInstance* p_plugin = (PluginInstance*) instance->pdata;
492
        \**************************************/
493

494 495
        if( printInfo->mode == NP_FULL )
        {
496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512
            /*
             * PLUGIN DEVELOPERS:
             *  If your plugin would like to take over
             *  printing completely when it is in full-screen mode,
             *  set printInfo->pluginPrinted to TRUE and print your
             *  plugin as you see fit.  If your plugin wants Netscape
             *  to handle printing in this case, set
             *  printInfo->pluginPrinted to FALSE (the default) and
             *  do nothing.  If you do want to handle printing
             *  yourself, printOne is true if the print button
             *  (as opposed to the print menu) was clicked.
             *  On the Macintosh, platformPrint is a THPrint; on
             *  Windows, platformPrint is a structure
             *  (defined in npapi.h) containing the printer name, port,
             *  etc.
             */

513
            /***** Insert NPP_Print code here *****\
514 515 516 517
            void* platformPrint =
                printInfo->print.fullPrint.platformPrint;
            NPBool printOne =
                printInfo->print.fullPrint.printOne;
518
            \**************************************/
519 520

            /* Do the default*/
521
            printInfo->print.fullPrint.pluginPrinted = false;
522
        }
523 524 525
        else
        {
            /* If not fullscreen, we must be embedded */
526 527 528 529 530 531 532 533 534 535 536 537
            /*
             * PLUGIN DEVELOPERS:
             *  If your plugin is embedded, or is full-screen
             *  but you returned false in pluginPrinted above, NPP_Print
             *  will be called with mode == NP_EMBED.  The NPWindow
             *  in the printInfo gives the location and dimensions of
             *  the embedded plugin on the printed page.  On the
             *  Macintosh, platformPrint is the printer port; on
             *  Windows, platformPrint is the handle to the printing
             *  device context.
             */

538
            /***** Insert NPP_Print code here *****\
539 540 541 542
            NPWindow* printWindow =
                &(printInfo->print.embedPrint.window);
            void* platformPrint =
                printInfo->print.embedPrint.platformPrint;
543
            \**************************************/
544 545 546
        }
    }
}