]> git.sesse.net Git - vlc/blob - mozilla/vlcplugin.cpp
vlcplugin.cpp: removed hardcoded path
[vlc] / mozilla / vlcplugin.cpp
1 /*****************************************************************************
2  * vlcplugin.cpp: a VLC plugin for Mozilla
3  *****************************************************************************
4  * Copyright (C) 2002-2005 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Samuel Hocevar <sam@zoy.org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include "config.h"
28
29 #ifdef HAVE_MOZILLA_CONFIG_H
30 #   include <mozilla-config.h>
31 #endif
32
33 #include "vlcplugin.h"
34 #include "control/npovlc.h"
35 #include "control/npolibvlc.h"
36
37 /*****************************************************************************
38  * VlcPlugin constructor and destructor
39  *****************************************************************************/
40 VlcPlugin::VlcPlugin( NPP instance, uint16 mode ) :
41     i_npmode(mode),
42     b_stream(0),
43     b_autoplay(0),
44     psz_target(NULL),
45     libvlc_instance(NULL),
46     scriptClass(NULL),
47     p_browser(instance),
48     psz_baseURL(NULL)
49 #if XP_WIN
50     ,pf_wndproc(NULL)
51 #endif
52 #if XP_UNIX
53     ,i_width((unsigned)-1)
54     ,i_height((unsigned)-1)
55 #endif
56 {
57     memset(&npwindow, 0, sizeof(NPWindow));
58 }
59
60 static int boolValue(const char *value) {
61     return ( !strcmp(value, "1") || 
62              !strcasecmp(value, "true") ||
63              !strcasecmp(value, "yes") );
64 }
65
66 NPError VlcPlugin::init(int argc, char* const argn[], char* const argv[])
67 {
68     /* prepare VLC command line */
69     char *ppsz_argv[32] =
70     {
71         "vlc",
72         "-vv",
73         "--no-stats",
74         "--intf", "dummy",
75     };
76     int ppsz_argc = 5;
77
78     /* locate VLC module path */
79 #ifdef XP_MACOSX
80     ppsz_argv[ppsz_argc++] = "--plugin-path";
81     ppsz_argv[ppsz_argc++] = "/Library/Internet Plug-Ins/VLC Plugin.plugin/"
82                              "Contents/MacOS/modules";
83 #elif defined(XP_WIN)
84     HKEY h_key;
85     DWORD i_type, i_data = MAX_PATH + 1;
86     char p_data[MAX_PATH + 1];
87     if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, "Software\\VideoLAN\\VLC",
88                       0, KEY_READ, &h_key ) == ERROR_SUCCESS )
89     {
90          if( RegQueryValueEx( h_key, "InstallDir", 0, &i_type,
91                               (LPBYTE)p_data, &i_data ) == ERROR_SUCCESS )
92          {
93              if( i_type == REG_SZ )
94              {
95                  strcat( p_data, "\\vlc" );
96                  ppsz_argv[0] = p_data;
97              }
98          }
99          RegCloseKey( h_key );
100     }
101     ppsz_argv[ppsz_argc++] = "--no-one-instance";
102
103 #endif /* XP_MACOSX */
104
105     const char *version = NULL;
106
107     /* parse plugin arguments */
108     for( int i = 0; i < argc ; i++ )
109     {
110         fprintf(stderr, "argn=%s, argv=%s\n", argn[i], argv[i]);
111
112         if( !strcmp( argn[i], "target" )
113          || !strcmp( argn[i], "mrl")
114          || !strcmp( argn[i], "filename")
115          || !strcmp( argn[i], "src") )
116         {
117             psz_target = argv[i];
118         }
119         else if( !strcmp( argn[i], "autoplay")
120               || !strcmp( argn[i], "autostart") )
121         {
122             b_autoplay = boolValue(argv[i]);
123         }
124         else if( !strcmp( argn[i], "fullscreen" ) )
125         {
126             if( boolValue(argv[i]) )
127             {
128                 ppsz_argv[ppsz_argc++] = "--fullscreen";
129             }
130             else
131             {
132                 ppsz_argv[ppsz_argc++] = "--no-fullscreen";
133             }
134         }
135         else if( !strcmp( argn[i], "mute" ) )
136         {
137             if( boolValue(argv[i]) )
138             {
139                 ppsz_argv[ppsz_argc++] = "--volume";
140                 ppsz_argv[ppsz_argc++] = "0";
141             }
142         }
143         else if( !strcmp( argn[i], "loop")
144               || !strcmp( argn[i], "autoloop") )
145         {
146             if( boolValue(argv[i]) )
147             {
148                 ppsz_argv[ppsz_argc++] = "--loop";
149             }
150             else {
151                 ppsz_argv[ppsz_argc++] = "--no-loop";
152             }
153         }
154         else if( !strcmp( argn[i], "version") )
155         {
156             version = argv[i];
157         }
158     }
159
160     libvlc_instance = libvlc_new(ppsz_argc, ppsz_argv, NULL);
161     if( ! libvlc_instance )
162     {
163         return NPERR_GENERIC_ERROR;
164     }
165
166     /*
167     ** fetch plugin base URL, which is the URL of the page containing the plugin
168     ** this URL is used for making absolute URL from relative URL that may be
169     ** passed as an MRL argument
170     */
171     NPObject *plugin;
172
173     if( NPERR_NO_ERROR == NPN_GetValue(p_browser, NPNVWindowNPObject, &plugin) )
174     {
175         /*
176         ** is there a better way to get that info ?
177         */
178         static const char docLocHref[] = "document.location.href";
179         NPString script;
180         NPVariant result;
181
182         script.utf8characters = docLocHref;
183         script.utf8length = sizeof(docLocHref)-1;
184
185         if( NPN_Evaluate(p_browser, plugin, &script, &result) )
186         {
187             if( NPVARIANT_IS_STRING(result) )
188             {
189                 NPString &location = NPVARIANT_TO_STRING(result);
190
191                 psz_baseURL = new char[location.utf8length+1];
192                 if( psz_baseURL )
193                 {
194                     strncpy(psz_baseURL, location.utf8characters, location.utf8length);
195                     psz_baseURL[location.utf8length] = '\0';
196                 }
197             }
198             NPN_ReleaseVariantValue(&result);
199         }
200         NPN_ReleaseObject(plugin);
201     }
202
203     if( psz_target )
204     {
205         // get absolute URL from src
206         psz_target = getAbsoluteURL(psz_target);
207     }
208
209     /* assign plugin script root class */
210     if( (NULL != version) && (!strcmp(version, "VideoLAN.VLCPlugin.2")) )
211     {
212         /* new APIs */
213         scriptClass = new RuntimeNPClass<LibvlcRootNPObject>();
214     }
215     else
216     {
217         /* legacy APIs */
218         scriptClass = new RuntimeNPClass<VlcNPObject>();
219     }
220
221     return NPERR_NO_ERROR;
222 }
223
224 #if 0
225 #ifdef XP_WIN
226 /* This is really ugly but there is a deadlock when stopping a stream
227  * (in VLC_CleanUp()) because the video output is a child of the drawable but
228  * is in a different thread. */
229 static void HackStopVout( VlcPlugin* p_plugin )
230 {
231     MSG msg;
232     HWND hwnd;
233     vlc_value_t value;
234
235     int i_vlc = libvlc_get_vlc_id(p_plugin->libvlc_instance);
236     VLC_VariableGet( i_vlc, "drawable", &value );
237
238     hwnd = FindWindowEx( (HWND)value.i_int, 0, 0, 0 );
239     if( !hwnd ) return;
240
241     PostMessage( hwnd, WM_CLOSE, 0, 0 );
242
243     do
244     {
245         while( PeekMessage( &msg, (HWND)value.i_int, 0, 0, PM_REMOVE ) )
246         {
247             TranslateMessage(&msg);
248             DispatchMessage(&msg);
249         }
250         if( FindWindowEx( (HWND)value.i_int, 0, 0, 0 ) ) Sleep( 10 );
251     }
252     while( (hwnd = FindWindowEx( (HWND)value.i_int, 0, 0, 0 )) );
253 }
254 #endif /* XP_WIN */
255 #endif
256
257 VlcPlugin::~VlcPlugin()
258 {
259     delete psz_baseURL;
260     delete psz_target;
261     if( libvlc_instance )
262         libvlc_destroy(libvlc_instance);
263 }
264
265 /*****************************************************************************
266  * VlcPlugin methods
267  *****************************************************************************/
268
269 char *VlcPlugin::getAbsoluteURL(const char *url)
270 {
271     if( NULL != url )
272     {
273         // check whether URL is already absolute
274         const char *end=strchr(url, ':');
275         if( (NULL != end) && (end != url) )
276         {
277             // validate protocol header
278             const char *start = url;
279             while( start != end ) {
280                 char c = *start | 0x20;
281                 if( (c < 'a') || (c > 'z') )
282                     // not valid protocol header, assume relative URL
283                     break;
284                 ++start;
285             }
286             /* we have a protocol header, therefore URL is absolute */
287             return strdup(url);
288         }
289
290         if( psz_baseURL )
291         {
292             size_t baseLen = strlen(psz_baseURL);
293             char *href = new char[baseLen+strlen(url)];
294             if( href )
295             {
296                 /* prepend base URL */
297                 strcpy(href, psz_baseURL);
298
299                 /*
300                 ** relative url could be empty,
301                 ** in which case return base URL
302                 */
303                 if( '\0' == *url )
304                     return href;
305
306                 /*
307                 ** locate pathname part of base URL
308                 */
309
310                 /* skip over protocol part  */
311                 char *pathstart = strchr(href, ':');
312                 char *pathend;
313                 if( '/' == *(++pathstart) )
314                 {
315                     if( '/' == *(++pathstart) )
316                     {
317                         ++pathstart;
318                     }
319                 }
320                 /* skip over host part */
321                 pathstart = strchr(pathstart, '/');
322                 pathend = href+baseLen;
323                 if( ! pathstart )
324                 {
325                     // no path, add a / past end of url (over '\0')
326                     pathstart = pathend;
327                     *pathstart = '/';
328                 }
329
330                 /* relative URL made of an absolute path ? */
331                 if( '/' == *url )
332                 {
333                     /* replace path completely */
334                     strcpy(pathstart, url);
335                     return href;
336                 }
337
338                 /* find last path component and replace it */ 
339                 while( '/' != *pathend) --pathend;
340
341                 /*
342                 ** if relative url path starts with one or more '../',
343                 ** factor them out of href so that we return a
344                 ** normalized URL
345                 */
346                 while( pathend != pathstart )
347                 {
348                     const char *p = url;
349                     if( '.' != *p )
350                         break;
351                     ++p;
352                     if( '.' != *p ) 
353                         break;
354                     ++p;
355                     if( '/' != *p ) 
356                         break;
357                     ++p;
358                     url = p;
359                     while( '/' != *pathend ) --pathend;
360                 }
361                 /* concatenate remaining base URL and relative URL */
362                 strcpy(pathend+1, url);
363             }
364             return href;
365         }
366     }
367     return NULL;
368 }
369
370 #if XP_UNIX
371 int  VlcPlugin::setSize(unsigned width, unsigned height)
372 {
373     int diff = (width != i_width) || (height != i_height);
374
375     i_width = width;
376     i_height = height;
377
378     /* return size */
379     return diff;
380 }
381 #endif
382