X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=projects%2Fmozilla%2Fvlcplugin.cpp;h=dea87e6a8ef98256f1c131057f1afab7d7220b66;hb=0b47b18cb742ffe0affa2baea50fcd52f36eb8e7;hp=6293f64671bd1baa12c9f45d431de816103bb937;hpb=b99a4797dca4d88cd0dcd786ed6e36374c81ddd4;p=vlc diff --git a/projects/mozilla/vlcplugin.cpp b/projects/mozilla/vlcplugin.cpp index 6293f64671..dea87e6a8e 100644 --- a/projects/mozilla/vlcplugin.cpp +++ b/projects/mozilla/vlcplugin.cpp @@ -1,7 +1,7 @@ /***************************************************************************** * vlcplugin.cpp: a VLC plugin for Mozilla ***************************************************************************** - * Copyright (C) 2002-2009 the VideoLAN team + * Copyright (C) 2002-2010 the VideoLAN team * $Id$ * * Authors: Samuel Hocevar @@ -28,36 +28,104 @@ *****************************************************************************/ #include "config.h" -#ifdef HAVE_MOZILLA_CONFIG_H -# include -#endif - #include "vlcplugin.h" #include "control/npolibvlc.h" #include +#if defined(XP_UNIX) +# include +#elif defined(XP_WIN) + /* windows headers */ +# include +#else +#warning "locking not implemented for this platform" +#endif + +#include +#include +#include + +/***************************************************************************** + * utilitiy functions + *****************************************************************************/ +static void plugin_lock_init(plugin_lock_t *lock) +{ + assert(lock); + +#if defined(XP_UNIX) + pthread_mutex_init(&lock->mutex, NULL); +#elif defined(XP_WIN) + InitializeCriticalSection(&lock->cs); +#else +#warning "locking not implemented in this platform" +#endif +} + +static void plugin_lock_destroy(plugin_lock_t *lock) +{ + assert(lock); + +#if defined(XP_UNIX) + pthread_mutex_destroy(&lock->mutex); +#elif defined(XP_WIN) + DeleteCriticalSection(&lock->cs); +#else +#warning "locking not implemented in this platform" +#endif +} + +static void plugin_lock(plugin_lock_t *lock) +{ + assert(lock); + +#if defined(XP_UNIX) + pthread_mutex_lock(&lock->mutex); +#elif defined(XP_WIN) + EnterCriticalSection(&lock->cs); +#else +#warning "locking not implemented in this platform" +#endif +} + +static void plugin_unlock(plugin_lock_t *lock) +{ + assert(lock); + +#if defined(XP_UNIX) + pthread_mutex_unlock(&lock->mutex); +#elif defined(XP_WIN) + LeaveCriticalSection(&lock->cs); +#else +#warning "locking not implemented in this platform" +#endif +} + /***************************************************************************** * VlcPlugin constructor and destructor *****************************************************************************/ +#if (((NP_VERSION_MAJOR << 8) + NP_VERSION_MINOR) < 20) VlcPlugin::VlcPlugin( NPP instance, uint16 mode ) : +#else +VlcPlugin::VlcPlugin( NPP instance, uint16_t mode ) : +#endif i_npmode(mode), b_stream(0), b_autoplay(1), b_toolbar(0), + psz_text(NULL), psz_target(NULL), playlist_index(-1), libvlc_instance(NULL), libvlc_media_list(NULL), libvlc_media_player(NULL), - libvlc_log(NULL), p_scriptClass(NULL), p_browser(instance), psz_baseURL(NULL) -#if XP_WIN +#if defined(XP_WIN) ,pf_wndproc(NULL) #endif -#if XP_UNIX +#if defined(XP_UNIX) ,i_width((unsigned)-1) ,i_height((unsigned)-1) ,i_tb_width(0) @@ -74,8 +142,10 @@ VlcPlugin::VlcPlugin( NPP instance, uint16 mode ) : #endif { memset(&npwindow, 0, sizeof(NPWindow)); +#if defined(XP_UNIX) memset(&npvideo, 0, sizeof(Window)); memset(&npcontrol, 0, sizeof(Window)); +#endif } static bool boolValue(const char *value) { @@ -84,6 +154,170 @@ static bool boolValue(const char *value) { !strcasecmp(value, "yes") ); } +bool EventObj::init() +{ + plugin_lock_init(&lock); + return true; +} + +EventObj::~EventObj() +{ + plugin_lock_destroy(&lock); +} + +void EventObj::deliver(NPP browser) +{ + NPVariant result; + NPVariant params[1]; + + plugin_lock(&lock); + + for( ev_l::iterator i=_elist.begin();i!=_elist.end();++i ) + { + libvlc_event_type_t event = *i; + STRINGZ_TO_NPVARIANT(libvlc_event_type_name(event), params[0]); + + // Invalid events aren't supposed to be queued up. + // if( !have_event(event) ) continue; + + for( lr_l::iterator j=_llist.begin();j!=_llist.end();++j ) + { + if (j->get(event)) + { + NPN_InvokeDefault(browser, j->listener(), params, 1, &result); + NPN_ReleaseVariantValue(&result); + } + } + } + _elist.clear(); + + plugin_unlock(&lock); +} + +void VlcPlugin::eventAsync(void *param) +{ + VlcPlugin *plugin = (VlcPlugin*)param; + plugin->events.deliver(plugin->getBrowser()); +} + +void EventObj::callback(const libvlc_event_t* event) +{ + plugin_lock(&lock); + + if( have_event(event->type) ) + _elist.push_back(event->type); + + plugin_unlock(&lock); +} + +void VlcPlugin::event_callback(const libvlc_event_t* event, void *param) +{ + VlcPlugin *plugin = (VlcPlugin*)param; +#if defined(XP_UNIX) + plugin->events.callback(event); + NPN_PluginThreadAsyncCall(plugin->getBrowser(), eventAsync, plugin); +#else +#warning NPN_PluginThreadAsyncCall not implemented yet. + printf("No NPN_PluginThreadAsyncCall(), doing nothing."); +#endif +} + +inline EventObj::event_t EventObj::find_event(const char *s) const +{ + event_t i; + for(i=0;i=maxbit() ) + return false; + + if( !have_event(e) && !ask_for_event(e) ) + return false; + + lr_l::iterator i; + for(i=_llist.begin();i!=_llist.end();++i) + if(i->listener()==l && i->bubble()==b) + break; + + if( i == _llist.end() ) { + _llist.push_back(Listener(e,l,b)); + } else { + if( i->get(e) ) + return false; + i->get(e); + } + return true; +} + + +bool EventObj::remove(const NPString &s, NPObject *l, bool b) +{ + event_t e = find_event(s.UTF8Characters); + if( e>=maxbit() || !get(e) ) + return false; + + bool any=false; + for(lr_l::iterator i=_llist.begin();i!=_llist.end();) + { + if(i->listener()!=l || i->bubble()!=b) + any|=i->get(e); + else + { + i->reset(e); + if(i->empty()) + { + i=_llist.erase(i); + continue; + } + } + ++i; + } + if(!any) + unask_for_event(e); + + return true; +} + + +void EventObj::hook_manager(libvlc_event_manager_t *em, + libvlc_callback_t cb, void *udata) +{ + _em = em; _cb = cb; _ud = udata; + if( !_em ) + return; + for(size_t i=0;i(malloc(location.utf8length+1)); + psz_baseURL = (char *) malloc(location.UTF8Length+1); if( psz_baseURL ) { - strncpy(psz_baseURL, location.utf8characters, location.utf8length); - psz_baseURL[location.utf8length] = '\0'; + strncpy(psz_baseURL, location.UTF8Characters, location.UTF8Length); + psz_baseURL[location.UTF8Length] = '\0'; } } NPN_ReleaseVariantValue(&result); @@ -257,6 +485,9 @@ NPError VlcPlugin::init(int argc, char* const argn[], char* const argv[]) /* new APIs */ p_scriptClass = RuntimeNPClass::getClass(); + if( !events.init() ) + return NPERR_GENERIC_ERROR; + return NPERR_NO_ERROR; } @@ -264,10 +495,15 @@ VlcPlugin::~VlcPlugin() { free(psz_baseURL); free(psz_target); - if( libvlc_log ) - libvlc_log_close(libvlc_log, NULL); + free(psz_text); + if( libvlc_media_player ) + { + if( playlist_isplaying() ) + playlist_stop(); + events.unhook_manager(); libvlc_media_player_release( libvlc_media_player ); + } if( libvlc_media_list ) libvlc_media_list_release( libvlc_media_list ); if( libvlc_instance ) @@ -277,34 +513,31 @@ VlcPlugin::~VlcPlugin() /***************************************************************************** * VlcPlugin playlist replacement methods *****************************************************************************/ -void VlcPlugin::set_player_window( libvlc_exception_t *ex ) +void VlcPlugin::set_player_window() { #ifdef XP_UNIX libvlc_media_player_set_xwindow(libvlc_media_player, - (libvlc_drawable_t)getVideoWindow(), - ex); + (uint32_t)getVideoWindow()); #endif #ifdef XP_MACOSX // XXX FIXME insert appropriate call here #endif #ifdef XP_WIN libvlc_media_player_set_hwnd(libvlc_media_player, - getVideoWindow(), - ex); + getWindow().window); #endif } -int VlcPlugin::playlist_add( const char *mrl, libvlc_exception_t *ex ) +int VlcPlugin::playlist_add( const char *mrl ) { int item = -1; - libvlc_media_t *p_m = libvlc_media_new(libvlc_instance,mrl,ex); - if( libvlc_exception_raised(ex) ) + libvlc_media_t *p_m = libvlc_media_new_location(libvlc_instance,mrl); + if( !p_m ) return -1; - + assert( libvlc_media_list ); libvlc_media_list_lock(libvlc_media_list); - libvlc_media_list_add_media(libvlc_media_list,p_m,ex); - if( !libvlc_exception_raised(ex) ) - item = libvlc_media_list_count(libvlc_media_list,ex)-1; + if( !libvlc_media_list_add_media(libvlc_media_list,p_m) ) + item = libvlc_media_list_count(libvlc_media_list)-1; libvlc_media_list_unlock(libvlc_media_list); libvlc_media_release(p_m); @@ -313,164 +546,128 @@ int VlcPlugin::playlist_add( const char *mrl, libvlc_exception_t *ex ) } int VlcPlugin::playlist_add_extended_untrusted( const char *mrl, const char *name, - int optc, const char **optv, libvlc_exception_t *ex ) + int optc, const char **optv ) { - libvlc_media_t *p_m = libvlc_media_new(libvlc_instance, mrl,ex); + libvlc_media_t *p_m; int item = -1; - if( libvlc_exception_raised(ex) ) + + assert( libvlc_media_list ); + + p_m = libvlc_media_new_location(libvlc_instance, mrl); + if( !p_m ) return -1; for( int i = 0; i < optc; ++i ) - { - libvlc_media_add_option_untrusted(p_m, optv[i],ex); - if( libvlc_exception_raised(ex) ) - { - libvlc_media_release(p_m); - return -1; - } - } + libvlc_media_add_option_flag(p_m, optv[i], libvlc_media_option_unique); libvlc_media_list_lock(libvlc_media_list); - libvlc_media_list_add_media(libvlc_media_list,p_m,ex); - if( !libvlc_exception_raised(ex) ) - item = libvlc_media_list_count(libvlc_media_list,ex)-1; + if( !libvlc_media_list_add_media(libvlc_media_list,p_m) ) + item = libvlc_media_list_count(libvlc_media_list)-1; libvlc_media_list_unlock(libvlc_media_list); libvlc_media_release(p_m); return item; } -void VlcPlugin::playlist_play( libvlc_exception_t *ex ) -{ - if( libvlc_media_player||playlist_select(0,ex) ) - libvlc_media_player_play(libvlc_media_player,ex); -} - -void VlcPlugin::playlist_play_item( int idx, libvlc_exception_t *ex ) -{ - if( playlist_select(idx,ex) ) - libvlc_media_player_play(libvlc_media_player,ex); -} - -void VlcPlugin::playlist_stop( libvlc_exception_t *ex ) -{ - if( libvlc_media_player ) - libvlc_media_player_stop(libvlc_media_player,ex); -} - -bool VlcPlugin::playlist_select( int idx, libvlc_exception_t *ex ) +bool VlcPlugin::playlist_select( int idx ) { libvlc_media_t *p_m = NULL; - libvlc_media_list_lock(libvlc_media_list); + assert( libvlc_media_list ); - int count = libvlc_media_list_count(libvlc_media_list,ex); - if( libvlc_exception_raised(ex) ) - goto bad_unlock; + libvlc_media_list_lock(libvlc_media_list); + int count = libvlc_media_list_count(libvlc_media_list); if( idx<0||idx>=count ) goto bad_unlock; playlist_index = idx; - p_m = libvlc_media_list_item_at_index(libvlc_media_list,playlist_index,ex); + p_m = libvlc_media_list_item_at_index(libvlc_media_list,playlist_index); libvlc_media_list_unlock(libvlc_media_list); - if( libvlc_exception_raised(ex) ) + if( !p_m ) return false; if( libvlc_media_player ) { + if( playlist_isplaying() ) + playlist_stop(); + events.unhook_manager(); libvlc_media_player_release( libvlc_media_player ); libvlc_media_player = NULL; } - libvlc_media_player = libvlc_media_player_new_from_media(p_m,ex); + libvlc_media_player = libvlc_media_player_new_from_media(p_m); if( libvlc_media_player ) - set_player_window(ex); + { + set_player_window(); + events.hook_manager( + libvlc_media_player_event_manager(libvlc_media_player), + event_callback, this); + } libvlc_media_release( p_m ); - return !libvlc_exception_raised(ex); + return true; bad_unlock: libvlc_media_list_unlock(libvlc_media_list); return false; } -void VlcPlugin::playlist_next( libvlc_exception_t *ex ) -{ - if( playlist_select(playlist_index+1,ex) ) - libvlc_media_player_play(libvlc_media_player,ex); -} - -void VlcPlugin::playlist_prev( libvlc_exception_t *ex ) -{ - if( playlist_select(playlist_index-1,ex) ) - libvlc_media_player_play(libvlc_media_player,ex); -} - -void VlcPlugin::playlist_pause( libvlc_exception_t *ex ) -{ - if( libvlc_media_player ) - libvlc_media_player_pause(libvlc_media_player,ex); -} - -void VlcPlugin::playlist_delete_item( int idx, libvlc_exception_t *ex ) +int VlcPlugin::playlist_delete_item( int idx ) { + if( !libvlc_media_list ) + return -1; libvlc_media_list_lock(libvlc_media_list); - libvlc_media_list_remove_index(libvlc_media_list,idx,ex); + int ret = libvlc_media_list_remove_index(libvlc_media_list,idx); libvlc_media_list_unlock(libvlc_media_list); + return ret; } -void VlcPlugin::playlist_clear( libvlc_exception_t *ex ) +void VlcPlugin::playlist_clear() { if( libvlc_media_list ) libvlc_media_list_release(libvlc_media_list); - libvlc_media_list = libvlc_media_list_new(getVLC(),ex); + libvlc_media_list = libvlc_media_list_new(getVLC()); } -int VlcPlugin::playlist_count( libvlc_exception_t *ex ) +int VlcPlugin::playlist_count() { int items_count = 0; + if( !libvlc_media_list ) + return items_count; libvlc_media_list_lock(libvlc_media_list); - items_count = libvlc_media_list_count(libvlc_media_list,ex); + items_count = libvlc_media_list_count(libvlc_media_list); libvlc_media_list_unlock(libvlc_media_list); return items_count; } -int VlcPlugin::playlist_isplaying( libvlc_exception_t *ex ) +void VlcPlugin::toggle_fullscreen() { - int is_playing = 0; - if( libvlc_media_player ) - is_playing = libvlc_media_player_is_playing( libvlc_media_player, ex ); - return is_playing; + if( playlist_isplaying() ) + libvlc_toggle_fullscreen(libvlc_media_player); } -void VlcPlugin::toggle_fullscreen( libvlc_exception_t *ex ) +void VlcPlugin::set_fullscreen( int yes ) { - if( playlist_isplaying(ex) ) - libvlc_toggle_fullscreen(libvlc_media_player,ex); + if( playlist_isplaying() ) + libvlc_set_fullscreen(libvlc_media_player,yes); } -void VlcPlugin::set_fullscreen( int yes, libvlc_exception_t *ex ) -{ - if( playlist_isplaying(ex) ) - libvlc_set_fullscreen(libvlc_media_player,yes,ex); -} - -int VlcPlugin::get_fullscreen( libvlc_exception_t *ex ) +int VlcPlugin::get_fullscreen() { int r = 0; - if( playlist_isplaying(ex) ) - r = libvlc_get_fullscreen(libvlc_media_player,ex); + if( playlist_isplaying() ) + r = libvlc_get_fullscreen(libvlc_media_player); return r; } -int VlcPlugin::player_has_vout( libvlc_exception_t *ex ) +bool VlcPlugin::player_has_vout() { - int r = 0; - if( playlist_isplaying(ex) ) - r = libvlc_media_player_has_vout(libvlc_media_player, ex); + bool r = false; + if( playlist_isplaying() ) + r = libvlc_media_player_has_vout(libvlc_media_player); return r; } @@ -515,11 +712,11 @@ relativeurl: if( psz_baseURL ) { size_t baseLen = strlen(psz_baseURL); - char *href = static_cast(malloc(baseLen+strlen(url)+1)); + char *href = (char *) malloc(baseLen+strlen(url)+1); if( href ) { /* prepend base URL */ - strcpy(href, psz_baseURL); + memcpy(href, psz_baseURL, baseLen+1); /* ** relative url could be empty, @@ -534,7 +731,7 @@ relativeurl: /* skip over protocol part */ char *pathstart = strchr(href, ':'); - char *pathend; + char *pathend = href+baseLen; if( pathstart ) { if( '/' == *(++pathstart) ) @@ -546,7 +743,6 @@ relativeurl: } /* skip over host part */ pathstart = strchr(pathstart, '/'); - pathend = href+baseLen; if( ! pathstart ) { // no path, add a / past end of url (over '\0') @@ -560,11 +756,10 @@ relativeurl: if( '/' != *href ) { /* baseURL is not an absolute path */ - free(href); + free(href); return NULL; } pathstart = href; - pathend = href+baseLen; } /* relative URL made of an absolute path ? */ @@ -634,7 +829,7 @@ relativeurl: return NULL; } -#if XP_UNIX +#if defined(XP_UNIX) int VlcPlugin::setSize(unsigned width, unsigned height) { int diff = (width != i_width) || (height != i_height); @@ -775,7 +970,6 @@ void VlcPlugin::hideToolbar() void VlcPlugin::redrawToolbar() { - libvlc_exception_t ex; int is_playing = 0; bool b_mute = false; unsigned int dst_x, dst_y; @@ -784,7 +978,7 @@ void VlcPlugin::redrawToolbar() unsigned int i_tb_width, i_tb_height; /* This method does nothing if toolbar is hidden. */ - if( !b_toolbar ) + if( !b_toolbar || !libvlc_media_player ) return; const NPWindow& window = getWindow(); @@ -793,11 +987,8 @@ void VlcPlugin::redrawToolbar() getToolbarSize( &i_tb_width, &i_tb_height ); - libvlc_exception_init( &ex ); - /* get mute info */ - b_mute = libvlc_audio_get_mute( getVLC(), &ex ); - libvlc_exception_clear( &ex ); + b_mute = libvlc_audio_get_mute( libvlc_media_player ); gcv.foreground = BlackPixel( p_display, 0 ); gc = XCreateGC( p_display, control, GCForeground, &gcv ); @@ -863,12 +1054,11 @@ void VlcPlugin::redrawToolbar() (window.width-(dst_x+BTN_SPACE)), p_timeline->height ); /* get movie position in % */ - if( playlist_isplaying(&ex) ) + if( playlist_isplaying() ) { i_last_position = (int)((window.width-(dst_x+BTN_SPACE))* - libvlc_media_player_get_position(libvlc_media_player,&ex)); + libvlc_media_player_get_position(libvlc_media_player)); } - libvlc_exception_clear( &ex ); if( p_btnTime ) XPutImage( p_display, control, gc, p_btnTime, @@ -884,7 +1074,6 @@ vlc_toolbar_clicked_t VlcPlugin::getToolbarButtonClicked( int i_xpos, int i_ypos unsigned int i_dest = BTN_SPACE; int is_playing = 0; bool b_mute = false; - libvlc_exception_t ex; #ifndef NDEBUG fprintf( stderr, "ToolbarButtonClicked:: " @@ -900,13 +1089,11 @@ vlc_toolbar_clicked_t VlcPlugin::getToolbarButtonClicked( int i_xpos, int i_ypos */ /* get isplaying */ - libvlc_exception_init( &ex ); - is_playing = playlist_isplaying( &ex ); - libvlc_exception_clear( &ex ); + is_playing = playlist_isplaying(); /* get mute info */ - b_mute = libvlc_audio_get_mute( getVLC(), &ex ); - libvlc_exception_clear( &ex ); + if( libvlc_media_player ) + b_mute = libvlc_audio_get_mute( libvlc_media_player ); /* is Pause of Play button clicked */ if( (is_playing != 1) && @@ -961,3 +1148,19 @@ vlc_toolbar_clicked_t VlcPlugin::getToolbarButtonClicked( int i_xpos, int i_ypos } #undef BTN_SPACE #endif + +// Verifies the version of the NPAPI. +// The eventListeners use a NPAPI function available +// since Gecko 1.9. +bool VlcPlugin::canUseEventListener() +{ + int plugin_major, plugin_minor; + int browser_major, browser_minor; + + NPN_Version(&plugin_major, &plugin_minor, + &browser_major, &browser_minor); + + if (browser_minor >= 19 || browser_major > 0) + return true; + return false; +}