abock / moonshine

An embedded media player plugin for Firefox that leverages Moonlight to provide native Windows Media support for Linux.

This URL has Read+Write access

jstedfast (author)
Wed Sep 02 12:33:04 -0700 2009
Aaron Bockover (committer)
Wed Sep 02 12:53:06 -0700 2009
moonshine / plugin / mmp-plugin-proxy.c
558c6c6c » Aaron Bockover 2009-02-09 Added license headers 1 //
2 // This file is licensed under the MIT X11 open source license.
3 // http://www.opensource.org/licenses/mit-license.php
4 //
5 // Authors: Aaron Bockover <abockover@novell.com>
6 //
7 // Copyright 2009 Novell, Inc.
8 //
9
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 10 #include <string.h>
f0a15111 » Aaron Bockover 2009-02-02 Removed the XPCOM implement... 11 #include <unistd.h>
08d00009 » Aaron Bockover 2009-01-30 Fixes, cleanups, and a firs... 12
f82fef26 » Aaron Bockover 2009-02-10 Build fixes, and added XPI ... 13 #include <config.h>
14
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 15 #include "mmp-plugin.h"
16 #include "mmp-binder.h"
17
18 #define MOON_CHECK_LOAD_PLUGIN() { \
19 if (G_UNLIKELY (MMP_HANDLE ()->module == NULL)) { \
20 mmp_plugin_proxy_load_moonlight (); \
21 } \
22 }
23
24 static struct {
25 const gchar *mime_type;
26 const gchar *extensions;
27 } mmp_plugin_proxy_mime_types [] = {
08d00009 » Aaron Bockover 2009-01-30 Fixes, cleanups, and a firs... 28 // Special application type for this plugin
ecec3876 » Aaron Bockover 2009-02-02 More build fixes, renamed t... 29 { "application/x-moonshine-player", "*" },
08d00009 » Aaron Bockover 2009-01-30 Fixes, cleanups, and a firs... 30
31 // Generic/WMP types?
32 { "application/x-mplayer2", "*" },
33 { "application/x-ms-wms", "*" },
34 { "application/x-ms-wmp", "*" },
35 { "application/asx", "*" },
36 { "video/x-ms-asf-plugin", "*" },
37 { "video/x-msvideo", "*" },
38 { "video/x-ms-wmp", "*" },
39
40 // Actual WM types?
41 { "video/x-ms-asf", "asf,asx,*" },
42 { "video/x-ms-wm", "wm,*" },
43 { "video/x-ms-wmv", "wmv,*" },
44 { "video/x-ms-wvx", "wvx,*" },
45 { "audio/x-ms-wma", "wma,*" },
46 { "audio/x-ms-wax", "wax,*" },
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 47 };
48
08d00009 » Aaron Bockover 2009-01-30 Fixes, cleanups, and a firs... 49 static gboolean moon_module_load_attempted = FALSE;
50
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 51 static gboolean
52 mmp_plugin_proxy_load_symbol (const gchar *symbol_name, gpointer *symbol)
53 {
08d00009 » Aaron Bockover 2009-01-30 Fixes, cleanups, and a firs... 54 MoonlightPlugin *plugin_host = MMP_HANDLE ();
55
56 if (!g_module_symbol (plugin_host->module, symbol_name, symbol)) {
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 57 mp_error ("Could not locate '%s' symbol in Moonlight plugin (%s)",
58 symbol_name, g_module_error ());
59
08d00009 » Aaron Bockover 2009-01-30 Fixes, cleanups, and a firs... 60 g_module_close (plugin_host->module);
61 plugin_host->module = NULL;
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 62
63 return FALSE;
64 }
65
66 return TRUE;
67 }
68
69 static gboolean
70 mmp_plugin_proxy_load_module (gchar *prefix)
71 {
08d00009 » Aaron Bockover 2009-01-30 Fixes, cleanups, and a firs... 72 MoonlightPlugin *plugin_host = MMP_HANDLE ();
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 73 gchar *path = g_module_build_path (prefix, "moonloader");
74
75 if (g_file_test (path, G_FILE_TEST_EXISTS)) {
1e6efed1 » jstedfast 2009-09-02 Fixes to work with Moonligh... 76 plugin_host->module = g_module_open (path, G_MODULE_BIND_LOCAL | G_MODULE_BIND_LAZY);
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 77
08d00009 » Aaron Bockover 2009-01-30 Fixes, cleanups, and a firs... 78 if (plugin_host->module != NULL
79 && mmp_plugin_proxy_load_symbol ("NP_Initialize", (gpointer *)&plugin_host->np_initialize)
80 && mmp_plugin_proxy_load_symbol ("NP_Shutdown", (gpointer *)&plugin_host->np_shutdown)
81 && mmp_plugin_proxy_load_symbol ("NP_GetValue", (gpointer *)&plugin_host->np_getvalue)) {
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 82 mp_debug ("Loaded Moonlight plugin: %s", path);
83 g_free (path);
84 return TRUE;
08d00009 » Aaron Bockover 2009-01-30 Fixes, cleanups, and a firs... 85 } else if (plugin_host->module != NULL) {
86 if (!g_module_close (plugin_host->module)) {
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 87 mp_error ("Could not unload library that was loaded but had invalid symbols: %s (%s)",
88 path, g_module_error ());
89 }
08d00009 » Aaron Bockover 2009-01-30 Fixes, cleanups, and a firs... 90 plugin_host->module = NULL;
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 91 }
92
93 mp_error ("Could not load Moonlight plugin: %s (%s)", path, g_module_error ());
94 }
95
96 g_free (path);
97 return FALSE;
98 }
99
f0a15111 » Aaron Bockover 2009-02-02 Removed the XPCOM implement... 100 static gchar *
101 mmp_plugin_proxy_get_xpi_moonlight_path ()
08d00009 » Aaron Bockover 2009-01-30 Fixes, cleanups, and a firs... 102 {
6a782e26 » Aaron Bockover 2009-01-30 Support loading libmoonload... 103 // If Moonlight is installed by the user into their Firefox profile (XPI),
f0a15111 » Aaron Bockover 2009-02-02 Removed the XPCOM implement... 104 // we need to find the directory. Originally I used XPCOM and the directory
105 // service provided by Mozilla, but I really wanted to avoid libstdc++
106 // and linking against libxpcom, etc.
107 //
108 // Instead I use an lsof inspired hack to look for the profile directory
109 // of the running process.
110 //
111
112 gchar pid_path[32];
113 gchar fd_path[sizeof (pid_path) * 2];
114 const gchar *fd_name = NULL;
115 gchar *xpi_dir = NULL;
116 GDir *dir;
117
118 if ((gsize)g_snprintf (pid_path, sizeof (pid_path),
119 "/proc/%d/fd", getpid ()) > sizeof (pid_path)) {
120 return NULL;
121 }
6a782e26 » Aaron Bockover 2009-01-30 Support loading libmoonload... 122
f0a15111 » Aaron Bockover 2009-02-02 Removed the XPCOM implement... 123 if ((dir = g_dir_open (pid_path, 0, NULL)) == NULL) {
124 return NULL;
6a782e26 » Aaron Bockover 2009-01-30 Support loading libmoonload... 125 }
126
f0a15111 » Aaron Bockover 2009-02-02 Removed the XPCOM implement... 127 while (xpi_dir == NULL && (fd_name = g_dir_read_name (dir)) != NULL) {
128 gchar *fd_resolved_path;
129 gchar *file_name;
130 gchar *dir_name;
131 gint ext_offset;
132
133 if ((gsize)g_snprintf (fd_path, sizeof (fd_path),
134 "%s/%s", pid_path, fd_name) > sizeof (fd_path) ||
135 (fd_resolved_path = g_file_read_link (fd_path, NULL)) == NULL) {
136 continue;
137 }
138
139 file_name = g_path_get_basename (fd_resolved_path);
140 ext_offset = strlen (file_name) - strlen (".sqlite");
141 if (strcmp (file_name, ".parentlock") == 0
142 || (ext_offset > 0 && strcmp (file_name + ext_offset, ".sqlite") == 0)) {
143 dir_name = g_path_get_dirname (fd_resolved_path);
144 xpi_dir = g_build_filename (dir_name,
145 "extensions",
146 "moonlight@novell.com",
147 "plugins",
148 NULL);
149 g_free (dir_name);
150 }
151
152 g_free (file_name);
153 g_free (fd_resolved_path);
6a782e26 » Aaron Bockover 2009-01-30 Support loading libmoonload... 154 }
155
f0a15111 » Aaron Bockover 2009-02-02 Removed the XPCOM implement... 156 g_dir_close (dir);
6a782e26 » Aaron Bockover 2009-01-30 Support loading libmoonload... 157
f0a15111 » Aaron Bockover 2009-02-02 Removed the XPCOM implement... 158 return xpi_dir;
08d00009 » Aaron Bockover 2009-01-30 Fixes, cleanups, and a firs... 159 }
160
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 161 static NPError
162 mmp_plugin_proxy_load_moonlight ()
163 {
164 static gchar *search_prefixes [] = {
165 NULL,
166 NULL,
f0a15111 » Aaron Bockover 2009-02-02 Removed the XPCOM implement... 167 NULL,
efeea06d » Aaron Bockover 2009-03-26 Add hard-coded /usr and /us... 168 (gchar *)"/usr/lib/moon/plugin",
169 (gchar *)"/usr/lib64/moon/plugin",
170 (gchar *)"/usr/local/lib/moon/plugin",
fae48135 » Aaron Bockover 2009-03-26 Fix typo 171 (gchar *)"/usr/local/lib64/moon/plugin",
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 172 (gchar *)INSTALL_PREFIX "/lib/moon/plugin",
efeea06d » Aaron Bockover 2009-03-26 Add hard-coded /usr and /us... 173 (gchar *)INSTALL_PREFIX "/lib64/moon/plugin"
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 174 };
175
08d00009 » Aaron Bockover 2009-01-30 Fixes, cleanups, and a firs... 176 MoonlightPlugin *plugin_host = MMP_HANDLE ();
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 177 guint i;
178
08d00009 » Aaron Bockover 2009-01-30 Fixes, cleanups, and a firs... 179 if (plugin_host->module != NULL) {
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 180 return NPERR_NO_ERROR;
08d00009 » Aaron Bockover 2009-01-30 Fixes, cleanups, and a firs... 181 } else if (moon_module_load_attempted) {
182 return NPERR_GENERIC_ERROR;
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 183 }
184
185 search_prefixes[0] = (gchar *)g_getenv ("MOON_LOADER_PATH");
f0a15111 » Aaron Bockover 2009-02-02 Removed the XPCOM implement... 186 search_prefixes[1] = mmp_plugin_proxy_get_xpi_moonlight_path ();
187 search_prefixes[2] = g_build_filename (g_get_home_dir (), ".mozilla", "plugins", NULL);
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 188
189 for (i = 0; i < G_N_ELEMENTS (search_prefixes)
190 && !mmp_plugin_proxy_load_module (search_prefixes[i]); i++);
191
f0a15111 » Aaron Bockover 2009-02-02 Removed the XPCOM implement... 192 if (search_prefixes[1] != NULL) {
193 g_free (search_prefixes[1]);
194 }
195
196 g_free (search_prefixes[2]);
197
08d00009 » Aaron Bockover 2009-01-30 Fixes, cleanups, and a firs... 198 moon_module_load_attempted = TRUE;
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 199
08d00009 » Aaron Bockover 2009-01-30 Fixes, cleanups, and a firs... 200 if (plugin_host->module == NULL) {
f0a15111 » Aaron Bockover 2009-02-02 Removed the XPCOM implement... 201 mp_error ("Could not find Moonlight's libmoonloader plugin");
202 return NPERR_GENERIC_ERROR;
08d00009 » Aaron Bockover 2009-01-30 Fixes, cleanups, and a firs... 203 }
204
205 return NPERR_NO_ERROR;
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 206 }
207
208 // Mozilla Plugin Entry Points
209
210 NPError
211 NP_Initialize (NPNetscapeFuncs *mozilla_funcs, NPPluginFuncs *plugin_funcs)
212 {
a94ba88c » Aaron Bockover 2009-01-29 Small fixes, player is work... 213 MoonlightPlugin *moon_host = MMP_HANDLE ();
214 gsize mozilla_funcs_size;
215
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 216 MOON_CHECK_LOAD_PLUGIN ();
a94ba88c » Aaron Bockover 2009-01-29 Small fixes, player is work... 217
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 218 mp_debug ("NP_Initialize (%p, %p)", mozilla_funcs, plugin_funcs);
219
a94ba88c » Aaron Bockover 2009-01-29 Small fixes, player is work... 220 // Copy the Mozilla function table
221 mozilla_funcs_size = sizeof (NPNetscapeFuncs);
222 memset (&moon_host->mozilla_funcs, 0, mozilla_funcs_size);
223 mozilla_funcs_size = mozilla_funcs->size < mozilla_funcs_size
224 ? mozilla_funcs->size
225 : mozilla_funcs_size;
226 memcpy (&moon_host->mozilla_funcs, mozilla_funcs, mozilla_funcs_size);
227 moon_host->mozilla_funcs.size = sizeof (moon_host->mozilla_funcs);
228
229 // Proxy NP_Initialize to Moonlight
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 230 if (MMP_HANDLE ()->np_initialize != NULL) {
a94ba88c » Aaron Bockover 2009-01-29 Small fixes, player is work... 231 NPError result = MMP_HANDLE ()->np_initialize (&moon_host->mozilla_funcs, plugin_funcs);
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 232 if (result == NPERR_NO_ERROR) {
233 // Override some Moonlight NPP functions
d45d9491 » Aaron Bockover 2009-01-28 Override setproperty, in th... 234 moon_host->moon_npp_new = plugin_funcs->newp;
3d136168 » Aaron Bockover 2009-01-28 Finished the binder, and wr... 235 plugin_funcs->newp = mmp_binder_npp_new;
236
d45d9491 » Aaron Bockover 2009-01-28 Override setproperty, in th... 237 moon_host->moon_npp_destroy = plugin_funcs->destroy;
3d136168 » Aaron Bockover 2009-01-28 Finished the binder, and wr... 238 plugin_funcs->destroy = mmp_binder_npp_destroy;
a2e11c52 » Aaron Bockover 2009-01-29 Override NPP_StreamAsFile t... 239
240 moon_host->moon_npp_stream_as_file = plugin_funcs->asfile;
241 plugin_funcs->asfile = mmp_binder_npp_stream_as_file;
a4c56e11 » Aaron Bockover 2009-02-02 Fixed the reload issue so t... 242 } else {
243 mp_error ("Unknown error in libmoonloader's NP_Initialize: %d", result);
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 244 }
245
246 return result;
247 }
248
a4c56e11 » Aaron Bockover 2009-02-02 Fixed the reload issue so t... 249 mp_error ("Could not call NP_Initialize from libmoonloader (NULL)");
250
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 251 return NPERR_GENERIC_ERROR;
252 }
253
254 NPError
255 NP_Shutdown ()
256 {
08d00009 » Aaron Bockover 2009-01-30 Fixes, cleanups, and a firs... 257 MoonlightPlugin *plugin_host = MMP_HANDLE ();
258
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 259 mp_debug ("NP_Shutdown");
260
08d00009 » Aaron Bockover 2009-01-30 Fixes, cleanups, and a firs... 261 if (plugin_host->np_shutdown != NULL) {
262 plugin_host->np_shutdown ();
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 263 }
264
08d00009 » Aaron Bockover 2009-01-30 Fixes, cleanups, and a firs... 265 if (plugin_host->module != NULL) {
266 g_module_close (plugin_host->module);
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 267 }
268
08d00009 » Aaron Bockover 2009-01-30 Fixes, cleanups, and a firs... 269 g_free (plugin_host->mime_description);
270 memset (plugin_host, 0, sizeof (MoonlightPlugin));
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 271
a4c56e11 » Aaron Bockover 2009-02-02 Fixed the reload issue so t... 272 moon_module_load_attempted = FALSE;
273
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 274 return NPERR_NO_ERROR;
275 }
276
277 NPError
278 NP_GetValue (gpointer future, NPPVariable variable, gpointer value)
279 {
280 switch (variable) {
281 case NPPVpluginNameString:
ecec3876 » Aaron Bockover 2009-02-02 More build fixes, renamed t... 282 *((gchar **)value) = (gchar *)"Windows Media Player Plug-in 10 (compatible; Moonshine Media Player)";
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 283 return NPERR_NO_ERROR;
284 case NPPVpluginDescriptionString:
09f5c50c » Aaron Bockover 2009-02-09 Removed link in description 285 *((gchar **)value) = (gchar *)"A media player powered by Moonlight, largely "
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 286 "compatible with the Windows Media Player ActiveX control.";
287 return NPERR_NO_ERROR;
08d00009 » Aaron Bockover 2009-01-30 Fixes, cleanups, and a firs... 288 default: {
289 MoonlightPlugin *plugin_host = MMP_HANDLE ();
290 if (plugin_host->np_getvalue != NULL) {
291 return plugin_host->np_getvalue (future, variable, value);
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 292 }
293
08d00009 » Aaron Bockover 2009-01-30 Fixes, cleanups, and a firs... 294 return NPERR_INVALID_PARAM;
295 }
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 296 }
297
298 g_assert_not_reached ();
299 }
300
301 gchar *
302 NP_GetMIMEDescription ()
303 {
08d00009 » Aaron Bockover 2009-01-30 Fixes, cleanups, and a firs... 304 MoonlightPlugin *plugin_host = MMP_HANDLE ();
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 305 GString *str;
306 guint i;
307
08d00009 » Aaron Bockover 2009-01-30 Fixes, cleanups, and a firs... 308 if (plugin_host->mime_description != NULL) {
309 return plugin_host->mime_description;
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 310 }
311
312 str = g_string_new ("");
313 for (i = 0; i < G_N_ELEMENTS (mmp_plugin_proxy_mime_types); i++) {
314 if (i > 0) {
315 g_string_append_c (str, ';');
316 }
317
318 g_string_append (str, mmp_plugin_proxy_mime_types[i].mime_type);
319 g_string_append_c (str, ':');
320
321 if (mmp_plugin_proxy_mime_types[i].extensions) {
322 g_string_append (str, mmp_plugin_proxy_mime_types[i].extensions);
323 }
324
08d00009 » Aaron Bockover 2009-01-30 Fixes, cleanups, and a firs... 325 g_string_append (str, ":Media Files");
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 326 }
327
08d00009 » Aaron Bockover 2009-01-30 Fixes, cleanups, and a firs... 328 plugin_host->mime_description = str->str;
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 329 g_string_free (str, false);
330
08d00009 » Aaron Bockover 2009-01-30 Fixes, cleanups, and a firs... 331 return plugin_host->mime_description;
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 332 }
333