abock / moonshine
- Source
- Commits
- Network (0)
- Issues (0)
- Downloads (1)
- Wiki (1)
- Graphs
-
Branch:
master
Aaron Bockover (committer)
Wed Sep 02 12:53:06 -0700 2009
| 558c6c6c » | Aaron Bockover | 2009-02-09 | 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 | 10 | #include <string.h> | |
| f0a15111 » | Aaron Bockover | 2009-02-02 | 11 | #include <unistd.h> | |
| 08d00009 » | Aaron Bockover | 2009-01-30 | 12 | ||
| f82fef26 » | Aaron Bockover | 2009-02-10 | 13 | #include <config.h> | |
| 14 | |||||
| dcb3f10f » | Aaron Bockover | 2009-01-28 | 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 | 28 | // Special application type for this plugin | |
| ecec3876 » | Aaron Bockover | 2009-02-02 | 29 | { "application/x-moonshine-player", "*" }, | |
| 08d00009 » | Aaron Bockover | 2009-01-30 | 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 | 47 | }; | |
| 48 | |||||
| 08d00009 » | Aaron Bockover | 2009-01-30 | 49 | static gboolean moon_module_load_attempted = FALSE; | |
| 50 | |||||
| dcb3f10f » | Aaron Bockover | 2009-01-28 | 51 | static gboolean | |
| 52 | mmp_plugin_proxy_load_symbol (const gchar *symbol_name, gpointer *symbol) | ||||
| 53 | { | ||||
| 08d00009 » | Aaron Bockover | 2009-01-30 | 54 | MoonlightPlugin *plugin_host = MMP_HANDLE (); | |
| 55 | |||||
| 56 | if (!g_module_symbol (plugin_host->module, symbol_name, symbol)) { | ||||
| dcb3f10f » | Aaron Bockover | 2009-01-28 | 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 | 60 | g_module_close (plugin_host->module); | |
| 61 | plugin_host->module = NULL; | ||||
| dcb3f10f » | Aaron Bockover | 2009-01-28 | 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 | 72 | MoonlightPlugin *plugin_host = MMP_HANDLE (); | |
| dcb3f10f » | Aaron Bockover | 2009-01-28 | 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 | 76 | plugin_host->module = g_module_open (path, G_MODULE_BIND_LOCAL | G_MODULE_BIND_LAZY); | |
| dcb3f10f » | Aaron Bockover | 2009-01-28 | 77 | ||
| 08d00009 » | Aaron Bockover | 2009-01-30 | 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 | 82 | mp_debug ("Loaded Moonlight plugin: %s", path); | |
| 83 | g_free (path); | ||||
| 84 | return TRUE; | ||||
| 08d00009 » | Aaron Bockover | 2009-01-30 | 85 | } else if (plugin_host->module != NULL) { | |
| 86 | if (!g_module_close (plugin_host->module)) { | ||||
| dcb3f10f » | Aaron Bockover | 2009-01-28 | 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 | 90 | plugin_host->module = NULL; | |
| dcb3f10f » | Aaron Bockover | 2009-01-28 | 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 | 100 | static gchar * | |
| 101 | mmp_plugin_proxy_get_xpi_moonlight_path () | ||||
| 08d00009 » | Aaron Bockover | 2009-01-30 | 102 | { | |
| 6a782e26 » | Aaron Bockover | 2009-01-30 | 103 | // If Moonlight is installed by the user into their Firefox profile (XPI), | |
| f0a15111 » | Aaron Bockover | 2009-02-02 | 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 | 122 | ||
| f0a15111 » | Aaron Bockover | 2009-02-02 | 123 | if ((dir = g_dir_open (pid_path, 0, NULL)) == NULL) { | |
| 124 | return NULL; | ||||
| 6a782e26 » | Aaron Bockover | 2009-01-30 | 125 | } | |
| 126 | |||||
| f0a15111 » | Aaron Bockover | 2009-02-02 | 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 | 154 | } | |
| 155 | |||||
| f0a15111 » | Aaron Bockover | 2009-02-02 | 156 | g_dir_close (dir); | |
| 6a782e26 » | Aaron Bockover | 2009-01-30 | 157 | ||
| f0a15111 » | Aaron Bockover | 2009-02-02 | 158 | return xpi_dir; | |
| 08d00009 » | Aaron Bockover | 2009-01-30 | 159 | } | |
| 160 | |||||
| dcb3f10f » | Aaron Bockover | 2009-01-28 | 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 | 167 | NULL, | |
| efeea06d » | Aaron Bockover | 2009-03-26 | 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 | 171 | (gchar *)"/usr/local/lib64/moon/plugin", | |
| dcb3f10f » | Aaron Bockover | 2009-01-28 | 172 | (gchar *)INSTALL_PREFIX "/lib/moon/plugin", | |
| efeea06d » | Aaron Bockover | 2009-03-26 | 173 | (gchar *)INSTALL_PREFIX "/lib64/moon/plugin" | |
| dcb3f10f » | Aaron Bockover | 2009-01-28 | 174 | }; | |
| 175 | |||||
| 08d00009 » | Aaron Bockover | 2009-01-30 | 176 | MoonlightPlugin *plugin_host = MMP_HANDLE (); | |
| dcb3f10f » | Aaron Bockover | 2009-01-28 | 177 | guint i; | |
| 178 | |||||
| 08d00009 » | Aaron Bockover | 2009-01-30 | 179 | if (plugin_host->module != NULL) { | |
| dcb3f10f » | Aaron Bockover | 2009-01-28 | 180 | return NPERR_NO_ERROR; | |
| 08d00009 » | Aaron Bockover | 2009-01-30 | 181 | } else if (moon_module_load_attempted) { | |
| 182 | return NPERR_GENERIC_ERROR; | ||||
| dcb3f10f » | Aaron Bockover | 2009-01-28 | 183 | } | |
| 184 | |||||
| 185 | search_prefixes[0] = (gchar *)g_getenv ("MOON_LOADER_PATH"); | ||||
| f0a15111 » | Aaron Bockover | 2009-02-02 | 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 | 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 | 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 | 198 | moon_module_load_attempted = TRUE; | |
| dcb3f10f » | Aaron Bockover | 2009-01-28 | 199 | ||
| 08d00009 » | Aaron Bockover | 2009-01-30 | 200 | if (plugin_host->module == NULL) { | |
| f0a15111 » | Aaron Bockover | 2009-02-02 | 201 | mp_error ("Could not find Moonlight's libmoonloader plugin"); | |
| 202 | return NPERR_GENERIC_ERROR; | ||||
| 08d00009 » | Aaron Bockover | 2009-01-30 | 203 | } | |
| 204 | |||||
| 205 | return NPERR_NO_ERROR; | ||||
| dcb3f10f » | Aaron Bockover | 2009-01-28 | 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 | 213 | MoonlightPlugin *moon_host = MMP_HANDLE (); | |
| 214 | gsize mozilla_funcs_size; | ||||
| 215 | |||||
| dcb3f10f » | Aaron Bockover | 2009-01-28 | 216 | MOON_CHECK_LOAD_PLUGIN (); | |
| a94ba88c » | Aaron Bockover | 2009-01-29 | 217 | ||
| dcb3f10f » | Aaron Bockover | 2009-01-28 | 218 | mp_debug ("NP_Initialize (%p, %p)", mozilla_funcs, plugin_funcs); | |
| 219 | |||||
| a94ba88c » | Aaron Bockover | 2009-01-29 | 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 | 230 | if (MMP_HANDLE ()->np_initialize != NULL) { | |
| a94ba88c » | Aaron Bockover | 2009-01-29 | 231 | NPError result = MMP_HANDLE ()->np_initialize (&moon_host->mozilla_funcs, plugin_funcs); | |
| dcb3f10f » | Aaron Bockover | 2009-01-28 | 232 | if (result == NPERR_NO_ERROR) { | |
| 233 | // Override some Moonlight NPP functions | ||||
| d45d9491 » | Aaron Bockover | 2009-01-28 | 234 | moon_host->moon_npp_new = plugin_funcs->newp; | |
| 3d136168 » | Aaron Bockover | 2009-01-28 | 235 | plugin_funcs->newp = mmp_binder_npp_new; | |
| 236 | |||||
| d45d9491 » | Aaron Bockover | 2009-01-28 | 237 | moon_host->moon_npp_destroy = plugin_funcs->destroy; | |
| 3d136168 » | Aaron Bockover | 2009-01-28 | 238 | plugin_funcs->destroy = mmp_binder_npp_destroy; | |
| a2e11c52 » | Aaron Bockover | 2009-01-29 | 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 | 242 | } else { | |
| 243 | mp_error ("Unknown error in libmoonloader's NP_Initialize: %d", result); | ||||
| dcb3f10f » | Aaron Bockover | 2009-01-28 | 244 | } | |
| 245 | |||||
| 246 | return result; | ||||
| 247 | } | ||||
| 248 | |||||
| a4c56e11 » | Aaron Bockover | 2009-02-02 | 249 | mp_error ("Could not call NP_Initialize from libmoonloader (NULL)"); | |
| 250 | |||||
| dcb3f10f » | Aaron Bockover | 2009-01-28 | 251 | return NPERR_GENERIC_ERROR; | |
| 252 | } | ||||
| 253 | |||||
| 254 | NPError | ||||
| 255 | NP_Shutdown () | ||||
| 256 | { | ||||
| 08d00009 » | Aaron Bockover | 2009-01-30 | 257 | MoonlightPlugin *plugin_host = MMP_HANDLE (); | |
| 258 | |||||
| dcb3f10f » | Aaron Bockover | 2009-01-28 | 259 | mp_debug ("NP_Shutdown"); | |
| 260 | |||||
| 08d00009 » | Aaron Bockover | 2009-01-30 | 261 | if (plugin_host->np_shutdown != NULL) { | |
| 262 | plugin_host->np_shutdown (); | ||||
| dcb3f10f » | Aaron Bockover | 2009-01-28 | 263 | } | |
| 264 | |||||
| 08d00009 » | Aaron Bockover | 2009-01-30 | 265 | if (plugin_host->module != NULL) { | |
| 266 | g_module_close (plugin_host->module); | ||||
| dcb3f10f » | Aaron Bockover | 2009-01-28 | 267 | } | |
| 268 | |||||
| 08d00009 » | Aaron Bockover | 2009-01-30 | 269 | g_free (plugin_host->mime_description); | |
| 270 | memset (plugin_host, 0, sizeof (MoonlightPlugin)); | ||||
| dcb3f10f » | Aaron Bockover | 2009-01-28 | 271 | ||
| a4c56e11 » | Aaron Bockover | 2009-02-02 | 272 | moon_module_load_attempted = FALSE; | |
| 273 | |||||
| dcb3f10f » | Aaron Bockover | 2009-01-28 | 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 | 282 | *((gchar **)value) = (gchar *)"Windows Media Player Plug-in 10 (compatible; Moonshine Media Player)"; | |
| dcb3f10f » | Aaron Bockover | 2009-01-28 | 283 | return NPERR_NO_ERROR; | |
| 284 | case NPPVpluginDescriptionString: | ||||
| 09f5c50c » | Aaron Bockover | 2009-02-09 | 285 | *((gchar **)value) = (gchar *)"A media player powered by Moonlight, largely " | |
| dcb3f10f » | Aaron Bockover | 2009-01-28 | 286 | "compatible with the Windows Media Player ActiveX control."; | |
| 287 | return NPERR_NO_ERROR; | ||||
| 08d00009 » | Aaron Bockover | 2009-01-30 | 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 | 292 | } | |
| 293 | |||||
| 08d00009 » | Aaron Bockover | 2009-01-30 | 294 | return NPERR_INVALID_PARAM; | |
| 295 | } | ||||
| dcb3f10f » | Aaron Bockover | 2009-01-28 | 296 | } | |
| 297 | |||||
| 298 | g_assert_not_reached (); | ||||
| 299 | } | ||||
| 300 | |||||
| 301 | gchar * | ||||
| 302 | NP_GetMIMEDescription () | ||||
| 303 | { | ||||
| 08d00009 » | Aaron Bockover | 2009-01-30 | 304 | MoonlightPlugin *plugin_host = MMP_HANDLE (); | |
| dcb3f10f » | Aaron Bockover | 2009-01-28 | 305 | GString *str; | |
| 306 | guint i; | ||||
| 307 | |||||
| 08d00009 » | Aaron Bockover | 2009-01-30 | 308 | if (plugin_host->mime_description != NULL) { | |
| 309 | return plugin_host->mime_description; | ||||
| dcb3f10f » | Aaron Bockover | 2009-01-28 | 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 | 325 | g_string_append (str, ":Media Files"); | |
| dcb3f10f » | Aaron Bockover | 2009-01-28 | 326 | } | |
| 327 | |||||
| 08d00009 » | Aaron Bockover | 2009-01-30 | 328 | plugin_host->mime_description = str->str; | |
| dcb3f10f » | Aaron Bockover | 2009-01-28 | 329 | g_string_free (str, false); | |
| 330 | |||||
| 08d00009 » | Aaron Bockover | 2009-01-30 | 331 | return plugin_host->mime_description; | |
| dcb3f10f » | Aaron Bockover | 2009-01-28 | 332 | } | |
| 333 | |||||
