aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/media_plugins/example
diff options
context:
space:
mode:
authorArmin Weatherwax2010-06-14 12:04:49 +0200
committerArmin Weatherwax2010-09-23 15:38:25 +0200
commit35df5441d3e2789663532c948731aff3a1e04728 (patch)
treeac7674289784a5f96106ea507637055a8dada78a /linden/indra/media_plugins/example
parentChanged version to Experimental 2010.09.18 (diff)
downloadmeta-impy-35df5441d3e2789663532c948731aff3a1e04728.zip
meta-impy-35df5441d3e2789663532c948731aff3a1e04728.tar.gz
meta-impy-35df5441d3e2789663532c948731aff3a1e04728.tar.bz2
meta-impy-35df5441d3e2789663532c948731aff3a1e04728.tar.xz
llmediaplugins first step
Diffstat (limited to 'linden/indra/media_plugins/example')
-rw-r--r--linden/indra/media_plugins/example/CMakeLists.txt74
-rw-r--r--linden/indra/media_plugins/example/media_plugin_example.cpp488
2 files changed, 562 insertions, 0 deletions
diff --git a/linden/indra/media_plugins/example/CMakeLists.txt b/linden/indra/media_plugins/example/CMakeLists.txt
new file mode 100644
index 0000000..4d82f27
--- /dev/null
+++ b/linden/indra/media_plugins/example/CMakeLists.txt
@@ -0,0 +1,74 @@
1# -*- cmake -*-
2
3project(media_plugin_example)
4
5include(00-Common)
6include(LLCommon)
7include(LLImage)
8include(LLPlugin)
9include(LLMath)
10include(LLRender)
11include(LLWindow)
12include(Linking)
13include(PluginAPI)
14include(MediaPluginBase)
15include(FindOpenGL)
16
17include(ExamplePlugin)
18
19include_directories(
20 ${LLPLUGIN_INCLUDE_DIRS}
21 ${MEDIA_PLUGIN_BASE_INCLUDE_DIRS}
22 ${LLCOMMON_INCLUDE_DIRS}
23 ${LLMATH_INCLUDE_DIRS}
24 ${LLIMAGE_INCLUDE_DIRS}
25 ${LLRENDER_INCLUDE_DIRS}
26 ${LLWINDOW_INCLUDE_DIRS}
27)
28
29
30### media_plugin_example
31
32set(media_plugin_example_SOURCE_FILES
33 media_plugin_example.cpp
34 )
35
36add_library(media_plugin_example
37 SHARED
38 ${media_plugin_example_SOURCE_FILES}
39)
40
41target_link_libraries(media_plugin_example
42 ${LLPLUGIN_LIBRARIES}
43 ${MEDIA_PLUGIN_BASE_LIBRARIES}
44 ${LLCOMMON_LIBRARIES}
45 ${EXAMPLE_PLUGIN_LIBRARIES}
46 ${PLUGIN_API_WINDOWS_LIBRARIES}
47)
48
49add_dependencies(media_plugin_example
50 ${LLPLUGIN_LIBRARIES}
51 ${MEDIA_PLUGIN_BASE_LIBRARIES}
52 ${LLCOMMON_LIBRARIES}
53)
54
55if (WINDOWS)
56 set_target_properties(
57 media_plugin_example
58 PROPERTIES
59 LINK_FLAGS "/MANIFEST:NO"
60 )
61endif (WINDOWS)
62
63if (DARWIN)
64 # Don't prepend 'lib' to the executable name, and don't embed a full path in the library's install name
65 set_target_properties(
66 media_plugin_example
67 PROPERTIES
68 PREFIX ""
69 BUILD_WITH_INSTALL_RPATH 1
70 INSTALL_NAME_DIR "@executable_path"
71 LINK_FLAGS "-exported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/../base/media_plugin_base.exp"
72 )
73
74endif (DARWIN) \ No newline at end of file
diff --git a/linden/indra/media_plugins/example/media_plugin_example.cpp b/linden/indra/media_plugins/example/media_plugin_example.cpp
new file mode 100644
index 0000000..99e0199
--- /dev/null
+++ b/linden/indra/media_plugins/example/media_plugin_example.cpp
@@ -0,0 +1,488 @@
1/**
2 * @file media_plugin_example.cpp
3 * @brief Example plugin for LLMedia API plugin system
4 *
5 * $LicenseInfo:firstyear=2008&license=viewergpl$
6 *
7 * Copyright (c) 2009, Linden Research, Inc.
8 *
9 * Second Life Viewer Source Code
10 * The source code in this file ("Source Code") is provided by Linden Lab
11 * to you under the terms of the GNU General Public License, version 2.0
12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2
16 *
17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception
21 *
22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above,
24 * and agree to abide by those obligations.
25 *
26 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
27 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
28 * COMPLETENESS OR PERFORMANCE.
29 * $/LicenseInfo$
30 */
31
32#include "linden_common.h"
33
34#include "llgl.h"
35#include "llplugininstance.h"
36#include "llpluginmessage.h"
37#include "llpluginmessageclasses.h"
38#include "media_plugin_base.h"
39
40#include <time.h>
41
42////////////////////////////////////////////////////////////////////////////////
43//
44class MediaPluginExample :
45 public MediaPluginBase
46{
47 public:
48 MediaPluginExample( LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data );
49 ~MediaPluginExample();
50
51 /*virtual*/ void receiveMessage( const char* message_string );
52
53 private:
54 bool init();
55 void update( F64 milliseconds );
56 void write_pixel( int x, int y, unsigned char r, unsigned char g, unsigned char b );
57 bool mFirstTime;
58
59 time_t mLastUpdateTime;
60 enum Constants { ENumObjects = 10 };
61 unsigned char* mBackgroundPixels;
62 int mColorR[ ENumObjects ];
63 int mColorG[ ENumObjects ];
64 int mColorB[ ENumObjects ];
65 int mXpos[ ENumObjects ];
66 int mYpos[ ENumObjects ];
67 int mXInc[ ENumObjects ];
68 int mYInc[ ENumObjects ];
69 int mBlockSize[ ENumObjects ];
70 bool mMouseButtonDown;
71 bool mStopAction;
72};
73
74////////////////////////////////////////////////////////////////////////////////
75//
76MediaPluginExample::MediaPluginExample( LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data ) :
77 MediaPluginBase( host_send_func, host_user_data )
78{
79 mFirstTime = true;
80 mWidth = 0;
81 mHeight = 0;
82 mDepth = 4;
83 mPixels = 0;
84 mMouseButtonDown = false;
85 mStopAction = false;
86 mLastUpdateTime = 0;
87}
88
89////////////////////////////////////////////////////////////////////////////////
90//
91MediaPluginExample::~MediaPluginExample()
92{
93}
94
95////////////////////////////////////////////////////////////////////////////////
96//
97void MediaPluginExample::receiveMessage( const char* message_string )
98{
99 LLPluginMessage message_in;
100
101 if ( message_in.parse( message_string ) >= 0 )
102 {
103 std::string message_class = message_in.getClass();
104 std::string message_name = message_in.getName();
105
106 if ( message_class == LLPLUGIN_MESSAGE_CLASS_BASE )
107 {
108 if ( message_name == "init" )
109 {
110 LLPluginMessage message( "base", "init_response" );
111 LLSD versions = LLSD::emptyMap();
112 versions[ LLPLUGIN_MESSAGE_CLASS_BASE ] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION;
113 versions[ LLPLUGIN_MESSAGE_CLASS_MEDIA ] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION;
114 versions[ LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER ] = LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER_VERSION;
115 message.setValueLLSD( "versions", versions );
116
117 std::string plugin_version = "Example media plugin, Example Version 1.0.0.0";
118 message.setValue( "plugin_version", plugin_version );
119 sendMessage( message );
120
121 // Plugin gets to decide the texture parameters to use.
122 message.setMessage( LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params" );
123 message.setValueS32( "default_width", mWidth );
124 message.setValueS32( "default_height", mHeight );
125 message.setValueS32( "depth", mDepth );
126 message.setValueU32( "internalformat", GL_RGBA );
127 message.setValueU32( "format", GL_RGBA );
128 message.setValueU32( "type", GL_UNSIGNED_BYTE );
129 message.setValueBoolean( "coords_opengl", false );
130 sendMessage( message );
131 }
132 else
133 if ( message_name == "idle" )
134 {
135 // no response is necessary here.
136 F64 time = message_in.getValueReal( "time" );
137
138 // Convert time to milliseconds for update()
139 update( time );
140 }
141 else
142 if ( message_name == "cleanup" )
143 {
144 // clean up here
145 }
146 else
147 if ( message_name == "shm_added" )
148 {
149 SharedSegmentInfo info;
150 info.mAddress = message_in.getValuePointer( "address" );
151 info.mSize = ( size_t )message_in.getValueS32( "size" );
152 std::string name = message_in.getValue( "name" );
153
154 mSharedSegments.insert( SharedSegmentMap::value_type( name, info ) );
155
156 }
157 else
158 if ( message_name == "shm_remove" )
159 {
160 std::string name = message_in.getValue( "name" );
161
162 SharedSegmentMap::iterator iter = mSharedSegments.find( name );
163 if( iter != mSharedSegments.end() )
164 {
165 if ( mPixels == iter->second.mAddress )
166 {
167 // This is the currently active pixel buffer.
168 // Make sure we stop drawing to it.
169 mPixels = NULL;
170 mTextureSegmentName.clear();
171 };
172 mSharedSegments.erase( iter );
173 }
174 else
175 {
176 //std::cerr << "MediaPluginExample::receiveMessage: unknown shared memory region!" << std::endl;
177 };
178
179 // Send the response so it can be cleaned up.
180 LLPluginMessage message( "base", "shm_remove_response" );
181 message.setValue( "name", name );
182 sendMessage( message );
183 }
184 else
185 {
186 //std::cerr << "MediaPluginExample::receiveMessage: unknown base message: " << message_name << std::endl;
187 };
188 }
189 else
190 if ( message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA )
191 {
192 if ( message_name == "size_change" )
193 {
194 std::string name = message_in.getValue( "name" );
195 S32 width = message_in.getValueS32( "width" );
196 S32 height = message_in.getValueS32( "height" );
197 S32 texture_width = message_in.getValueS32( "texture_width" );
198 S32 texture_height = message_in.getValueS32( "texture_height" );
199
200 if ( ! name.empty() )
201 {
202 // Find the shared memory region with this name
203 SharedSegmentMap::iterator iter = mSharedSegments.find( name );
204 if ( iter != mSharedSegments.end() )
205 {
206 mPixels = ( unsigned char* )iter->second.mAddress;
207 mWidth = width;
208 mHeight = height;
209
210 mTextureWidth = texture_width;
211 mTextureHeight = texture_height;
212
213 init();
214 };
215 };
216
217 LLPluginMessage message( LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response" );
218 message.setValue( "name", name );
219 message.setValueS32( "width", width );
220 message.setValueS32( "height", height );
221 message.setValueS32( "texture_width", texture_width );
222 message.setValueS32( "texture_height", texture_height );
223 sendMessage( message );
224 }
225 else
226 if ( message_name == "load_uri" )
227 {
228 std::string uri = message_in.getValue( "uri" );
229 if ( ! uri.empty() )
230 {
231 };
232 }
233 else
234 if ( message_name == "mouse_event" )
235 {
236 std::string event = message_in.getValue( "event" );
237 S32 button = message_in.getValueS32( "button" );
238
239 // left mouse button
240 if ( button == 0 )
241 {
242 int mouse_x = message_in.getValueS32( "x" );
243 int mouse_y = message_in.getValueS32( "y" );
244 std::string modifiers = message_in.getValue( "modifiers" );
245
246 if ( event == "move" )
247 {
248 if ( mMouseButtonDown )
249 write_pixel( mouse_x, mouse_y, rand() % 0x80 + 0x80, rand() % 0x80 + 0x80, rand() % 0x80 + 0x80 );
250 }
251 else
252 if ( event == "down" )
253 {
254 mMouseButtonDown = true;
255 }
256 else
257 if ( event == "up" )
258 {
259 mMouseButtonDown = false;
260 }
261 else
262 if ( event == "double_click" )
263 {
264 };
265 };
266 }
267 else
268 if ( message_name == "key_event" )
269 {
270 std::string event = message_in.getValue( "event" );
271 S32 key = message_in.getValueS32( "key" );
272 std::string modifiers = message_in.getValue( "modifiers" );
273
274 if ( event == "down" )
275 {
276 if ( key == ' ')
277 {
278 mLastUpdateTime = 0;
279 update( 0.0f );
280 };
281 };
282 }
283 else
284 {
285 //std::cerr << "MediaPluginExample::receiveMessage: unknown media message: " << message_string << std::endl;
286 };
287 }
288 else
289 if ( message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER )
290 {
291 if ( message_name == "browse_reload" )
292 {
293 mLastUpdateTime = 0;
294 mFirstTime = true;
295 mStopAction = false;
296 update( 0.0f );
297 }
298 else
299 if ( message_name == "browse_stop" )
300 {
301 for( int n = 0; n < ENumObjects; ++n )
302 mXInc[ n ] = mYInc[ n ] = 0;
303
304 mStopAction = true;
305 update( 0.0f );
306 }
307 else
308 {
309 //std::cerr << "MediaPluginExample::receiveMessage: unknown media_browser message: " << message_string << std::endl;
310 };
311 }
312 else
313 {
314 //std::cerr << "MediaPluginExample::receiveMessage: unknown message class: " << message_class << std::endl;
315 };
316 };
317}
318
319////////////////////////////////////////////////////////////////////////////////
320//
321void MediaPluginExample::write_pixel( int x, int y, unsigned char r, unsigned char g, unsigned char b )
322{
323 // make sure we don't write outside the buffer
324 if ( ( x < 0 ) || ( x >= mWidth ) || ( y < 0 ) || ( y >= mHeight ) )
325 return;
326
327 if ( mBackgroundPixels != NULL )
328 {
329 unsigned char *pixel = mBackgroundPixels;
330 pixel += y * mWidth * mDepth;
331 pixel += ( x * mDepth );
332 pixel[ 0 ] = b;
333 pixel[ 1 ] = g;
334 pixel[ 2 ] = r;
335
336 setDirty( x, y, x + 1, y + 1 );
337 };
338}
339
340////////////////////////////////////////////////////////////////////////////////
341//
342void MediaPluginExample::update( F64 milliseconds )
343{
344 if ( mWidth < 1 || mWidth > 2048 || mHeight < 1 || mHeight > 2048 )
345 return;
346
347 if ( mPixels == 0 )
348 return;
349
350 if ( mFirstTime )
351 {
352 for( int n = 0; n < ENumObjects; ++n )
353 {
354 mXpos[ n ] = ( mWidth / 2 ) + rand() % ( mWidth / 16 ) - ( mWidth / 32 );
355 mYpos[ n ] = ( mHeight / 2 ) + rand() % ( mHeight / 16 ) - ( mHeight / 32 );
356
357 mColorR[ n ] = rand() % 0x60 + 0x60;
358 mColorG[ n ] = rand() % 0x60 + 0x60;
359 mColorB[ n ] = rand() % 0x60 + 0x60;
360
361 mXInc[ n ] = 0;
362 while ( mXInc[ n ] == 0 )
363 mXInc[ n ] = rand() % 7 - 3;
364
365 mYInc[ n ] = 0;
366 while ( mYInc[ n ] == 0 )
367 mYInc[ n ] = rand() % 9 - 4;
368
369 mBlockSize[ n ] = rand() % 0x30 + 0x10;
370 };
371
372 delete [] mBackgroundPixels;
373
374 mBackgroundPixels = new unsigned char[ mWidth * mHeight * mDepth ];
375
376 mFirstTime = false;
377 };
378
379 if ( mStopAction )
380 return;
381
382 if ( time( NULL ) > mLastUpdateTime + 3 )
383 {
384 const int num_squares = rand() % 20 + 4;
385 int sqr1_r = rand() % 0x80 + 0x20;
386 int sqr1_g = rand() % 0x80 + 0x20;
387 int sqr1_b = rand() % 0x80 + 0x20;
388 int sqr2_r = rand() % 0x80 + 0x20;
389 int sqr2_g = rand() % 0x80 + 0x20;
390 int sqr2_b = rand() % 0x80 + 0x20;
391
392 for ( int y1 = 0; y1 < num_squares; ++y1 )
393 {
394 for ( int x1 = 0; x1 < num_squares; ++x1 )
395 {
396 int px_start = mWidth * x1 / num_squares;
397 int px_end = ( mWidth * ( x1 + 1 ) ) / num_squares;
398 int py_start = mHeight * y1 / num_squares;
399 int py_end = ( mHeight * ( y1 + 1 ) ) / num_squares;
400
401 for( int y2 = py_start; y2 < py_end; ++y2 )
402 {
403 for( int x2 = px_start; x2 < px_end; ++x2 )
404 {
405 int rowspan = mWidth * mDepth;
406
407 if ( ( y1 % 2 ) ^ ( x1 % 2 ) )
408 {
409 mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 0 ] = sqr1_r;
410 mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 1 ] = sqr1_g;
411 mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 2 ] = sqr1_b;
412 }
413 else
414 {
415 mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 0 ] = sqr2_r;
416 mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 1 ] = sqr2_g;
417 mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 2 ] = sqr2_b;
418 };
419 };
420 };
421 };
422 };
423
424 time( &mLastUpdateTime );
425 };
426
427 memcpy( mPixels, mBackgroundPixels, mWidth * mHeight * mDepth );
428
429 for( int n = 0; n < ENumObjects; ++n )
430 {
431 if ( rand() % 50 == 0 )
432 {
433 mXInc[ n ] = 0;
434 while ( mXInc[ n ] == 0 )
435 mXInc[ n ] = rand() % 7 - 3;
436
437 mYInc[ n ] = 0;
438 while ( mYInc[ n ] == 0 )
439 mYInc[ n ] = rand() % 9 - 4;
440 };
441
442 if ( mXpos[ n ] + mXInc[ n ] < 0 || mXpos[ n ] + mXInc[ n ] >= mWidth - mBlockSize[ n ] )
443 mXInc[ n ] =- mXInc[ n ];
444
445 if ( mYpos[ n ] + mYInc[ n ] < 0 || mYpos[ n ] + mYInc[ n ] >= mHeight - mBlockSize[ n ] )
446 mYInc[ n ] =- mYInc[ n ];
447
448 mXpos[ n ] += mXInc[ n ];
449 mYpos[ n ] += mYInc[ n ];
450
451 for( int y = 0; y < mBlockSize[ n ]; ++y )
452 {
453 for( int x = 0; x < mBlockSize[ n ]; ++x )
454 {
455 mPixels[ ( mXpos[ n ] + x ) * mDepth + ( mYpos[ n ] + y ) * mDepth * mWidth + 0 ] = mColorR[ n ];
456 mPixels[ ( mXpos[ n ] + x ) * mDepth + ( mYpos[ n ] + y ) * mDepth * mWidth + 1 ] = mColorG[ n ];
457 mPixels[ ( mXpos[ n ] + x ) * mDepth + ( mYpos[ n ] + y ) * mDepth * mWidth + 2 ] = mColorB[ n ];
458 };
459 };
460 };
461
462 setDirty( 0, 0, mWidth, mHeight );
463};
464
465////////////////////////////////////////////////////////////////////////////////
466//
467bool MediaPluginExample::init()
468{
469 LLPluginMessage message( LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text" );
470 message.setValue( "name", "Example Plugin" );
471 sendMessage( message );
472
473 return true;
474};
475
476////////////////////////////////////////////////////////////////////////////////
477//
478int init_media_plugin( LLPluginInstance::sendMessageFunction host_send_func,
479 void* host_user_data,
480 LLPluginInstance::sendMessageFunction *plugin_send_func,
481 void **plugin_user_data )
482{
483 MediaPluginExample* self = new MediaPluginExample( host_send_func, host_user_data );
484 *plugin_send_func = MediaPluginExample::staticReceiveMessage;
485 *plugin_user_data = ( void* )self;
486
487 return 0;
488}