abock / moonshine

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

jstedfast (author)
Wed Sep 02 12:33:04 -0700 2009
Aaron Bockover (committer)
Wed Sep 02 12:53:06 -0700 2009
moonshine / plugin / mmp-binder.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
1e6efed1 » jstedfast 2009-09-02 Fixes to work with Moonligh... 10 #include <config.h>
11
d45d9491 » Aaron Bockover 2009-01-28 Override setproperty, in th... 12 #include <string.h>
13
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 14 #include "mmp-binder.h"
3d136168 » Aaron Bockover 2009-01-28 Finished the binder, and wr... 15 #include "mmp-script.h"
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 16 #include "mmp-resources.h"
17
bb7c4009 » Aaron Bockover 2009-02-09 Fixes to make the player wo... 18 #define MLMP_XAML_LOAD_FUNCTION "__MoonshineWmpPluginBindInstance"
b24b7d3d » Aaron Bockover 2009-02-09 Iterate the 'all' array to ... 19 #define MLMP_XAML_DOM_ID "__MoonshineEmptyFakeXamlTrickery"
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 20
3d136168 » Aaron Bockover 2009-01-28 Finished the binder, and wr... 21 typedef enum {
22 XAML_LOAD_ERROR = 0,
23 XAML_LOAD_SUCCESS = 1,
24 XAML_LOAD_ALREADY_LOADED = 2
25 } XamlLoadStatus;
26
27 static XamlLoadStatus
28 mmp_binder_load_player_xaml (MoonlightPluginInstance *plugin)
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 29 {
3d136168 » Aaron Bockover 2009-01-28 Finished the binder, and wr... 30 NPP npp = plugin->moz_instance;
31 NPObject *window = mmp_script_get_window (npp);
32 NPVariant document;
33 NPVariant script_element;
34 NPVariant xaml_node;
35 NPVariant body;
36 XamlLoadStatus xaml_loaded = XAML_LOAD_ERROR;
37
38 g_return_val_if_fail (npp != NULL, XAML_LOAD_ERROR);
39 g_return_val_if_fail (window != NULL, XAML_LOAD_ERROR);
40
41 // Load the document object
42 if (!mmp_script_get_document (npp, window, &document)) {
43 mp_error ("Unable to get document object via npruntime");
44 return XAML_LOAD_ERROR;
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 45 }
46
3d136168 » Aaron Bockover 2009-01-28 Finished the binder, and wr... 47 // Check to see if the XAML was already loaded into the DOM
48 if (mmp_script_document_get_element_by_id (npp, &document, MLMP_XAML_DOM_ID, &xaml_node)) {
49 NPN_ReleaseVariantValue (&xaml_node);
50 NPN_ReleaseVariantValue (&document);
51 return XAML_LOAD_ALREADY_LOADED;
52 }
53
54 // Create the XAML and add to the DOM (<script id='foo' type='text/xaml'>[xaml data]</script>)
55 if (mmp_script_document_create_element (npp, &document, "script", &script_element)) {
56 if (mmp_script_element_set_property_string (npp, &script_element, "id", MLMP_XAML_DOM_ID) &&
57 mmp_script_element_set_property_string (npp, &script_element, "type", "text/xaml") &&
1e6efed1 » jstedfast 2009-09-02 Fixes to work with Moonligh... 58 mmp_script_document_create_text_node (npp, &document, "<Canvas xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"/>", &xaml_node)) {
3d136168 » Aaron Bockover 2009-01-28 Finished the binder, and wr... 59
60 if (mmp_script_element_append_child (npp, &script_element, &xaml_node)) {
61 if (mmp_script_element_get_property_object (npp, &document, "body", &body)) {
62 if (mmp_script_element_append_child (npp, &body, &script_element)) {
63 xaml_loaded = XAML_LOAD_SUCCESS;
64 }
65
66 NPN_ReleaseVariantValue (&body);
67 }
68 }
69
70 NPN_ReleaseVariantValue (&xaml_node);
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 71 }
3d136168 » Aaron Bockover 2009-01-28 Finished the binder, and wr... 72
73 NPN_ReleaseVariantValue (&script_element);
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 74 }
75
3d136168 » Aaron Bockover 2009-01-28 Finished the binder, and wr... 76 NPN_ReleaseVariantValue (&document);
77 return xaml_loaded;
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 78 }
79
3d136168 » Aaron Bockover 2009-01-28 Finished the binder, and wr... 80 static void
81 mmp_binder_bind (MoonlightPluginInstance *plugin)
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 82 {
3d136168 » Aaron Bockover 2009-01-28 Finished the binder, and wr... 83 XamlLoadStatus status;
84
85 status = mmp_binder_load_player_xaml (plugin);
86
87 if (status == XAML_LOAD_ERROR) {
88 mp_error ("Unable to load player XAML into the DOM");
89 return;
90 } else if (status == XAML_LOAD_SUCCESS) {
91 // Only load the JS once, when the XAML is actually added to the DOM
b24b7d3d » Aaron Bockover 2009-02-09 Iterate the 'all' array to ... 92 gint i = 0;
93 for (; MLMP_RESOURCES_ALL[i]; i++) {
94 mmp_script_evaluate (plugin->moz_instance, MLMP_RESOURCES_ALL[i]);
95 }
3d136168 » Aaron Bockover 2009-01-28 Finished the binder, and wr... 96 }
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 97 }
98
3d136168 » Aaron Bockover 2009-01-28 Finished the binder, and wr... 99 NPError mmp_binder_npp_new (NPMIMEType pluginType, NPP instance, gushort mode,
100 gshort argc, gchar **argn, gchar **argv, NPSavedData *saved)
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 101 {
3d136168 » Aaron Bockover 2009-01-28 Finished the binder, and wr... 102 NPError result;
103 gchar **param_names;
104 gchar **param_values;
105 gint param_count = 0, i;
106 MoonlightPluginInstance *plugin;
107
108 mp_debug ("NPP_New");
109
1462a0e3 » Aaron Bockover 2009-01-30 Pass source as an NPP_New p... 110 // +2 to ensure space for onload and source
b49f550a » Aaron Bockover 2009-02-12 Tell moonlight to emit the ... 111 param_names = g_new0 (gchar *, argc + 3);
112 param_values = g_new0 (gchar *, argc + 3);
3d136168 » Aaron Bockover 2009-01-28 Finished the binder, and wr... 113
2d4ceb23 » Aaron Bockover 2009-01-29 Fix argument init 114 // We only preserve and proxy id, width, and height
3d136168 » Aaron Bockover 2009-01-28 Finished the binder, and wr... 115 for (i = 0; i < argc; i++) {
2d4ceb23 » Aaron Bockover 2009-01-29 Fix argument init 116 if (g_ascii_strncasecmp (argn[i], "id", 2) == 0 ||
117 g_ascii_strncasecmp (argn[i], "width", 5) == 0 ||
118 g_ascii_strncasecmp (argn[i], "height", 6) == 0) {
119 param_names[param_count] = g_strdup (argn[i]);
120 param_values[param_count] = g_strdup (argv[i]);
121 param_count++;
3d136168 » Aaron Bockover 2009-01-28 Finished the binder, and wr... 122 }
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 123 }
124
1462a0e3 » Aaron Bockover 2009-01-30 Pass source as an NPP_New p... 125 param_names[param_count] = g_strdup ("source");
126 param_values[param_count++] = g_strdup ( "#" MLMP_XAML_DOM_ID );
127
3d136168 » Aaron Bockover 2009-01-28 Finished the binder, and wr... 128 param_names[param_count] = g_strdup ("onload");
129 param_values[param_count++] = g_strdup (MLMP_XAML_LOAD_FUNCTION);
b49f550a » Aaron Bockover 2009-02-12 Tell moonlight to emit the ... 130
7d8f3483 » Aaron Bockover 2009-02-23 Use the new init flag 131 param_names[param_count] = g_strdup ("moonlight-relaxed-media-mode");
b49f550a » Aaron Bockover 2009-02-12 Tell moonlight to emit the ... 132 param_values[param_count++] = g_strdup ("true");
2d4ceb23 » Aaron Bockover 2009-01-29 Fix argument init 133
134 // Create an NPP wrapper and send the NPP_New to Moonlight
3d136168 » Aaron Bockover 2009-01-28 Finished the binder, and wr... 135 plugin = mmp_plugin_new (instance);
136 plugin->param_names = param_names;
137 plugin->param_values = param_values;
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 138
2d4ceb23 » Aaron Bockover 2009-01-29 Fix argument init 139 result = MMP_HANDLE ()->moon_npp_new ("application/x-silverlight", instance, mode,
140 param_count, param_names, param_values, saved);
141
3d136168 » Aaron Bockover 2009-01-28 Finished the binder, and wr... 142 if (result == NPERR_NO_ERROR) {
2d4ceb23 » Aaron Bockover 2009-01-29 Fix argument init 143 // Everything was okay, so bind XAML and JS to the plugin instance
3d136168 » Aaron Bockover 2009-01-28 Finished the binder, and wr... 144 mmp_binder_bind (plugin);
145 return NPERR_NO_ERROR;
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 146 }
147
3d136168 » Aaron Bockover 2009-01-28 Finished the binder, and wr... 148 mmp_plugin_free (plugin);
149
150 return result;
dcb3f10f » Aaron Bockover 2009-01-28 Lots of cleanup and refacto... 151 }
3d136168 » Aaron Bockover 2009-01-28 Finished the binder, and wr... 152
153 NPError
154 mmp_binder_npp_destroy (NPP instance, NPSavedData **save)
155 {
156 MoonlightPluginInstance *plugin;
157
158 mp_debug ("NPP_Destroy");
159
160 plugin = mmp_plugin_find_instance (instance);
161 if (plugin != NULL) {
162 mmp_plugin_free (plugin);
163 }
164
165 return MMP_HANDLE ()->moon_npp_destroy (instance, save);
166 }
167
dfbe809f » Aaron Bockover 2009-02-11 Major fix for codec downloa... 168 // This is the NPStream::notifyData type that Moonlight uses internally!
169
170 typedef enum {
171 STREAM_NOTIFY_NONE = 0,
172 STREAM_NOTIFY_SOURCE = 1,
173 STREAM_NOTIFY_DOWNLOADER = 2,
174 STREAM_NOTIFY_REQUEST = 3
175 } StreamNotifyFlags;
176
177 typedef struct {
178 StreamNotifyFlags type;
179 gpointer pdata;
180 } StreamNotify;
181
a2e11c52 » Aaron Bockover 2009-01-29 Override NPP_StreamAsFile t... 182 void
183 mmp_binder_npp_stream_as_file (NPP instance, NPStream *stream, const gchar *fname)
184 {
1462a0e3 » Aaron Bockover 2009-01-30 Pass source as an NPP_New p... 185 // Mozilla ends up calling this in some cases. It results in the file
186 // being loaded as XAML inside of Moonlight, which is very bad since
187 // it's going to be some kind of WM content.
188 //
189 // Observed cases where Mozilla does this:
190 //
191 // <embed src="..." />
192 // <object data="..." />
193 //
dfbe809f » Aaron Bockover 2009-02-11 Major fix for codec downloa... 194
195 if (stream && stream->notifyData && ((StreamNotify *)stream->notifyData)->type == STREAM_NOTIFY_DOWNLOADER) {
fa4218d4 » Aaron Bockover 2009-02-12 Call ReloadMediaSource on t... 196 gchar *basename = g_path_get_basename (stream->url);
197
dfbe809f » Aaron Bockover 2009-02-11 Major fix for codec downloa... 198 MMP_HANDLE ()->moon_npp_stream_as_file (instance, stream, fname);
fa4218d4 » Aaron Bockover 2009-02-12 Call ReloadMediaSource on t... 199
200 if (g_str_has_prefix (basename, "silverlight-media-pack") && g_str_has_suffix (basename, ".so")) {
201 NPObject *object = NULL;
202 NPVariant result;
203 NPIdentifier method = NPN_GetStringIdentifier ("ReloadMediaSource");
204
205 if (NPN_GetValue (instance, NPNVPluginElementNPObject, &object) == NPERR_NO_ERROR &&
206 NPN_Invoke (instance, object, method, NULL, 0, &result) == NPERR_NO_ERROR) {
207 mp_debug ("Silverlight Media Pack downloaded, reloading media");
208 }
209 }
210
211 g_free (basename);
dfbe809f » Aaron Bockover 2009-02-11 Major fix for codec downloa... 212 }
a2e11c52 » Aaron Bockover 2009-01-29 Override NPP_StreamAsFile t... 213 }
214