vlcplugin_base.h 11.9 KB
Newer Older
1
/*****************************************************************************
2
 * vlcplugin_base.h: a VLC plugin for Mozilla
3 4 5 6 7 8 9
 *****************************************************************************
 * Copyright (C) 2002-2009 the VideoLAN team
 * $Id$
 *
 * Authors: Samuel Hocevar <sam@zoy.org>
 *          Damien Fouilleul <damienf@videolan.org>
 *          Jean-Paul Saman <jpsaman@videolan.org>
10
 *          Sergey Radionov <rsatom@gmail.com>
11
 *          Cheng Sun <chengsun9@gmail.com>
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
 *
 * 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
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

/*******************************************************************************
 * Instance state information about the plugin.
 ******************************************************************************/
#ifndef __VLCPLUGIN_BASE_H__
#define __VLCPLUGIN_BASE_H__

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

#include <vlc/vlc.h>

// Setup XP_MACOSX, XP_UNIX, XP_WIN
#if defined(_WIN32)
#define XP_WIN 1
#elif defined(__APPLE__)
#define XP_MACOSX 1
#else
#define XP_UNIX 1
#define MOZ_X11 1
#endif

#if !defined(XP_MACOSX) && !defined(XP_UNIX) && !defined(XP_WIN)
#define XP_UNIX 1
#elif defined(XP_MACOSX)
#undef XP_UNIX
#endif

#ifdef XP_WIN
    /* Windows stuff */
#   include <windows.h>
#   include <winbase.h>
#endif

#ifdef XP_UNIX
#   include <pthread.h>
#endif

#ifndef __MAX
#   define __MAX(a, b)   ( ((a) > (b)) ? (a) : (b) )
#endif
#ifndef __MIN
#   define __MIN(a, b)   ( ((a) < (b)) ? (a) : (b) )
#endif

#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))

//on windows, to avoid including <npapi.h> 
//from Microsoft SDK (rather then from Mozilla SDK),
//#include it indirectly via <npfunctions.h>
#include <npfunctions.h>

#include <vector>
81
#include <set>
82 83 84
#include <assert.h>

#include "control/nporuntime.h"
85
#include "../common/vlc_player_options.h"
86
#include "../common/vlc_player.h"
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130

#if (((NP_VERSION_MAJOR << 8) + NP_VERSION_MINOR) < 20)
    typedef uint16 NPuint16_t;
    typedef int16 NPint16_t;
    typedef int32 NPint32_t;
#else
    typedef uint16_t NPuint16_t;
    typedef int16_t NPint16_t;
    typedef int32_t NPint32_t;
#endif

typedef struct {
#if defined(XP_UNIX)
    pthread_mutex_t mutex;
#elif defined(XP_WIN)
    CRITICAL_SECTION cs;
#else
#warning "locking not implemented in this platform"
#endif
} plugin_lock_t;

typedef struct {
    const char *name;                      /* event name */
    const libvlc_event_type_t libvlc_type; /* libvlc event type */
    libvlc_callback_t libvlc_callback;     /* libvlc callback function */
} vlcplugin_event_t;

class EventObj
{
private:

    class Listener
    {
    public:
        Listener(vlcplugin_event_t *event, NPObject *p_object, bool b_bubble):
            _event(event), _listener(p_object), _bubble(b_bubble)
            {
                assert(event);
                assert(p_object);
            }
        Listener(): _event(NULL), _listener(NULL), _bubble(false) { }
        ~Listener()
            {
            }
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
131
        libvlc_event_type_t event_type() const { return _event->libvlc_type; }
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
        NPObject *listener() const { return _listener; }
        bool bubble() const { return _bubble; }
    private:
        vlcplugin_event_t *_event;
        NPObject *_listener;
        bool _bubble;
    };

    class VLCEvent
    {
    public:
        VLCEvent(libvlc_event_type_t libvlc_event_type, NPVariant *npparams, uint32_t npcount):
            _libvlc_event_type(libvlc_event_type), _npparams(npparams), _npcount(npcount)
            {
            }
        VLCEvent(): _libvlc_event_type(0), _npparams(NULL), _npcount(0) { }
        ~VLCEvent()
            {
            }
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
151
        libvlc_event_type_t event_type() const { return _libvlc_event_type; }
152
        NPVariant *params() const { return _npparams; }
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
153
        uint32_t count() const { return _npcount; }
154 155 156 157 158 159 160
    private:
        libvlc_event_type_t _libvlc_event_type;
        NPVariant *_npparams;
        uint32_t _npcount;
    };
    libvlc_event_manager_t *_em; /* libvlc media_player event manager */
public:
161
    EventObj(): _em(NULL), _already_in_deliver(false) { /* deferred to init() */ }
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
    bool init();
    ~EventObj();

