]> git.sesse.net Git - vlc/blob - projects/mozilla/vlcplugin.cpp
mozilla: fix video overwritting toolbar issue
[vlc] / projects / mozilla / vlcplugin.cpp
1 /*****************************************************************************
2  * vlcplugin.cpp: a VLC plugin for Mozilla
3  *****************************************************************************
4  * Copyright (C) 2002-2009 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Samuel Hocevar <sam@zoy.org>
8  *          Damien Fouilleul <damienf.fouilleul@laposte.net>
9  *          Jean-Paul Saman <jpsaman@videolan.org>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24  *****************************************************************************/
25
26 /*****************************************************************************
27  * Preamble
28  *****************************************************************************/
29 #include "config.h"
30
31 #ifdef HAVE_MOZILLA_CONFIG_H
32 #   include <mozilla-config.h>
33 #endif
34
35 #include "vlcplugin.h"
36 #include "control/npolibvlc.h"
37
38 #include <ctype.h>
39
40 /*****************************************************************************
41  * VlcPlugin constructor and destructor
42  *****************************************************************************/
43 VlcPlugin::VlcPlugin( NPP instance, uint16 mode ) :
44     i_npmode(mode),
45     b_stream(0),
46     b_autoplay(1),
47     b_toolbar(0),
48     psz_target(NULL),
49     playlist_index(-1),
50     libvlc_instance(NULL),
51     libvlc_media_list(NULL),
52     libvlc_media_player(NULL),
53     libvlc_log(NULL),
54     p_scriptClass(NULL),
55     p_browser(instance),
56     psz_baseURL(NULL)
57 #if XP_WIN
58     ,pf_wndproc(NULL)
59 #endif
60 #if XP_UNIX
61     ,i_width((unsigned)-1)
62     ,i_height((unsigned)-1)
63     ,i_tb_width(0)
64     ,i_tb_height(0)
65     ,i_last_position(0)
66     ,p_btnPlay(NULL)
67     ,p_btnPause(NULL)
68     ,p_btnStop(NULL)
69     ,p_btnMute(NULL)
70     ,p_btnUnmute(NULL)
71     ,p_btnFullscreen(NULL)
72     ,p_btnTime(NULL)
73     ,p_timeline(NULL)
74 #endif
75 {
76     memset(&npwindow, 0, sizeof(NPWindow));
77     memset(&npvideo, 0, sizeof(Window));
78     memset(&npcontrol, 0, sizeof(Window));
79 }
80
81 static bool boolValue(const char *value) {
82     return ( !strcmp(value, "1") ||
83              !strcasecmp(value, "true") ||
84              !strcasecmp(value, "yes") );
85 }
86
87 NPError VlcPlugin::init(int argc, char* const argn[], char* const argv[])
88 {
89     /* prepare VLC command line */
90     const char *ppsz_argv[32];
91     int ppsz_argc = 0;
92
93 #ifndef NDEBUG
94     ppsz_argv[ppsz_argc++] = "--no-plugins-cache";
95 #endif
96
97     /* locate VLC module path */
98 #ifdef XP_MACOSX
99     ppsz_argv[ppsz_argc++] = "--plugin-path=/Library/Internet\\ Plug-Ins/VLC\\ Plugin.plugin/Contents/MacOS/modules";
100     ppsz_argv[ppsz_argc++] = "--vout=macosx";
101 #elif defined(XP_WIN)
102     HKEY h_key;
103     DWORD i_type, i_data = MAX_PATH + 1;
104     char p_data[MAX_PATH + 1];
105     if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, "Software\\VideoLAN\\VLC",
106                       0, KEY_READ, &h_key ) == ERROR_SUCCESS )
107     {
108          if( RegQueryValueEx( h_key, "InstallDir", 0, &i_type,
109                               (LPBYTE)p_data, &i_data ) == ERROR_SUCCESS )
110          {
111              if( i_type == REG_SZ )
112              {
113                  strcat( p_data, "\\plugins" );
114                  ppsz_argv[ppsz_argc++] = "--plugin-path";
115                  ppsz_argv[ppsz_argc++] = p_data;
116              }
117          }
118          RegCloseKey( h_key );
119     }
120     ppsz_argv[ppsz_argc++] = "--no-one-instance";
121
122 #endif /* XP_MACOSX */
123
124     /* common settings */
125     ppsz_argv[ppsz_argc++] = "-vv";
126     ppsz_argv[ppsz_argc++] = "--no-stats";
127     ppsz_argv[ppsz_argc++] = "--no-media-library";
128     ppsz_argv[ppsz_argc++] = "--ignore-config";
129     ppsz_argv[ppsz_argc++] = "--intf=dummy";
130     const char *progid = NULL;
131
132     /* parse plugin arguments */
133     for( int i = 0; i < argc ; i++ )
134     {
135         fprintf(stderr, "argn=%s, argv=%s\n", argn[i], argv[i]);
136
137         if( !strcmp( argn[i], "target" )
138          || !strcmp( argn[i], "mrl")
139          || !strcmp( argn[i], "filename")
140          || !strcmp( argn[i], "src") )
141         {
142             psz_target = argv[i];
143         }
144         else if( !strcmp( argn[i], "autoplay")
145               || !strcmp( argn[i], "autostart") )
146         {
147             b_autoplay = boolValue(argv[i]);
148         }
149         else if( !strcmp( argn[i], "fullscreen" ) )
150         {
151             if( boolValue(argv[i]) )
152             {
153                 ppsz_argv[ppsz_argc++] = "--fullscreen";
154             }
155             else
156             {
157                 ppsz_argv[ppsz_argc++] = "--no-fullscreen";
158             }
159         }
160         else if( !strcmp( argn[i], "mute" ) )
161         {
162             if( boolValue(argv[i]) )
163             {
164                 ppsz_argv[ppsz_argc++] = "--volume=0";
165             }
166         }
167         else if( !strcmp( argn[i], "loop")
168               || !strcmp( argn[i], "autoloop") )
169         {
170             if( boolValue(argv[i]) )
171             {
172                 ppsz_argv[ppsz_argc++] = "--loop";
173             }
174             else
175             {
176                 ppsz_argv[ppsz_argc++] = "--no-loop";
177             }
178         }
179         else if( !strcmp( argn[i], "version")
180               || !strcmp( argn[i], "progid") )
181         {
182             progid = argv[i];
183         }
184         else if( !strcmp( argn[i], "toolbar" ) )
185         {
186 /* FIXME: Remove this when toolbar functionality has been implemented on\
187  * MacOS X and Win32 for Firefox/Mozilla/Safari. */
188 #ifdef XP_UNIX
189             b_toolbar = boolValue(argv[i]);
190 #endif
191         }
192     }
193
194     libvlc_exception_t ex;
195     libvlc_exception_init(&ex);
196
197     libvlc_instance = libvlc_new(ppsz_argc, ppsz_argv, &ex);
198
199     if( libvlc_exception_raised(&ex) )
200     {
201         libvlc_exception_clear(&ex);
202         return NPERR_GENERIC_ERROR;
203     }
204
205     libvlc_media_list = libvlc_media_list_new(libvlc_instance,&ex);
206     if( libvlc_exception_raised(&ex) )
207     {
208         libvlc_exception_clear(&ex);
209         return NPERR_GENERIC_ERROR;
210     }
211
212     /*
213     ** fetch plugin base URL, which is the URL of the page containing the plugin
214     ** this URL is used for making absolute URL from relative URL that may be
215     ** passed as an MRL argument
216     */
217     NPObject *plugin;
218
219     if( NPERR_NO_ERROR == NPN_GetValue(p_browser, NPNVWindowNPObject, &plugin) )
220     {
221         /*
222         ** is there a better way to get that info ?
223         */
224         static const char docLocHref[] = "document.location.href";
225         NPString script;
226         NPVariant result;
227
228         script.utf8characters = docLocHref;
229         script.utf8length = sizeof(docLocHref)-1;
230
231         if( NPN_Evaluate(p_browser, plugin, &script, &result) )
232         {
233             if( NPVARIANT_IS_STRING(result) )
234             {
235                 NPString &location = NPVARIANT_TO_STRING(result);
236
237                 psz_baseURL = static_cast<char*>(malloc(location.utf8length+1));
238                 if( psz_baseURL )
239                 {
240                     strncpy(psz_baseURL, location.utf8characters, location.utf8length);
241                     psz_baseURL[location.utf8length] = '\0';
242                 }
243             }
244             NPN_ReleaseVariantValue(&result);
245         }
246         NPN_ReleaseObject(plugin);
247     }
248
249     if( psz_target )
250     {
251         // get absolute URL from src
252         char *psz_absurl = getAbsoluteURL(psz_target);
253         psz_target = psz_absurl ? psz_absurl : strdup(psz_target);
254     }
255
256     /* assign plugin script root class */
257     /* new APIs */
258     p_scriptClass = RuntimeNPClass<LibvlcRootNPObject>::getClass();
259
260     return NPERR_NO_ERROR;
261 }
262
263 VlcPlugin::~VlcPlugin()
264 {
265     free(psz_baseURL);
266     free(psz_target);
267     if( libvlc_log )
268         libvlc_log_close(libvlc_log, NULL);
269     if( libvlc_media_player )
270         libvlc_media_player_release( libvlc_media_player );
271     if( libvlc_media_list )
272         libvlc_media_list_release( libvlc_media_list );
273     if( libvlc_instance )
274         libvlc_release(libvlc_instance);
275 }
276
277 /*****************************************************************************
278  * VlcPlugin playlist replacement methods
279  *****************************************************************************/
280 void VlcPlugin::set_player_window( libvlc_exception_t *ex )
281 {
282 #ifdef XP_UNIX
283     libvlc_media_player_set_xwindow(libvlc_media_player,
284                                     (libvlc_drawable_t)getVideoWindow(),
285                                     ex);
286 #endif
287 #ifdef XP_MACOSX
288     // XXX FIXME insert appropriate call here
289 #endif
290 #ifdef XP_WIN
291     libvlc_media_player_set_hwnd(libvlc_media_player,
292                                  getVideoWindow(),
293                                  ex);
294 #endif
295 }
296
297 int VlcPlugin::playlist_add( const char *mrl, libvlc_exception_t *ex )
298 {
299     int item = -1;
300     libvlc_media_t *p_m = libvlc_media_new(libvlc_instance,mrl,ex);
301     if( libvlc_exception_raised(ex) )
302         return -1;
303
304     libvlc_media_list_lock(libvlc_media_list);
305     libvlc_media_list_add_media(libvlc_media_list,p_m,ex);
306     if( !libvlc_exception_raised(ex) )
307         item = libvlc_media_list_count(libvlc_media_list,ex)-1;
308     libvlc_media_list_unlock(libvlc_media_list);
309
310     libvlc_media_release(p_m);
311
312     return item;
313 }
314
315 int VlcPlugin::playlist_add_extended_untrusted( const char *mrl, const char *name,
316                     int optc, const char **optv, libvlc_exception_t *ex )
317 {
318     libvlc_media_t *p_m = libvlc_media_new(libvlc_instance, mrl,ex);
319     int item = -1;
320     if( libvlc_exception_raised(ex) )
321         return -1;
322
323     for( int i = 0; i < optc; ++i )
324     {
325         libvlc_media_add_option_untrusted(p_m, optv[i],ex);
326         if( libvlc_exception_raised(ex) )
327         {
328             libvlc_media_release(p_m);
329             return -1;
330         }
331     }
332
333     libvlc_media_list_lock(libvlc_media_list);
334     libvlc_media_list_add_media(libvlc_media_list,p_m,ex);
335     if( !libvlc_exception_raised(ex) )
336         item = libvlc_media_list_count(libvlc_media_list,ex)-1;
337     libvlc_media_list_unlock(libvlc_media_list);
338     libvlc_media_release(p_m);
339
340     return item;
341 }
342
343 void VlcPlugin::playlist_play( libvlc_exception_t *ex )
344 {
345     if( libvlc_media_player||playlist_select(0,ex) )
346         libvlc_media_player_play(libvlc_media_player,ex);
347 }
348
349 void VlcPlugin::playlist_play_item( int idx, libvlc_exception_t *ex )
350 {
351     if( playlist_select(idx,ex) )
352         libvlc_media_player_play(libvlc_media_player,ex);
353 }
354
355 void VlcPlugin::playlist_stop( libvlc_exception_t *ex )
356 {
357     if( libvlc_media_player )
358         libvlc_media_player_stop(libvlc_media_player,ex);
359 }
360
361 bool VlcPlugin::playlist_select( int idx, libvlc_exception_t *ex )
362 {
363     libvlc_media_t *p_m = NULL;
364
365     libvlc_media_list_lock(libvlc_media_list);
366
367     int count = libvlc_media_list_count(libvlc_media_list,ex);
368     if( libvlc_exception_raised(ex) )
369         goto bad_unlock;
370
371     if( idx<0||idx>=count )
372         goto bad_unlock;
373
374     playlist_index = idx;
375
376     p_m = libvlc_media_list_item_at_index(libvlc_media_list,playlist_index,ex);
377     libvlc_media_list_unlock(libvlc_media_list);
378
379     if( libvlc_exception_raised(ex) )
380         return false;
381
382     if( libvlc_media_player )
383     {
384         libvlc_media_player_release( libvlc_media_player );
385         libvlc_media_player = NULL;
386     }
387
388     libvlc_media_player = libvlc_media_player_new_from_media(p_m,ex);
389     if( libvlc_media_player )
390         set_player_window(ex);
391
392     libvlc_media_release( p_m );
393     return !libvlc_exception_raised(ex);
394
395 bad_unlock:
396     libvlc_media_list_unlock(libvlc_media_list);
397     return false;
398 }
399
400 void VlcPlugin::playlist_next( libvlc_exception_t *ex )
401 {
402     if( playlist_select(playlist_index+1,ex) )
403         libvlc_media_player_play(libvlc_media_player,ex);
404 }
405
406 void VlcPlugin::playlist_prev( libvlc_exception_t *ex )
407 {
408     if( playlist_select(playlist_index-1,ex) )
409         libvlc_media_player_play(libvlc_media_player,ex);
410 }
411
412 void VlcPlugin::playlist_pause( libvlc_exception_t *ex )
413 {
414     if( libvlc_media_player )
415         libvlc_media_player_pause(libvlc_media_player,ex);
416 }
417
418 void VlcPlugin::playlist_delete_item( int idx, libvlc_exception_t *ex )
419 {
420     libvlc_media_list_lock(libvlc_media_list);
421     libvlc_media_list_remove_index(libvlc_media_list,idx,ex);
422     libvlc_media_list_unlock(libvlc_media_list);
423 }
424
425 void VlcPlugin::playlist_clear( libvlc_exception_t *ex )
426 {
427     if( libvlc_media_list )
428         libvlc_media_list_release(libvlc_media_list);
429     libvlc_media_list = libvlc_media_list_new(getVLC(),ex);
430 }
431
432 int VlcPlugin::playlist_count( libvlc_exception_t *ex )
433 {
434     int items_count = 0;
435     libvlc_media_list_lock(libvlc_media_list);
436     items_count = libvlc_media_list_count(libvlc_media_list,ex);
437     libvlc_media_list_unlock(libvlc_media_list);
438     return items_count;
439 }
440
441 int VlcPlugin::playlist_isplaying( libvlc_exception_t *ex )
442 {
443     int is_playing = 0;
444     if( libvlc_media_player )
445         libvlc_media_player_is_playing( libvlc_media_player, ex );
446     return is_playing;
447 }
448
449 void VlcPlugin::toggle_fullscreen( libvlc_exception_t *ex )
450 {
451     if( playlist_isplaying(ex) )
452         libvlc_toggle_fullscreen(libvlc_media_player,ex);
453 }
454
455 void VlcPlugin::set_fullscreen( int yes, libvlc_exception_t *ex )
456 {
457     if( playlist_isplaying(ex) )
458         libvlc_set_fullscreen(libvlc_media_player,yes,ex);
459 }
460
461 int  VlcPlugin::get_fullscreen( libvlc_exception_t *ex )
462 {
463     int r = 0;
464     if( playlist_isplaying(ex) )
465         r = libvlc_get_fullscreen(libvlc_media_player,ex);
466     return r;
467 }
468
469 int  VlcPlugin::player_has_vout( libvlc_exception_t *ex )
470 {
471     int r = 0;
472     if( playlist_isplaying(ex) )
473         r = libvlc_media_player_has_vout(libvlc_media_player, ex);
474     return r;
475 }
476
477
478 /*****************************************************************************
479  * VlcPlugin methods
480  *****************************************************************************/
481
482 char *VlcPlugin::getAbsoluteURL(const char *url)
483 {
484     if( NULL != url )
485     {
486         // check whether URL is already absolute
487         const char *end=strchr(url, ':');
488         if( (NULL != end) && (end != url) )
489         {
490             // validate protocol header
491             const char *start = url;
492             char c = *start;
493             if( isalpha(c) )
494             {
495                 ++start;
496                 while( start != end )
497                 {
498                     c  = *start;
499                     if( ! (isalnum(c)
500                        || ('-' == c)
501                        || ('+' == c)
502                        || ('.' == c)
503                        || ('/' == c)) ) /* VLC uses / to allow user to specify a demuxer */
504                         // not valid protocol header, assume relative URL
505                         goto relativeurl;
506                     ++start;
507                 }
508                 /* we have a protocol header, therefore URL is absolute */
509                 return strdup(url);
510             }
511             // not a valid protocol header, assume relative URL
512         }
513
514 relativeurl:
515
516         if( psz_baseURL )
517         {
518             size_t baseLen = strlen(psz_baseURL);
519             char *href = static_cast<char*>(malloc(baseLen+strlen(url)+1));
520             if( href )
521             {
522                 /* prepend base URL */
523                 strcpy(href, psz_baseURL);
524
525                 /*
526                 ** relative url could be empty,
527                 ** in which case return base URL
528                 */
529                 if( '\0' == *url )
530                     return href;
531
532                 /*
533                 ** locate pathname part of base URL
534                 */
535
536                 /* skip over protocol part  */
537                 char *pathstart = strchr(href, ':');
538                 char *pathend;
539                 if( pathstart )
540                 {
541                     if( '/' == *(++pathstart) )
542                     {
543                         if( '/' == *(++pathstart) )
544                         {
545                             ++pathstart;
546                         }
547                     }
548                     /* skip over host part */
549                     pathstart = strchr(pathstart, '/');
550                     pathend = href+baseLen;
551                     if( ! pathstart )
552                     {
553                         // no path, add a / past end of url (over '\0')
554                         pathstart = pathend;
555                         *pathstart = '/';
556                     }
557                 }
558                 else
559                 {
560                     /* baseURL is just a UNIX path */
561                     if( '/' != *href )
562                     {
563                         /* baseURL is not an absolute path */
564                         free(href);
565                         return NULL;
566                     }
567                     pathstart = href;
568                     pathend = href+baseLen;
569                 }
570
571                 /* relative URL made of an absolute path ? */
572                 if( '/' == *url )
573                 {
574                     /* replace path completely */
575                     strcpy(pathstart, url);
576                     return href;
577                 }
578
579                 /* find last path component and replace it */
580                 while( '/' != *pathend)
581                     --pathend;
582
583                 /*
584                 ** if relative url path starts with one or more '../',
585                 ** factor them out of href so that we return a
586                 ** normalized URL
587                 */
588                 while( pathend != pathstart )
589                 {
590                     const char *p = url;
591                     if( '.' != *p )
592                         break;
593                     ++p;
594                     if( '\0' == *p  )
595                     {
596                         /* relative url is just '.' */
597                         url = p;
598                         break;
599                     }
600                     if( '/' == *p  )
601                     {
602                         /* relative url starts with './' */
603                         url = ++p;
604                         continue;
605                     }
606                     if( '.' != *p )
607                         break;
608                     ++p;
609                     if( '\0' == *p )
610                     {
611                         /* relative url is '..' */
612                     }
613                     else
614                     {
615                         if( '/' != *p )
616                             break;
617                         /* relative url starts with '../' */
618                         ++p;
619                     }
620                     url = p;
621                     do
622                     {
623                         --pathend;
624                     }
625                     while( '/' != *pathend );
626                 }
627                 /* skip over '/' separator */
628                 ++pathend;
629                 /* concatenate remaining base URL and relative URL */
630                 strcpy(pathend, url);
631             }
632             return href;
633         }
634     }
635     return NULL;
636 }
637
638 #if XP_UNIX
639 int  VlcPlugin::setSize(unsigned width, unsigned height)
640 {
641     int diff = (width != i_width) || (height != i_height);
642
643     i_width = width;
644     i_height = height;
645
646     /* return size */
647     return diff;
648 }
649
650 #define BTN_SPACE ((unsigned int)4)
651 void VlcPlugin::showToolbar()
652 {
653     const NPWindow& window = getWindow();
654     Window control = getControlWindow();
655     Window video = getVideoWindow();
656     Display *p_display = ((NPSetWindowCallbackStruct *)window.ws_info)->display;
657     unsigned int i_height = 0, i_width = BTN_SPACE;
658
659     /* load icons */
660     if( !p_btnPlay )
661         XpmReadFileToImage( p_display, DATA_PATH "/mozilla/play.xpm",
662                             &p_btnPlay, NULL, NULL);
663     if( p_btnPlay )
664     {
665         i_height = __MAX( i_height, p_btnPlay->height );
666     }
667     if( !p_btnPause )
668         XpmReadFileToImage( p_display, DATA_PATH "/mozilla/pause.xpm",
669                             &p_btnPause, NULL, NULL);
670     if( p_btnPause )
671     {
672         i_height = __MAX( i_height, p_btnPause->height );
673     }
674     i_width += __MAX( p_btnPause->width, p_btnPlay->width );
675
676     if( !p_btnStop )
677         XpmReadFileToImage( p_display, DATA_PATH "/mozilla/stop.xpm",
678                             &p_btnStop, NULL, NULL );
679     if( p_btnStop )
680     {
681         i_height = __MAX( i_height, p_btnStop->height );
682         i_width += BTN_SPACE + p_btnStop->width;
683     }
684     if( !p_timeline )
685         XpmReadFileToImage( p_display, DATA_PATH "/mozilla/time_line.xpm",
686                             &p_timeline, NULL, NULL);
687     if( p_timeline )
688     {
689         i_height = __MAX( i_height, p_timeline->height );
690         i_width += BTN_SPACE + p_timeline->width;
691     }
692     if( !p_btnTime )
693         XpmReadFileToImage( p_display, DATA_PATH "/mozilla/time_icon.xpm",
694                             &p_btnTime, NULL, NULL);
695     if( p_btnTime )
696     {
697         i_height = __MAX( i_height, p_btnTime->height );
698         i_width += BTN_SPACE + p_btnTime->width;
699     }
700     if( !p_btnFullscreen )
701         XpmReadFileToImage( p_display, DATA_PATH "/mozilla/fullscreen.xpm",
702                             &p_btnFullscreen, NULL, NULL);
703     if( p_btnFullscreen )
704     {
705         i_height = __MAX( i_height, p_btnFullscreen->height );
706         i_width += BTN_SPACE + p_btnFullscreen->width;
707     }
708     if( !p_btnMute )
709         XpmReadFileToImage( p_display, DATA_PATH "/mozilla/volume_max.xpm",
710                             &p_btnMute, NULL, NULL);
711     if( p_btnMute )
712     {
713         i_height = __MAX( i_height, p_btnMute->height );
714     }
715     if( !p_btnUnmute )
716         XpmReadFileToImage( p_display, DATA_PATH "/mozilla/volume_mute.xpm",
717                             &p_btnUnmute, NULL, NULL);
718     if( p_btnUnmute )
719     {
720         i_height = __MAX( i_height, p_btnUnmute->height );
721     }
722     i_width += BTN_SPACE + __MAX( p_btnUnmute->width, p_btnMute->width );
723
724     setToolbarSize( i_width, i_height );
725
726     if( !p_btnPlay || !p_btnPause || !p_btnStop || !p_timeline ||
727         !p_btnTime || !p_btnFullscreen || !p_btnMute || !p_btnUnmute )
728         fprintf(stderr, "Error: some button images not found in %s\n", DATA_PATH );
729
730     /* reset panels position and size */
731     /* XXX  use i_width */
732     XResizeWindow( p_display, video, window.width, window.height - i_height);
733     XMoveWindow( p_display, control, 0, window.height - i_height );
734     XResizeWindow( p_display, control, window.width, i_height -1);
735
736     b_toolbar = 1; /* says toolbar is now shown */
737     redrawToolbar();
738 }
739
740 void VlcPlugin::hideToolbar()
741 {
742     const NPWindow& window = getWindow();
743     Display *p_display = ((NPSetWindowCallbackStruct *)window.ws_info)->display;
744     Window control = getControlWindow();
745     Window video = getVideoWindow();
746
747     i_tb_width = i_tb_height = 0;
748
749     if( p_btnPlay )  XDestroyImage( p_btnPlay );
750     if( p_btnPause ) XDestroyImage( p_btnPause );
751     if( p_btnStop )  XDestroyImage( p_btnStop );
752     if( p_timeline ) XDestroyImage( p_timeline );
753     if( p_btnTime )  XDestroyImage( p_btnTime );
754     if( p_btnFullscreen ) XDestroyImage( p_btnFullscreen );
755     if( p_btnMute )  XDestroyImage( p_btnMute );
756     if( p_btnUnmute ) XDestroyImage( p_btnUnmute );
757
758     p_btnPlay = NULL;
759     p_btnPause = NULL;
760     p_btnStop = NULL;
761     p_timeline = NULL;
762     p_btnTime = NULL;
763     p_btnFullscreen = NULL;
764     p_btnMute = NULL;
765     p_btnUnmute = NULL;
766
767     /* reset panels position and size */
768     /* XXX  use i_width */
769     XResizeWindow( p_display, video, window.width, window.height );
770     XMoveWindow( p_display, control, 0, window.height-1 );
771     XResizeWindow( p_display, control, window.width, 1 );
772
773     b_toolbar = 0; /* says toolbar is now hidden */
774     redrawToolbar();
775 }
776
777 void VlcPlugin::redrawToolbar()
778 {
779     libvlc_exception_t ex;
780     int is_playing = 0;
781     bool b_mute = false;
782     unsigned int dst_x, dst_y;
783     GC gc;
784     XGCValues gcv;
785     unsigned int i_tb_width, i_tb_height;
786
787     /* This method does nothing if toolbar is hidden. */
788     if( !b_toolbar )
789         return;
790
791     const NPWindow& window = getWindow();
792     Window control = getControlWindow();
793     Display *p_display = ((NPSetWindowCallbackStruct *)window.ws_info)->display;
794
795     getToolbarSize( &i_tb_width, &i_tb_height );
796
797     libvlc_exception_init( &ex );
798
799     /* get mute info */
800     b_mute = libvlc_audio_get_mute( getVLC(), &ex );
801     libvlc_exception_clear( &ex );
802
803     gcv.foreground = BlackPixel( p_display, 0 );
804     gc = XCreateGC( p_display, control, GCForeground, &gcv );
805
806     XFillRectangle( p_display, control, gc,
807                     0, 0, window.width, i_tb_height );
808     gcv.foreground = WhitePixel( p_display, 0 );
809     XChangeGC( p_display, gc, GCForeground, &gcv );
810
811     /* position icons */
812     dst_x = BTN_SPACE;
813     dst_y = i_tb_height >> 1; /* baseline = vertical middle */
814
815     if( p_btnPause && (is_playing == 1) )
816     {
817         XPutImage( p_display, control, gc, p_btnPause, 0, 0, dst_x,
818                    dst_y - (p_btnPause->height >> 1),
819                    p_btnPause->width, p_btnPause->height );
820         dst_x += BTN_SPACE + p_btnPause->width;
821     }
822     else if( p_btnPlay )
823     {
824         XPutImage( p_display, control, gc, p_btnPlay, 0, 0, dst_x,
825                    dst_y - (p_btnPlay->height >> 1),
826                    p_btnPlay->width, p_btnPlay->height );
827         dst_x += BTN_SPACE + p_btnPlay->width;
828     }
829
830     if( p_btnStop )
831         XPutImage( p_display, control, gc, p_btnStop, 0, 0, dst_x,
832                    dst_y - (p_btnStop->height >> 1),
833                    p_btnStop->width, p_btnStop->height );
834
835     dst_x += BTN_SPACE + ( p_btnStop ? p_btnStop->width : 0 );
836
837     if( p_btnFullscreen )
838         XPutImage( p_display, control, gc, p_btnFullscreen, 0, 0, dst_x,
839                    dst_y - (p_btnFullscreen->height >> 1),
840                    p_btnFullscreen->width, p_btnFullscreen->height );
841
842     dst_x += BTN_SPACE + ( p_btnFullscreen ? p_btnFullscreen->width : 0 );
843
844     if( p_btnUnmute && b_mute )
845     {
846         XPutImage( p_display, control, gc, p_btnUnmute, 0, 0, dst_x,
847                    dst_y - (p_btnUnmute->height >> 1),
848                    p_btnUnmute->width, p_btnUnmute->height );
849
850         dst_x += BTN_SPACE + ( p_btnUnmute ? p_btnUnmute->width : 0 );
851     }
852     else if( p_btnMute )
853     {
854         XPutImage( p_display, control, gc, p_btnMute, 0, 0, dst_x,
855                    dst_y - (p_btnMute->height >> 1),
856                    p_btnMute->width, p_btnMute->height );
857
858         dst_x += BTN_SPACE + ( p_btnMute ? p_btnMute->width : 0 );
859     }
860
861     if( p_timeline )
862         XPutImage( p_display, control, gc, p_timeline, 0, 0, dst_x,
863                    dst_y - (p_timeline->height >> 1),
864                    (window.width-(dst_x+BTN_SPACE)), p_timeline->height );
865
866
867
868     /* get movie position in % */
869     if( playlist_isplaying(&ex) )
870     {
871         i_last_position = (int)((window.width-(dst_x+BTN_SPACE))*
872                    libvlc_media_player_get_position(libvlc_media_player,&ex));
873     }
874     libvlc_exception_clear( &ex );
875
876     if( p_btnTime )
877         XPutImage( p_display, control, gc, p_btnTime,
878                    0, 0, (dst_x+i_last_position),
879                    dst_y - (p_btnTime->height >> 1),
880                    p_btnTime->width, p_btnTime->height );
881
882     XFreeGC( p_display, gc );
883 }
884
885 vlc_toolbar_clicked_t VlcPlugin::getToolbarButtonClicked( int i_xpos, int i_ypos )
886 {
887     unsigned int i_dest = BTN_SPACE;//(i_tb_height >> 1);
888     int is_playing = 0;
889     bool b_mute = false;
890     libvlc_exception_t ex;
891
892     fprintf( stderr, "ToolbarButtonClicked:: "
893                      "trying to match (%d,%d) (%d,%d)\n",
894              i_xpos, i_ypos, i_tb_height, i_tb_width );
895
896     if( i_ypos >= i_tb_width )
897         return clicked_Unknown;
898
899     /* Note: the order of testing is dependend on the original
900      * drawing positions of the icon buttons. Buttons are tested
901      * left to right.
902      */
903
904     /* get isplaying */
905     libvlc_exception_init( &ex );
906     is_playing = playlist_isplaying( &ex );
907     libvlc_exception_clear( &ex );
908
909     /* get mute info */
910     b_mute = libvlc_audio_get_mute( getVLC(), &ex );
911     libvlc_exception_clear( &ex );
912
913     /* is Pause of Play button clicked */
914     if( (is_playing != 1) &&
915         (i_xpos >= (BTN_SPACE>>1)) &&
916         (i_xpos <= i_dest + p_btnPlay->width + (BTN_SPACE>>1)) )
917         return clicked_Play;
918     else if( (i_xpos >= (BTN_SPACE>>1))  &&
919              (i_xpos <= i_dest + p_btnPause->width) )
920         return clicked_Pause;
921
922     /* is Stop button clicked */
923     if( is_playing != 1 )
924         i_dest += (p_btnPlay->width + (BTN_SPACE>>1));
925     else
926         i_dest += (p_btnPause->width + (BTN_SPACE>>1));
927
928     if( (i_xpos >= i_dest) &&
929         (i_xpos <= i_dest + p_btnStop->width + (BTN_SPACE>>1)) )
930         return clicked_Stop;
931
932     /* is Fullscreen button clicked */
933     i_dest += (p_btnStop->width + (BTN_SPACE>>1));
934     if( (i_xpos >= i_dest) &&
935         (i_xpos <= i_dest + p_btnFullscreen->width + (BTN_SPACE>>1)) )
936         return clicked_Fullscreen;
937
938     /* is Mute or Unmute button clicked */
939     i_dest += (p_btnFullscreen->width + (BTN_SPACE>>1));
940     if( !b_mute && (i_xpos >= i_dest) &&
941         (i_xpos <= i_dest + p_btnMute->width + (BTN_SPACE>>1)) )
942         return clicked_Mute;
943     else if( (i_xpos >= i_dest) &&
944              (i_xpos <= i_dest + p_btnUnmute->width + (BTN_SPACE>>1)) )
945         return clicked_Unmute;
946
947     /* is timeline clicked */
948     if( !b_mute )
949         i_dest += (p_btnMute->width + (BTN_SPACE>>1));
950     else
951         i_dest += (p_btnUnmute->width + (BTN_SPACE>>1));
952     if( (i_xpos >= i_dest) &&
953         (i_xpos <= i_dest + p_timeline->width + (BTN_SPACE>>1)) )
954         return clicked_timeline;
955
956     /* is time button clicked */
957     i_dest += (p_timeline->width + (BTN_SPACE>>1));
958     if( (i_xpos >= i_dest) &&
959         (i_xpos <= i_dest + p_btnTime->width + (BTN_SPACE>>1)) )
960         return clicked_Time;
961
962     return clicked_Unknown;
963 }
964 #undef BTN_SPACE
965 #endif