aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra
diff options
context:
space:
mode:
authorArmin Weatherwax2010-09-23 20:30:12 +0200
committerArmin Weatherwax2010-09-23 20:30:12 +0200
commit197f915816579a14e102075cf25a26127dfc1d32 (patch)
treeb6f3212d612c79a2740c347866089ea39935ee04 /linden/indra
parentImprudence style gstreamer plugin (remove llgst, syms and such) (diff)
downloadmeta-impy-197f915816579a14e102075cf25a26127dfc1d32.zip
meta-impy-197f915816579a14e102075cf25a26127dfc1d32.tar.gz
meta-impy-197f915816579a14e102075cf25a26127dfc1d32.tar.bz2
meta-impy-197f915816579a14e102075cf25a26127dfc1d32.tar.xz
linux* kill imprudence gstreamer, use system gstreamer instead.
who ever builds a release with that needs to consider to install some really old gstreamer at /usr/local/lib - lenny has 0.10.19
Diffstat (limited to 'linden/indra')
-rw-r--r--linden/indra/cmake/GStreamer.cmake114
-rw-r--r--linden/indra/cmake/GStreamer010Plugin.cmake20
-rw-r--r--linden/indra/llmedia/llmediaimplgstreamer.cpp928
-rwxr-xr-xlinden/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp~1219
-rwxr-xr-xlinden/indra/newview/linux_tools/getvoice.sh5
-rwxr-xr-xlinden/indra/newview/linux_tools/wrapper.sh8
-rwxr-xr-xlinden/indra/newview/viewer_manifest.py248
-rwxr-xr-xlinden/indra/newview/viewer_manifest.py~1176
8 files changed, 143 insertions, 3575 deletions
diff --git a/linden/indra/cmake/GStreamer.cmake b/linden/indra/cmake/GStreamer.cmake
deleted file mode 100644
index f5f9c03..0000000
--- a/linden/indra/cmake/GStreamer.cmake
+++ /dev/null
@@ -1,114 +0,0 @@
1# -*- cmake -*-
2include(Prebuilt)
3
4 # Maybe libxml and glib should have their own .cmake files
5 use_prebuilt_binary(libxml)
6 use_prebuilt_binary(glib)
7
8 set(GSTREAMER_FOUND ON FORCE BOOL)
9 set(GSTREAMER_PLUGINS_BASE_FOUND ON FORCE BOOL)
10
11 use_prebuilt_binary(gstreamer)
12 use_prebuilt_binary(gstreamer-plugins)
13
14if (WINDOWS)
15
16 use_prebuilt_binary(iconv)
17 set(GSTREAMER_FOUND ON FORCE BOOL)
18 set(GSTREAMER_INCLUDE_DIRS
19 ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/glib
20 ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/gio
21 ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/gobject
22 ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/libxml2
23 ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/iconv
24 ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/gst
25 )
26
27 set(GSTREAMER_LIBRARIES
28 glib-2.0
29 gio-2.0
30 gmodule-2.0
31 gobject-2.0
32 gthread-2.0
33 libgstvideo.lib
34 libgsttag.lib
35 libgstsdp.lib
36 libgstrtsp.lib
37 libgstrtp.lib
38 libgstriff.lib
39 libgstreamer-0.10.lib
40 libgstpbutils.lib
41 libgstnetbuffer.lib
42 libgstnet-0.10.lib
43 libgstinterfaces.lib
44 libgstdshow.lib
45 libgstdataprotocol-0.10.lib
46 libgstcontroller-0.10.lib
47 libgstbase-0.10.lib
48 libgstaudio.lib
49 libgstapp.lib
50 libxml2
51 libxml2_a
52 libxml2_a_dll
53 iconv
54 iconv_a
55 )
56
57else (WINDOWS)
58
59 set(GSTREAMER_INCLUDE_DIRS
60 ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/gstreamer-0.10
61 ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/glib-2.0
62 ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/glib-2.0/glib
63 ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/glib-2.0/gobject
64 ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/libxml2
65 )
66
67 if (DARWIN) # Mac
68
69 use_prebuilt_binary(flac)
70 use_prebuilt_binary(liboil)
71 use_prebuilt_binary(neon)
72 use_prebuilt_binary(theora)
73
74 set(GSTREAMER_LIBRARIES
75 gstvideo-0.10
76 gstaudio-0.10
77 gstbase-0.10
78 gstreamer-0.10
79 gobject-2.0
80 gmodule-2.0
81 gthread-2.0
82 glib-2.0
83 xml2.2
84 )
85
86 else (DARWIN) # Linux
87
88 use_prebuilt_binary(liboil)
89 use_prebuilt_binary(theora)
90
91 set(GSTREAMER_LIBRARIES
92 gstvideo-0.10
93 gstaudio-0.10
94 gstbase-0.10
95 gstreamer-0.10
96 gobject-2.0
97 gmodule-2.0
98 dl
99 gthread-2.0
100 rt
101 glib-2.0
102 )
103
104 endif (DARWIN)
105
106endif (WINDOWS)
107
108if (GSTREAMER_FOUND AND GSTREAMER_PLUGINS_BASE_FOUND)
109 set(GSTREAMER ON CACHE BOOL "Build with GStreamer streaming media support.")
110endif (GSTREAMER_FOUND AND GSTREAMER_PLUGINS_BASE_FOUND)
111
112if (GSTREAMER)
113 add_definitions(-DLL_GSTREAMER_ENABLED=1)
114endif (GSTREAMER)
diff --git a/linden/indra/cmake/GStreamer010Plugin.cmake b/linden/indra/cmake/GStreamer010Plugin.cmake
index 0d33483..78ffd94 100644
--- a/linden/indra/cmake/GStreamer010Plugin.cmake
+++ b/linden/indra/cmake/GStreamer010Plugin.cmake
@@ -19,14 +19,18 @@ elseif (LINUX)
19 ) 19 )
20 # We don't need to explicitly link against gstreamer itself, because 20 # We don't need to explicitly link against gstreamer itself, because
21 # LLMediaImplGStreamer probes for the system's copy at runtime. 21 # LLMediaImplGStreamer probes for the system's copy at runtime.
22 set(GSTREAMER010_LIBRARIES 22 set(GSTREAMER010_LIBRARIES
23 gobject-2.0 23 gstvideo-0.10
24 gmodule-2.0 24 gstaudio-0.10
25 dl 25 gstbase-0.10
26 gthread-2.0 26 gstreamer-0.10
27 rt 27 gobject-2.0
28 glib-2.0 28 gmodule-2.0
29 ) 29 dl
30 gthread-2.0
31 rt
32 glib-2.0
33 )
30endif (STANDALONE) 34endif (STANDALONE)
31 35
32if (GSTREAMER010_FOUND AND GSTREAMER010_PLUGINS_BASE_FOUND) 36if (GSTREAMER010_FOUND AND GSTREAMER010_PLUGINS_BASE_FOUND)
diff --git a/linden/indra/llmedia/llmediaimplgstreamer.cpp b/linden/indra/llmedia/llmediaimplgstreamer.cpp
deleted file mode 100644
index 7af9c9a..0000000
--- a/linden/indra/llmedia/llmediaimplgstreamer.cpp
+++ /dev/null
@@ -1,928 +0,0 @@
1/**
2 * @file llmediaimplgstreamer.cpp
3 * @author Tofu Linden
4 * @brief implementation that supports various media through GStreamer.
5 *
6 * $LicenseInfo:firstyear=2007&license=viewergpl$
7 *
8 * Copyright (c) 2007-2009, 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://secondlifegrid.net/programs/open_source/licensing/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 http://secondlifegrid.net/programs/open_source/licensing/flossexception
22 *
23 * By copying, modifying or distributing this software, you acknowledge
24 * that you have read and understood your obligations described above,
25 * and agree to abide by those obligations.
26 *
27 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
28 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
29 * COMPLETENESS OR PERFORMANCE.
30 * $/LicenseInfo$
31 */
32
33///#if LL_GSTREAMER_ENABLED
34
35#if LL_WINDOWS
36 // GStreamer 0.10.22 - gstutils.h - conversion from 'guint64' to 'guint8'.
37 // This was an intentional change to make GStreamer more threadsafe, and
38 // is okay. Delete this bit if GStreamer ever gets more VS-friendly -- McCabe
39 #pragma warning(disable : 4244)
40#endif
41
42#include "linden_common.h"
43#include "llmediaimplgstreamer.h"
44
45extern "C" {
46#include <gst/gst.h>
47#include <gst/gstelement.h>
48}
49
50#if LL_WINDOWS
51 #pragma warning(default : 4244)
52#include <direct.h>
53#include <stdlib.h>
54#endif
55
56#include "llmediamanager.h"
57#include "llmediaimplregister.h"
58
59#include "llmediaimplgstreamervidplug.h"
60#include "llgstplaythread.h"
61
62
63#if LL_DARWIN
64#include <CoreFoundation/CoreFoundation.h> // For CF functions used in set_gst_plugin_path
65#endif
66
67// register this impl with media manager factory
68static LLMediaImplRegister sLLMediaImplGStreamerReg( "LLMediaImplGStreamer", new LLMediaImplGStreamerMaker() );
69
70LLMediaImplGStreamerMaker::LLMediaImplGStreamerMaker()
71{
72 // Register to handle the scheme
73 mSchema.push_back( "rtsp" );
74 mSchema.push_back( "rtmp" );
75
76 // Register to handle the category
77 mMimeTypeCategories.push_back( "video" );
78 mMimeTypeCategories.push_back( "audio" );
79}
80
81///////////////////////////////////////////////////////////////////////////////
82//
83LLMediaImplGStreamer::
84LLMediaImplGStreamer () :
85 mediaData ( NULL ),
86 mMediaRowbytes ( 1 ),
87 mTextureFormatPrimary ( LL_MEDIA_BGRA ),
88 mTextureFormatType ( LL_MEDIA_UNSIGNED_INT_8_8_8_8_REV ),
89 mPump ( NULL ),
90 mPlaybin ( NULL ),
91 mVideoSink ( NULL ),
92 mLastTitle ( "" ),
93 mState( GST_STATE_NULL ),
94 mPlayThread ( NULL )
95{
96 startup( NULL ); // Startup gstreamer if it hasn't been already.
97
98 LL_DEBUGS("MediaManager") << "constructing media..." << LL_ENDL;
99 mVolume = -1.0; // XXX Hack to make the vould change happend first time
100
101 setMediaDepth(4);
102
103 // Create a pumpable main-loop for this media
104 mPump = g_main_loop_new (NULL, FALSE);
105 if (!mPump)
106 {
107 return; // error
108 }
109
110 // instantiate a playbin element to do the hard work
111 mPlaybin = gst_element_factory_make ("playbin", "play");
112 if (!mPlaybin)
113 {
114 // todo: cleanup pump
115 return; // error
116 }
117
118 if (NULL == getenv("LL_GSTREAMER_EXTERNAL"))
119 {
120 // instantiate and connect a custom video sink
121 LL_DEBUGS("MediaManager") << "extrenal video sink..." << LL_ENDL;
122
123 // Plays inworld instead of in external player
124 mVideoSink =
125 GST_SLVIDEO(gst_element_factory_make ("private-slvideo", "slvideo"));
126 if (!mVideoSink)
127 {
128 LL_WARNS("MediaImpl") << "Could not instantiate private-slvideo element." << LL_ENDL;
129 // todo: cleanup.
130 return; // error
131 }
132
133 g_object_set(mPlaybin, "video-sink", mVideoSink, (void*)NULL);
134 }
135}
136
137// virtual
138int LLMediaImplGStreamer::getTextureFormatPrimary() const
139{
140 return mTextureFormatPrimary;
141}
142
143// virtual
144int LLMediaImplGStreamer::getTextureFormatType() const
145{
146 return mTextureFormatType;
147}
148
149// virtual
150int LLMediaImplGStreamer::getTextureFormatInternal() const
151{
152 return LL_MEDIA_RGB8;
153}
154
155///////////////////////////////////////////////////////////////////////////////
156//
157LLMediaImplGStreamer::
158~LLMediaImplGStreamer ()
159{
160 LL_DEBUGS("MediaImpl") << ("dtor of media...") << LL_ENDL;
161 unload();
162}
163
164////////////////////////////////////////////////////////////////////////////////
165// virtual
166std::string LLMediaImplGStreamer::getVersion()
167{
168 guint major, minor, micro, nano;
169 gst_version(&major, &minor, &micro, &nano);
170 std::string version = llformat("%d.%d.%d.%d",major,minor,micro,nano);
171 return version;
172}
173
174//
175// STARTUP
176///////////////////////////////////////////////////////////////////////////////
177// (static) super-initialization - called once at application startup
178bool LLMediaImplGStreamer::startup (LLMediaManagerData* init_data)
179{
180 static bool done_init = false;
181 if (!done_init)
182 {
183 // Init the glib type system - we need it.
184 g_type_init();
185
186 set_gst_plugin_path();
187
188 // Protect against GStreamer resetting the locale, yuck.
189 static std::string saved_locale;
190 saved_locale = setlocale(LC_ALL, NULL);
191 if (0 == gst_init_check(NULL, NULL, NULL))
192 {
193 LL_WARNS("MediaImpl") << "GStreamer library failed to initialize and load standard plugins." << LL_ENDL;
194 setlocale(LC_ALL, saved_locale.c_str() );
195 return false;
196 }
197 setlocale(LC_ALL, saved_locale.c_str() );
198
199 // Set up logging facilities
200 gst_debug_remove_log_function( gst_debug_log_default );
201 gst_debug_add_log_function( gstreamer_log, NULL );
202
203 // Init our custom plugins - only really need do this once.
204 gst_slvideo_init_class();
205
206
207 // List the plugins GStreamer can find
208 LL_DEBUGS("MediaImpl") << "Found GStreamer plugins:" << LL_ENDL;
209 GList *list;
210 GstRegistry *registry = gst_registry_get_default();
211 std::string loaded = "";
212 for (list = gst_registry_get_plugin_list(registry);
213 list != NULL;
214 list = g_list_next(list))
215 {
216 GstPlugin *list_plugin = (GstPlugin *)list->data;
217 (bool)gst_plugin_is_loaded(list_plugin) ? loaded = "Yes" : loaded = "No";
218 LL_DEBUGS("MediaImpl") << gst_plugin_get_name(list_plugin) << ", loaded? " << loaded << LL_ENDL;
219 }
220 gst_plugin_list_free(list);
221
222
223 done_init = true;
224 }
225 return true;
226}
227
228
229void LLMediaImplGStreamer::set_gst_plugin_path()
230{
231 // Linux sets GST_PLUGIN_PATH in wrapper.sh, not here.
232#if LL_WINDOWS || LL_DARWIN
233
234 std::string imp_dir = "";
235
236 // Get the current working directory:
237#if LL_WINDOWS
238 char* raw_dir;
239 raw_dir = _getcwd(NULL,0);
240 if( raw_dir != NULL )
241 {
242 imp_dir = std::string( raw_dir );
243 }
244#elif LL_DARWIN
245 CFBundleRef main_bundle = CFBundleGetMainBundle();
246 if( main_bundle != NULL )
247 {
248 CFURLRef bundle_url = CFBundleCopyBundleURL( main_bundle );
249 if( bundle_url != NULL )
250 {
251 #ifndef MAXPATHLEN
252 #define MAXPATHLEN 1024
253 #endif
254 char raw_dir[MAXPATHLEN];
255 if( CFURLGetFileSystemRepresentation( bundle_url, true, (UInt8 *)raw_dir, MAXPATHLEN) )
256 {
257 imp_dir = std::string( raw_dir ) + "/Contents/MacOS/";
258 }
259 CFRelease(bundle_url);
260 }
261 }
262#endif
263
264 if( imp_dir == "" )
265 {
266 LL_WARNS("MediaImpl") << "Could not get application directory, not setting GST_PLUGIN_PATH."
267 << LL_ENDL;
268 return;
269 }
270
271 LL_DEBUGS("MediaImpl") << "Imprudence is installed at "
272 << imp_dir << LL_ENDL;
273
274 // ":" on Mac and 'Nix, ";" on Windows
275 std::string separator = G_SEARCHPATH_SEPARATOR_S;
276
277 // Grab the current path, if it's set.
278 std::string old_plugin_path = "";
279 char *old_path = getenv("GST_PLUGIN_PATH");
280 if(old_path == NULL)
281 {
282 LL_DEBUGS("MediaImpl") << "Did not find user-set GST_PLUGIN_PATH."
283 << LL_ENDL;
284 }
285 else
286 {
287 old_plugin_path = separator + std::string( old_path );
288 }
289
290
291 // Search both Imprudence and Imprudence\lib\gstreamer-plugins.
292 // But we also want to search the path the user has set, if any.
293 std::string plugin_path =
294#if LL_WINDOWS
295 imp_dir + "\\lib\\gstreamer-plugins" +
296#elif LL_DARWIN
297 imp_dir + separator +
298 imp_dir + "/../Resources/lib/gstreamer-plugins" +
299#endif
300 old_plugin_path;
301
302 int put_result;
303
304 // Place GST_PLUGIN_PATH in the environment settings
305#if LL_WINDOWS
306 put_result = _putenv_s( "GST_PLUGIN_PATH", (char*)plugin_path.c_str() );
307#elif LL_DARWIN
308 put_result = setenv( "GST_PLUGIN_PATH", (char*)plugin_path.c_str(), 1 );
309#endif
310
311 if( put_result == -1 )
312 {
313 LL_WARNS("MediaImpl") << "Setting GST_PLUGIN_PATH failed!" << LL_ENDL;
314 }
315 else
316 {
317 LL_DEBUGS("MediaImpl") << "GST_PLUGIN_PATH set to "
318 << getenv("GST_PLUGIN_PATH") << LL_ENDL;
319 }
320
321 // Don't load system plugins. We only want to use ours, to avoid conflicts.
322#if LL_WINDOWS
323 put_result = _putenv_s( "GST_PLUGIN_SYSTEM_PATH", "" );
324#elif LL_DARWIN
325 put_result = setenv( "GST_PLUGIN_SYSTEM_PATH", "", 1 );
326#endif
327
328 if( put_result == -1 )
329 {
330 LL_WARNS("MediaImpl") << "Setting GST_PLUGIN_SYSTEM_PATH=\"\" failed!"
331 << LL_ENDL;
332 }
333
334#endif // LL_WINDOWS || LL_DARWIN
335}
336
337
338void LLMediaImplGStreamer::gstreamer_log(GstDebugCategory *category,
339 GstDebugLevel level,
340 const gchar *file,
341 const gchar *function,
342 gint line,
343 GObject *object,
344 GstDebugMessage *message,
345 gpointer data)
346{
347 std::stringstream log(std::stringstream::out);
348
349 // Log format example:
350 //
351 // GST_ELEMENT_PADS: removing pad 'sink' (in gstelement.c:757:gst_element_remove_pad)
352 //
353 log << gst_debug_category_get_name( category ) << ": "
354 << gst_debug_message_get(message) << " "
355 << "(in " << file << ":" << line << ":" << function << ")";
356
357 switch( level )
358 {
359 case GST_LEVEL_ERROR:
360 LL_WARNS("MediaImpl") << "(ERROR) " << log.str() << LL_ENDL;
361 break;
362 case GST_LEVEL_WARNING:
363 LL_WARNS("MediaImpl") << log.str() << LL_ENDL;
364 break;
365 case GST_LEVEL_DEBUG:
366 LL_DEBUGS("MediaImpl") << log.str() << LL_ENDL;
367 break;
368 case GST_LEVEL_INFO:
369 LL_INFOS("MediaImpl") << log.str() << LL_ENDL;
370 break;
371 default:
372 // Do nothing.
373 break;
374 }
375}
376
377
378bool LLMediaImplGStreamer::closedown()
379{
380 return true;
381}
382
383
384bool LLMediaImplGStreamer::setDebugLevel( LLMediaBase::EDebugLevel level )
385{
386 // Do parent class stuff.
387 LLMediaImplCommon::setDebugLevel(level);
388
389 // Set GStreamer verbosity.
390 gst_debug_set_default_threshold( (GstDebugLevel)level );
391
392 return true;
393}
394
395
396///////////////////////////////////////////////////////////////////////////////
397//
398// Uncomment the line below to enable spammy debug data.
399//#define LL_GST_REPORT_STATE_CHANGES
400#ifdef LL_GST_REPORT_STATE_CHANGES
401static const char* get_gst_state_name(GstState state)
402{
403 switch (state)
404 {
405 case GST_STATE_VOID_PENDING: return "VOID_PENDING";
406 case GST_STATE_NULL: return "NULL";
407 case GST_STATE_READY: return "READY";
408 case GST_STATE_PAUSED: return "PAUSED";
409 case GST_STATE_PLAYING: return "PLAYING";
410 }
411 return "(unknown)";
412}
413#endif // LL_GST_REPORT_STATE_CHANGES
414
415//static
416gboolean LLMediaImplGStreamer::bus_callback(GstBus *bus, GstMessage *message, gpointer data)
417{
418#ifdef LL_GST_REPORT_STATE_CHANGES
419 LL_DEBUGS("MediaCallback") << "Got GST message type: " << GST_MESSAGE_TYPE_NAME (message) << LL_ENDL;
420#endif
421
422 LLMediaImplGStreamer *impl = (LLMediaImplGStreamer*)data;
423
424 switch (GST_MESSAGE_TYPE (message))
425 {
426 case GST_MESSAGE_BUFFERING:
427 {
428 gint percent = 0;
429 gst_message_parse_buffering(message, &percent);
430#ifdef LL_GST_REPORT_STATE_CHANGES
431 LL_DEBUGS("MediaBuffering") << "GST buffering: " << percent << "%%" << LL_ENDL;
432#endif
433 LLMediaEvent event( impl, percent );
434 impl->getEventEmitter().update( &LLMediaObserver::onUpdateProgress, event );
435 }
436 break;
437 case GST_MESSAGE_STATE_CHANGED:
438 {
439 GstState old_state;
440 GstState new_state;
441 GstState pending_state;
442 gst_message_parse_state_changed(message,
443 &old_state,
444 &new_state,
445 &pending_state);
446#ifdef LL_GST_REPORT_STATE_CHANGES
447 // not generally very useful, and rather spammy.
448 LL_DEBUGS("MediaState") << "GST state change (old,<new>,pending): "<< get_gst_state_name(old_state) << ",<" << get_gst_state_name(new_state) << ">," << get_gst_state_name(pending_state) << LL_ENDL;
449#endif // LL_GST_REPORT_STATE_CHANGES
450
451 switch (new_state)
452 {
453 case GST_STATE_VOID_PENDING:
454 break;
455 case GST_STATE_NULL:
456#ifdef LL_GST_REPORT_STATE_CHANGES
457 LL_DEBUGS("MediaImpl") << "State changed to NULL" << LL_ENDL;
458#endif
459 if (impl->getState() == GST_STATE_PLAYING)
460 {
461 // Stream was probably dropped, trying to restart
462 impl->play();
463#ifdef LL_GST_REPORT_STATE_CHANGES
464 LL_DEBUGS("MediaImpl") << "Trying to restart." << LL_ENDL;
465#endif
466 }
467 break;
468 case GST_STATE_READY:
469 break;
470 case GST_STATE_PAUSED:
471 break;
472 case GST_STATE_PLAYING:
473 //impl->mLastTitle = "";
474
475 LLMediaEvent event( impl, 100 );
476 impl->getEventEmitter().update( &LLMediaObserver::onUpdateProgress, event );
477 // emit an event to say that a media source was loaded
478 LLMediaEvent event2( impl );
479 impl->getEventEmitter().update( &LLMediaObserver::onMediaLoaded, event2 );
480 break;
481 }
482 break;
483 }
484 case GST_MESSAGE_ERROR:
485 {
486 GError *err = NULL;
487 gchar *debug = NULL;
488
489 gst_message_parse_error (message, &err, &debug);
490 LL_WARNS("MediaImpl") << "GST Error: " << err->message << LL_ENDL;
491 g_error_free (err);
492 g_free (debug);
493
494 impl->addCommand(LLMediaBase::COMMAND_STOP);
495 //impl->addCommand(LLMediaBase::COMMAND_START);
496
497 break;
498 }
499 case GST_MESSAGE_INFO:
500 {
501 GError *err = NULL;
502 gchar *debug = NULL;
503
504 gst_message_parse_info (message, &err, &debug);
505 LL_INFOS("MediaImpl") << "GST info: " << err->message
506 << LL_ENDL;
507 g_error_free (err);
508 g_free (debug);
509 break;
510 }
511 case GST_MESSAGE_WARNING:
512 {
513 GError *err = NULL;
514 gchar *debug = NULL;
515
516 gst_message_parse_warning (message, &err, &debug);
517 LL_WARNS("MediaImpl") << "GST warning: " << err->message
518 << LL_ENDL;
519 g_error_free (err);
520 g_free (debug);
521
522 break;
523 }
524 case GST_MESSAGE_TAG:
525 {
526 GstTagList *new_tags;
527
528 gst_message_parse_tag( message, &new_tags );
529
530 gchar *title;
531
532 if ( gst_tag_list_get_string(new_tags, GST_TAG_TITLE, &title) )
533 {
534 LL_INFOS("MediaInfo") << "Title: " << title << LL_ENDL;
535 std::string newtitle(title);
536 gst_tag_list_free(new_tags);
537
538 if ( newtitle != impl->mLastTitle && newtitle != "" )
539 {
540 impl->mLastTitle = newtitle;
541 LLMediaEvent event( impl, impl->mLastTitle );
542 impl->getEventEmitter().update( &LLMediaObserver::onMediaTitleChange, event );
543 }
544
545 g_free(title);
546 }
547
548 break;
549 }
550 case GST_MESSAGE_EOS:
551 {
552 /* end-of-stream */
553 LL_DEBUGS("MediaImpl") << "GST end-of-stream." << LL_ENDL;
554 if (impl->isLooping())
555 {
556 LL_DEBUGS("MediaImpl") << "looping media..." << LL_ENDL;
557 impl->stop();
558 impl->play();
559 }
560 else
561 {
562 // inject a COMMAND_STOP
563 impl->addCommand(LLMediaBase::COMMAND_STOP);
564 }
565 break;
566 }
567 default:
568 /* unhandled message */
569 break;
570 }
571 /* we want to be notified again the next time there is a message
572 * on the bus, so return true (false means we want to stop watching
573 * for messages on the bus and our callback should not be called again)
574 */
575 return TRUE;
576}
577
578///////////////////////////////////////////////////////////
579// virtual
580bool LLMediaImplGStreamer::navigateTo (const std::string urlIn)
581{
582 LL_DEBUGS("MediaImpl") << "Setting media URI: " << urlIn.c_str()
583 << LL_ENDL;
584
585 if (mPump == NULL || mPlaybin == NULL)
586 {
587 return false;
588 }
589
590 setStatus( LLMediaBase::STATUS_NAVIGATING );
591
592 // set URI
593 g_object_set (G_OBJECT (mPlaybin), "uri", urlIn.c_str(), (void*)NULL);
594
595 // get playbin's bus - perhaps this can/should be done in ctor
596 GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (mPlaybin));
597 if (!bus)
598 {
599 return false;
600 }
601 gst_bus_add_watch (bus, bus_callback, this);
602 gst_object_unref (bus);
603
604 mState = GST_STATE_READY;
605
606 return true;
607}
608
609///////////////////////////////////////////////////////////////////////////////
610//
611bool LLMediaImplGStreamer::unload()
612{
613 LL_DEBUGS("MediaImpl") << "unloading media..." << LL_ENDL;
614 if (mPlaybin)
615 {
616 gst_element_set_state (mPlaybin, GST_STATE_NULL);
617 mState = GST_STATE_NULL;
618 gst_object_unref (GST_OBJECT (mPlaybin));
619 mPlaybin = NULL;
620 }
621
622 if (mPump)
623 {
624 g_main_loop_quit(mPump);
625 mPump = NULL;
626 }
627
628 if (mediaData)
629 {
630 delete [] mediaData;
631 mediaData = NULL;
632 }
633
634 mVideoSink = NULL;
635 mState = GST_STATE_NULL;
636 setStatus(LLMediaBase::STATUS_UNKNOWN);
637
638 return true;
639}
640
641///////////////////////////////////////////////////////////////////////////////
642// virtual
643bool LLMediaImplGStreamer::updateMedia()
644{
645 //LL_DEBUGS("MediaImpl") << "updating media..." << LL_ENDL;
646
647 // sanity check
648 if (mPump == NULL || mPlaybin == NULL)
649 {
650#ifdef LL_GST_REPORT_STATE_CHANGES
651 LL_DEBUGS("MediaImpl") << "dead media..." << LL_ENDL;
652#endif
653 mState = GST_STATE_NULL;
654 setStatus(LLMediaBase::STATUS_DEAD);
655 return false;
656 }
657
658 if (mState == GST_STATE_VOID_PENDING || mState == GST_STATE_NULL)
659 return false;
660
661 // process next outstanding command
662 switch (nextCommand())
663 {
664 case LLMediaBase::COMMAND_START:
665 LL_DEBUGS("MediaImpl") << "COMMAND_START" << LL_ENDL;
666 if (getStatus() == LLMediaBase::STATUS_PAUSED ||
667 getStatus() == LLMediaBase::STATUS_NAVIGATING ||
668 getStatus() == LLMediaBase::STATUS_STOPPED)
669 {
670 play();
671 setStatus(LLMediaBase::STATUS_STARTED);
672 clearCommand();
673 }
674 break;
675 case LLMediaBase::COMMAND_STOP:
676 LL_DEBUGS("MediaImpl") << "COMMAND_STOP" << LL_ENDL;
677 stop();
678 setStatus(LLMediaBase::STATUS_STOPPED);
679 clearCommand();
680 break;
681 case LLMediaBase::COMMAND_PAUSE:
682 LL_DEBUGS("MediaImpl") << "COMMAND_PAUSE" << LL_ENDL;
683 if (getStatus() == LLMediaBase::STATUS_STARTED)
684 {
685 pause();
686 setStatus(LLMediaBase::STATUS_PAUSED);
687 clearCommand();
688 }
689 break;
690 default:
691 LL_INFOS("MediaImpl") << "Unknown command" << LL_ENDL;
692 clearCommand();
693 break;
694 case LLMediaBase::COMMAND_NONE:
695 break;
696 }
697
698 // deal with results
699 if (g_main_context_pending(g_main_loop_get_context(mPump)))
700 {
701 g_main_context_iteration(g_main_loop_get_context(mPump), FALSE);
702 }
703
704 if (mVideoSink)
705 {
706 GST_OBJECT_LOCK(mVideoSink);
707 if (mVideoSink->retained_frame_ready)
708 {
709#ifdef LL_GST_REPORT_STATE_CHANGES
710 LL_DEBUGS("MediaImpl") <<"NEW FRAME " << LL_ENDL;
711#endif
712 if (mVideoSink->retained_frame_width != getMediaWidth() ||
713 mVideoSink->retained_frame_height != getMediaHeight())
714 // *TODO: also check for change in format
715 {
716 // just resize containe
717 int neww = mVideoSink->retained_frame_width;
718 int newh = mVideoSink->retained_frame_height;
719 int newd = SLVPixelFormatBytes[mVideoSink->retained_frame_format];
720 if (SLV_PF_RGBX == mVideoSink->retained_frame_format)
721 {
722 mTextureFormatPrimary = LL_MEDIA_RGBA;
723 mTextureFormatType = LL_MEDIA_UNSIGNED_INT_8_8_8_8_REV;
724 }
725 else
726 {
727 mTextureFormatPrimary = LL_MEDIA_BGRA;
728 mTextureFormatType = LL_MEDIA_UNSIGNED_INT_8_8_8_8_REV;
729 }
730 mMediaRowbytes = neww * newd;
731 LL_DEBUGS("MediaImpl")
732 << "video container resized to " <<
733 neww <<"x"<< newh << LL_ENDL;
734
735 delete[] mediaData;
736 mediaData = new unsigned char[mMediaRowbytes *
737 newh];
738
739 GST_OBJECT_UNLOCK(mVideoSink);
740
741 setMediaDepth(newd);
742 setMediaSize(neww, newh);
743 return true;
744 }
745
746 // we're gonna totally consume this frame - reset 'ready' flag
747 mVideoSink->retained_frame_ready = FALSE;
748 memcpy(mediaData, mVideoSink->retained_frame_data,
749 mMediaRowbytes * getMediaHeight());
750
751 GST_OBJECT_UNLOCK(mVideoSink);
752 LLMediaEvent event( this );
753 mEventEmitter.update( &LLMediaObserver::onMediaContentsChange, event );
754 return true;
755 }
756 else
757 {
758 // nothing to do yet.
759 GST_OBJECT_UNLOCK(mVideoSink);
760 return true;
761 }
762 }
763
764 return true;
765}
766
767///////////////////////////////////////////////////////////////////////////////
768//
769bool LLMediaImplGStreamer::stop()
770{
771 LL_DEBUGS("MediaImpl") << "attempting to stop..." << LL_ENDL;
772
773 if (!mPlaybin || mState == GST_STATE_NULL)
774 return true;
775
776 GstStateChangeReturn state_change;
777
778 state_change = gst_element_set_state(mPlaybin, GST_STATE_READY);
779
780 LL_DEBUGS("MediaImpl") << gst_element_state_change_return_get_name(state_change) << LL_ENDL;
781
782 if (state_change == GST_STATE_CHANGE_FAILURE)
783 {
784 LL_WARNS("MediaImpl") << "could not stop stream!" << LL_ENDL;
785 return false;
786 }
787 else
788 {
789 // Going into pending after play keeps dead streams from looping
790 (mState == GST_STATE_PLAYING) ? (mState = GST_STATE_VOID_PENDING) : (mState = GST_STATE_READY);
791 return true;
792 }
793}
794
795///////////////////////////////////////////////////////////////////////////////
796//
797bool LLMediaImplGStreamer::play()
798{
799 LL_DEBUGS("MediaImpl") << "attempting to play..." << LL_ENDL;
800
801 if (!mPlaybin || mState == GST_STATE_NULL)
802 return true;
803
804
805 if( getState() == GST_STATE_PLAYING )
806 {
807 LL_DEBUGS("MediaImpl") << "... but already playing." << LL_ENDL;
808 return true;
809 }
810
811 // Clean up the existing thread, if any.
812 if( mPlayThread != NULL && mPlayThread->isStopped())
813 {
814 delete mPlayThread;
815 mPlayThread = NULL;
816 }
817
818 if( mPlayThread == NULL )
819 {
820 // Make a new thread to start playing. This keeps the viewer
821 // responsive while the stream is resolved and buffered.
822 mPlayThread = new LLGstPlayThread( (LLMediaImplCommon *)this, "GstPlayThread", NULL);
823 mPlayThread->start();
824 }
825
826 return true;
827}
828
829
830void LLMediaImplGStreamer::startPlay()
831{
832 GstStateChangeReturn state_change;
833
834 state_change = gst_element_set_state(mPlaybin, GST_STATE_PLAYING);
835 mState = GST_STATE_PLAYING;
836
837 LL_DEBUGS("MediaImpl") << gst_element_state_change_return_get_name(state_change) << LL_ENDL;
838
839 // Check to make sure playing was successful. If not, stop.
840 // NOTE: state_change is almost always GST_STATE_CHANGE_ASYNC
841 if (state_change == GST_STATE_CHANGE_FAILURE)
842 {
843 // If failing from a bad stream, go into an unknown
844 // state to stop bus_callback from looping back.
845 // We also force a stop in case the operations don't sync
846 setStatus(LLMediaBase::STATUS_UNKNOWN);
847 stop();
848 }
849}
850
851///////////////////////////////////////////////////////////////////////////////
852//
853bool LLMediaImplGStreamer::pause()
854{
855 LL_DEBUGS("MediaImpl") << "attempting to pause..." << LL_ENDL;
856
857 if (!mPlaybin || mState == GST_STATE_NULL)
858 return true;
859
860 GstStateChangeReturn state_change;
861
862 state_change = gst_element_set_state(mPlaybin, GST_STATE_PAUSED);
863
864 LL_DEBUGS("MediaImpl") << gst_element_state_change_return_get_name(state_change) << LL_ENDL;
865
866 if (state_change == GST_STATE_CHANGE_FAILURE)
867 {
868 LL_WARNS("MediaImpl") << "could not pause stream!" << LL_ENDL;
869 return false;
870 }
871 else
872 {
873 mState = GST_STATE_PAUSED;
874 return true;
875 }
876};
877
878
879///////////////////////////////////////////////////////////////////////////////
880// virtual
881unsigned char* LLMediaImplGStreamer::getMediaData()
882{
883 return mediaData;
884}
885
886
887///////////////////////////////////////////////////////////////////////////////
888// virtual
889bool LLMediaImplGStreamer::seek(double time)
890{
891 bool success = false;
892 if (mPlaybin)
893 {
894 success = gst_element_seek(mPlaybin, 1.0F, GST_FORMAT_TIME,
895 GstSeekFlags(GST_SEEK_FLAG_FLUSH |
896 GST_SEEK_FLAG_KEY_UNIT),
897 GST_SEEK_TYPE_SET, gint64(time*1000000000.0F),
898 GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
899 }
900 LL_DEBUGS("MediaImpl") << "MEDIA SEEK REQUEST to " << float(time)
901 << "sec result was " << int(success) << LL_ENDL;
902 return success;
903}
904
905
906///////////////////////////////////////////////////////////////////////////////
907// virtual
908bool LLMediaImplGStreamer::setVolume(float volume)
909{
910 // we try to only update volume as conservatively as
911 // possible, as many gst-plugins-base versions up to at least
912 // November 2008 have critical race-conditions in setting volume - sigh
913 if (mVolume == volume)
914 return true; // nothing to do, everything's fine
915
916 mVolume = volume;
917 if (mPlaybin)
918 {
919 g_object_set(mPlaybin, "volume", mVolume, (void*)NULL);
920 return true;
921 }
922
923 return false;
924}
925
926
927
928///#endif // LL_GSTREAMER_ENABLED
diff --git a/linden/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp~ b/linden/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp~
deleted file mode 100755
index 7d34a1e..0000000
--- a/linden/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp~
+++ /dev/null
@@ -1,1219 +0,0 @@
1/**
2 * @file media_plugin_gstreamer010.cpp
3 * @brief GStreamer-0.10 plugin for LLMedia API plugin system
4 *
5 * @cond
6 * $LicenseInfo:firstyear=2007&license=viewergpl$
7 *
8 * Copyright (c) 2007-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#include "linden_common.h"
37
38#include "llgl.h"
39
40#include "llplugininstance.h"
41#include "llpluginmessage.h"
42#include "llpluginmessageclasses.h"
43#include "media_plugin_base.h"
44
45#if LL_GSTREAMER010_ENABLED
46
47extern "C" {
48#include <gst/gst.h>
49}
50
51#include "llmediaimplgstreamer.h"
52#include "llmediaimplgstreamertriviallogging.h"
53
54#include "llmediaimplgstreamervidplug.h"
55
56#include "llmediaimplgstreamer_syms.h"
57
58//////////////////////////////////////////////////////////////////////////////
59//
60class MediaPluginGStreamer010 : public MediaPluginBase
61{
62public:
63 MediaPluginGStreamer010(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data);
64 ~MediaPluginGStreamer010();
65
66 /* virtual */ void receiveMessage(const char *message_string);
67
68 static bool startup();
69 static bool closedown();
70
71 gboolean processGSTEvents(GstBus *bus,
72 GstMessage *message);
73
74private:
75 std::string getVersion();
76 bool navigateTo( const std::string urlIn );
77 bool seek( double time_sec );
78 bool setVolume( float volume );
79
80 // misc
81 bool pause();
82 bool stop();
83 bool play(double rate);
84 bool getTimePos(double &sec_out);
85
86 static const double MIN_LOOP_SEC = 1.0F;
87
88 bool mIsLooping;
89
90 enum ECommand {
91 COMMAND_NONE,
92 COMMAND_STOP,
93 COMMAND_PLAY,
94 COMMAND_FAST_FORWARD,
95 COMMAND_FAST_REWIND,
96 COMMAND_PAUSE,
97 COMMAND_SEEK,
98 };
99 ECommand mCommand;
100
101private:
102 bool unload();
103 bool load();
104
105 bool update(int milliseconds);
106 void mouseDown( int x, int y );
107 void mouseUp( int x, int y );
108 void mouseMove( int x, int y );
109
110 void sizeChanged();
111
112 static bool mDoneInit;
113
114 guint mBusWatchID;
115
116 float mVolume;
117
118 int mDepth;
119
120 // media NATURAL size
121 int mNaturalWidth;
122 int mNaturalHeight;
123 // media current size
124 int mCurrentWidth;
125 int mCurrentHeight;
126 int mCurrentRowbytes;
127 // previous media size so we can detect changes
128 int mPreviousWidth;
129 int mPreviousHeight;
130 // desired render size from host
131 int mWidth;
132 int mHeight;
133 // padded texture size we need to write into
134 int mTextureWidth;
135 int mTextureHeight;
136
137 int mTextureFormatPrimary;
138 int mTextureFormatType;
139
140 bool mSeekWanted;
141 double mSeekDestination;
142
143 // Very GStreamer-specific
144 GMainLoop *mPump; // event pump for this media
145 GstElement *mPlaybin;
146 GstSLVideo *mVideoSink;
147};
148
149//static
150bool MediaPluginGStreamer010::mDoneInit = false;
151
152MediaPluginGStreamer010::MediaPluginGStreamer010(
153 LLPluginInstance::sendMessageFunction host_send_func,
154 void *host_user_data ) :
155 MediaPluginBase(host_send_func, host_user_data),
156 mBusWatchID ( 0 ),
157 mCurrentRowbytes ( 4 ),
158 mTextureFormatPrimary ( GL_RGBA ),
159 mTextureFormatType ( GL_UNSIGNED_INT_8_8_8_8_REV ),
160 mSeekWanted(false),
161 mSeekDestination(0.0),
162 mPump ( NULL ),
163 mPlaybin ( NULL ),
164 mVideoSink ( NULL ),
165 mCommand ( COMMAND_NONE )
166{
167 std::ostringstream str;
168 INFOMSG("MediaPluginGStreamer010 constructor - my PID=%u", U32(getpid()));
169}
170
171///////////////////////////////////////////////////////////////////////////////
172//
173//#define LL_GST_REPORT_STATE_CHANGES
174#ifdef LL_GST_REPORT_STATE_CHANGES
175static char* get_gst_state_name(GstState state)
176{
177 switch (state) {
178 case GST_STATE_VOID_PENDING: return "VOID_PENDING";
179 case GST_STATE_NULL: return "NULL";
180 case GST_STATE_READY: return "READY";
181 case GST_STATE_PAUSED: return "PAUSED";
182 case GST_STATE_PLAYING: return "PLAYING";
183 }
184 return "(unknown)";
185}
186#endif // LL_GST_REPORT_STATE_CHANGES
187
188gboolean
189MediaPluginGStreamer010::processGSTEvents(GstBus *bus,
190 GstMessage *message)
191{
192 if (!message)
193 return TRUE; // shield against GStreamer bug
194
195 if (GST_MESSAGE_TYPE(message) != GST_MESSAGE_STATE_CHANGED &&
196 GST_MESSAGE_TYPE(message) != GST_MESSAGE_BUFFERING)
197 {
198 DEBUGMSG("Got GST message type: %s",
199 LLGST_MESSAGE_TYPE_NAME (message));
200 }
201 else
202 {
203 // TODO: grok 'duration' message type
204 DEBUGMSG("Got GST message type: %s",
205 LLGST_MESSAGE_TYPE_NAME (message));
206 }
207
208 switch (GST_MESSAGE_TYPE (message)) {
209 case GST_MESSAGE_BUFFERING: {
210 // NEEDS GST 0.10.11+
211 if (llgst_message_parse_buffering)
212 {
213 gint percent = 0;
214 llgst_message_parse_buffering(message, &percent);
215 DEBUGMSG("GST buffering: %d%%", percent);
216 }
217 break;
218 }
219 case GST_MESSAGE_STATE_CHANGED: {
220 GstState old_state;
221 GstState new_state;
222 GstState pending_state;
223 llgst_message_parse_state_changed(message,
224 &old_state,
225 &new_state,
226 &pending_state);
227#ifdef LL_GST_REPORT_STATE_CHANGES
228 // not generally very useful, and rather spammy.
229 DEBUGMSG("state change (old,<new>,pending): %s,<%s>,%s",
230 get_gst_state_name(old_state),
231 get_gst_state_name(new_state),
232 get_gst_state_name(pending_state));
233#endif // LL_GST_REPORT_STATE_CHANGES
234
235 switch (new_state) {
236 case GST_STATE_VOID_PENDING:
237 break;
238 case GST_STATE_NULL:
239 break;
240 case GST_STATE_READY:
241 setStatus(STATUS_LOADED);
242 break;
243 case GST_STATE_PAUSED:
244 setStatus(STATUS_PAUSED);
245 break;
246 case GST_STATE_PLAYING:
247 setStatus(STATUS_PLAYING);
248 break;
249 }
250 break;
251 }
252 case GST_MESSAGE_ERROR: {
253 GError *err = NULL;
254 gchar *debug = NULL;
255
256 llgst_message_parse_error (message, &err, &debug);
257 WARNMSG("GST error: %s", err?err->message:"(unknown)");
258 if (err)
259 g_error_free (err);
260 g_free (debug);
261
262 mCommand = COMMAND_STOP;
263
264 setStatus(STATUS_ERROR);
265
266 break;
267 }
268 case GST_MESSAGE_INFO: {
269 if (llgst_message_parse_info)
270 {
271 GError *err = NULL;
272 gchar *debug = NULL;
273
274 llgst_message_parse_info (message, &err, &debug);
275 INFOMSG("GST info: %s", err?err->message:"(unknown)");
276 if (err)
277 g_error_free (err);
278 g_free (debug);
279 }
280 break;
281 }
282 case GST_MESSAGE_WARNING: {
283 GError *err = NULL;
284 gchar *debug = NULL;
285
286 llgst_message_parse_warning (message, &err, &debug);
287 WARNMSG("GST warning: %s", err?err->message:"(unknown)");
288 if (err)
289 g_error_free (err);
290 g_free (debug);
291
292 break;
293 }
294 case GST_MESSAGE_EOS:
295 /* end-of-stream */
296 DEBUGMSG("GST end-of-stream.");
297 if (mIsLooping)
298 {
299 DEBUGMSG("looping media...");
300 double eos_pos_sec = 0.0F;
301 bool got_eos_position = getTimePos(eos_pos_sec);
302
303 if (got_eos_position && eos_pos_sec < MIN_LOOP_SEC)
304 {
305 // if we know that the movie is really short, don't
306 // loop it else it can easily become a time-hog
307 // because of GStreamer spin-up overhead
308 DEBUGMSG("really short movie (%0.3fsec) - not gonna loop this, pausing instead.", eos_pos_sec);
309 // inject a COMMAND_PAUSE
310 mCommand = COMMAND_PAUSE;
311 }
312 else
313 {
314#undef LLGST_LOOP_BY_SEEKING
315// loop with a stop-start instead of a seek, because it actually seems rather
316// faster than seeking on remote streams.
317#ifdef LLGST_LOOP_BY_SEEKING
318 // first, try looping by an explicit rewind
319 bool seeksuccess = seek(0.0);
320 if (seeksuccess)
321 {
322 play(1.0);
323 }
324 else
325#endif // LLGST_LOOP_BY_SEEKING
326 { // use clumsy stop-start to loop
327 DEBUGMSG("didn't loop by rewinding - stopping and starting instead...");
328 stop();
329 play(1.0);
330 }
331 }
332 }
333 else // not a looping media
334 {
335 // inject a COMMAND_STOP
336 mCommand = COMMAND_STOP;
337 }
338 break;
339 default:
340 /* unhandled message */
341 break;
342 }
343
344 /* we want to be notified again the next time there is a message
345 * on the bus, so return true (false means we want to stop watching
346 * for messages on the bus and our callback should not be called again)
347 */
348 return TRUE;
349}
350
351extern "C" {
352gboolean
353llmediaimplgstreamer_bus_callback (GstBus *bus,
354 GstMessage *message,
355 gpointer data)
356{
357 MediaPluginGStreamer010 *impl = (MediaPluginGStreamer010*)data;
358 return impl->processGSTEvents(bus, message);
359}
360} // extern "C"
361
362
363
364bool
365MediaPluginGStreamer010::navigateTo ( const std::string urlIn )
366{
367 if (!mDoneInit)
368 return false; // error
369
370 setStatus(STATUS_LOADING);
371
372 DEBUGMSG("Setting media URI: %s", urlIn.c_str());
373
374 mSeekWanted = false;
375
376 if (NULL == mPump ||
377 NULL == mPlaybin)
378 {
379 setStatus(STATUS_ERROR);
380 return false; // error
381 }
382
383 // set URI
384 g_object_set (G_OBJECT (mPlaybin), "uri", urlIn.c_str(), NULL);
385 //g_object_set (G_OBJECT (mPlaybin), "uri", "file:///tmp/movie", NULL);
386
387 // navigateTo implicitly plays, too.
388 play(1.0);
389
390 return true;
391}
392
393
394bool
395MediaPluginGStreamer010::update(int milliseconds)
396{
397 if (!mDoneInit)
398 return false; // error
399
400 DEBUGMSG("updating media...");
401
402 // sanity check
403 if (NULL == mPump ||
404 NULL == mPlaybin)
405 {
406 DEBUGMSG("dead media...");
407 return false;
408 }
409
410 // see if there's an outstanding seek wanted
411 if (mSeekWanted &&
412 // bleh, GST has to be happy that the movie is really truly playing
413 // or it may quietly ignore the seek (with rtsp:// at least).
414 (GST_STATE(mPlaybin) == GST_STATE_PLAYING))
415 {
416 seek(mSeekDestination);
417 mSeekWanted = false;
418 }
419
420 // *TODO: time-limit - but there isn't a lot we can do here, most
421 // time is spent in gstreamer's own opaque worker-threads. maybe
422 // we can do something sneaky like only unlock the video object
423 // for 'milliseconds' and otherwise hold the lock.
424 while (g_main_context_pending(g_main_loop_get_context(mPump)))
425 {
426 g_main_context_iteration(g_main_loop_get_context(mPump), FALSE);
427 }
428
429 // check for availability of a new frame
430
431 if (mVideoSink)
432 {
433 GST_OBJECT_LOCK(mVideoSink);
434 if (mVideoSink->retained_frame_ready)
435 {
436 DEBUGMSG("NEW FRAME READY");
437
438 if (mVideoSink->retained_frame_width != mCurrentWidth ||
439 mVideoSink->retained_frame_height != mCurrentHeight)
440 // *TODO: also check for change in format
441 {
442 // just resize container, don't consume frame
443 int neww = mVideoSink->retained_frame_width;
444 int newh = mVideoSink->retained_frame_height;
445
446 int newd = 4;
447 mTextureFormatPrimary = GL_RGBA;
448 mTextureFormatType = GL_UNSIGNED_INT_8_8_8_8_REV;
449
450 /*
451 int newd = SLVPixelFormatBytes[mVideoSink->retained_frame_format];
452 if (SLV_PF_BGRX == mVideoSink->retained_frame_format)
453 {
454 mTextureFormatPrimary = GL_BGRA;
455 mTextureFormatType = GL_UNSIGNED_INT_8_8_8_8_REV;
456 }
457 else
458 {
459 mTextureFormatPrimary = GL_RGBA;
460 mTextureFormatType = GL_UNSIGNED_INT_8_8_8_8_REV;
461 }
462 */
463
464 GST_OBJECT_UNLOCK(mVideoSink);
465
466 mCurrentRowbytes = neww * newd;
467 DEBUGMSG("video container resized to %dx%d",
468 neww, newh);
469
470 mDepth = newd;
471 mCurrentWidth = neww;
472 mCurrentHeight = newh;
473 sizeChanged();
474 return true;
475 }
476
477 if (mPixels &&
478 mCurrentHeight <= mHeight &&
479 mCurrentWidth <= mWidth &&
480 !mTextureSegmentName.empty())
481 {
482 // we're gonna totally consume this frame - reset 'ready' flag
483 mVideoSink->retained_frame_ready = FALSE;
484 int destination_rowbytes = mWidth * mDepth;
485 for (int row=0; row<mCurrentHeight; ++row)
486 {
487 memcpy(&mPixels
488 [destination_rowbytes * row],
489 &mVideoSink->retained_frame_data
490 [mCurrentRowbytes * row],
491 mCurrentRowbytes);
492 }
493
494 GST_OBJECT_UNLOCK(mVideoSink);
495 DEBUGMSG("NEW FRAME REALLY TRULY CONSUMED, TELLING HOST");
496
497 setDirty(0,0,mCurrentWidth,mCurrentHeight);
498 }
499 else
500 {
501 // new frame ready, but we're not ready to
502 // consume it.
503
504 GST_OBJECT_UNLOCK(mVideoSink);
505
506 DEBUGMSG("NEW FRAME not consumed, still waiting for a shm segment and/or shm resize");
507 }
508
509 return true;
510 }
511 else
512 {
513 // nothing to do yet.
514 GST_OBJECT_UNLOCK(mVideoSink);
515 return true;
516 }
517 }
518
519 return true;
520}
521
522
523void
524MediaPluginGStreamer010::mouseDown( int x, int y )
525{
526 // do nothing
527}
528
529void
530MediaPluginGStreamer010::mouseUp( int x, int y )
531{
532 // do nothing
533}
534
535void
536MediaPluginGStreamer010::mouseMove( int x, int y )
537{
538 // do nothing
539}
540
541
542bool
543MediaPluginGStreamer010::pause()
544{
545 DEBUGMSG("pausing media...");
546 // todo: error-check this?
547 llgst_element_set_state(mPlaybin, GST_STATE_PAUSED);
548 return true;
549}
550
551bool
552MediaPluginGStreamer010::stop()
553{
554 DEBUGMSG("stopping media...");
555 // todo: error-check this?
556 llgst_element_set_state(mPlaybin, GST_STATE_READY);
557 return true;
558}
559
560bool
561MediaPluginGStreamer010::play(double rate)
562{
563 // NOTE: we don't actually support non-natural rate.
564
565 DEBUGMSG("playing media... rate=%f", rate);
566 // todo: error-check this?
567 llgst_element_set_state(mPlaybin, GST_STATE_PLAYING);
568 return true;
569}
570
571bool
572MediaPluginGStreamer010::setVolume( float volume )
573{
574 // we try to only update volume as conservatively as
575 // possible, as many gst-plugins-base versions up to at least
576 // November 2008 have critical race-conditions in setting volume - sigh
577 if (mVolume == volume)
578 return true; // nothing to do, everything's fine
579
580 mVolume = volume;
581 if (mDoneInit && mPlaybin)
582 {
583 g_object_set(mPlaybin, "volume", mVolume, NULL);
584 return true;
585 }
586
587 return false;
588}
589
590bool
591MediaPluginGStreamer010::seek(double time_sec)
592{
593 bool success = false;
594 if (mDoneInit && mPlaybin)
595 {
596 success = llgst_element_seek(mPlaybin, 1.0F, GST_FORMAT_TIME,
597 GstSeekFlags(GST_SEEK_FLAG_FLUSH |
598 GST_SEEK_FLAG_KEY_UNIT),
599 GST_SEEK_TYPE_SET, gint64(time_sec*GST_SECOND),
600 GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
601 }
602 DEBUGMSG("MEDIA SEEK REQUEST to %fsec result was %d",
603 float(time_sec), int(success));
604 return success;
605}
606
607bool
608MediaPluginGStreamer010::getTimePos(double &sec_out)
609{
610 bool got_position = false;
611 if (mPlaybin)
612 {
613 gint64 pos;
614 GstFormat timefmt = GST_FORMAT_TIME;
615 got_position =
616 llgst_element_query_position &&
617 llgst_element_query_position(mPlaybin,
618 &timefmt,
619 &pos);
620 got_position = got_position
621 && (timefmt == GST_FORMAT_TIME);
622 // GStreamer may have other ideas, but we consider the current position
623 // undefined if not PLAYING or PAUSED
624 got_position = got_position &&
625 (GST_STATE(mPlaybin) == GST_STATE_PLAYING ||
626 GST_STATE(mPlaybin) == GST_STATE_PAUSED);
627 if (got_position && !GST_CLOCK_TIME_IS_VALID(pos))
628 {
629 if (GST_STATE(mPlaybin) == GST_STATE_PLAYING)
630 {
631 // if we're playing then we treat an invalid clock time
632 // as 0, for complicated reasons (insert reason here)
633 pos = 0;
634 }
635 else
636 {
637 got_position = false;
638 }
639
640 }
641 // If all the preconditions succeeded... we can trust the result.
642 if (got_position)
643 {
644 sec_out = double(pos) / double(GST_SECOND); // gst to sec
645 }
646 }
647 return got_position;
648}
649
650bool
651MediaPluginGStreamer010::load()
652{
653 if (!mDoneInit)
654 return false; // error
655
656 setStatus(STATUS_LOADING);
657
658 DEBUGMSG("setting up media...");
659
660 mIsLooping = false;
661 mVolume = 0.1234567; // minor hack to force an initial volume update
662
663 // Create a pumpable main-loop for this media
664 mPump = g_main_loop_new (NULL, FALSE);
665 if (!mPump)
666 {
667 setStatus(STATUS_ERROR);
668 return false; // error
669 }
670
671 // instantiate a playbin element to do the hard work
672 mPlaybin = llgst_element_factory_make ("playbin", "play");
673 if (!mPlaybin)
674 {
675 setStatus(STATUS_ERROR);
676 return false; // error
677 }
678
679 // get playbin's bus
680 GstBus *bus = llgst_pipeline_get_bus (GST_PIPELINE (mPlaybin));
681 if (!bus)
682 {
683 setStatus(STATUS_ERROR);
684 return false; // error
685 }
686 mBusWatchID = llgst_bus_add_watch (bus,
687 llmediaimplgstreamer_bus_callback,
688 this);
689 llgst_object_unref (bus);
690
691 if (NULL == getenv("LL_GSTREAMER_EXTERNAL")) {
692 // instantiate a custom video sink
693 mVideoSink =
694 GST_SLVIDEO(llgst_element_factory_make ("private-slvideo", "slvideo"));
695 if (!mVideoSink)
696 {
697 WARNMSG("Could not instantiate private-slvideo element.");
698 // todo: cleanup.
699 setStatus(STATUS_ERROR);
700 return false; // error
701 }
702
703 // connect the pieces
704 g_object_set(mPlaybin, "video-sink", mVideoSink, NULL);
705 }
706
707 return true;
708}
709
710bool
711MediaPluginGStreamer010::unload ()
712{
713 if (!mDoneInit)
714 return false; // error
715
716 DEBUGMSG("unloading media...");
717
718 // stop getting callbacks for this bus
719 g_source_remove(mBusWatchID);
720 mBusWatchID = 0;
721
722 if (mPlaybin)
723 {
724 llgst_element_set_state (mPlaybin, GST_STATE_NULL);
725 llgst_object_unref (GST_OBJECT (mPlaybin));
726 mPlaybin = NULL;
727 }
728
729 if (mPump)
730 {
731 g_main_loop_quit(mPump);
732 mPump = NULL;
733 }
734
735 mVideoSink = NULL;
736
737 setStatus(STATUS_NONE);
738
739 return true;
740}
741
742
743//static
744bool
745MediaPluginGStreamer010::startup()
746{
747 // first - check if GStreamer is explicitly disabled
748 if (NULL != getenv("LL_DISABLE_GSTREAMER"))
749 return false;
750
751 // only do global GStreamer initialization once.
752 if (!mDoneInit)
753 {
754 g_thread_init(NULL);
755
756 // Init the glib type system - we need it.
757 g_type_init();
758
759 // Get symbols!
760#if LL_DARWIN
761 if (! grab_gst_syms("libgstreamer-0.10.dylib",
762 "libgstvideo-0.10.dylib") )
763#elseif LL_WINDOWS
764 if (! grab_gst_syms("libgstreamer-0.10.dll",
765 "libgstvideo-0.10.dll") )
766#else // linux or other ELFy unixoid
767 if (! grab_gst_syms("libgstreamer-0.10.so.0",
768 "libgstvideo-0.10.so.0") )
769#endif
770 {
771 WARNMSG("Couldn't find suitable GStreamer 0.10 support on this system - video playback disabled.");
772 return false;
773 }
774
775 if (llgst_segtrap_set_enabled)
776 {
777 llgst_segtrap_set_enabled(FALSE);
778 }
779 else
780 {
781 WARNMSG("gst_segtrap_set_enabled() is not available; plugin crashes won't be caught.");
782 }
783
784#if LL_LINUX
785 // Gstreamer tries a fork during init, waitpid-ing on it,
786 // which conflicts with any installed SIGCHLD handler...
787 struct sigaction tmpact, oldact;
788 if (llgst_registry_fork_set_enabled) {
789 // if we can disable SIGCHLD-using forking behaviour,
790 // do it.
791 llgst_registry_fork_set_enabled(false);
792 }
793 else {
794 // else temporarily install default SIGCHLD handler
795 // while GStreamer initialises
796 tmpact.sa_handler = SIG_DFL;
797 sigemptyset( &tmpact.sa_mask );
798 tmpact.sa_flags = SA_SIGINFO;
799 sigaction(SIGCHLD, &tmpact, &oldact);
800 }
801#endif // LL_LINUX
802
803 // Protect against GStreamer resetting the locale, yuck.
804 static std::string saved_locale;
805 saved_locale = setlocale(LC_ALL, NULL);
806
807 // finally, try to initialize GStreamer!
808 GError *err = NULL;
809 gboolean init_gst_success = llgst_init_check(NULL, NULL, &err);
810
811 // restore old locale
812 setlocale(LC_ALL, saved_locale.c_str() );
813
814#if LL_LINUX
815 // restore old SIGCHLD handler
816 if (!llgst_registry_fork_set_enabled)
817 sigaction(SIGCHLD, &oldact, NULL);
818#endif // LL_LINUX
819
820 if (!init_gst_success) // fail
821 {
822 if (err)
823 {
824 WARNMSG("GST init failed: %s", err->message);
825 g_error_free(err);
826 }
827 else
828 {
829 WARNMSG("GST init failed for unspecified reason.");
830 }
831 return false;
832 }
833
834 // Init our custom plugins - only really need do this once.
835 gst_slvideo_init_class();
836
837 mDoneInit = true;
838 }
839
840 return true;
841}
842
843
844void
845MediaPluginGStreamer010::sizeChanged()
846{
847 // the shared writing space has possibly changed size/location/whatever
848
849 // Check to see whether the movie's NATURAL size has been set yet
850 if (1 == mNaturalWidth &&
851 1 == mNaturalHeight)
852 {
853 mNaturalWidth = mCurrentWidth;
854 mNaturalHeight = mCurrentHeight;
855 DEBUGMSG("Media NATURAL size better detected as %dx%d",
856 mNaturalWidth, mNaturalHeight);
857 }
858
859 // if the size has changed then the shm has changed and the app needs telling
860 if (mCurrentWidth != mPreviousWidth ||
861 mCurrentHeight != mPreviousHeight)
862 {
863 mPreviousWidth = mCurrentWidth;
864 mPreviousHeight = mCurrentHeight;
865
866 LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_request");
867 message.setValue("name", mTextureSegmentName);
868 message.setValueS32("width", mNaturalWidth);
869 message.setValueS32("height", mNaturalHeight);
870 DEBUGMSG("<--- Sending size change request to application with name: '%s' - natural size is %d x %d", mTextureSegmentName.c_str(), mNaturalWidth, mNaturalHeight);
871 sendMessage(message);
872 }
873}
874
875
876
877//static
878bool
879MediaPluginGStreamer010::closedown()
880{
881 if (!mDoneInit)
882 return false; // error
883
884 ungrab_gst_syms();
885
886 mDoneInit = false;
887
888 return true;
889}
890
891MediaPluginGStreamer010::~MediaPluginGStreamer010()
892{
893 DEBUGMSG("MediaPluginGStreamer010 destructor");
894
895 closedown();
896
897 DEBUGMSG("GStreamer010 closing down");
898}
899
900
901std::string
902MediaPluginGStreamer010::getVersion()
903{
904 std::string plugin_version = "GStreamer010 media plugin, GStreamer version ";
905 if (mDoneInit &&
906 llgst_version)
907 {
908 guint major, minor, micro, nano;
909 llgst_version(&major, &minor, &micro, &nano);
910 plugin_version += llformat("%u.%u.%u.%u (runtime), %u.%u.%u.%u (headers)", (unsigned int)major, (unsigned int)minor, (unsigned int)micro, (unsigned int)nano, (unsigned int)GST_VERSION_MAJOR, (unsigned int)GST_VERSION_MINOR, (unsigned int)GST_VERSION_MICRO, (unsigned int)GST_VERSION_NANO);
911 }
912 else
913 {
914 plugin_version += "(unknown)";
915 }
916 return plugin_version;
917}
918
919void MediaPluginGStreamer010::receiveMessage(const char *message_string)
920{
921 //std::cerr << "MediaPluginGStreamer010::receiveMessage: received message: \"" << message_string << "\"" << std::endl;
922
923 LLPluginMessage message_in;
924
925 if(message_in.parse(message_string) >= 0)
926 {
927 std::string message_class = message_in.getClass();
928 std::string message_name = message_in.getName();
929 if(message_class == LLPLUGIN_MESSAGE_CLASS_BASE)
930 {
931 if(message_name == "init")
932 {
933 LLPluginMessage message("base", "init_response");
934 LLSD versions = LLSD::emptyMap();
935 versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION;
936 versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION;
937 versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME] = LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME_VERSION;
938 message.setValueLLSD("versions", versions);
939
940 if ( load() )
941 {
942 DEBUGMSG("GStreamer010 media instance set up");
943 }
944 else
945 {
946 WARNMSG("GStreamer010 media instance failed to set up");
947 }
948
949 message.setValue("plugin_version", getVersion());
950 sendMessage(message);
951 }
952 else if(message_name == "idle")
953 {
954 // no response is necessary here.
955 double time = message_in.getValueReal("time");
956
957 // Convert time to milliseconds for update()
958 update((int)(time * 1000.0f));
959 }
960 else if(message_name == "cleanup")
961 {
962 unload();
963 closedown();
964 }
965 else if(message_name == "shm_added")
966 {
967 SharedSegmentInfo info;
968 info.mAddress = message_in.getValuePointer("address");
969 info.mSize = (size_t)message_in.getValueS32("size");
970 std::string name = message_in.getValue("name");
971
972 std::ostringstream str;
973 INFOMSG("MediaPluginGStreamer010::receiveMessage: shared memory added, name: %s, size: %d, address: %p", name.c_str(), int(info.mSize), info.mAddress);
974
975 mSharedSegments.insert(SharedSegmentMap::value_type(name, info));
976 }
977 else if(message_name == "shm_remove")
978 {
979 std::string name = message_in.getValue("name");
980
981 DEBUGMSG("MediaPluginGStreamer010::receiveMessage: shared memory remove, name = %s", name.c_str());
982
983 SharedSegmentMap::iterator iter = mSharedSegments.find(name);
984 if(iter != mSharedSegments.end())
985 {
986 if(mPixels == iter->second.mAddress)
987 {
988 // This is the currently active pixel buffer. Make sure we stop drawing to it.
989 mPixels = NULL;
990 mTextureSegmentName.clear();
991
992 // Make sure the movie decoder is no longer pointed at the shared segment.
993 sizeChanged();
994 }
995 mSharedSegments.erase(iter);
996 }
997 else
998 {
999 WARNMSG("MediaPluginGStreamer010::receiveMessage: unknown shared memory region!");
1000 }
1001
1002 // Send the response so it can be cleaned up.
1003 LLPluginMessage message("base", "shm_remove_response");
1004 message.setValue("name", name);
1005 sendMessage(message);
1006 }
1007 else
1008 {
1009 std::ostringstream str;
1010 INFOMSG("MediaPluginGStreamer010::receiveMessage: unknown base message: %s", message_name.c_str());
1011 }
1012 }
1013 else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA)
1014 {
1015 if(message_name == "init")
1016 {
1017 // Plugin gets to decide the texture parameters to use.
1018 LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params");
1019 // lame to have to decide this now, it depends on the movie. Oh well.
1020 mDepth = 4;
1021
1022 mCurrentWidth = 1;
1023 mCurrentHeight = 1;
1024 mPreviousWidth = 1;
1025 mPreviousHeight = 1;
1026 mNaturalWidth = 1;
1027 mNaturalHeight = 1;
1028 mWidth = 1;
1029 mHeight = 1;
1030 mTextureWidth = 1;
1031 mTextureHeight = 1;
1032
1033 message.setValueU32("format", GL_RGBA);
1034 message.setValueU32("type", GL_UNSIGNED_INT_8_8_8_8_REV);
1035
1036 message.setValueS32("depth", mDepth);
1037 message.setValueS32("default_width", mWidth);
1038 message.setValueS32("default_height", mHeight);
1039 message.setValueU32("internalformat", GL_RGBA8);
1040 message.setValueBoolean("coords_opengl", true); // true == use OpenGL-style coordinates, false == (0,0) is upper left.
1041 message.setValueBoolean("allow_downsample", true); // we respond with grace and performance if asked to downscale
1042 sendMessage(message);
1043 }
1044 else if(message_name == "size_change")
1045 {
1046 std::string name = message_in.getValue("name");
1047 S32 width = message_in.getValueS32("width");
1048 S32 height = message_in.getValueS32("height");
1049 S32 texture_width = message_in.getValueS32("texture_width");
1050 S32 texture_height = message_in.getValueS32("texture_height");
1051
1052 std::ostringstream str;
1053 INFOMSG("---->Got size change instruction from application with shm name: %s - size is %d x %d", name.c_str(), width, height);
1054
1055 LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response");
1056 message.setValue("name", name);
1057 message.setValueS32("width", width);
1058 message.setValueS32("height", height);
1059 message.setValueS32("texture_width", texture_width);
1060 message.setValueS32("texture_height", texture_height);
1061 sendMessage(message);
1062
1063 if(!name.empty())
1064 {
1065 // Find the shared memory region with this name
1066 SharedSegmentMap::iterator iter = mSharedSegments.find(name);
1067 if(iter != mSharedSegments.end())
1068 {
1069 INFOMSG("*** Got size change with matching shm, new size is %d x %d", width, height);
1070 INFOMSG("*** Got size change with matching shm, texture size size is %d x %d", texture_width, texture_height);
1071
1072 mPixels = (unsigned char*)iter->second.mAddress;
1073 mTextureSegmentName = name;
1074 mWidth = width;
1075 mHeight = height;
1076
1077 if (texture_width > 1 ||
1078 texture_height > 1) // not a dummy size from the app, a real explicit forced size
1079 {
1080 INFOMSG("**** = REAL RESIZE REQUEST FROM APP");
1081
1082 GST_OBJECT_LOCK(mVideoSink);
1083 mVideoSink->resize_forced_always = true;
1084 mVideoSink->resize_try_width = texture_width;
1085 mVideoSink->resize_try_height = texture_height;
1086 GST_OBJECT_UNLOCK(mVideoSink);
1087 }
1088
1089 mTextureWidth = texture_width;
1090 mTextureHeight = texture_height;
1091 }
1092 }
1093 }
1094 else if(message_name == "load_uri")
1095 {
1096 std::string uri = message_in.getValue("uri");
1097 navigateTo( uri );
1098 sendStatus();
1099 }
1100 else if(message_name == "mouse_event")
1101 {
1102 std::string event = message_in.getValue("event");
1103 S32 x = message_in.getValueS32("x");
1104 S32 y = message_in.getValueS32("y");
1105
1106 if(event == "down")
1107 {
1108 mouseDown(x, y);
1109 }
1110 else if(event == "up")
1111 {
1112 mouseUp(x, y);
1113 }
1114 else if(event == "move")
1115 {
1116 mouseMove(x, y);
1117 };
1118 };
1119 }
1120 else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME)
1121 {
1122 if(message_name == "stop")
1123 {
1124 stop();
1125 }
1126 else if(message_name == "start")
1127 {
1128 double rate = 0.0;
1129 if(message_in.hasValue("rate"))
1130 {
1131 rate = message_in.getValueReal("rate");
1132 }
1133 // NOTE: we don't actually support rate.
1134 play(rate);
1135 }
1136 else if(message_name == "pause")
1137 {
1138 pause();
1139 }
1140 else if(message_name == "seek")
1141 {
1142 double time = message_in.getValueReal("time");
1143 // defer the actual seek in case we haven't
1144 // really truly started yet in which case there
1145 // is nothing to seek upon
1146 mSeekWanted = true;
1147 mSeekDestination = time;
1148 }
1149 else if(message_name == "set_loop")
1150 {
1151 bool loop = message_in.getValueBoolean("loop");
1152 mIsLooping = loop;
1153 }
1154 else if(message_name == "set_volume")
1155 {
1156 double volume = message_in.getValueReal("volume");
1157 setVolume(volume);
1158 }
1159 }
1160 else
1161 {
1162 INFOMSG("MediaPluginGStreamer010::receiveMessage: unknown message class: %s", message_class.c_str());
1163 }
1164 }
1165}
1166
1167int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data)
1168{
1169 if (MediaPluginGStreamer010::startup())
1170 {
1171 MediaPluginGStreamer010 *self = new MediaPluginGStreamer010(host_send_func, host_user_data);
1172 *plugin_send_func = MediaPluginGStreamer010::staticReceiveMessage;
1173 *plugin_user_data = (void*)self;
1174
1175 return 0; // okay
1176 }
1177 else
1178 {
1179 return -1; // failed to init
1180 }
1181}
1182
1183#else // LL_GSTREAMER010_ENABLED
1184
1185// Stubbed-out class with constructor/destructor (necessary or windows linker
1186// will just think its dead code and optimize it all out)
1187class MediaPluginGStreamer010 : public MediaPluginBase
1188{
1189public:
1190 MediaPluginGStreamer010(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data);
1191 ~MediaPluginGStreamer010();
1192 /* virtual */ void receiveMessage(const char *message_string);
1193};
1194
1195MediaPluginGStreamer010::MediaPluginGStreamer010(
1196 LLPluginInstance::sendMessageFunction host_send_func,
1197 void *host_user_data ) :
1198 MediaPluginBase(host_send_func, host_user_data)
1199{
1200 // no-op
1201}
1202
1203MediaPluginGStreamer010::~MediaPluginGStreamer010()
1204{
1205 // no-op
1206}
1207
1208void MediaPluginGStreamer010::receiveMessage(const char *message_string)
1209{
1210 // no-op
1211}
1212
1213// We're building without GStreamer enabled. Just refuse to initialize.
1214int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data)
1215{
1216 return -1;
1217}
1218
1219#endif // LL_GSTREAMER010_ENABLED
diff --git a/linden/indra/newview/linux_tools/getvoice.sh b/linden/indra/newview/linux_tools/getvoice.sh
index 13b632f..afebda9 100755
--- a/linden/indra/newview/linux_tools/getvoice.sh
+++ b/linden/indra/newview/linux_tools/getvoice.sh
@@ -3,8 +3,9 @@
3SCRIPTSRC=`readlink -f "$0" || echo "$0"` 3SCRIPTSRC=`readlink -f "$0" || echo "$0"`
4RUN_PATH=`dirname "${SCRIPTSRC}" || echo .` 4RUN_PATH=`dirname "${SCRIPTSRC}" || echo .`
5 5
6#if mozilla-runtime-linux-x86_64 is present we are using 64bit Imprudence on 64bit Linux 6BINARY_SYSTEM=$(expr match "$(file -b /bin/uname)" '\(.*executable\)')
7if [ -d "${RUN_PATH}/app_settings/mozilla-runtime-linux-x86_64/" ]; then 7BINARY_VIEWER=$(expr match "$(file -b ${RUN_PATH}/bin/do-not-directly-run-imprudence-bin)" '\(.*executable\)')
8if ( [ "$BINARY_SYSTEM" == "ELF 64-bit LSB executable" ] && [ "$BINARY_VIEWER" == "ELF 64-bit LSB executable" ] ); then
8 LIB_INSTALLDIR="lib32/" # It's 32bit voice on 64bit Linux and 64bit viewer. Not using lib/ for avoiding ambiguity. 9 LIB_INSTALLDIR="lib32/" # It's 32bit voice on 64bit Linux and 64bit viewer. Not using lib/ for avoiding ambiguity.
9else 10else
10 LIB_INSTALLDIR="lib/" # It's 32bit voice on 32 or 64bit Linux and 32bit viewer. 11 LIB_INSTALLDIR="lib/" # It's 32bit voice on 32 or 64bit Linux and 32bit viewer.
diff --git a/linden/indra/newview/linux_tools/wrapper.sh b/linden/indra/newview/linux_tools/wrapper.sh
index bc2c127..8c47434 100755
--- a/linden/indra/newview/linux_tools/wrapper.sh
+++ b/linden/indra/newview/linux_tools/wrapper.sh
@@ -106,13 +106,13 @@ if [ -n "$LL_TCMALLOC" ]; then
106 fi 106 fi
107 fi 107 fi
108fi 108fi
109 109BINARY_SYSTEM=$(expr match "$(file -b /bin/uname)" '\(.*executable\)')
110if([ "`uname -m`" = "x86_64" ] && [ -d "${RUN_PATH}/app_settings/mozilla-runtime-linux-x86_64/" ]); then 110BINARY_VIEWER=$(expr match "$(file -b ${RUN_PATH}/bin/do-not-directly-run-imprudence-bin)" '\(.*executable\)')
111 export GST_PLUGIN_PATH="${GST_PLUGIN_PATH}:${RUN_PATH}/lib64/gstreamer-plugins/" 111echo "viewer: $BINARY_VIEWER system: $BINARY_SYSTEM"
112if ( [ "$BINARY_SYSTEM" == "ELF 64-bit LSB executable" ] && [ "$BINARY_VIEWER" == "ELF 64-bit LSB executable" ] ); then
112 113
113 export SL_ENV='LD_LIBRARY_PATH="`pwd`"/lib64:"`pwd`"/lib32:"`pwd`"/app_settings/mozilla-runtime-linux-x86_64:"${LD_LIBRARY_PATH}"' 114 export SL_ENV='LD_LIBRARY_PATH="`pwd`"/lib64:"`pwd`"/lib32:"`pwd`"/app_settings/mozilla-runtime-linux-x86_64:"${LD_LIBRARY_PATH}"'
114else 115else
115 export GST_PLUGIN_PATH="${GST_PLUGIN_PATH}:${RUN_PATH}/lib/gstreamer-plugins/"
116 export SL_ENV='LD_LIBRARY_PATH="`pwd`"/lib:"`pwd`"/app_settings/mozilla-runtime-linux-i686:"${LD_LIBRARY_PATH}"' 116 export SL_ENV='LD_LIBRARY_PATH="`pwd`"/lib:"`pwd`"/app_settings/mozilla-runtime-linux-i686:"${LD_LIBRARY_PATH}"'
117fi 117fi
118 118
diff --git a/linden/indra/newview/viewer_manifest.py b/linden/indra/newview/viewer_manifest.py
index 0c00995..4c95f00 100755
--- a/linden/indra/newview/viewer_manifest.py
+++ b/linden/indra/newview/viewer_manifest.py
@@ -973,68 +973,69 @@ class Linux_i686Manifest(LinuxManifest):
973 # self.path("libpangoxft-1.0.so.0") 973 # self.path("libpangoxft-1.0.so.0")
974 self.path("libpixman-1.so.0") 974 self.path("libpixman-1.so.0")
975 975
976#KILL IT WITH FIRE
976 # Gstreamer libs 977 # Gstreamer libs
977 self.path("libgstbase-0.10.so.0") 978 #self.path("libgstbase-0.10.so.0")
978 self.path("libgstreamer-0.10.so.0") 979 #self.path("libgstreamer-0.10.so.0")
979 self.path("libgstaudio-0.10.so.0") 980 #self.path("libgstaudio-0.10.so.0")
980 self.path("libgstbase-0.10.so.0") 981 #self.path("libgstbase-0.10.so.0")
981 self.path("libgstcontroller-0.10.so.0") 982 #self.path("libgstcontroller-0.10.so.0")
982 self.path("libgstdataprotocol-0.10.so.0") 983 #self.path("libgstdataprotocol-0.10.so.0")
983 self.path("libgstinterfaces-0.10.so.0") 984 #self.path("libgstinterfaces-0.10.so.0")
984 self.path("libgstnetbuffer-0.10.so.0") 985 #self.path("libgstnetbuffer-0.10.so.0")
985 self.path("libgstpbutils-0.10.so.0") 986 #self.path("libgstpbutils-0.10.so.0")
986 self.path("libgstriff-0.10.so.0") 987 #self.path("libgstriff-0.10.so.0")
987 self.path("libgstrtp-0.10.so.0") 988 #self.path("libgstrtp-0.10.so.0")
988 self.path("libgstrtsp-0.10.so.0") 989 #self.path("libgstrtsp-0.10.so.0")
989 self.path("libgstsdp-0.10.so.0") 990 #self.path("libgstsdp-0.10.so.0")
990 self.path("libgsttag-0.10.so.0") 991 #self.path("libgsttag-0.10.so.0")
991 self.path("libgstvideo-0.10.so.0") 992 #self.path("libgstvideo-0.10.so.0")
992 993
993 # Gstreamer plugin dependencies 994 ## Gstreamer plugin dependencies
994 self.path("libfaad.so.0") 995 #self.path("libfaad.so.0")
995 self.path("libogg.so.0") 996 #self.path("libogg.so.0")
996 self.path("libtheora.so.0") 997 #self.path("libtheora.so.0")
997 self.path("libvorbis.so.0") 998 #self.path("libvorbis.so.0")
998 self.path("libvorbisenc.so.2") 999 #self.path("libvorbisenc.so.2")
999 self.path("liboil-0.3.so.0") 1000 #self.path("liboil-0.3.so.0")
1000 1001
1001 # Gstreamer plugins 1002 ## Gstreamer plugins
1002 if self.prefix("gstreamer-plugins"): 1003 #if self.prefix("gstreamer-plugins"):
1003 self.path("libgstalsa.so") 1004 #self.path("libgstalsa.so")
1004 self.path("libgstasf.so") 1005 #self.path("libgstasf.so")
1005 self.path("libgstaudioconvert.so") 1006 #self.path("libgstaudioconvert.so")
1006 self.path("libgstaudioresample.so") 1007 #self.path("libgstaudioresample.so")
1007 self.path("libgstautodetect.so") 1008 #self.path("libgstautodetect.so")
1008 self.path("libgstavi.so") 1009 #self.path("libgstavi.so")
1009 self.path("libgstcoreelements.so") 1010 #self.path("libgstcoreelements.so")
1010 self.path("libgstcoreindexers.so") 1011 #self.path("libgstcoreindexers.so")
1011 self.path("libgstdecodebin2.so") 1012 #self.path("libgstdecodebin2.so")
1012 self.path("libgstdecodebin.so") 1013 #self.path("libgstdecodebin.so")
1013 self.path("libgstesd.so") 1014 #self.path("libgstesd.so")
1014 self.path("libgstfaad.so") 1015 #self.path("libgstfaad.so")
1015 self.path("libgstffmpeg.so") 1016 #self.path("libgstffmpeg.so")
1016 self.path("libgstgnomevfs.so") 1017 #self.path("libgstgnomevfs.so")
1017 self.path("libgsticydemux.so") 1018 #self.path("libgsticydemux.so")
1018 self.path("libgstid3demux.so") 1019 #self.path("libgstid3demux.so")
1019 self.path("libgstmpegdemux.so") 1020 #self.path("libgstmpegdemux.so")
1020 self.path("libgstmultifile.so") 1021 #self.path("libgstmultifile.so")
1021 self.path("libgstmultipart.so") 1022 #self.path("libgstmultipart.so")
1022 self.path("libgstogg.so") 1023 #self.path("libgstogg.so")
1023 self.path("libgstossaudio.so") 1024 #self.path("libgstossaudio.so")
1024 self.path("libgstplaybin.so") 1025 #self.path("libgstplaybin.so")
1025 self.path("libgstpulse.so") 1026 #self.path("libgstpulse.so")
1026 self.path("libgstqtdemux.so") 1027 #self.path("libgstqtdemux.so")
1027 self.path("libgstqueue2.so") 1028 #self.path("libgstqueue2.so")
1028 self.path("libgsttcp.so") 1029 #self.path("libgsttcp.so")
1029 self.path("libgsttheora.so") 1030 #self.path("libgsttheora.so")
1030 self.path("libgsttypefindfunctions.so") 1031 #self.path("libgsttypefindfunctions.so")
1031 self.path("libgstudp.so") 1032 #self.path("libgstudp.so")
1032 self.path("libgstvideoscale.so") 1033 #self.path("libgstvideoscale.so")
1033 self.path("libgstvolume.so") 1034 #self.path("libgstvolume.so")
1034 self.path("libgstvorbis.so") 1035 #self.path("libgstvorbis.so")
1035 self.path("libgstwavparse.so") 1036 #self.path("libgstwavparse.so")
1036 1037
1037 self.end_prefix("gstreamer-plugins") 1038 #self.end_prefix("gstreamer-plugins")
1038 1039
1039 self.end_prefix("lib") 1040 self.end_prefix("lib")
1040 1041
@@ -1064,8 +1065,6 @@ class Linux_x86_64Manifest(LinuxManifest):
1064 self.path("featuretable_linux.txt") 1065 self.path("featuretable_linux.txt")
1065 #self.path("secondlife-x86_64.supp") 1066 #self.path("secondlife-x86_64.supp")
1066 1067
1067 self.path("app_settings/mozilla-runtime-linux-x86_64")
1068
1069 if self.prefix("../../libraries/x86_64-linux/lib_release_client", dst="lib64"): 1068 if self.prefix("../../libraries/x86_64-linux/lib_release_client", dst="lib64"):
1070 self.path("libapr-1.so.0") 1069 self.path("libapr-1.so.0")
1071 self.path("libaprutil-1.so.0") 1070 self.path("libaprutil-1.so.0")
@@ -1102,69 +1101,70 @@ class Linux_x86_64Manifest(LinuxManifest):
1102# self.path("libpangoxft-1.0.so.0") # So we depend system gdk pixbufs and pango anyway. 1101# self.path("libpangoxft-1.0.so.0") # So we depend system gdk pixbufs and pango anyway.
1103 self.path("libpixman-1.so.0") 1102 self.path("libpixman-1.so.0")
1104 1103
1105 # Gstreamer libs 1104#KILL IT WITH FIRE
1106 self.path("libgstbase-0.10.so.0") 1105 ## Gstreamer libs
1107 self.path("libgstreamer-0.10.so.0") 1106 #self.path("libgstbase-0.10.so.0")
1108 self.path("libgstaudio-0.10.so.0") 1107 #self.path("libgstreamer-0.10.so.0")
1109 self.path("libgstbase-0.10.so.0") 1108 #self.path("libgstaudio-0.10.so.0")
1110 self.path("libgstcontroller-0.10.so.0") 1109 #self.path("libgstbase-0.10.so.0")
1111 self.path("libgstdataprotocol-0.10.so.0") 1110 #self.path("libgstcontroller-0.10.so.0")
1112 self.path("libgstinterfaces-0.10.so.0") 1111 #self.path("libgstdataprotocol-0.10.so.0")
1113 self.path("libgstnetbuffer-0.10.so.0") 1112 #self.path("libgstinterfaces-0.10.so.0")
1114 self.path("libgstpbutils-0.10.so.0") 1113 #self.path("libgstnetbuffer-0.10.so.0")
1115 self.path("libgstriff-0.10.so.0") 1114 #self.path("libgstpbutils-0.10.so.0")
1116 self.path("libgstrtp-0.10.so.0") 1115 #self.path("libgstriff-0.10.so.0")
1117 self.path("libgstrtsp-0.10.so.0") 1116 #self.path("libgstrtp-0.10.so.0")
1118 self.path("libgstsdp-0.10.so.0") 1117 #self.path("libgstrtsp-0.10.so.0")
1119 self.path("libgsttag-0.10.so.0") 1118 #self.path("libgstsdp-0.10.so.0")
1120 self.path("libgstvideo-0.10.so.0") 1119 #self.path("libgsttag-0.10.so.0")
1121 1120 #self.path("libgstvideo-0.10.so.0")
1122 # Gstreamer plugin dependencies 1121
1123 self.path("libfaad.so.0") 1122 ## Gstreamer plugin dependencies
1124 self.path("libogg.so.0") 1123 #self.path("libfaad.so.0")
1125 self.path("libtheora.so.0") 1124 #self.path("libogg.so.0")
1126 self.path("libvorbis.so.0") 1125 #self.path("libtheora.so.0")
1127 self.path("libvorbisenc.so.2") 1126 #self.path("libvorbis.so.0")
1128 self.path("liboil-0.3.so.0") 1127 #self.path("libvorbisenc.so.2")
1129 1128 #self.path("liboil-0.3.so.0")
1130 # Gstreamer plugins 1129
1131 if self.prefix("gstreamer-plugins"): 1130 ## Gstreamer plugins
1132 self.path("libgstalsa.so") 1131 #if self.prefix("gstreamer-plugins"):
1133 self.path("libgstasf.so") 1132 #self.path("libgstalsa.so")
1134 self.path("libgstaudioconvert.so") 1133 #self.path("libgstasf.so")
1135 self.path("libgstaudioresample.so") 1134 #self.path("libgstaudioconvert.so")
1136 self.path("libgstautodetect.so") 1135 #self.path("libgstaudioresample.so")
1137 self.path("libgstavi.so") 1136 #self.path("libgstautodetect.so")
1138 self.path("libgstcoreelements.so") 1137 #self.path("libgstavi.so")
1139 self.path("libgstcoreindexers.so") 1138 #self.path("libgstcoreelements.so")
1140 self.path("libgstdecodebin2.so") 1139 #self.path("libgstcoreindexers.so")
1141 self.path("libgstdecodebin.so") 1140 #self.path("libgstdecodebin2.so")
1142 self.path("libgstesd.so") 1141 #self.path("libgstdecodebin.so")
1143 self.path("libgstfaad.so") 1142 #self.path("libgstesd.so")
1144 self.path("libgstffmpeg.so") 1143 #self.path("libgstfaad.so")
1145 self.path("libgstffmpegcolorspace.so") 1144 #self.path("libgstffmpeg.so")
1146 self.path("libgstgnomevfs.so") 1145 #self.path("libgstffmpegcolorspace.so")
1147 self.path("libgsticydemux.so") 1146 #self.path("libgstgnomevfs.so")
1148 self.path("libgstid3demux.so") 1147 #self.path("libgsticydemux.so")
1149 self.path("libgstmpegdemux.so") 1148 #self.path("libgstid3demux.so")
1150 self.path("libgstmultifile.so") 1149 #self.path("libgstmpegdemux.so")
1151 self.path("libgstmultipart.so") 1150 #self.path("libgstmultifile.so")
1152 self.path("libgstogg.so") 1151 #self.path("libgstmultipart.so")
1153 self.path("libgstossaudio.so") 1152 #self.path("libgstogg.so")
1154 self.path("libgstplaybin.so") 1153 #self.path("libgstossaudio.so")
1155 self.path("libgstpulse.so") 1154 #self.path("libgstplaybin.so")
1156 self.path("libgstqtdemux.so") 1155 #self.path("libgstpulse.so")
1157 self.path("libgstqueue2.so") 1156 #self.path("libgstqtdemux.so")
1158 self.path("libgsttcp.so") 1157 #self.path("libgstqueue2.so")
1159 self.path("libgsttheora.so") 1158 #self.path("libgsttcp.so")
1160 self.path("libgsttypefindfunctions.so") 1159 #self.path("libgsttheora.so")
1161 self.path("libgstudp.so") 1160 #self.path("libgsttypefindfunctions.so")
1162 self.path("libgstvideoscale.so") 1161 #self.path("libgstudp.so")
1163 self.path("libgstvolume.so") 1162 #self.path("libgstvideoscale.so")
1164 self.path("libgstvorbis.so") 1163 #self.path("libgstvolume.so")
1165 self.path("libgstwavparse.so") 1164 #self.path("libgstvorbis.so")
1165 #self.path("libgstwavparse.so")
1166 1166
1167 self.end_prefix("gstreamer-plugins") 1167 #self.end_prefix("gstreamer-plugins")
1168 self.end_prefix("lib64") 1168 self.end_prefix("lib64")
1169 1169
1170 1170
diff --git a/linden/indra/newview/viewer_manifest.py~ b/linden/indra/newview/viewer_manifest.py~
deleted file mode 100755
index 452b165..0000000
--- a/linden/indra/newview/viewer_manifest.py~
+++ /dev/null
@@ -1,1176 +0,0 @@
1#!/usr/bin/python
2# @file viewer_manifest.py
3# @author Ryan Williams
4# @brief Description of all installer viewer files, and methods for packaging
5# them into installers for all supported platforms.
6#
7# $LicenseInfo:firstyear=2006&license=viewergpl$
8#
9# Copyright (c) 2006-2009, Linden Research, Inc.
10#
11# Second Life Viewer Source Code
12# The source code in this file ("Source Code") is provided by Linden Lab
13# to you under the terms of the GNU General Public License, version 2.0
14# ("GPL"), unless you have obtained a separate licensing agreement
15# ("Other License"), formally executed by you and Linden Lab. Terms of
16# the GPL can be found in doc/GPL-license.txt in this distribution, or
17# online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
18#
19# There are special exceptions to the terms and conditions of the GPL as
20# it is applied to this Source Code. View the full text of the exception
21# in the file doc/FLOSS-exception.txt in this software distribution, or
22# online at
23# http://secondlifegrid.net/programs/open_source/licensing/flossexception
24#
25# By copying, modifying or distributing this software, you acknowledge
26# that you have read and understood your obligations described above,
27# and agree to abide by those obligations.
28#
29# ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
30# WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
31# COMPLETENESS OR PERFORMANCE.
32# $/LicenseInfo$
33
34# DO NOT RUN THIS FILE DIRECTLY
35# Instead, run develop.py with "configure -DPACKAGE:BOOL=ON" e.g.:
36# develop.py -G vc80 configure -DPACKAGE:BOOL=ON
37# to generate the "package" project in Visual Studio 2005
38# Note: as of Imprudence 1.3, this defaults to on for Windows
39
40import sys
41import os.path
42import re
43import tarfile
44viewer_dir = os.path.dirname(__file__)
45# add llmanifest library to our path so we don't have to muck with PYTHONPATH
46sys.path.append(os.path.join(viewer_dir, '../lib/python/indra/util'))
47from llmanifest import LLManifest, main, proper_windows_path, path_ancestors
48
49class ViewerManifest(LLManifest):
50 def construct(self):
51 super(ViewerManifest, self).construct()
52 self.exclude("*.svn*")
53 self.path(src="../../scripts/messages/message_template.msg", dst="app_settings/message_template.msg")
54 self.path(src="../../etc/message.xml", dst="app_settings/message.xml")
55
56 if self.prefix(src="app_settings"):
57 self.exclude("logcontrol.xml")
58 self.exclude("logcontrol-dev.xml")
59 self.path("*.pem")
60 self.path("*.ini")
61 self.path("*.xml")
62 self.path("*.db2")
63
64 # include the entire shaders directory recursively
65 self.path("shaders")
66 # ... and the entire windlight directory
67 self.path("windlight")
68 self.end_prefix("app_settings")
69
70 if self.prefix(src="character"):
71 self.path("*.llm")
72 self.path("*.xml")
73 self.path("*.tga")
74 self.end_prefix("character")
75
76 # Include our fonts
77 if self.prefix(src="fonts"):
78 self.path("LiberationSans-Bold.ttf")
79 self.path("LiberationSans-Regular.ttf")
80 self.path("VeraMono.ttf")
81 self.path("DejaVuSansCondensed-BoldOblique.ttf")
82 self.path("DejaVuSansCondensed-Bold.ttf")
83 self.path("DejaVuSansCondensed-Oblique.ttf")
84 self.path("DejaVuSansCondensed.ttf")
85 self.path("GPL.txt")
86 self.path("Liberation-License.txt")
87 self.path("Vera-License.txt")
88 self.end_prefix("fonts")
89
90 # skins
91 if self.prefix(src="skins"):
92 self.path("paths.xml")
93 # include the entire textures directory recursively
94 if self.prefix(src="*/textures"):
95 self.path("*.tga")
96 self.path("*.j2c")
97 self.path("*.jpg")
98 self.path("*.png")
99 self.path("textures.xml")
100 self.end_prefix("*/textures")
101 self.path("*/xui/*/*.xml")
102 self.path("*/*.xml")
103
104 # Local HTML files (e.g. loading screen)
105 if self.prefix(src="*/html"):
106 self.path("*.png")
107 self.path("*/*/*.html")
108 self.path("*/*/*.gif")
109 self.path("*/*/*.png")
110 self.end_prefix("*/html")
111 self.end_prefix("skins")
112
113 # Files in the newview/ directory
114 self.path("gpu_table.txt")
115
116
117 # Gather up the README file, etc.
118 def gather_documents(self):
119 # From the top level directory (imprudence)
120 if self.prefix("../../..", dst=""):
121 self.path("README.txt")
122 self.path("MANIFESTO.txt")
123 self.path("CONTRIBUTE.txt")
124 self.path("RELEASE_NOTES.txt")
125 self.path("ChangeLog.txt", required=False)
126 self.end_prefix("../../..")
127
128 # From the linden directory
129 if self.prefix("../..", dst="doc"):
130 self.path("LICENSE-source.txt")
131 self.path("LICENSE-logos.txt", "LICENSE-artwork.txt")
132 self.end_prefix("../..")
133
134 # From the linden/doc directory
135 if self.prefix("../../doc", dst="doc"):
136 self.path("contributions.txt")
137 self.path("GPL-license.txt", "GPL.txt")
138 self.path("FLOSS-exception.txt")
139 self.end_prefix("../../doc")
140
141
142 def login_channel(self):
143 """Channel reported for login and upgrade purposes ONLY;
144 used for A/B testing"""
145 # NOTE: Do not return the normal channel if login_channel
146 # is not specified, as some code may branch depending on
147 # whether or not this is present
148 return self.args.get('login_channel')
149
150 def grid(self):
151 return self.args['grid']
152 def channel(self):
153 return self.args['channel']
154 def channel_unique(self):
155 return self.channel().replace("Imprudence", "").strip()
156 def channel_oneword(self):
157 return "".join(self.channel_unique().split())
158 def channel_lowerword(self):
159 return self.channel_oneword().lower()
160
161 def flags_list(self):
162 """ Convenience function that returns the command-line flags
163 for the grid"""
164
165 # Set command line flags relating to the target grid
166 grid_flags = ''
167 if not self.default_grid():
168 grid_flags = "--grid %(grid)s "\
169 "--helperuri http://preview-%(grid)s.secondlife.com/helpers/" %\
170 {'grid':self.grid()}
171
172 # set command line flags for channel
173 channel_flags = ''
174 if self.login_channel() and self.login_channel() != self.channel():
175 # Report a special channel during login, but use default
176 channel_flags = '--channel "%s"' % (self.login_channel())
177 elif not self.default_channel():
178 channel_flags = '--channel "%s"' % self.channel()
179
180 # Deal with settings
181 setting_flags = ''
182 if not self.default_channel() or not self.default_grid():
183 if self.default_grid():
184 setting_flags = '--settings settings_%s.xml'\
185 % self.channel_lowerword()
186 else:
187 setting_flags = '--settings settings_%s_%s.xml'\
188 % (self.grid(), self.channel_lowerword())
189
190 return " ".join((channel_flags, grid_flags, setting_flags)).strip()
191
192
193class WindowsManifest(ViewerManifest):
194 def final_exe(self):
195 if self.default_channel():
196 if self.default_grid():
197 return "imprudence.exe"
198 else:
199 return "imprudencepreview.exe"
200 else:
201 return ''.join(self.channel().split()) + '.exe'
202
203
204 def construct(self):
205 super(WindowsManifest, self).construct()
206 # the final exe is complicated because we're not sure where it's coming from,
207 # nor do we have a fixed name for the executable
208 self.path(self.find_existing_file('debug/imprudence-bin.exe', 'release/imprudence-bin.exe', 'relwithdebinfo/imprudence-bin.exe'), dst=self.final_exe())
209
210 self.gather_documents()
211
212 if self.prefix("../..", dst="doc"):
213 self.path("LICENSE-libraries.txt")
214 self.end_prefix("../..")
215
216
217 self.path("imprudence.url")
218
219 # Plugin host application
220 self.path(os.path.join(os.pardir,
221 'llplugin', 'slplugin', self.args['configuration'], "SLPlugin.exe"),
222 "SLPlugin.exe")
223
224
225 self.path("featuretable.txt")
226
227 # For use in crash reporting (generates minidumps)
228 self.path("dbghelp.dll")
229
230 # For using FMOD for sound... DJS
231 #self.path("fmod.dll")
232
233 # For spellchecking
234 self.path("libhunspell.dll")
235
236 # For textures
237 if self.prefix(src="../../libraries/i686-win32/lib/release", dst=""):
238 self.path("openjpeg.dll")
239 self.end_prefix()
240
241 # For sound
242 if self.prefix(src="../../libraries/i686-win32/lib/release", dst=""):
243 self.path("openal32.dll")
244 self.path("alut.dll")
245 self.end_prefix()
246
247
248 # Media plugins - QuickTime
249 if self.prefix(src='../media_plugins/quicktime/%s' % self.args['configuration'], dst="llplugin"):
250 self.path("media_plugin_quicktime.dll")
251 self.end_prefix()
252
253 # Media plugins - WebKit/Qt
254 if self.prefix(src='../media_plugins/webkit/%s' % self.args['configuration'], dst="llplugin"):
255 self.path("media_plugin_webkit.dll")
256 self.end_prefix()
257
258 # For WebKit/Qt plugin runtimes
259 if self.prefix(src="../../libraries/i686-win32/lib/release", dst="llplugin"):
260 self.path("libeay32.dll")
261 self.path("qtcore4.dll")
262 self.path("qtgui4.dll")
263 self.path("qtnetwork4.dll")
264 self.path("qtopengl4.dll")
265 self.path("qtwebkit4.dll")
266 self.path("ssleay32.dll")
267 self.end_prefix()
268
269 # For WebKit/Qt plugin runtimes (image format plugins)
270 if self.prefix(src="../../libraries/i686-win32/lib/release/imageformats", dst="llplugin/imageformats"):
271 self.path("qgif4.dll")
272 self.path("qico4.dll")
273 self.path("qjpeg4.dll")
274 self.path("qmng4.dll")
275 self.path("qsvg4.dll")
276 self.path("qtiff4.dll")
277 self.end_prefix()
278
279 # Per platform MIME config on the cheap. See SNOW-307 / DEV-41388
280 self.path("skins/default/xui/en-us/mime_types_windows.xml", "skins/default/xui/en-us/mime_types.xml")
281
282 # These need to be installed as a SxS assembly, currently a 'private' assembly.
283 # See http://msdn.microsoft.com/en-us/library/ms235291(VS.80).aspx
284 if self.prefix(src=self.args['configuration'], dst=""):
285 if self.args['configuration'] == 'Debug':
286 self.path("msvcr80d.dll")
287 self.path("msvcp80d.dll")
288 self.path("Microsoft.VC80.DebugCRT.manifest")
289 else:
290 self.path("msvcr80.dll")
291 self.path("msvcp80.dll")
292 self.path("Microsoft.VC80.CRT.manifest")
293 self.end_prefix()
294
295 # The config file name needs to match the exe's name.
296 self.path(src="%s/imprudence-bin.exe.config" % self.args['configuration'], dst=self.final_exe() + ".config")
297
298 # We need this one too, so that llkdu loads at runtime - DEV-41194
299 #self.path(src="%s/imprudence-bin.exe.config" % self.args['configuration'], dst="llkdu.dll.2.config")
300 self.path("llkdu.dll.2.config")
301
302 # We need this one too, so that win_crash_logger.exe loads at runtime - DEV-19004
303 #self.path(src="%s/imprudence-bin.exe.config" % self.args['configuration'], dst="win_crash_logger.exe.config")
304
305 # same thing for auto-updater.
306 #self.path(src="%s/imprudence-bin.exe.config" % self.args['configuration'], dst="updater.exe.config")
307
308 # Vivox runtimes
309 if self.prefix(src="vivox-runtime/i686-win32", dst=""):
310 # self.path("alut.dll")
311 self.path("wrap_oal.dll")
312 self.path("SLVoice.exe")
313 # self.path("SLVoiceAgent.exe")
314 # self.path("libeay32.dll")
315 # self.path("srtp.dll")
316 # self.path("ssleay32.dll")
317 # self.path("tntk.dll")
318 self.path("vivoxsdk.dll")
319 self.path("ortp.dll")
320
321 self.end_prefix()
322
323 # Gstreamer plugins
324 if self.prefix(src="lib/gstreamer-plugins", dst=""):
325 self.path("*.dll", dst="lib/gstreamer-plugins/*.dll")
326 self.end_prefix()
327
328 # Gstreamer libs
329 if self.prefix(src="../../libraries/i686-win32/lib/release", dst=""):
330 self.path("iconv.dll")
331 self.path("libxml2.dll")
332 self.path("libcairo-2.dll")
333 self.path("libgio-2.0-0.dll")
334 self.path("libglib-2.0-0.dll")
335 self.path("libgmodule-2.0-0.dll")
336 self.path("libgobject-2.0-0.dll")
337 self.path("libgthread-2.0-0.dll")
338 self.path("charset.dll")
339 self.path("intl.dll")
340 self.path("libgcrypt-11.dll")
341 self.path("libgnutls-26.dll")
342 self.path("libgpg-error-0.dll")
343 self.path("libgstapp.dll")
344 self.path("libgstaudio.dll")
345 self.path("libgstbase-0.10.dll")
346 self.path("libgstcdda.dll")
347 self.path("libgstcontroller-0.10.dll")
348 self.path("libgstdataprotocol-0.10.dll")
349 self.path("libgstdshow.dll")
350 self.path("libgstfft.dll")
351 self.path("libgstinterfaces.dll")
352 self.path("libgstnet-0.10.dll")
353 self.path("libgstnetbuffer.dll")
354 self.path("libgstpbutils.dll")
355 self.path("libgstreamer-0.10.dll")
356 self.path("libgstriff.dll")
357 self.path("libgstrtp.dll")
358 self.path("libgstrtsp.dll")
359 self.path("libgstsdp.dll")
360 self.path("libgsttag.dll")
361 self.path("libgstvideo.dll")
362 self.path("libjpeg.dll")
363 self.path("libmp3lame-0.dll")
364 self.path("libneon-27.dll")
365 self.path("libogg-0.dll")
366 self.path("liboil-0.3-0.dll")
367 self.path("libopenjpeg-2.dll")
368 self.path("libpng12-0.dll")
369 self.path("libschroedinger-1.0-0.dll")
370 self.path("libspeex-1.dll")
371 self.path("libtheora-0.dll")
372 self.path("libvorbis-0.dll")
373 self.path("libvorbisenc-2.dll")
374 self.path("libxml2-2.dll")
375 self.path("glew32.dll")
376 self.path("xvidcore.dll")
377 self.path("zlib1.dll")
378 self.end_prefix()
379
380# # pull in the crash logger and updater from other projects
381# self.path(src=self.find_existing_file( # tag:"crash-logger" here as a cue to the exporter
382# "../win_crash_logger/debug/windows-crash-logger.exe",
383# "../win_crash_logger/release/windows-crash-logger.exe",
384# "../win_crash_logger/relwithdebinfo/windows-crash-logger.exe"),
385# dst="win_crash_logger.exe")
386 self.path(src=self.find_existing_file(
387 "../win_updater/debug/windows-updater.exe",
388 "../win_updater/release/windows-updater.exe",
389 "../win_updater/relwithdebinfo/windows-updater.exe"),
390 dst="updater.exe")
391
392 # For google-perftools tcmalloc allocator.
393 #if self.prefix(src="../../libraries/i686-win32/lib/release", dst=""):
394 # self.path("libtcmalloc_minimal.dll")
395 # self.end_prefix()
396
397
398 def nsi_file_commands(self, install=True):
399 def wpath(path):
400 if path.endswith('/') or path.endswith(os.path.sep):
401 path = path[:-1]
402 path = path.replace('/', '\\')
403 return path
404
405 result = ""
406 dest_files = [pair[1] for pair in self.file_list if pair[0] and os.path.isfile(pair[1])]
407 # sort deepest hierarchy first
408 dest_files.sort(lambda a,b: cmp(a.count(os.path.sep),b.count(os.path.sep)) or cmp(a,b))
409 dest_files.reverse()
410 out_path = None
411 for pkg_file in dest_files:
412 rel_file = os.path.normpath(pkg_file.replace(self.get_dst_prefix()+os.path.sep,''))
413 installed_dir = wpath(os.path.join('$INSTDIR', os.path.dirname(rel_file)))
414 pkg_file = wpath(os.path.normpath(pkg_file))
415 if installed_dir != out_path:
416 if install:
417 out_path = installed_dir
418 result += 'SetOutPath ' + out_path + '\n'
419 if install:
420 result += 'File ' + pkg_file + '\n'
421 else:
422 result += 'Delete ' + wpath(os.path.join('$INSTDIR', rel_file)) + '\n'
423 # at the end of a delete, just rmdir all the directories
424 if not install:
425 deleted_file_dirs = [os.path.dirname(pair[1].replace(self.get_dst_prefix()+os.path.sep,'')) for pair in self.file_list]
426 # find all ancestors so that we don't skip any dirs that happened to have no non-dir children
427 deleted_dirs = []
428 for d in deleted_file_dirs:
429 deleted_dirs.extend(path_ancestors(d))
430 # sort deepest hierarchy first
431 deleted_dirs.sort(lambda a,b: cmp(a.count(os.path.sep),b.count(os.path.sep)) or cmp(a,b))
432 deleted_dirs.reverse()
433 prev = None
434 for d in deleted_dirs:
435 if d != prev: # skip duplicates
436 result += 'RMDir ' + wpath(os.path.join('$INSTDIR', os.path.normpath(d))) + '\n'
437 prev = d
438
439 return result
440
441 def package_finish(self):
442 # a standard map of strings for replacing in the templates
443 substitution_strings = {
444 'version' : '.'.join(self.args['version']).replace(' ', '_'),
445 'version_short' : '.'.join(self.args['version'][:-1]).replace(' ', '_'),
446 'version_dashes' : '-'.join(self.args['version']).replace(' ', '_'),
447 'final_exe' : self.final_exe(),
448 'grid':self.args['grid'],
449 'grid_caps':self.args['grid'].upper(),
450 # escape quotes becase NSIS doesn't handle them well
451 'flags':self.flags_list().replace('"', '$\\"'),
452 'channel':self.channel(),
453 'channel_oneword':self.channel_oneword(),
454 'channel_unique':self.channel_unique(),
455 }
456
457 version_vars = """
458 !define INSTEXE "%(final_exe)s"
459 !define VERSION "%(version_short)s"
460 !define VERSION_LONG "%(version)s"
461 !define VERSION_DASHES "%(version_dashes)s"
462 """ % substitution_strings
463 if self.default_channel():
464 if self.default_grid():
465 # release viewer
466 installer_file = "Imprudence_%(version_dashes)s_Setup.exe"
467 grid_vars_template = """
468 OutFile "%(installer_file)s"
469 !define INSTFLAGS "%(flags)s"
470 !define INSTNAME "Imprudence"
471 !define SHORTCUT "Imprudence"
472 !define URLNAME "imprudence"
473 Caption "Imprudence ${VERSION}"
474 """
475 else:
476 # beta grid viewer
477 installer_file = "Imprudence_%(version_dashes)s_(%(grid_caps)s)_Setup.exe"
478 grid_vars_template = """
479 OutFile "%(installer_file)s"
480 !define INSTFLAGS "%(flags)s"
481 !define INSTNAME "Imprudence%(grid_caps)s"
482 !define SHORTCUT "Imprudence (%(grid_caps)s)"
483 !define URLNAME "imprudence%(grid)s"
484 !define UNINSTALL_SETTINGS 1
485 Caption "Imprudence %(grid)s ${VERSION}"
486 """
487 else:
488 # some other channel on some grid
489 installer_file = "Imprudence_%(version_dashes)s_%(channel_oneword)s_Setup.exe"
490 grid_vars_template = """
491 OutFile "%(installer_file)s"
492 !define INSTFLAGS "%(flags)s"
493 !define INSTNAME "Imprudence%(channel_oneword)s"
494 !define SHORTCUT "%(channel)s"
495 !define URLNAME "imprudence"
496 !define UNINSTALL_SETTINGS 1
497 Caption "%(channel)s ${VERSION}"
498 """
499 if 'installer_name' in self.args:
500 installer_file = self.args['installer_name']
501 else:
502 installer_file = installer_file % substitution_strings
503 substitution_strings['installer_file'] = installer_file
504
505 tempfile = "imprudence_setup_tmp.nsi"
506 # the following replaces strings in the nsi template
507 # it also does python-style % substitution
508 self.replace_in("installers/windows/installer_template.nsi", tempfile, {
509 "%%VERSION%%":version_vars,
510 "%%SOURCE%%":self.get_src_prefix(),
511 "%%GRID_VARS%%":grid_vars_template % substitution_strings,
512 "%%INSTALL_FILES%%":self.nsi_file_commands(True),
513 "%%DELETE_FILES%%":self.nsi_file_commands(False)})
514
515 # We use the Unicode version of NSIS, available from
516 # http://www.scratchpaper.com/
517 NSIS_path = 'C:\\Program Files\\NSIS\\Unicode\\makensis.exe'
518 self.run_command('"' + proper_windows_path(NSIS_path) + '" ' + self.dst_path_of(tempfile))
519 # self.remove(self.dst_path_of(tempfile))
520 # If we're on a build machine, sign the code using our Authenticode certificate. JC
521 sign_py = 'C:\\buildscripts\\code-signing\\sign.py'
522 if os.path.exists(sign_py):
523 self.run_command(sign_py + ' ' + self.dst_path_of(installer_file))
524 else:
525 print "Skipping code signing,", sign_py, "does not exist"
526 self.created_path(self.dst_path_of(installer_file))
527 self.package_file = installer_file
528
529
530class DarwinManifest(ViewerManifest):
531 def construct(self):
532 # copy over the build result (this is a no-op if run within the xcode script)
533 self.path(self.args['configuration'] + "/Imprudence.app", dst="")
534
535 if self.prefix(src="", dst="Contents"): # everything goes in Contents
536
537 self.path("Info-Imprudence.plist", dst="Info.plist")
538
539 # copy additional libs in <bundle>/Contents/MacOS/
540 if self.prefix(src="../../libraries/universal-darwin/lib_release", dst="MacOS/"):
541
542 self.path("libndofdev.dylib")
543
544 self.path("libopenal.1.dylib")
545 self.path("libalut.0.dylib")
546
547 self.path("libglib-2.0.dylib")
548 self.path("libgmodule-2.0.dylib")
549 self.path("libgobject-2.0.dylib")
550 self.path("libgthread-2.0.dylib")
551
552 self.path("libgstreamer-0.10.dylib")
553 self.path("libgstapp-0.10.dylib")
554 self.path("libgstaudio-0.10.dylib")
555 self.path("libgstbase-0.10.dylib")
556 self.path("libgstcdda-0.10.dylib")
557 self.path("libgstcontroller-0.10.dylib")
558 self.path("libgstdataprotocol-0.10.dylib")
559 self.path("libgstfft-0.10.dylib")
560 self.path("libgstinterfaces-0.10.dylib")
561 self.path("libgstnet-0.10.dylib")
562 self.path("libgstnetbuffer-0.10.dylib")
563 self.path("libgstpbutils-0.10.dylib")
564 self.path("libgstriff-0.10.dylib")
565 self.path("libgstrtp-0.10.dylib")
566 self.path("libgstrtsp-0.10.dylib")
567 self.path("libgstsdp-0.10.dylib")
568 self.path("libgsttag-0.10.dylib")
569 self.path("libgstvideo-0.10.dylib")
570
571 self.path("libxml2.2.dylib")
572 self.path("libfaad.2.dylib")
573 self.path("libFLAC.8.dylib")
574 self.path("libintl.3.dylib")
575 self.path("libjpeg.62.dylib")
576 self.path("libpng12.0.dylib")
577 self.path("libneon.27.dylib")
578 self.path("libogg.0.dylib")
579 self.path("liboil-0.3.0.dylib")
580 self.path("libopenjpeg.1.4.dylib")
581 self.path("libtheora.0.dylib")
582 self.path("libvorbis.0.dylib")
583 self.path("libvorbisenc.2.dylib")
584 self.path("libvorbisfile.3.dylib")
585
586 self.end_prefix("../../libraries/universal-darwin/lib_release")
587
588 # most everything goes in the Resources directory
589 if self.prefix(src="", dst="Resources"):
590 super(DarwinManifest, self).construct()
591
592 if self.prefix("cursors_mac"):
593 self.path("*.tif")
594 self.end_prefix("cursors_mac")
595
596 # From the linden directory
597 if self.prefix("../..", dst="doc"):
598 self.path("LICENSE-libraries.txt")
599 self.end_prefix("../..")
600
601 self.gather_documents()
602
603 self.path("featuretable_mac.txt")
604 self.path("SecondLife.nib")
605
606 self.path("viewer.icns")
607
608 # Translations
609 self.path("English.lproj")
610 self.path("German.lproj")
611 self.path("Japanese.lproj")
612 self.path("Korean.lproj")
613 self.path("da.lproj")
614 self.path("es.lproj")
615 self.path("fr.lproj")
616 self.path("hu.lproj")
617 self.path("it.lproj")
618 self.path("nl.lproj")
619 self.path("pl.lproj")
620 self.path("pt.lproj")
621 self.path("ru.lproj")
622 self.path("tr.lproj")
623 self.path("uk.lproj")
624 self.path("zh-Hans.lproj")
625
626
627 if self.prefix(src="../../libraries/universal-darwin/lib_release/gstreamer-plugins", dst="lib/gstreamer-plugins"):
628 self.path("libgstaacparse.so")
629 self.path("libgstadder.so")
630 self.path("libgstaiffparse.so")
631 self.path("libgstamrparse.so")
632 self.path("libgstapp.so")
633 self.path("libgstaudioconvert.so")
634 self.path("libgstaudiorate.so")
635 self.path("libgstaudioresample.so")
636 self.path("libgstautodetect.so")
637 self.path("libgstavi.so")
638 self.path("libgstcoreelements.so")
639 self.path("libgstcoreindexers.so")
640 self.path("libgstdebug.so")
641 self.path("libgstdecodebin.so")
642 self.path("libgstdecodebin2.so")
643 self.path("libgstdeinterlace2.so")
644 self.path("libgstequalizer.so")
645 self.path("libgstfaad.so")
646 self.path("libgstffmpeg.so")
647 self.path("libgstffmpegcolorspace.so")
648 self.path("libgstffmpegscale.so")
649 self.path("libgstfilter.so")
650 self.path("libgstflac.so")
651 self.path("libgstflv.so")
652 self.path("libgstgdp.so")
653 self.path("libgsth264parse.so")
654 self.path("libgsticydemux.so")
655 self.path("libgstid3demux.so")
656 self.path("libgstinterleave.so")
657 self.path("libgstjpeg.so")
658 self.path("libgstlevel.so")
659 self.path("libgstmetadata.so")
660 self.path("libgstmpeg4videoparse.so")
661 self.path("libgstmpegdemux.so")
662 self.path("libgstmpegvideoparse.so")
663 self.path("libgstmultifile.so")
664 self.path("libgstmultipart.so")
665 self.path("libgstneonhttpsrc.so")
666 self.path("libgstogg.so")
667 self.path("libgstosxaudio.so")
668 self.path("libgstosxvideosink.so")
669 self.path("libgstplaybin.so")
670 self.path("libgstpng.so")
671 self.path("libgstpostproc.so")
672 self.path("libgstqtdemux.so")
673 #self.path("libgstqtwrapper.so")
674 self.path("libgstqueue2.so")
675 self.path("libgstreal.so")
676 self.path("libgstrtp.so")
677 self.path("libgstrtpmanager.so")
678 self.path("libgstrtsp.so")
679 self.path("libgstsdpelem.so")
680 self.path("libgstselector.so")
681 self.path("libgststereo.so")
682 self.path("libgsttcp.so")
683 self.path("libgsttheora.so")
684 self.path("libgsttypefindfunctions.so")
685 self.path("libgstudp.so")
686 self.path("libgstvideobalance.so")
687 self.path("libgstvideobox.so")
688 self.path("libgstvideocrop.so")
689 self.path("libgstvideoflip.so")
690 self.path("libgstvideomixer.so")
691 self.path("libgstvideorate.so")
692 self.path("libgstvideoscale.so")
693 self.path("libgstvideosignal.so")
694 self.path("libgstvolume.so")
695 self.path("libgstvorbis.so")
696 self.path("libgstwavparse.so")
697
698 self.end_prefix("../../libraries/universal-darwin/lib_release/gstreamer-plugins")
699
700
701 # SLVoice and vivox lols
702 self.path("vivox-runtime/universal-darwin/libalut.dylib", "libalut.dylib")
703 self.path("vivox-runtime/universal-darwin/libopenal.dylib", "libopenal.dylib")
704 self.path("vivox-runtime/universal-darwin/libortp.dylib", "libortp.dylib")
705 self.path("vivox-runtime/universal-darwin/libvivoxsdk.dylib", "libvivoxsdk.dylib")
706 self.path("vivox-runtime/universal-darwin/SLVoice", "SLVoice")
707 #self.path("vivox-runtime/universal-darwin/SLVoiceAgent.app", "SLVoiceAgent.app")
708
709 #libfmodwrapper.dylib
710 #self.path(self.args['configuration'] + "/libfmodwrapper.dylib", "libfmodwrapper.dylib")
711
712 # our apps
713# self.path("../mac_crash_logger/" + self.args['configuration'] + "/mac-crash-logger.app", "mac-crash-logger.app")
714 self.path("../mac_updater/" + self.args['configuration'] + "/mac-updater.app", "mac-updater.app")
715
716 # plugin launcher
717 self.path("../llplugin/slplugin/" + self.args['configuration'] + "/SLPlugin", "SLPlugin")
718
719 # plugins
720 if self.prefix(src="", dst="llplugin"):
721 self.path("../media_plugins/quicktime/" + self.args['configuration'] + "/media_plugin_quicktime.dylib", "media_plugin_quicktime.dylib")
722 self.path("../media_plugins/webkit/" + self.args['configuration'] + "/media_plugin_webkit.dylib", "media_plugin_webkit.dylib")
723 self.path("../../libraries/universal-darwin/lib_release/libllqtwebkit.dylib", "libllqtwebkit.dylib")
724
725 self.end_prefix("llplugin")
726
727 # Per platform MIME config on the cheap. See SNOW-307 / DEV-41388
728 self.path("skins/default/xui/en-us/mime_types_mac.xml", "skins/default/xui/en-us/mime_types.xml")
729
730 # command line arguments for connecting to the proper grid
731 self.put_in_file(self.flags_list(), 'arguments.txt')
732
733 self.end_prefix("Resources")
734
735 self.end_prefix("Contents")
736
737 # NOTE: the -S argument to strip causes it to keep enough info for
738 # annotated backtraces (i.e. function names in the crash log). 'strip' with no
739 # arguments yields a slightly smaller binary but makes crash logs mostly useless.
740 # This may be desirable for the final release. Or not.
741 if ("package" in self.args['actions'] or
742 "unpacked" in self.args['actions']):
743 self.run_command('strip -S "%(viewer_binary)s"' %
744 { 'viewer_binary' : self.dst_path_of('Contents/MacOS/Second Life')})
745
746
747 def package_finish(self):
748 channel_standin = 'Imprudence' # hah, our default channel is not usable on its own
749 if not self.default_channel():
750 channel_standin = self.channel()
751
752 imagename="Imprudence_" + '_'.join(self.args['version'])
753
754 # MBW -- If the mounted volume name changes, it breaks the .DS_Store's background image and icon positioning.
755 # If we really need differently named volumes, we'll need to create multiple DS_Store file images, or use some other trick.
756
757 volname="Imprudence Installer" # DO NOT CHANGE without understanding comment above
758
759 if self.default_channel():
760 if not self.default_grid():
761 # beta case
762 imagename = imagename + '_' + self.args['grid'].upper()
763 else:
764 # first look, etc
765 imagename = imagename + '_' + self.channel_oneword().upper()
766
767 sparsename = imagename + ".sparseimage"
768 finalname = imagename + ".dmg"
769 # make sure we don't have stale files laying about
770 self.remove(sparsename, finalname)
771
772 self.run_command('hdiutil create "%(sparse)s" -volname "%(vol)s" -fs HFS+ -type SPARSE -megabytes 400 -layout SPUD' % {
773 'sparse':sparsename,
774 'vol':volname})
775
776 # mount the image and get the name of the mount point and device node
777 hdi_output = self.run_command('hdiutil attach -private "' + sparsename + '"')
778 devfile = re.search("/dev/disk([0-9]+)[^s]", hdi_output).group(0).strip()
779 volpath = re.search('HFS\s+(.+)', hdi_output).group(1).strip()
780
781 # Copy everything in to the mounted .dmg
782
783 if self.default_channel() and not self.default_grid():
784 app_name = "Imprudence " + self.args['grid']
785 else:
786 app_name = channel_standin.strip()
787
788 # Hack:
789 # Because there is no easy way to coerce the Finder into positioning
790 # the app bundle in the same place with different app names, we are
791 # adding multiple .DS_Store files to svn. There is one for release,
792 # one for release candidate and one for first look. Any other channels
793 # will use the release .DS_Store, and will look broken.
794 # - Ambroff 2008-08-20
795 dmg_template = os.path.join(
796 'installers',
797 'darwin',
798 '%s-dmg' % "".join(self.channel_unique().split()).lower())
799
800 if not os.path.exists (self.src_path_of(dmg_template)):
801 dmg_template = os.path.join ('installers', 'darwin', 'release-dmg')
802
803 for s,d in {self.get_dst_prefix():app_name + ".app",
804 os.path.join(dmg_template, "_VolumeIcon.icns"): ".VolumeIcon.icns",
805 os.path.join(dmg_template, "background.jpg"): "background.jpg",
806 os.path.join(dmg_template, "_DS_Store"): ".DS_Store"}.items():
807 print "Copying to dmg", s, d
808 self.copy_action(self.src_path_of(s), os.path.join(volpath, d))
809
810 # Hide the background image, DS_Store file, and volume icon file (set their "visible" bit)
811 self.run_command('SetFile -a V "' + os.path.join(volpath, ".VolumeIcon.icns") + '"')
812 self.run_command('SetFile -a V "' + os.path.join(volpath, "background.jpg") + '"')
813 self.run_command('SetFile -a V "' + os.path.join(volpath, ".DS_Store") + '"')
814
815 # Create the alias file (which is a resource file) from the .r
816 self.run_command('rez "' + self.src_path_of("installers/darwin/release-dmg/Applications-alias.r") + '" -o "' + os.path.join(volpath, "Applications") + '"')
817
818 # Set the alias file's alias and custom icon bits
819 self.run_command('SetFile -a AC "' + os.path.join(volpath, "Applications") + '"')
820
821 # Set the disk image root's custom icon bit
822 self.run_command('SetFile -a C "' + volpath + '"')
823
824 # Unmount the image
825 self.run_command('hdiutil detach -force "' + devfile + '"')
826
827 print "Converting temp disk image to final disk image"
828 self.run_command('hdiutil convert "%(sparse)s" -format UDZO -imagekey zlib-level=9 -o "%(final)s"' % {'sparse':sparsename, 'final':finalname})
829 # get rid of the temp file
830 self.package_file = finalname
831 self.remove(sparsename)
832
833class LinuxManifest(ViewerManifest):
834 def construct(self):
835 super(LinuxManifest, self).construct()
836
837 self.path("res/imprudence_icon.png","imprudence_icon.png")
838 if self.prefix("linux_tools", dst=""):
839 #self.path("client-readme.txt","README-linux.txt")
840 self.path("client-readme-voice.txt","README-linux-voice.txt")
841 #self.path("client-readme-joystick.txt","README-linux-joystick.txt")
842 self.path("wrapper.sh","imprudence")
843 self.path("handle_secondlifeprotocol.sh")
844 self.path("register_secondlifeprotocol.sh")
845 self.path("getvoice.sh")
846 self.end_prefix("linux_tools")
847
848 self.gather_documents()
849
850 # From the linden directory
851 if self.prefix("../..", dst="doc"):
852 self.path("LICENSE-libraries.txt")
853 self.end_prefix("../..")
854
855 # Create an appropriate gridargs.dat for this package, denoting required grid.
856 self.put_in_file(self.flags_list(), 'gridargs.dat')
857 self.path("linux_tools/launch_url.sh","launch_url.sh")
858 self.path("../llplugin/slplugin/SLPlugin", "bin/SLPlugin")
859 if self.prefix("res-sdl"):
860 self.path("*")
861 # recurse
862 self.end_prefix("res-sdl")
863
864 # plugins
865 if self.prefix(src="", dst="bin/llplugin"):
866 self.path("../media_plugins/webkit/libmedia_plugin_webkit.so", "libmedia_plugin_webkit.so")
867 self.path("../media_plugins/gstreamer010/libmedia_plugin_gstreamer010.so", "libmedia_plugin_gstreamer.so")
868 self.end_prefix("bin/llplugin")
869
870 # Per platform MIME config on the cheap. See SNOW-307 / DEV-41388
871 self.path("skins/default/xui/en-us/mime_types_linux.xml", "skins/default/xui/en-us/mime_types.xml")
872
873 self.path("featuretable_linux.txt")
874
875
876 def package_finish(self):
877 if 'installer_name' in self.args:
878 installer_name = self.args['installer_name']
879 else:
880 installer_name_components = ['Imprudence_', self.args.get('arch')]
881 installer_name_components.extend(self.args['version'])
882 installer_name = "_".join(installer_name_components)
883 if self.default_channel():
884 if not self.default_grid():
885 installer_name += '_' + self.args['grid'].upper()
886 else:
887 installer_name += '_' + self.channel_oneword().upper()
888
889 # Fix access permissions
890 self.run_command("""
891 find %(dst)s -type d | xargs --no-run-if-empty chmod 755;
892 find %(dst)s -type f -perm 0700 | xargs --no-run-if-empty chmod 0755;
893 find %(dst)s -type f -perm 0500 | xargs --no-run-if-empty chmod 0555;
894 find %(dst)s -type f -perm 0600 | xargs --no-run-if-empty chmod 0644;
895 find %(dst)s -type f -perm 0400 | xargs --no-run-if-empty chmod 0444;
896 true""" % {'dst':self.get_dst_prefix() })
897
898 self.package_file = installer_name + '.tar.bz2'
899
900 # Disabled for now. It's a waste of time to package every compile.
901
902 # if("package" in self.args['actions'] or
903 # "unpacked" in self.args['actions']):
904 #
905 # # temporarily move directory tree so that it has the right
906 # # name in the tarfile
907 # self.run_command("mv %(dst)s %(inst)s" % {
908 # 'dst': self.get_dst_prefix(),
909 # 'inst': self.build_path_of(installer_name)})
910 # try:
911 # # --numeric-owner hides the username of the builder for
912 # # security etc.
913 # self.run_command('tar -C %(dir)s --numeric-owner -cjf '
914 # '%(inst_path)s.tar.bz2 %(inst_name)s' % {
915 # 'dir': self.get_build_prefix(),
916 # 'inst_name': installer_name,
917 # 'inst_path':self.build_path_of(installer_name)})
918 # finally:
919 # self.run_command("mv %(inst)s %(dst)s" % {
920 # 'dst': self.get_dst_prefix(),
921 # 'inst': self.build_path_of(installer_name)})
922
923class Linux_i686Manifest(LinuxManifest):
924 def construct(self):
925 super(Linux_i686Manifest, self).construct()
926 self.path("imprudence-stripped","bin/do-not-directly-run-imprudence-bin")
927
928
929 if self.prefix("../../libraries/i686-linux/lib_release_client", dst="lib"):
930 self.path("libapr-1.so.0")
931 self.path("libaprutil-1.so.0")
932 self.path("libdb-4.2.so")
933 self.path("libcrypto.so.0.9.7")
934 self.path("libexpat.so.1")
935 self.path("libssl.so.0.9.7")
936 self.path("libuuid.so", "libuuid.so.1")
937 self.path("libSDL-1.2.so.0")
938 self.path("libELFIO.so")
939 self.path("libopenjpeg.so.2")
940 self.path("libxml2.so.2")
941 self.path("libz.so.1")
942
943 # OpenAL
944 self.path("libopenal.so.1")
945 self.path("libalut.so.0")
946
947 # GTK+ and dependencies
948 self.path("libatk-1.0.so.0")
949 self.path("libcairo.so.2")
950 self.path("libfontconfig.so.1")
951 self.path("libfreetype.so.6")
952 # self.path("libgdk_pixbuf-2.0.so.0") # see linux64 why
953 self.path("libgdk-x11-2.0.so.0")
954 self.path("libgtk-x11-2.0.so.0")
955 # self.path("libpango-1.0.so.0") # dto.
956 # self.path("libpangoft2-1.0.so.0")
957 # self.path("libpangox-1.0.so.0")
958 # self.path("libpangoxft-1.0.so.0")
959 self.path("libpixman-1.so.0")
960
961 # Gstreamer libs
962 self.path("libgstbase-0.10.so.0")
963 self.path("libgstreamer-0.10.so.0")
964 self.path("libgstaudio-0.10.so.0")
965 self.path("libgstbase-0.10.so.0")
966 self.path("libgstcontroller-0.10.so.0")
967 self.path("libgstdataprotocol-0.10.so.0")
968 self.path("libgstinterfaces-0.10.so.0")
969 self.path("libgstnetbuffer-0.10.so.0")
970 self.path("libgstpbutils-0.10.so.0")
971 self.path("libgstriff-0.10.so.0")
972 self.path("libgstrtp-0.10.so.0")
973 self.path("libgstrtsp-0.10.so.0")
974 self.path("libgstsdp-0.10.so.0")
975 self.path("libgsttag-0.10.so.0")
976 self.path("libgstvideo-0.10.so.0")
977
978 # Gstreamer plugin dependencies
979 self.path("libfaad.so.0")
980 self.path("libogg.so.0")
981 self.path("libtheora.so.0")
982 self.path("libvorbis.so.0")
983 self.path("libvorbisenc.so.2")
984 self.path("liboil-0.3.so.0")
985
986 # Gstreamer plugins
987 if self.prefix("gstreamer-plugins"):
988 self.path("libgstalsa.so")
989 self.path("libgstasf.so")
990 self.path("libgstaudioconvert.so")
991 self.path("libgstaudioresample.so")
992 self.path("libgstautodetect.so")
993 self.path("libgstavi.so")
994 self.path("libgstcoreelements.so")
995 self.path("libgstcoreindexers.so")
996 self.path("libgstdecodebin2.so")
997 self.path("libgstdecodebin.so")
998 self.path("libgstesd.so")
999 self.path("libgstfaad.so")
1000 self.path("libgstffmpeg.so")
1001 self.path("libgstgnomevfs.so")
1002 self.path("libgsticydemux.so")
1003 self.path("libgstid3demux.so")
1004 self.path("libgstmpegdemux.so")
1005 self.path("libgstmultifile.so")
1006 self.path("libgstmultipart.so")
1007 self.path("libgstogg.so")
1008 self.path("libgstossaudio.so")
1009 self.path("libgstplaybin.so")
1010 self.path("libgstpulse.so")
1011 self.path("libgstqtdemux.so")
1012 self.path("libgstqueue2.so")
1013 self.path("libgsttcp.so")
1014 self.path("libgsttheora.so")
1015 self.path("libgsttypefindfunctions.so")
1016 self.path("libgstudp.so")
1017 self.path("libgstvideoscale.so")
1018 self.path("libgstvolume.so")
1019 self.path("libgstvorbis.so")
1020 self.path("libgstwavparse.so")
1021
1022 self.end_prefix("gstreamer-plugins")
1023
1024 self.end_prefix("lib")
1025
1026 # Vivox runtimes and libs
1027 if self.prefix(src="vivox-runtime/i686-linux", dst="bin"):
1028 self.path("SLVoice")
1029 self.end_prefix("bin")
1030
1031 if self.prefix(src="vivox-runtime/i686-linux", dst="lib"):
1032 self.path("libalut.so")
1033 self.path("libortp.so")
1034 self.path("libvivoxsdk.so")
1035 self.end_prefix("lib")
1036
1037class Linux_x86_64Manifest(LinuxManifest):
1038 def construct(self):
1039 super(Linux_x86_64Manifest, self).construct()
1040 self.path("imprudence-stripped","bin/do-not-directly-run-imprudence-bin")
1041# self.path("../linux_crash_logger/linux-crash-logger-stripped","linux-crash-logger.bin")
1042
1043 self.path("linux_tools/launch_url.sh","launch_url.sh")
1044 if self.prefix("res-sdl"):
1045 self.path("*")
1046 # recurse
1047 self.end_prefix("res-sdl")
1048
1049 self.path("featuretable_linux.txt")
1050 #self.path("secondlife-x86_64.supp")
1051
1052 self.path("app_settings/mozilla-runtime-linux-x86_64")
1053
1054 if self.prefix("../../libraries/x86_64-linux/lib_release_client", dst="lib64"):
1055 self.path("libapr-1.so.0")
1056 self.path("libaprutil-1.so.0")
1057 self.path("libdb-4.2.so")
1058 self.path("libcrypto.so.0.9.8")
1059 self.path("libexpat.so.1")
1060 self.path("libssl.so.0.9.8")
1061 self.path("libuuid.so", "libuuid.so.1")
1062 self.path("libSDL-1.2.so.0")
1063 self.path("libELFIO.so")
1064 self.path("libjpeg.so.7")
1065 self.path("libpng12.so.0")
1066 self.path("libopenjpeg.so.2")
1067 self.path("libxml2.so.2")
1068 #self.path("libz.so.1") #not needed
1069
1070 # OpenAL
1071 self.path("libopenal.so.1")
1072 self.path("libalut.so.0")
1073
1074 # GTK+ and dependencies
1075 self.path("libatk-1.0.so.0")
1076 self.path("libcairo.so.2")
1077 self.path("libfontconfig.so.1")
1078 self.path("libfreetype.so.6")
1079 self.path("libgdk_pixbuf-2.0.so.0") # was commented to use systems gdk pixbufs instead -
1080 # but seems webkit needs it o_O . Packaging for testing now.
1081 self.path("libgdk-x11-2.0.so.0")
1082 self.path("libgtk-x11-2.0.so.0")
1083# self.path("libpango-1.0.so.0") # use systems pango instead
1084# self.path("libpangoft2-1.0.so.0") # Both gdk pixbufs and pango would load systems modules
1085# self.path("libpangox-1.0.so.0") # and crash if not compatible or present.
1086# self.path("libpangoxft-1.0.so.0") # So we depend system gdk pixbufs and pango anyway.
1087 self.path("libpixman-1.so.0")
1088
1089 # Gstreamer libs
1090 self.path("libgstbase-0.10.so.0")
1091 self.path("libgstreamer-0.10.so.0")
1092 self.path("libgstaudio-0.10.so.0")
1093 self.path("libgstbase-0.10.so.0")
1094 self.path("libgstcontroller-0.10.so.0")
1095 self.path("libgstdataprotocol-0.10.so.0")
1096 self.path("libgstinterfaces-0.10.so.0")
1097 self.path("libgstnetbuffer-0.10.so.0")
1098 self.path("libgstpbutils-0.10.so.0")
1099 self.path("libgstriff-0.10.so.0")
1100 self.path("libgstrtp-0.10.so.0")
1101 self.path("libgstrtsp-0.10.so.0")
1102 self.path("libgstsdp-0.10.so.0")
1103 self.path("libgsttag-0.10.so.0")
1104 self.path("libgstvideo-0.10.so.0")
1105
1106 # Gstreamer plugin dependencies
1107 self.path("libfaad.so.0")
1108 self.path("libogg.so.0")
1109 self.path("libtheora.so.0")
1110 self.path("libvorbis.so.0")
1111 self.path("libvorbisenc.so.2")
1112 self.path("liboil-0.3.so.0")
1113
1114 # Gstreamer plugins
1115 if self.prefix("gstreamer-plugins"):
1116 self.path("libgstalsa.so")
1117 self.path("libgstasf.so")
1118 self.path("libgstaudioconvert.so")
1119 self.path("libgstaudioresample.so")
1120 self.path("libgstautodetect.so")
1121 self.path("libgstavi.so")
1122 self.path("libgstcoreelements.so")
1123 self.path("libgstcoreindexers.so")
1124 self.path("libgstdecodebin2.so")
1125 self.path("libgstdecodebin.so")
1126 self.path("libgstesd.so")
1127 self.path("libgstfaad.so")
1128 self.path("libgstffmpeg.so")
1129 self.path("libgstffmpegcolorspace.so")
1130 self.path("libgstgnomevfs.so")
1131 self.path("libgsticydemux.so")
1132 self.path("libgstid3demux.so")
1133 self.path("libgstmpegdemux.so")
1134 self.path("libgstmultifile.so")
1135 self.path("libgstmultipart.so")
1136 self.path("libgstogg.so")
1137 self.path("libgstossaudio.so")
1138 self.path("libgstplaybin.so")
1139 self.path("libgstpulse.so")
1140 self.path("libgstqtdemux.so")
1141 self.path("libgstqueue2.so")
1142 self.path("libgsttcp.so")
1143 self.path("libgsttheora.so")
1144 self.path("libgsttypefindfunctions.so")
1145 self.path("libgstudp.so")
1146 self.path("libgstvideoscale.so")
1147 self.path("libgstvolume.so")
1148 self.path("libgstvorbis.so")
1149 self.path("libgstwavparse.so")
1150
1151 self.end_prefix("gstreamer-plugins")
1152 self.end_prefix("lib64")
1153
1154
1155 # Vivox runtimes and libs
1156 if self.prefix(src="vivox-runtime/i686-linux", dst="bin"):
1157 self.path("SLVoice")
1158 self.end_prefix("bin")
1159
1160 if self.prefix(src="vivox-runtime/i686-linux", dst="lib32"):
1161 #self.path("libalut.so")
1162 self.path("libortp.so")
1163 self.path("libvivoxsdk.so")
1164 self.end_prefix("lib32")
1165
1166 # 32bit libs needed for voice
1167 if self.prefix("../../libraries/x86_64-linux/lib_release_client/32bit-compat", dst="lib32"):
1168 self.path("libalut.so")
1169 self.path("libidn.so.11")
1170 self.path("libopenal.so.1")
1171 # self.path("libortp.so")
1172 self.path("libuuid.so.1")
1173 self.end_prefix("lib32")
1174
1175if __name__ == "__main__":
1176 main()