    void deliver(NPP browser);
    void callback(const libvlc_event_t *event, NPVariant *npparams, uint32_t count);
    bool insert(const NPString &name, NPObject *listener, bool bubble);
    bool remove(const NPString &name, NPObject *listener, bool bubble);
    void unhook_manager(void *);
    void hook_manager(libvlc_event_manager_t *, void *);
private:
    vlcplugin_event_t *find_event(const char *s) const;
    const char *find_name(const libvlc_event_t *event);
    typedef std::vector<Listener> lr_l;
    typedef std::vector<VLCEvent> ev_l;
    lr_l _llist; /* list of registered listeners with 'addEventListener' method */
    ev_l _elist; /* scheduled events list for delivery to browser */

    plugin_lock_t lock;
180
    bool _already_in_deliver;
181 182 183 184 185 186 187 188 189 190 191 192 193 194
};

typedef enum vlc_toolbar_clicked_e {
    clicked_Unknown = 0,
    clicked_Play,
    clicked_Pause,
    clicked_Stop,
    clicked_timeline,
    clicked_Time,
    clicked_Fullscreen,
    clicked_Mute,
    clicked_Unmute
} vlc_toolbar_clicked_t;

195
class VlcPluginBase: private vlc_player_options, private vlc_player
196 197 198 199 200 201 202
{
protected:

public:
    VlcPluginBase( NPP, NPuint16_t );
    virtual ~VlcPluginBase();

203 204 205 206 207
    vlc_player& get_player()
    {
        return *static_cast<vlc_player*>(this);
    }

208 209 210 211 212
    vlc_player_options& get_options()
        { return *static_cast<vlc_player_options*>(this); }
    const vlc_player_options& get_options() const
        { return *static_cast<const vlc_player_options*>(this); }

213 214 215 216 217
    NPError             init(int argc, char* const argn[], char* const argv[]);
    libvlc_instance_t*  getVLC()
                            { return libvlc_instance; };
    libvlc_media_player_t* getMD()
    {
218
        if( !get_player().is_open() )
219 220 221
        {
             libvlc_printerr("no mediaplayer");
        }
222
        return get_player().get_mp();
223 224 225 226 227 228
    }
    NPP                 getBrowser()
                            { return p_browser; };
    char*               getAbsoluteURL(const char *url);
    NPWindow&           getWindow()
                            { return npwindow; };
229
    virtual void        setWindow(const NPWindow &window);
230 231 232 233 234 235 236 237 238 239 240 241

    NPClass*            getScriptClass()
                            { return p_scriptClass; };

    NPuint16_t  i_npmode; /* either NP_EMBED or NP_FULL */

    /* plugin properties */
    int      b_stream;
    char *   psz_target;

    void playlist_play()
    {
242
        get_player().play();
243 244 245
    }
    void playlist_play_item(int idx)
    {
246
        get_player().play(idx);
247 248 249
    }
    void playlist_stop()
    {
250
        get_player().stop();
251 252 253
    }
    void playlist_next()
    {
254
        get_player().next();
255 256 257
    }
    void playlist_prev()
    {
258
        get_player().prev();
259 260 261
    }
    void playlist_pause()
    {
262
        get_player().pause();
263 264 265
    }
    int playlist_isplaying()
    {
266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287
        return get_player().is_playing();
    }
    int playlist_add( const char * mrl)
    {
        return get_player().add_item(mrl);
    }
    int playlist_add_extended_untrusted( const char *mrl, const char *,
                    int optc, const char **optv )
    {
        return get_player().add_item(mrl, optc, optv);
    }
    int playlist_delete_item( int idx)
    {
        return get_player().delete_item(idx);
    }
    void playlist_clear()
    {
        get_player().clear_items() ;
    }
    int  playlist_count()
    {
        return get_player().items_count();
288 289 290 291 292 293 294 295 296 297
    }

    void control_handler(vlc_toolbar_clicked_t);

    bool  player_has_vout();

    virtual bool create_windows() = 0;
    virtual bool resize_windows() = 0;
    virtual bool destroy_windows() = 0;

298 299
    virtual bool handle_event(void *event);

300
    virtual void toggle_fullscreen() = 0;
301 302 303 304 305
    virtual void set_fullscreen(int) = 0;
    virtual int get_fullscreen() = 0;

    virtual void set_toolbar_visible(bool) = 0;
    virtual bool get_toolbar_visible() = 0;
306

307
    virtual void update_controls() = 0;
308
    virtual void popup_menu() = 0;
309

310 311
    virtual void set_player_window() = 0;

312 313 314 315 316 317
    static bool canUseEventListener();

    EventObj events;
    void event_callback(const libvlc_event_t *, NPVariant *, uint32_t);

protected:
318 319 320 321 322
    // called after libvlc_media_player_new_from_media
    virtual void on_media_player_new()     {};
    // called before libvlc_media_player_release
    virtual void on_media_player_release() {};

323 324 325 326 327 328 329 330
    bool playlist_select(int);

    /* VLC reference */
    libvlc_instance_t   *libvlc_instance;
    NPClass             *p_scriptClass;

    /* browser reference */
    NPP     p_browser;
331
    char    *psz_baseURL;
332 333 334 335 336

    /* display settings */
    NPWindow  npwindow;

    static void eventAsync(void *);
337 338 339

private:
    static std::set<VlcPluginBase*> _instances;
340 341
};

