aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/media_plugins/webkit
diff options
context:
space:
mode:
authorArmin Weatherwax2010-06-14 16:27:25 +0200
committerArmin Weatherwax2010-09-23 15:42:38 +0200
commit3069d8886241b2d9deaadfbf8823d463b469ec6b (patch)
treee70aeae85d110d66a7c048a0132085e0301ab068 /linden/indra/media_plugins/webkit
parentmake it compile and run. (diff)
downloadmeta-impy-3069d8886241b2d9deaadfbf8823d463b469ec6b.zip
meta-impy-3069d8886241b2d9deaadfbf8823d463b469ec6b.tar.gz
meta-impy-3069d8886241b2d9deaadfbf8823d463b469ec6b.tar.bz2
meta-impy-3069d8886241b2d9deaadfbf8823d463b469ec6b.tar.xz
update to latest SG2 media_plugins
Diffstat (limited to 'linden/indra/media_plugins/webkit')
-rw-r--r--linden/indra/media_plugins/webkit/CMakeLists.txt10
-rwxr-xr-xlinden/indra/media_plugins/webkit/linux_volume_catcher.cpp490
-rwxr-xr-xlinden/indra/media_plugins/webkit/linux_volume_catcher.h56
-rwxr-xr-xlinden/indra/media_plugins/webkit/linux_volume_catcher_pa_syms.inc21
-rwxr-xr-xlinden/indra/media_plugins/webkit/linux_volume_catcher_paglib_syms.inc6
-rwxr-xr-xlinden/indra/media_plugins/webkit/media_plugin_webkit.cpp352
6 files changed, 821 insertions, 114 deletions
diff --git a/linden/indra/media_plugins/webkit/CMakeLists.txt b/linden/indra/media_plugins/webkit/CMakeLists.txt
index 1c999ba..be02781 100644
--- a/linden/indra/media_plugins/webkit/CMakeLists.txt
+++ b/linden/indra/media_plugins/webkit/CMakeLists.txt
@@ -14,10 +14,12 @@ include(Linking)
14include(PluginAPI) 14include(PluginAPI)
15include(MediaPluginBase) 15include(MediaPluginBase)
16include(FindOpenGL) 16include(FindOpenGL)
17#include(PulseAudio)
17 18
18include(WebKitLibPlugin) 19include(WebKitLibPlugin)
19 20
20include_directories( 21include_directories(
22 ${PULSEAUDIO_INCLUDE_DIRS}
21 ${LLPLUGIN_INCLUDE_DIRS} 23 ${LLPLUGIN_INCLUDE_DIRS}
22 ${MEDIA_PLUGIN_BASE_INCLUDE_DIRS} 24 ${MEDIA_PLUGIN_BASE_INCLUDE_DIRS}
23 ${LLCOMMON_INCLUDE_DIRS} 25 ${LLCOMMON_INCLUDE_DIRS}
@@ -35,13 +37,13 @@ set(media_plugin_webkit_SOURCE_FILES
35 media_plugin_webkit.cpp 37 media_plugin_webkit.cpp
36 ) 38 )
37 39
38if(WORD_SIZE EQUAL 64) 40if(NOT CMAKE_SIZEOF_VOID_P MATCHES 4)
39 if(WINDOWS) 41 if(WINDOWS)
40 add_definitions(/FIXED:NO) 42 add_definitions(/FIXED:NO)
41 else(WINDOWS) # not windows therefore gcc LINUX and DARWIN 43 else(WINDOWS) # not windows therefore gcc LINUX and DARWIN
42 add_definitions(-fPIC) 44 add_definitions(-fPIC)
43 endif(WINDOWS) 45 endif(WINDOWS)
44endif (WORD_SIZE EQUAL 64) 46endif (NOT CMAKE_SIZEOF_VOID_P MATCHES 4)
45 47
46set(media_plugin_webkit_LINK_LIBRARIES 48set(media_plugin_webkit_LINK_LIBRARIES
47 ${LLPLUGIN_LIBRARIES} 49 ${LLPLUGIN_LIBRARIES}
@@ -49,9 +51,11 @@ set(media_plugin_webkit_LINK_LIBRARIES
49 ${LLCOMMON_LIBRARIES} 51 ${LLCOMMON_LIBRARIES}
50 ${WEBKIT_PLUGIN_LIBRARIES} 52 ${WEBKIT_PLUGIN_LIBRARIES}
51 ${PLUGIN_API_WINDOWS_LIBRARIES} 53 ${PLUGIN_API_WINDOWS_LIBRARIES}
54 ${PULSEAUDIO_LIBRARIES}
52) 55)
53 56
54if(LINUX) 57if (LINUX)
58 list(APPEND media_plugin_webkit_SOURCE_FILES linux_volume_catcher.cpp)
55 list(APPEND media_plugin_webkit_LINK_LIBRARIES 59 list(APPEND media_plugin_webkit_LINK_LIBRARIES
56 ${UI_LIBRARIES} # for glib/GTK 60 ${UI_LIBRARIES} # for glib/GTK
57 ) 61 )
diff --git a/linden/indra/media_plugins/webkit/linux_volume_catcher.cpp b/linden/indra/media_plugins/webkit/linux_volume_catcher.cpp
new file mode 100755
index 0000000..15a2dfb
--- /dev/null
+++ b/linden/indra/media_plugins/webkit/linux_volume_catcher.cpp
@@ -0,0 +1,490 @@
1/**
2 * @file linux_volume_catcher.cpp
3 * @brief A Linux-specific, PulseAudio-specific hack to detect and volume-adjust new audio sources
4 *
5 * @cond
6 * $LicenseInfo:firstyear=2010&license=viewergpl$
7 *
8 * Copyright (c) 2010, Linden Research, Inc.
9 *
10 * Second Life Viewer Source Code
11 * The source code in this file ("Source Code") is provided by Linden Lab
12 * to you under the terms of the GNU General Public License, version 2.0
13 * ("GPL"), unless you have obtained a separate licensing agreement
14 * ("Other License"), formally executed by you and Linden Lab. Terms of
15 * the GPL can be found in doc/GPL-license.txt in this distribution, or
16 * online at http://secondlife.com/developers/opensource/gplv2
17 *
18 * There are special exceptions to the terms and conditions of the GPL as
19 * it is applied to this Source Code. View the full text of the exception
20 * in the file doc/FLOSS-exception.txt in this software distribution, or
21 * online at
22 * http://secondlife.com/developers/opensource/flossexception
23 *
24 * By copying, modifying or distributing this software, you acknowledge
25 * that you have read and understood your obligations described above,
26 * and agree to abide by those obligations.
27 *
28 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
29 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
30 * COMPLETENESS OR PERFORMANCE.
31 * $/LicenseInfo$
32 *
33 * @endcond
34 */
35
36/*
37 The high-level design is as follows:
38 1) Connect to the PulseAudio daemon
39 2) Watch for the creation of new audio players connecting to the daemon (this includes ALSA clients running on the PulseAudio emulation layer, such as Flash plugins)
40 3) Examine any new audio player's PID to see if it belongs to our own process
41 4) If so, tell PA to adjust the volume of that audio player ('sink input' in PA parlance)
42 5) Keep a list of all living audio players that we care about, adjust the volumes of all of them when we get a new setVolume() call
43 */
44
45#include "linden_common.h"
46
47#include "linux_volume_catcher.h"
48
49
50#if LL_PULSEAUDIO_ENABLED
51
52extern "C" {
53#include <glib.h>
54
55#include <pulse/introspect.h>
56#include <pulse/context.h>
57#include <pulse/subscribe.h>
58#include <pulse/glib-mainloop.h> // There's no special reason why we want the *glib* PA mainloop, but the generic polling implementation seems broken.
59
60#include "apr_pools.h"
61#include "apr_dso.h"
62}
63
64////////////////////////////////////////////////////
65
66#define DEBUGMSG(...) do {} while(0)
67#define INFOMSG(...) do {} while(0)
68#define WARNMSG(...) do {} while(0)
69
70#define LL_PA_SYM(REQUIRED, PASYM, RTN, ...) RTN (*ll##PASYM)(__VA_ARGS__) = NULL
71#include "linux_volume_catcher_pa_syms.inc"
72#include "linux_volume_catcher_paglib_syms.inc"
73#undef LL_PA_SYM
74
75static bool sSymsGrabbed = false;
76static apr_pool_t *sSymPADSOMemoryPool = NULL;
77static apr_dso_handle_t *sSymPADSOHandleG = NULL;
78
79bool grab_pa_syms(std::string pulse_dso_name)
80{
81 if (sSymsGrabbed)
82 {
83 // already have grabbed good syms
84 return true;
85 }
86
87 bool sym_error = false;
88 bool rtn = false;
89 apr_status_t rv;
90 apr_dso_handle_t *sSymPADSOHandle = NULL;
91
92#define LL_PA_SYM(REQUIRED, PASYM, RTN, ...) do{rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll##PASYM, sSymPADSOHandle, #PASYM); if (rv != APR_SUCCESS) {INFOMSG("Failed to grab symbol: %s", #PASYM); if (REQUIRED) sym_error = true;} else DEBUGMSG("grabbed symbol: %s from %p", #PASYM, (void*)ll##PASYM);}while(0)
93
94 //attempt to load the shared library
95 apr_pool_create(&sSymPADSOMemoryPool, NULL);
96
97 if ( APR_SUCCESS == (rv = apr_dso_load(&sSymPADSOHandle,
98 pulse_dso_name.c_str(),
99 sSymPADSOMemoryPool) ))
100 {
101 INFOMSG("Found DSO: %s", pulse_dso_name.c_str());
102
103#include "linux_volume_catcher_pa_syms.inc"
104#include "linux_volume_catcher_paglib_syms.inc"
105
106 if ( sSymPADSOHandle )
107 {
108 sSymPADSOHandleG = sSymPADSOHandle;
109 sSymPADSOHandle = NULL;
110 }
111
112 rtn = !sym_error;
113 }
114 else
115 {
116 INFOMSG("Couldn't load DSO: %s", pulse_dso_name.c_str());
117 rtn = false; // failure
118 }
119
120 if (sym_error)
121 {
122 WARNMSG("Failed to find necessary symbols in PulseAudio libraries.");
123 }
124#undef LL_PA_SYM
125
126 sSymsGrabbed = rtn;
127 return rtn;
128}
129
130
131void ungrab_pa_syms()
132{
133 // should be safe to call regardless of whether we've
134 // actually grabbed syms.
135
136 if ( sSymPADSOHandleG )
137 {
138 apr_dso_unload(sSymPADSOHandleG);
139 sSymPADSOHandleG = NULL;
140 }
141
142 if ( sSymPADSOMemoryPool )
143 {
144 apr_pool_destroy(sSymPADSOMemoryPool);
145 sSymPADSOMemoryPool = NULL;
146 }
147
148 // NULL-out all of the symbols we'd grabbed
149#define LL_PA_SYM(REQUIRED, PASYM, RTN, ...) do{ll##PASYM = NULL;}while(0)
150#include "linux_volume_catcher_pa_syms.inc"
151#include "linux_volume_catcher_paglib_syms.inc"
152#undef LL_PA_SYM
153
154 sSymsGrabbed = false;
155}
156////////////////////////////////////////////////////
157
158// PulseAudio requires a chain of callbacks with C linkage
159extern "C" {
160 void callback_discovered_sinkinput(pa_context *context, const pa_sink_input_info *i, int eol, void *userdata);
161 void callback_subscription_alert(pa_context *context, pa_subscription_event_type_t t, uint32_t index, void *userdata);
162 void callback_context_state(pa_context *context, void *userdata);
163}
164
165
166class LinuxVolumeCatcherImpl
167{
168public:
169 LinuxVolumeCatcherImpl();
170 ~LinuxVolumeCatcherImpl();
171
172 void setVolume(F32 volume);
173 void pump(void);
174
175 // for internal use - can't be private because used from our C callbacks
176
177 bool loadsyms(std::string pulse_dso_name);
178 void init();
179 void cleanup();
180
181 void update_all_volumes(F32 volume);
182 void update_index_volume(U32 index, F32 volume);
183 void connected_okay();
184
185 std::set<U32> mSinkInputIndices;
186 std::map<U32,U32> mSinkInputNumChannels;
187 F32 mDesiredVolume;
188 pa_glib_mainloop *mMainloop;
189 pa_context *mPAContext;
190 bool mConnected;
191 bool mGotSyms;
192};
193
194LinuxVolumeCatcherImpl::LinuxVolumeCatcherImpl()
195 : mDesiredVolume(0.0f),
196 mMainloop(NULL),
197 mPAContext(NULL),
198 mConnected(false),
199 mGotSyms(false)
200{
201 init();
202}
203
204LinuxVolumeCatcherImpl::~LinuxVolumeCatcherImpl()
205{
206 cleanup();
207}
208
209bool LinuxVolumeCatcherImpl::loadsyms(std::string pulse_dso_name)
210{
211 return grab_pa_syms(pulse_dso_name);
212}
213
214void LinuxVolumeCatcherImpl::init()
215{
216 // try to be as defensive as possible because PA's interface is a
217 // bit fragile and (for our purposes) we'd rather simply not function
218 // than crash
219
220 // we cheat and rely upon libpulse-mainloop-glib.so.0 to pull-in
221 // libpulse.so.0 - this isn't a great assumption, and the two DSOs should
222 // probably be loaded separately. Our Linux DSO framework needs refactoring,
223 // we do this sort of thing a lot with practically identical logic...
224 mGotSyms = loadsyms("libpulse-mainloop-glib.so.0");
225 if (!mGotSyms) return;
226
227 mMainloop = llpa_glib_mainloop_new(g_main_context_default());
228 if (mMainloop)
229 {
230 pa_mainloop_api *api = llpa_glib_mainloop_get_api(mMainloop);
231 if (api)
232 {
233 pa_proplist *proplist = llpa_proplist_new();
234 if (proplist)
235 {
236 llpa_proplist_sets(proplist, PA_PROP_APPLICATION_ICON_NAME, "multimedia-player");
237 llpa_proplist_sets(proplist, PA_PROP_APPLICATION_ID, "com.secondlife.viewer.mediaplugvoladjust");
238 llpa_proplist_sets(proplist, PA_PROP_APPLICATION_NAME, "SL Plugin Volume Adjuster");
239 llpa_proplist_sets(proplist, PA_PROP_APPLICATION_VERSION, "1");
240
241 // plain old pa_context_new() is broken!
242 mPAContext = llpa_context_new_with_proplist(api, NULL, proplist);
243 llpa_proplist_free(proplist);
244 }
245 }
246 }
247
248 // Now we've set up a PA context and mainloop, try connecting the
249 // PA context to a PA daemon.
250 if (mPAContext)
251 {
252 llpa_context_set_state_callback(mPAContext, callback_context_state, this);
253 pa_context_flags_t cflags = (pa_context_flags)0; // maybe add PA_CONTEXT_NOAUTOSPAWN?
254 if (llpa_context_connect(mPAContext, NULL, cflags, NULL) >= 0)
255 {
256 // Okay! We haven't definitely connected, but we
257 // haven't definitely failed yet.
258 }
259 else
260 {
261 // Failed to connect to PA manager... we'll leave
262 // things like that. Perhaps we should try again later.
263 }
264 }
265}
266
267void LinuxVolumeCatcherImpl::cleanup()
268{
269 mConnected = false;
270
271 if (mGotSyms && mPAContext)
272 {
273 llpa_context_disconnect(mPAContext);
274 llpa_context_unref(mPAContext);
275 }
276 mPAContext = NULL;
277
278 if (mGotSyms && mMainloop)
279 {
280 llpa_glib_mainloop_free(mMainloop);
281 }
282 mMainloop = NULL;
283}
284
285void LinuxVolumeCatcherImpl::setVolume(F32 volume)
286{
287 mDesiredVolume = volume;
288
289 if (!mGotSyms) return;
290
291 if (mConnected && mPAContext)
292 {
293 update_all_volumes(mDesiredVolume);
294 }
295
296 pump();
297}
298
299void LinuxVolumeCatcherImpl::pump()
300{
301 gboolean may_block = FALSE;
302 g_main_context_iteration(g_main_context_default(), may_block);
303}
304
305void LinuxVolumeCatcherImpl::connected_okay()
306{
307 pa_operation *op;
308
309 // fetch global list of existing sinkinputs
310 if ((op = llpa_context_get_sink_input_info_list(mPAContext,
311 callback_discovered_sinkinput,
312 this)))
313 {
314 llpa_operation_unref(op);
315 }
316
317 // subscribe to future global sinkinput changes
318 llpa_context_set_subscribe_callback(mPAContext,
319 callback_subscription_alert,
320 this);
321 if ((op = llpa_context_subscribe(mPAContext, (pa_subscription_mask_t)
322 (PA_SUBSCRIPTION_MASK_SINK_INPUT),
323 NULL, NULL)))
324 {
325 llpa_operation_unref(op);
326 }
327}
328
329void LinuxVolumeCatcherImpl::update_all_volumes(F32 volume)
330{
331 for (std::set<U32>::iterator it = mSinkInputIndices.begin();
332 it != mSinkInputIndices.end(); ++it)
333 {
334 update_index_volume(*it, volume);
335 }
336}
337
338void LinuxVolumeCatcherImpl::update_index_volume(U32 index, F32 volume)
339{
340 static pa_cvolume cvol;
341 llpa_cvolume_set(&cvol, mSinkInputNumChannels[index],
342 llpa_sw_volume_from_linear(volume));
343
344 pa_context *c = mPAContext;
345 uint32_t idx = index;
346 const pa_cvolume *cvolumep = &cvol;
347 pa_context_success_cb_t cb = NULL; // okay as null
348 void *userdata = NULL; // okay as null
349
350 pa_operation *op;
351 if ((op = llpa_context_set_sink_input_volume(c, idx, cvolumep, cb, userdata)))
352 {
353 llpa_operation_unref(op);
354 }
355}
356
357
358void callback_discovered_sinkinput(pa_context *context, const pa_sink_input_info *sii, int eol, void *userdata)
359{
360 LinuxVolumeCatcherImpl *impl = dynamic_cast<LinuxVolumeCatcherImpl*>((LinuxVolumeCatcherImpl*)userdata);
361 llassert(impl);
362
363 if (0 == eol)
364 {
365 pa_proplist *proplist = sii->proplist;
366 pid_t sinkpid = atoll(llpa_proplist_gets(proplist, PA_PROP_APPLICATION_PROCESS_ID));
367
368 if (sinkpid == getpid()) // does the discovered sinkinput belong to this process?
369 {
370 bool is_new = (impl->mSinkInputIndices.find(sii->index) ==
371 impl->mSinkInputIndices.end());
372
373 impl->mSinkInputIndices.insert(sii->index);
374 impl->mSinkInputNumChannels[sii->index] = sii->channel_map.channels;
375
376 if (is_new)
377 {
378 // new!
379 impl->update_index_volume(sii->index, impl->mDesiredVolume);
380 }
381 else
382 {
383 // seen it already, do nothing.
384 }
385 }
386 }
387}
388
389void callback_subscription_alert(pa_context *context, pa_subscription_event_type_t t, uint32_t index, void *userdata)
390{
391 LinuxVolumeCatcherImpl *impl = dynamic_cast<LinuxVolumeCatcherImpl*>((LinuxVolumeCatcherImpl*)userdata);
392 llassert(impl);
393
394 switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) {
395 case PA_SUBSCRIPTION_EVENT_SINK_INPUT:
396 if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) ==
397 PA_SUBSCRIPTION_EVENT_REMOVE)
398 {
399 // forget this sinkinput, if we were caring about it
400 impl->mSinkInputIndices.erase(index);
401 impl->mSinkInputNumChannels.erase(index);
402 }
403 else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) ==
404 PA_SUBSCRIPTION_EVENT_NEW)
405 {
406 // ask for more info about this new sinkinput
407 pa_operation *op;
408 if ((op = llpa_context_get_sink_input_info(impl->mPAContext, index, callback_discovered_sinkinput, impl)))
409 {
410 llpa_operation_unref(op);
411 }
412 }
413 else
414 {
415 // property change on this sinkinput - we don't care.
416 }
417 break;
418
419 default:;
420 }
421}
422
423void callback_context_state(pa_context *context, void *userdata)
424{
425 LinuxVolumeCatcherImpl *impl = dynamic_cast<LinuxVolumeCatcherImpl*>((LinuxVolumeCatcherImpl*)userdata);
426 llassert(impl);
427
428 switch (llpa_context_get_state(context))
429 {
430 case PA_CONTEXT_READY:
431 impl->mConnected = true;
432 impl->connected_okay();
433 break;
434 case PA_CONTEXT_TERMINATED:
435 impl->mConnected = false;
436 break;
437 case PA_CONTEXT_FAILED:
438 impl->mConnected = false;
439 break;
440 default:;
441 }
442}
443
444/////////////////////////////////////////////////////
445
446LinuxVolumeCatcher::LinuxVolumeCatcher()
447{
448 pimpl = new LinuxVolumeCatcherImpl();
449}
450
451LinuxVolumeCatcher::~LinuxVolumeCatcher()
452{
453 delete pimpl;
454 pimpl = NULL;
455}
456
457void LinuxVolumeCatcher::setVolume(F32 volume)
458{
459 llassert(pimpl);
460 pimpl->setVolume(volume);
461}
462
463void LinuxVolumeCatcher::pump()
464{
465 llassert(pimpl);
466 pimpl->pump();
467}
468
469#else // !LL_PULSEAUDIO_ENABLED
470
471// stub.
472
473LinuxVolumeCatcher::LinuxVolumeCatcher()
474{
475 pimpl = NULL;
476}
477
478LinuxVolumeCatcher::~LinuxVolumeCatcher()
479{
480}
481
482void LinuxVolumeCatcher::setVolume(F32 volume)
483{
484}
485
486void LinuxVolumeCatcher::pump()
487{
488}
489
490#endif // LL_PULSEAUDIO_ENABLED
diff --git a/linden/indra/media_plugins/webkit/linux_volume_catcher.h b/linden/indra/media_plugins/webkit/linux_volume_catcher.h
new file mode 100755
index 0000000..d4a1b38
--- /dev/null
+++ b/linden/indra/media_plugins/webkit/linux_volume_catcher.h
@@ -0,0 +1,56 @@
1/**
2 * @file linux_volume_catcher.h
3 * @brief A Linux-specific, PulseAudio-specific hack to detect and volume-adjust new audio sources
4 *
5 * @cond
6 * $LicenseInfo:firstyear=2010&license=viewergpl$
7 *
8 * Copyright (c) 2010, Linden Research, Inc.
9 *
10 * Second Life Viewer Source Code
11 * The source code in this file ("Source Code") is provided by Linden Lab
12 * to you under the terms of the GNU General Public License, version 2.0
13 * ("GPL"), unless you have obtained a separate licensing agreement
14 * ("Other License"), formally executed by you and Linden Lab. Terms of
15 * the GPL can be found in doc/GPL-license.txt in this distribution, or
16 * online at http://secondlife.com/developers/opensource/gplv2
17 *
18 * There are special exceptions to the terms and conditions of the GPL as
19 * it is applied to this Source Code. View the full text of the exception
20 * in the file doc/FLOSS-exception.txt in this software distribution, or
21 * online at
22 * http://secondlife.com/developers/opensource/flossexception
23 *
24 * By copying, modifying or distributing this software, you acknowledge
25 * that you have read and understood your obligations described above,
26 * and agree to abide by those obligations.
27 *
28 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
29 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
30 * COMPLETENESS OR PERFORMANCE.
31 * $/LicenseInfo$
32 *
33 * @endcond
34 */
35
36#ifndef LINUX_VOLUME_CATCHER_H
37#define LINUX_VOLUME_CATCHER_H
38
39#include "linden_common.h"
40
41class LinuxVolumeCatcherImpl;
42
43class LinuxVolumeCatcher
44{
45 public:
46 LinuxVolumeCatcher();
47 ~LinuxVolumeCatcher();
48
49 void setVolume(F32 volume); // 0.0 - 1.0
50 void pump(); // call this at least a few times a second if you can - it affects how quickly we can 'catch' a new audio source and adjust its volume
51
52 private:
53 LinuxVolumeCatcherImpl *pimpl;
54};
55
56#endif // LINUX_VOLUME_CATCHER_H
diff --git a/linden/indra/media_plugins/webkit/linux_volume_catcher_pa_syms.inc b/linden/indra/media_plugins/webkit/linux_volume_catcher_pa_syms.inc
new file mode 100755
index 0000000..d806b48
--- /dev/null
+++ b/linden/indra/media_plugins/webkit/linux_volume_catcher_pa_syms.inc
@@ -0,0 +1,21 @@
1// required symbols to grab
2LL_PA_SYM(true, pa_context_connect, int, pa_context *c, const char *server, pa_context_flags_t flags, const pa_spawn_api *api);
3LL_PA_SYM(true, pa_context_disconnect, void, pa_context *c);
4LL_PA_SYM(true, pa_context_get_sink_input_info, pa_operation*, pa_context *c, uint32_t idx, pa_sink_input_info_cb_t cb, void *userdata);
5LL_PA_SYM(true, pa_context_get_sink_input_info_list, pa_operation*, pa_context *c, pa_sink_input_info_cb_t cb, void *userdata);
6LL_PA_SYM(true, pa_context_get_state, pa_context_state_t, pa_context *c);
7LL_PA_SYM(true, pa_context_new_with_proplist, pa_context*, pa_mainloop_api *mainloop, const char *name, pa_proplist *proplist);
8LL_PA_SYM(true, pa_context_set_sink_input_volume, pa_operation*, pa_context *c, uint32_t idx, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata);
9LL_PA_SYM(true, pa_context_set_state_callback, void, pa_context *c, pa_context_notify_cb_t cb, void *userdata);
10LL_PA_SYM(true, pa_context_set_subscribe_callback, void, pa_context *c, pa_context_subscribe_cb_t cb, void *userdata);
11LL_PA_SYM(true, pa_context_subscribe, pa_operation*, pa_context *c, pa_subscription_mask_t m, pa_context_success_cb_t cb, void *userdata);
12LL_PA_SYM(true, pa_context_unref, void, pa_context *c);
13LL_PA_SYM(true, pa_cvolume_set, pa_cvolume*, pa_cvolume *a, unsigned channels, pa_volume_t v);
14LL_PA_SYM(true, pa_operation_unref, void, pa_operation *o);
15LL_PA_SYM(true, pa_proplist_free, void, pa_proplist* p);
16LL_PA_SYM(true, pa_proplist_gets, const char*, pa_proplist *p, const char *key);
17LL_PA_SYM(true, pa_proplist_new, pa_proplist*, void);
18LL_PA_SYM(true, pa_proplist_sets, int, pa_proplist *p, const char *key, const char *value);
19LL_PA_SYM(true, pa_sw_volume_from_linear, pa_volume_t, double v);
20
21// optional symbols to grab
diff --git a/linden/indra/media_plugins/webkit/linux_volume_catcher_paglib_syms.inc b/linden/indra/media_plugins/webkit/linux_volume_catcher_paglib_syms.inc
new file mode 100755
index 0000000..abf628c
--- /dev/null
+++ b/linden/indra/media_plugins/webkit/linux_volume_catcher_paglib_syms.inc
@@ -0,0 +1,6 @@
1// required symbols to grab
2LL_PA_SYM(true, pa_glib_mainloop_free, void, pa_glib_mainloop* g);
3LL_PA_SYM(true, pa_glib_mainloop_get_api, pa_mainloop_api*, pa_glib_mainloop* g);
4LL_PA_SYM(true, pa_glib_mainloop_new, pa_glib_mainloop *, GMainContext *c);
5
6// optional symbols to grab
diff --git a/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp b/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp
index 2e3f06d..28c6e98 100755
--- a/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp
+++ b/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp
@@ -13,13 +13,13 @@
13 * ("GPL"), unless you have obtained a separate licensing agreement 13 * ("GPL"), unless you have obtained a separate licensing agreement
14 * ("Other License"), formally executed by you and Linden Lab. Terms of 14 * ("Other License"), formally executed by you and Linden Lab. Terms of
15 * the GPL can be found in doc/GPL-license.txt in this distribution, or 15 * the GPL can be found in doc/GPL-license.txt in this distribution, or
16 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 16 * online at http://secondlife.com/developers/opensource/gplv2
17 * 17 *
18 * There are special exceptions to the terms and conditions of the GPL as 18 * There are special exceptions to the terms and conditions of the GPL as
19 * it is applied to this Source Code. View the full text of the exception 19 * it is applied to this Source Code. View the full text of the exception
20 * in the file doc/FLOSS-exception.txt in this software distribution, or 20 * in the file doc/FLOSS-exception.txt in this software distribution, or
21 * online at 21 * online at
22 * http://secondlifegrid.net/programs/open_source/licensing/flossexception 22 * http://secondlife.com/developers/opensource/flossexception
23 * 23 *
24 * By copying, modifying or distributing this software, you acknowledge 24 * By copying, modifying or distributing this software, you acknowledge
25 * that you have read and understood your obligations described above, 25 * that you have read and understood your obligations described above,
@@ -29,9 +29,10 @@
29 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, 29 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
30 * COMPLETENESS OR PERFORMANCE. 30 * COMPLETENESS OR PERFORMANCE.
31 * $/LicenseInfo$ 31 * $/LicenseInfo$
32 *
32 * @endcond 33 * @endcond
33 */ 34 */
34#include <iomanip>//FIXME: This is included from elsewhere in SG2.0 35
35#include "llqtwebkit.h" 36#include "llqtwebkit.h"
36 37
37#include "linden_common.h" 38#include "linden_common.h"
@@ -44,11 +45,22 @@
44#include "llpluginmessageclasses.h" 45#include "llpluginmessageclasses.h"
45#include "media_plugin_base.h" 46#include "media_plugin_base.h"
46 47
48// set to 1 if you're using the version of llqtwebkit that's QPixmap-ified
49#if LL_LINUX
50# define LL_QTWEBKIT_USES_PIXMAPS 0
51#else
52# define LL_QTWEBKIT_USES_PIXMAPS 0
53#endif // LL_LINUX
54
55#if LL_LINUX
56# include "linux_volume_catcher.h"
57#endif // LL_LINUX
58
47#if LL_WINDOWS 59#if LL_WINDOWS
48#include <direct.h> 60# include <direct.h>
49#else 61#else
50#include <unistd.h> 62# include <unistd.h>
51#include <stdlib.h> 63# include <stdlib.h>
52#endif 64#endif
53 65
54#if LL_WINDOWS 66#if LL_WINDOWS
@@ -78,10 +90,16 @@ public:
78private: 90private:
79 91
80 std::string mProfileDir; 92 std::string mProfileDir;
93 std::string mHostLanguage;
94 std::string mUserAgent;
95 bool mCookiesEnabled;
96 bool mJavascriptEnabled;
97 bool mPluginsEnabled;
81 98
82 enum 99 enum
83 { 100 {
84 INIT_STATE_UNINITIALIZED, // Browser instance hasn't been set up yet 101 INIT_STATE_UNINITIALIZED, // LLQtWebkit hasn't been set up yet
102 INIT_STATE_INITIALIZED, // LLQtWebkit has been set up, but no browser window has been created yet.
85 INIT_STATE_NAVIGATING, // Browser instance has been set up and initial navigate to about:blank has been issued 103 INIT_STATE_NAVIGATING, // Browser instance has been set up and initial navigate to about:blank has been issued
86 INIT_STATE_NAVIGATE_COMPLETE, // initial navigate to about:blank has completed 104 INIT_STATE_NAVIGATE_COMPLETE, // initial navigate to about:blank has completed
87 INIT_STATE_WAIT_REDRAW, // First real navigate begin has been received, waiting for page changed event to start handling redraws 105 INIT_STATE_WAIT_REDRAW, // First real navigate begin has been received, waiting for page changed event to start handling redraws
@@ -103,6 +121,10 @@ private:
103 F32 mBackgroundG; 121 F32 mBackgroundG;
104 F32 mBackgroundB; 122 F32 mBackgroundB;
105 123
124#if LL_LINUX
125 LinuxVolumeCatcher mLinuxVolumeCatcher;
126#endif // LL_LINUX
127
106 void setInitState(int state) 128 void setInitState(int state)
107 { 129 {
108// std::cerr << "changing init state to " << state << std::endl; 130// std::cerr << "changing init state to " << state << std::endl;
@@ -115,6 +137,10 @@ private:
115 { 137 {
116 LLQtWebKit::getInstance()->pump( milliseconds ); 138 LLQtWebKit::getInstance()->pump( milliseconds );
117 139
140#if LL_LINUX
141 mLinuxVolumeCatcher.pump();
142#endif // LL_LINUX
143
118 checkEditState(); 144 checkEditState();
119 145
120 if(mInitState == INIT_STATE_NAVIGATE_COMPLETE) 146 if(mInitState == INIT_STATE_NAVIGATE_COMPLETE)
@@ -131,7 +157,11 @@ private:
131 { 157 {
132 const unsigned char* browser_pixels = LLQtWebKit::getInstance()->grabBrowserWindow( mBrowserWindowId ); 158 const unsigned char* browser_pixels = LLQtWebKit::getInstance()->grabBrowserWindow( mBrowserWindowId );
133 159
134 unsigned int buffer_size = LLQtWebKit::getInstance()->getBrowserRowSpan( mBrowserWindowId ) * LLQtWebKit::getInstance()->getBrowserHeight( mBrowserWindowId ); 160 unsigned int rowspan = LLQtWebKit::getInstance()->getBrowserRowSpan( mBrowserWindowId );
161 unsigned int height = LLQtWebKit::getInstance()->getBrowserHeight( mBrowserWindowId );
162#if !LL_QTWEBKIT_USES_PIXMAPS
163 unsigned int buffer_size = rowspan * height;
164#endif // !LL_QTWEBKIT_USES_PIXMAPS
135 165
136// std::cerr << "webkit plugin: updating" << std::endl; 166// std::cerr << "webkit plugin: updating" << std::endl;
137 167
@@ -139,7 +169,16 @@ private:
139 if ( mPixels && browser_pixels ) 169 if ( mPixels && browser_pixels )
140 { 170 {
141// std::cerr << " memcopy of " << buffer_size << " bytes" << std::endl; 171// std::cerr << " memcopy of " << buffer_size << " bytes" << std::endl;
172
173#if LL_QTWEBKIT_USES_PIXMAPS
174 // copy the pixel data upside-down because of the co-ord system
175 for (int y=0; y<height; ++y)
176 {
177 memcpy( &mPixels[(height-y-1)*rowspan], &browser_pixels[y*rowspan], rowspan );
178 }
179#else
142 memcpy( mPixels, browser_pixels, buffer_size ); 180 memcpy( mPixels, browser_pixels, buffer_size );
181#endif // LL_QTWEBKIT_USES_PIXMAPS
143 } 182 }
144 183
145 if ( mWidth > 0 && mHeight > 0 ) 184 if ( mWidth > 0 && mHeight > 0 )
@@ -160,13 +199,6 @@ private:
160 if ( mInitState > INIT_STATE_UNINITIALIZED ) 199 if ( mInitState > INIT_STATE_UNINITIALIZED )
161 return true; 200 return true;
162 201
163 // not enough information to initialize the browser yet.
164 if ( mWidth < 0 || mHeight < 0 || mDepth < 0 ||
165 mTextureWidth < 0 || mTextureHeight < 0 )
166 {
167 return false;
168 };
169
170 // set up directories 202 // set up directories
171 char cwd[ FILENAME_MAX ]; // I *think* this is defined on all platforms we use 203 char cwd[ FILENAME_MAX ]; // I *think* this is defined on all platforms we use
172 if (NULL == getcwd( cwd, FILENAME_MAX - 1 )) 204 if (NULL == getcwd( cwd, FILENAME_MAX - 1 ))
@@ -177,12 +209,12 @@ private:
177 std::string application_dir = std::string( cwd ); 209 std::string application_dir = std::string( cwd );
178 210
179#if LL_DARWIN 211#if LL_DARWIN
180 // When running under the Xcode debugger, there's a setting called "Break on Debugger()/DebugStr()" which defaults to being turned on. 212 // When running under the Xcode debugger, there's a setting called "Break on Debugger()/DebugStr()" which defaults to being turned on.
181 // This causes the environment variable USERBREAK to be set to 1, which causes these legacy calls to break into the debugger. 213 // This causes the environment variable USERBREAK to be set to 1, which causes these legacy calls to break into the debugger.
182 // This wouldn't cause any problems except for the fact that the current release version of the Flash plugin has a call to Debugger() in it 214 // This wouldn't cause any problems except for the fact that the current release version of the Flash plugin has a call to Debugger() in it
183 // which gets hit when the plugin is probed by webkit. 215 // which gets hit when the plugin is probed by webkit.
184 // Unsetting the environment variable here works around this issue. 216 // Unsetting the environment variable here works around this issue.
185 unsetenv("USERBREAK"); 217 unsetenv("USERBREAK");
186#endif 218#endif
187 219
188#if LL_WINDOWS 220#if LL_WINDOWS
@@ -223,65 +255,91 @@ private:
223 bool result = LLQtWebKit::getInstance()->init( application_dir, component_dir, mProfileDir, native_window_handle ); 255 bool result = LLQtWebKit::getInstance()->init( application_dir, component_dir, mProfileDir, native_window_handle );
224 if ( result ) 256 if ( result )
225 { 257 {
226 // create single browser window 258 mInitState = INIT_STATE_INITIALIZED;
227 mBrowserWindowId = LLQtWebKit::getInstance()->createBrowserWindow( mWidth, mHeight );
228#if LL_WINDOWS
229 // Enable plugins
230 LLQtWebKit::getInstance()->enablePlugins(true);
231#elif LL_DARWIN
232 // Enable plugins
233 LLQtWebKit::getInstance()->enablePlugins(true);
234#elif LL_LINUX
235 // Enable plugins
236 LLQtWebKit::getInstance()->enablePlugins(true);
237#endif
238 // Enable cookies
239 LLQtWebKit::getInstance()->enableCookies( true );
240
241 // tell LLQtWebKit about the size of the browser window
242 LLQtWebKit::getInstance()->setSize( mBrowserWindowId, mWidth, mHeight );
243
244 // observer events that LLQtWebKit emits
245 LLQtWebKit::getInstance()->addObserver( mBrowserWindowId, this );
246
247 // append details to agent string
248 LLQtWebKit::getInstance()->setBrowserAgentId( "LLPluginMedia Web Browser" );
249
250 // don't flip bitmap
251 LLQtWebKit::getInstance()->flipWindow( mBrowserWindowId, true );
252
253 // set background color
254 // convert background color channels from [0.0, 1.0] to [0, 255];
255 LLQtWebKit::getInstance()->setBackgroundColor( mBrowserWindowId, int(mBackgroundR * 255.0f), int(mBackgroundG * 255.0f), int(mBackgroundB * 255.0f) );
256
257 // Set state _before_ starting the navigate, since onNavigateBegin might get called before this call returns.
258 setInitState(INIT_STATE_NAVIGATING);
259
260 // Don't do this here -- it causes the dreaded "white flash" when loading a browser instance.
261 // FIXME: Re-added this because navigating to a "page" initializes things correctly - especially
262 // for the HTTP AUTH dialog issues (DEV-41731). Will fix at a later date.
263 // Build a data URL like this: "data:text/html,%3Chtml%3E%3Cbody bgcolor=%22#RRGGBB%22%3E%3C/body%3E%3C/html%3E"
264 // where RRGGBB is the background color in HTML style
265 std::stringstream url;
266 259
267 url << "data:text/html,%3Chtml%3E%3Cbody%20bgcolor=%22#";
268 // convert background color channels from [0.0, 1.0] to [0, 255];
269 url << std::setfill('0') << std::setw(2) << std::hex << int(mBackgroundR * 255.0f);
270 url << std::setfill('0') << std::setw(2) << std::hex << int(mBackgroundG * 255.0f);
271 url << std::setfill('0') << std::setw(2) << std::hex << int(mBackgroundB * 255.0f);
272 url << "%22%3E%3C/body%3E%3C/html%3E";
273
274 lldebugs << "data url is: " << url.str() << llendl;
275
276 LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, url.str() );
277// LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, "about:blank" );
278
279 return true; 260 return true;
280 }; 261 };
281 262
282 return false; 263 return false;
283 }; 264 };
284 265
266 ////////////////////////////////////////////////////////////////////////////////
267 //
268 bool initBrowserWindow()
269 {
270 // already initialized
271 if ( mInitState > INIT_STATE_INITIALIZED )
272 return true;
273
274 // not enough information to initialize the browser yet.
275 if ( mWidth < 0 || mHeight < 0 || mDepth < 0 ||
276 mTextureWidth < 0 || mTextureHeight < 0 )
277 {
278 return false;
279 };
280
281 // Set up host language before creating browser window
282 if(!mHostLanguage.empty())
283 {
284 LLQtWebKit::getInstance()->setHostLanguage(mHostLanguage);
285 }
286
287 // turn on/off cookies based on what host app tells us
288 LLQtWebKit::getInstance()->enableCookies( mCookiesEnabled );
289
290 // turn on/off plugins based on what host app tells us
291 LLQtWebKit::getInstance()->enablePlugins( mPluginsEnabled );
292
293 // turn on/off Javascript based on what host app tells us
294 LLQtWebKit::getInstance()->enableJavascript( mJavascriptEnabled );
295
296 // create single browser window
297 mBrowserWindowId = LLQtWebKit::getInstance()->createBrowserWindow( mWidth, mHeight );
298
299 // tell LLQtWebKit about the size of the browser window
300 LLQtWebKit::getInstance()->setSize( mBrowserWindowId, mWidth, mHeight );
301
302 // observer events that LLQtWebKit emits
303 LLQtWebKit::getInstance()->addObserver( mBrowserWindowId, this );
304
305 // append details to agent string
306 LLQtWebKit::getInstance()->setBrowserAgentId( mUserAgent );
307
308#if !LL_QTWEBKIT_USES_PIXMAPS
309 // don't flip bitmap
310 LLQtWebKit::getInstance()->flipWindow( mBrowserWindowId, true );
311#endif // !LL_QTWEBKIT_USES_PIXMAPS
312
313 // set background color
314 // convert background color channels from [0.0, 1.0] to [0, 255];
315 LLQtWebKit::getInstance()->setBackgroundColor( mBrowserWindowId, int(mBackgroundR * 255.0f), int(mBackgroundG * 255.0f), int(mBackgroundB * 255.0f) );
316
317 // Set state _before_ starting the navigate, since onNavigateBegin might get called before this call returns.
318 setInitState(INIT_STATE_NAVIGATING);
319
320 // Don't do this here -- it causes the dreaded "white flash" when loading a browser instance.
321 // FIXME: Re-added this because navigating to a "page" initializes things correctly - especially
322 // for the HTTP AUTH dialog issues (DEV-41731). Will fix at a later date.
323 // Build a data URL like this: "data:text/html,%3Chtml%3E%3Cbody bgcolor=%22#RRGGBB%22%3E%3C/body%3E%3C/html%3E"
324 // where RRGGBB is the background color in HTML style
325 std::stringstream url;
326
327 url << "data:text/html,%3Chtml%3E%3Cbody%20bgcolor=%22#";
328 // convert background color channels from [0.0, 1.0] to [0, 255];
329 url << std::setfill('0') << std::setw(2) << std::hex << int(mBackgroundR * 255.0f);
330 url << std::setfill('0') << std::setw(2) << std::hex << int(mBackgroundG * 255.0f);
331 url << std::setfill('0') << std::setw(2) << std::hex << int(mBackgroundB * 255.0f);
332 url << "%22%3E%3C/body%3E%3C/html%3E";
333
334 lldebugs << "data url is: " << url.str() << llendl;
335
336 LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, url.str() );
337// LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, "about:blank" );
338
339 return true;
340 }
341
342 void setVolume(F32 vol);
285 343
286 //////////////////////////////////////////////////////////////////////////////// 344 ////////////////////////////////////////////////////////////////////////////////
287 // virtual 345 // virtual
@@ -616,6 +674,11 @@ MediaPluginWebKit::MediaPluginWebKit(LLPluginInstance::sendMessageFunction host_
616 mBackgroundR = 0.0f; 674 mBackgroundR = 0.0f;
617 mBackgroundG = 0.0f; 675 mBackgroundG = 0.0f;
618 mBackgroundB = 0.0f; 676 mBackgroundB = 0.0f;
677
678 mHostLanguage = "en"; // default to english
679 mJavascriptEnabled = true; // default to on
680 mPluginsEnabled = true; // default to on
681 mUserAgent = "LLPluginMedia Web Browser";
619} 682}
620 683
621MediaPluginWebKit::~MediaPluginWebKit() 684MediaPluginWebKit::~MediaPluginWebKit()
@@ -642,9 +705,6 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)
642 { 705 {
643 if(message_name == "init") 706 if(message_name == "init")
644 { 707 {
645 std::string user_data_path = message_in.getValue("user_data_path"); // n.b. always has trailing platform-specific dir-delimiter
646 mProfileDir = user_data_path + "browser_profile";
647
648 LLPluginMessage message("base", "init_response"); 708 LLPluginMessage message("base", "init_response");
649 LLSD versions = LLSD::emptyMap(); 709 LLSD versions = LLSD::emptyMap();
650 versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION; 710 versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION;
@@ -656,19 +716,6 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)
656 plugin_version += LLQtWebKit::getInstance()->getVersion(); 716 plugin_version += LLQtWebKit::getInstance()->getVersion();
657 message.setValue("plugin_version", plugin_version); 717 message.setValue("plugin_version", plugin_version);
658 sendMessage(message); 718 sendMessage(message);
659
660 // Plugin gets to decide the texture parameters to use.
661 mDepth = 4;
662
663 message.setMessage(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params");
664 message.setValueS32("default_width", 1024);
665 message.setValueS32("default_height", 1024);
666 message.setValueS32("depth", mDepth);
667 message.setValueU32("internalformat", GL_RGBA);
668 message.setValueU32("format", GL_RGBA);
669 message.setValueU32("type", GL_UNSIGNED_BYTE);
670 message.setValueBoolean("coords_opengl", true);
671 sendMessage(message);
672 } 719 }
673 else if(message_name == "idle") 720 else if(message_name == "idle")
674 { 721 {
@@ -733,9 +780,68 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)
733// std::cerr << "MediaPluginWebKit::receiveMessage: unknown base message: " << message_name << std::endl; 780// std::cerr << "MediaPluginWebKit::receiveMessage: unknown base message: " << message_name << std::endl;
734 } 781 }
735 } 782 }
783 else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME)
784 {
785 if(message_name == "set_volume")
786 {
787 F32 volume = message_in.getValueReal("volume");
788 setVolume(volume);
789 }
790 }
736 else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA) 791 else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA)
737 { 792 {
738 if(message_name == "size_change") 793 if(message_name == "init")
794 {
795 // This is the media init message -- all necessary data for initialization should have been received.
796 if(initBrowser())
797 {
798
799 // Plugin gets to decide the texture parameters to use.
800 mDepth = 4;
801
802 LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params");
803 message.setValueS32("default_width", 1024);
804 message.setValueS32("default_height", 1024);
805 message.setValueS32("depth", mDepth);
806 message.setValueU32("internalformat", GL_RGBA);
807 #if LL_QTWEBKIT_USES_PIXMAPS
808 message.setValueU32("format", GL_BGRA_EXT); // I hope this isn't system-dependant... is it? If so, we'll have to check the root window's pixel layout or something... yuck.
809 #else
810 message.setValueU32("format", GL_RGBA);
811 #endif // LL_QTWEBKIT_USES_PIXMAPS
812 message.setValueU32("type", GL_UNSIGNED_BYTE);
813 message.setValueBoolean("coords_opengl", true);
814 sendMessage(message);
815 }
816 else
817 {
818 // if initialization failed, we're done.
819 mDeleteMe = true;
820 }
821
822 }
823 else if(message_name == "set_user_data_path")
824 {
825 std::string user_data_path = message_in.getValue("path"); // n.b. always has trailing platform-specific dir-delimiter
826 mProfileDir = user_data_path + "browser_profile";
827
828 // FIXME: Should we do anything with this if it comes in after the browser has been initialized?
829 }
830 else if(message_name == "set_language_code")
831 {
832 mHostLanguage = message_in.getValue("language");
833
834 // FIXME: Should we do anything with this if it comes in after the browser has been initialized?
835 }
836 else if(message_name == "plugins_enabled")
837 {
838 mPluginsEnabled = message_in.getValueBoolean("enable");
839 }
840 else if(message_name == "javascript_enabled")
841 {
842 mJavascriptEnabled = message_in.getValueBoolean("enable");
843 }
844 else if(message_name == "size_change")
739 { 845 {
740 std::string name = message_in.getValue("name"); 846 std::string name = message_in.getValue("name");
741 S32 width = message_in.getValueS32("width"); 847 S32 width = message_in.getValueS32("width");
@@ -757,29 +863,36 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)
757 mWidth = width; 863 mWidth = width;
758 mHeight = height; 864 mHeight = height;
759 865
760 // initialize (only gets called once) 866 if(initBrowserWindow())
761 initBrowser();
762
763 // size changed so tell the browser
764 LLQtWebKit::getInstance()->setSize( mBrowserWindowId, mWidth, mHeight );
765
766// std::cerr << "webkit plugin: set size to " << mWidth << " x " << mHeight
767// << ", rowspan is " << LLQtWebKit::getInstance()->getBrowserRowSpan(mBrowserWindowId) << std::endl;
768
769 S32 real_width = LLQtWebKit::getInstance()->getBrowserRowSpan(mBrowserWindowId) / LLQtWebKit::getInstance()->getBrowserDepth(mBrowserWindowId);
770
771 // The actual width the browser will be drawing to is probably smaller... let the host know by modifying texture_width in the response.
772 if(real_width <= texture_width)
773 { 867 {
774 texture_width = real_width; 868
869 // size changed so tell the browser
870 LLQtWebKit::getInstance()->setSize( mBrowserWindowId, mWidth, mHeight );
871
872 // std::cerr << "webkit plugin: set size to " << mWidth << " x " << mHeight
873 // << ", rowspan is " << LLQtWebKit::getInstance()->getBrowserRowSpan(mBrowserWindowId) << std::endl;
874
875 S32 real_width = LLQtWebKit::getInstance()->getBrowserRowSpan(mBrowserWindowId) / LLQtWebKit::getInstance()->getBrowserDepth(mBrowserWindowId);
876
877 // The actual width the browser will be drawing to is probably smaller... let the host know by modifying texture_width in the response.
878 if(real_width <= texture_width)
879 {
880 texture_width = real_width;
881 }
882 else
883 {
884 // This won't work -- it'll be bigger than the allocated memory. This is a fatal error.
885 // std::cerr << "Fatal error: browser rowbytes greater than texture width" << std::endl;
886 mDeleteMe = true;
887 return;
888 }
775 } 889 }
776 else 890 else
777 { 891 {
778 // This won't work -- it'll be bigger than the allocated memory. This is a fatal error. 892 // Setting up the browser window failed. This is a fatal error.
779// std::cerr << "Fatal error: browser rowbytes greater than texture width" << std::endl;
780 mDeleteMe = true; 893 mDeleteMe = true;
781 return;
782 } 894 }
895
783 896
784 mTextureWidth = texture_width; 897 mTextureWidth = texture_width;
785 mTextureHeight = texture_height; 898 mTextureHeight = texture_height;
@@ -929,8 +1042,18 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)
929 } 1042 }
930 else if(message_name == "enable_cookies") 1043 else if(message_name == "enable_cookies")
931 { 1044 {
932 bool val = message_in.getValueBoolean("enable"); 1045 mCookiesEnabled = message_in.getValueBoolean("enable");
933 LLQtWebKit::getInstance()->enableCookies( val ); 1046 LLQtWebKit::getInstance()->enableCookies( mCookiesEnabled );
1047 }
1048 else if(message_name == "enable_plugins")
1049 {
1050 mPluginsEnabled = message_in.getValueBoolean("enable");
1051 LLQtWebKit::getInstance()->enablePlugins( mPluginsEnabled );
1052 }
1053 else if(message_name == "enable_javascript")
1054 {
1055 mJavascriptEnabled = message_in.getValueBoolean("enable");
1056 //LLQtWebKit::getInstance()->enableJavascript( mJavascriptEnabled );
934 } 1057 }
935 else if(message_name == "proxy_setup") 1058 else if(message_name == "proxy_setup")
936 { 1059 {
@@ -967,8 +1090,8 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)
967 } 1090 }
968 else if(message_name == "set_user_agent") 1091 else if(message_name == "set_user_agent")
969 { 1092 {
970 std::string user_agent = message_in.getValue("user_agent"); 1093 mUserAgent = message_in.getValue("user_agent");
971 LLQtWebKit::getInstance()->setBrowserAgentId( user_agent ); 1094 LLQtWebKit::getInstance()->setBrowserAgentId( mUserAgent );
972 } 1095 }
973 else if(message_name == "init_history") 1096 else if(message_name == "init_history")
974 { 1097 {
@@ -999,6 +1122,13 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)
999 } 1122 }
1000} 1123}
1001 1124
1125void MediaPluginWebKit::setVolume(F32 volume)
1126{
1127#if LL_LINUX
1128 mLinuxVolumeCatcher.setVolume(volume);
1129#endif // LL_LINUX
1130}
1131
1002int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data) 1132int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data)
1003{ 1133{
1004 MediaPluginWebKit *self = new MediaPluginWebKit(host_send_func, host_user_data); 1134 MediaPluginWebKit *self = new MediaPluginWebKit(host_send_func, host_user_data);