diff options
author | Armin Weatherwax | 2010-09-23 20:30:12 +0200 |
---|---|---|
committer | Armin Weatherwax | 2010-09-23 20:30:12 +0200 |
commit | 197f915816579a14e102075cf25a26127dfc1d32 (patch) | |
tree | b6f3212d612c79a2740c347866089ea39935ee04 /linden/indra | |
parent | Imprudence style gstreamer plugin (remove llgst, syms and such) (diff) | |
download | meta-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.cmake | 114 | ||||
-rw-r--r-- | linden/indra/cmake/GStreamer010Plugin.cmake | 20 | ||||
-rw-r--r-- | linden/indra/llmedia/llmediaimplgstreamer.cpp | 928 | ||||
-rwxr-xr-x | linden/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp~ | 1219 | ||||
-rwxr-xr-x | linden/indra/newview/linux_tools/getvoice.sh | 5 | ||||
-rwxr-xr-x | linden/indra/newview/linux_tools/wrapper.sh | 8 | ||||
-rwxr-xr-x | linden/indra/newview/viewer_manifest.py | 248 | ||||
-rwxr-xr-x | linden/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 -*- | ||
2 | include(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 | |||
14 | if (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 | |||
57 | else (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 | |||
106 | endif (WINDOWS) | ||
107 | |||
108 | if (GSTREAMER_FOUND AND GSTREAMER_PLUGINS_BASE_FOUND) | ||
109 | set(GSTREAMER ON CACHE BOOL "Build with GStreamer streaming media support.") | ||
110 | endif (GSTREAMER_FOUND AND GSTREAMER_PLUGINS_BASE_FOUND) | ||
111 | |||
112 | if (GSTREAMER) | ||
113 | add_definitions(-DLL_GSTREAMER_ENABLED=1) | ||
114 | endif (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 | ) | ||
30 | endif (STANDALONE) | 34 | endif (STANDALONE) |
31 | 35 | ||
32 | if (GSTREAMER010_FOUND AND GSTREAMER010_PLUGINS_BASE_FOUND) | 36 | if (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 | |||
45 | extern "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 | ||
68 | static LLMediaImplRegister sLLMediaImplGStreamerReg( "LLMediaImplGStreamer", new LLMediaImplGStreamerMaker() ); | ||
69 | |||
70 | LLMediaImplGStreamerMaker::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 | // | ||
83 | LLMediaImplGStreamer:: | ||
84 | LLMediaImplGStreamer () : | ||
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 | ||
138 | int LLMediaImplGStreamer::getTextureFormatPrimary() const | ||
139 | { | ||
140 | return mTextureFormatPrimary; | ||
141 | } | ||
142 | |||
143 | // virtual | ||
144 | int LLMediaImplGStreamer::getTextureFormatType() const | ||
145 | { | ||
146 | return mTextureFormatType; | ||
147 | } | ||
148 | |||
149 | // virtual | ||
150 | int LLMediaImplGStreamer::getTextureFormatInternal() const | ||
151 | { | ||
152 | return LL_MEDIA_RGB8; | ||
153 | } | ||
154 | |||
155 | /////////////////////////////////////////////////////////////////////////////// | ||
156 | // | ||
157 | LLMediaImplGStreamer:: | ||
158 | ~LLMediaImplGStreamer () | ||
159 | { | ||
160 | LL_DEBUGS("MediaImpl") << ("dtor of media...") << LL_ENDL; | ||
161 | unload(); | ||
162 | } | ||
163 | |||
164 | //////////////////////////////////////////////////////////////////////////////// | ||
165 | // virtual | ||
166 | std::string LLMediaImplGStreamer::getVersion() | ||
167 | { | ||
168 | guint major, minor, micro, nano; | ||
169 | gst_version(&major, &minor, µ, &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 | ||
178 | bool 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 | |||
229 | void 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 | |||
338 | void 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 | |||
378 | bool LLMediaImplGStreamer::closedown() | ||
379 | { | ||
380 | return true; | ||
381 | } | ||
382 | |||
383 | |||
384 | bool 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 | ||
401 | static 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 | ||
416 | gboolean 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 | ||
580 | bool 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 | // | ||
611 | bool 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 | ||
643 | bool 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 | // | ||
769 | bool 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 | // | ||
797 | bool 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 | |||
830 | void 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 | // | ||
853 | bool 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 | ||
881 | unsigned char* LLMediaImplGStreamer::getMediaData() | ||
882 | { | ||
883 | return mediaData; | ||
884 | } | ||
885 | |||
886 | |||
887 | /////////////////////////////////////////////////////////////////////////////// | ||
888 | // virtual | ||
889 | bool 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 | ||
908 | bool 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 | |||
47 | extern "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 | // | ||
60 | class MediaPluginGStreamer010 : public MediaPluginBase | ||
61 | { | ||
62 | public: | ||
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 | |||
74 | private: | ||
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 | |||
101 | private: | ||
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 | ||
150 | bool MediaPluginGStreamer010::mDoneInit = false; | ||
151 | |||
152 | MediaPluginGStreamer010::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 | ||
175 | static 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 | |||
188 | gboolean | ||
189 | MediaPluginGStreamer010::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 | |||
351 | extern "C" { | ||
352 | gboolean | ||
353 | llmediaimplgstreamer_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 | |||
364 | bool | ||
365 | MediaPluginGStreamer010::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 | |||
394 | bool | ||
395 | MediaPluginGStreamer010::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 | |||
523 | void | ||
524 | MediaPluginGStreamer010::mouseDown( int x, int y ) | ||
525 | { | ||
526 | // do nothing | ||
527 | } | ||
528 | |||
529 | void | ||
530 | MediaPluginGStreamer010::mouseUp( int x, int y ) | ||
531 | { | ||
532 | // do nothing | ||
533 | } | ||
534 | |||
535 | void | ||
536 | MediaPluginGStreamer010::mouseMove( int x, int y ) | ||
537 | { | ||
538 | // do nothing | ||
539 | } | ||
540 | |||
541 | |||
542 | bool | ||
543 | MediaPluginGStreamer010::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 | |||
551 | bool | ||
552 | MediaPluginGStreamer010::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 | |||
560 | bool | ||
561 | MediaPluginGStreamer010::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 | |||
571 | bool | ||
572 | MediaPluginGStreamer010::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 | |||
590 | bool | ||
591 | MediaPluginGStreamer010::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 | |||
607 | bool | ||
608 | MediaPluginGStreamer010::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 | |||
650 | bool | ||
651 | MediaPluginGStreamer010::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 | |||
710 | bool | ||
711 | MediaPluginGStreamer010::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 | ||
744 | bool | ||
745 | MediaPluginGStreamer010::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 | |||
844 | void | ||
845 | MediaPluginGStreamer010::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 | ||
878 | bool | ||
879 | MediaPluginGStreamer010::closedown() | ||
880 | { | ||
881 | if (!mDoneInit) | ||
882 | return false; // error | ||
883 | |||
884 | ungrab_gst_syms(); | ||
885 | |||
886 | mDoneInit = false; | ||
887 | |||
888 | return true; | ||
889 | } | ||
890 | |||
891 | MediaPluginGStreamer010::~MediaPluginGStreamer010() | ||
892 | { | ||
893 | DEBUGMSG("MediaPluginGStreamer010 destructor"); | ||
894 | |||
895 | closedown(); | ||
896 | |||
897 | DEBUGMSG("GStreamer010 closing down"); | ||
898 | } | ||
899 | |||
900 | |||
901 | std::string | ||
902 | MediaPluginGStreamer010::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, µ, &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 | |||
919 | void 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 | |||
1167 | int 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) | ||
1187 | class MediaPluginGStreamer010 : public MediaPluginBase | ||
1188 | { | ||
1189 | public: | ||
1190 | MediaPluginGStreamer010(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); | ||
1191 | ~MediaPluginGStreamer010(); | ||
1192 | /* virtual */ void receiveMessage(const char *message_string); | ||
1193 | }; | ||
1194 | |||
1195 | MediaPluginGStreamer010::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 | |||
1203 | MediaPluginGStreamer010::~MediaPluginGStreamer010() | ||
1204 | { | ||
1205 | // no-op | ||
1206 | } | ||
1207 | |||
1208 | void MediaPluginGStreamer010::receiveMessage(const char *message_string) | ||
1209 | { | ||
1210 | // no-op | ||
1211 | } | ||
1212 | |||
1213 | // We're building without GStreamer enabled. Just refuse to initialize. | ||
1214 | int 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 @@ | |||
3 | SCRIPTSRC=`readlink -f "$0" || echo "$0"` | 3 | SCRIPTSRC=`readlink -f "$0" || echo "$0"` |
4 | RUN_PATH=`dirname "${SCRIPTSRC}" || echo .` | 4 | RUN_PATH=`dirname "${SCRIPTSRC}" || echo .` |
5 | 5 | ||
6 | #if mozilla-runtime-linux-x86_64 is present we are using 64bit Imprudence on 64bit Linux | 6 | BINARY_SYSTEM=$(expr match "$(file -b /bin/uname)" '\(.*executable\)') |
7 | if [ -d "${RUN_PATH}/app_settings/mozilla-runtime-linux-x86_64/" ]; then | 7 | BINARY_VIEWER=$(expr match "$(file -b ${RUN_PATH}/bin/do-not-directly-run-imprudence-bin)" '\(.*executable\)') |
8 | if ( [ "$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. |
9 | else | 10 | else |
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 |
108 | fi | 108 | fi |
109 | 109 | BINARY_SYSTEM=$(expr match "$(file -b /bin/uname)" '\(.*executable\)') | |
110 | if([ "`uname -m`" = "x86_64" ] && [ -d "${RUN_PATH}/app_settings/mozilla-runtime-linux-x86_64/" ]); then | 110 | BINARY_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/" | 111 | echo "viewer: $BINARY_VIEWER system: $BINARY_SYSTEM" |
112 | if ( [ "$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}"' |
114 | else | 115 | else |
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}"' |
117 | fi | 117 | fi |
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 | |||
40 | import sys | ||
41 | import os.path | ||
42 | import re | ||
43 | import tarfile | ||
44 | viewer_dir = os.path.dirname(__file__) | ||
45 | # add llmanifest library to our path so we don't have to muck with PYTHONPATH | ||
46 | sys.path.append(os.path.join(viewer_dir, '../lib/python/indra/util')) | ||
47 | from llmanifest import LLManifest, main, proper_windows_path, path_ancestors | ||
48 | |||
49 | class 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 | |||
193 | class 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 | |||
530 | class 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 | |||
833 | class 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 | |||
923 | class 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 | |||
1037 | class 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 | |||
1175 | if __name__ == "__main__": | ||
1176 | main() | ||