342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408

const char DEF_CHROMA[] = "RV32";
enum{
    DEF_PIXEL_BYTES = 4
};

class VlcWindowlessBase : public VlcPluginBase
{
public:
    VlcWindowlessBase(NPP, NPuint16_t);
    virtual ~VlcWindowlessBase();

    //for libvlc_video_set_format_callbacks
    static unsigned video_format_proxy(void **opaque, char *chroma,
                                       unsigned *width, unsigned *height,
                                       unsigned *pitches, unsigned *lines)
        { return reinterpret_cast<VlcWindowlessBase*>(*opaque)->video_format_cb(chroma,
                                                                  width, height,
                                                                  pitches, lines); }
    static void video_cleanup_proxy(void *opaque)
        { reinterpret_cast<VlcWindowlessBase*>(opaque)->video_cleanup_cb(); };

    unsigned video_format_cb(char *chroma,
                             unsigned *width, unsigned *height,
                             unsigned *pitches, unsigned *lines);
    void video_cleanup_cb();
    //end (for libvlc_video_set_format_callbacks)

    //for libvlc_video_set_callbacks
    static void* video_lock_proxy(void *opaque, void **planes)
        { return reinterpret_cast<VlcWindowlessBase*>(opaque)->video_lock_cb(planes); }
    static void video_unlock_proxy(void *opaque, void *picture, void *const *planes)
        { reinterpret_cast<VlcWindowlessBase*>(opaque)->video_unlock_cb(picture, planes); }
    static void video_display_proxy(void *opaque, void *picture)
        { reinterpret_cast<VlcWindowlessBase*>(opaque)->video_display_cb(picture); }

    void* video_lock_cb(void **planes);
    void video_unlock_cb(void *picture, void *const *planes);
    void video_display_cb(void *picture);
    //end (for libvlc_video_set_callbacks)

    static void invalidate_window_proxy(void *opaque)
        { reinterpret_cast<VlcWindowlessBase*>(opaque)->invalidate_window(); }
    void invalidate_window();

    void set_player_window();


    bool create_windows() { return true; }
    bool resize_windows() { return true; }
    bool destroy_windows() { return true; }

    void toggle_fullscreen() { /* STUB */ }
    void set_fullscreen( int ) { /* STUB */ }
    int  get_fullscreen() { return false; }

    void set_toolbar_visible(bool)  { /* STUB */ }
    bool get_toolbar_visible()  { return false; }
    void update_controls()      {/* STUB */}
    void popup_menu()           {/* STUB */}

protected:
    std::vector<char> m_frame_buf;
    unsigned int m_media_width;
    unsigned int m_media_height;
};

409
#endif