llmediaplugintest.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:68k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /**
  2.  * @file LLMediaPluginTest.cpp
  3.  * @brief Primary test application for LLMedia (Separate Process) Plugin system
  4.  *
  5.  * $LicenseInfo:firstyear=2008&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2008-2010, 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://secondlifegrid.net/programs/open_source/licensing/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
  21.  * 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. #include "linden_common.h"
  33. #include "indra_constants.h"
  34. #include "llapr.h"
  35. #include "llerrorcontrol.h"
  36. #include <math.h>
  37. #include <iomanip>
  38. #include <sstream>
  39. #include <ctime>
  40. #include "llmediaplugintest.h"
  41. #if __APPLE__
  42. #include <GLUT/glut.h>
  43. #include <CoreFoundation/CoreFoundation.h>
  44. #else
  45. #define FREEGLUT_STATIC
  46. #include "GL/freeglut.h"
  47. #define GLUI_FREEGLUT
  48. #endif
  49. #if LL_WINDOWS
  50. #pragma warning(disable: 4263)
  51. #pragma warning(disable: 4264)
  52. #endif
  53. #include "glui.h"
  54. LLMediaPluginTest* gApplication = 0;
  55. static void gluiCallbackWrapper( int control_id );
  56. ////////////////////////////////////////////////////////////////////////////////
  57. //
  58. static bool isTexture( GLuint texture )
  59. {
  60. bool result = false;
  61. // glIsTexture will sometimes return false for real textures... do this instead.
  62. if(texture != 0)
  63. result = true;
  64. return result;
  65. }
  66. ////////////////////////////////////////////////////////////////////////////////
  67. //
  68. mediaPanel::mediaPanel()
  69. {
  70. mMediaTextureHandle = 0;
  71. mPickTextureHandle = 0;
  72. mMediaSource = NULL;
  73. mPickTexturePixels = NULL;
  74. }
  75. ////////////////////////////////////////////////////////////////////////////////
  76. //
  77. mediaPanel::~mediaPanel()
  78. {
  79. // delete OpenGL texture handles
  80. if ( isTexture( mPickTextureHandle ) )
  81. {
  82. std::cerr << "remMediaPanel: deleting pick texture " << mPickTextureHandle << std::endl;
  83. glDeleteTextures( 1, &mPickTextureHandle );
  84. mPickTextureHandle = 0;
  85. }
  86. if ( isTexture( mMediaTextureHandle ) )
  87. {
  88. std::cerr << "remMediaPanel: deleting media texture " << mMediaTextureHandle << std::endl;
  89. glDeleteTextures( 1, &mMediaTextureHandle );
  90. mMediaTextureHandle = 0;
  91. }
  92. if(mPickTexturePixels)
  93. {
  94. delete mPickTexturePixels;
  95. }
  96. if(mMediaSource)
  97. {
  98. delete mMediaSource;
  99. }
  100. }
  101. ////////////////////////////////////////////////////////////////////////////////
  102. //
  103. LLMediaPluginTest::LLMediaPluginTest( int app_window, int window_width, int window_height ) :
  104. mVersionMajor( 2 ),
  105. mVersionMinor( 0 ),
  106. mVersionPatch( 0 ),
  107. mMaxPanels( 25 ),
  108. mViewportAspect( 0 ),
  109. mAppWindow( app_window ),
  110. mCurMouseX( 0 ),
  111. mCurMouseY( 0 ),
  112. mFuzzyMedia( true ),
  113. mSelectedPanel( 0 ),
  114. mMediaBrowserControlEnableCookies( 0 ),
  115. mMediaBrowserControlBackButton( 0 ),
  116. mMediaBrowserControlForwardButton( 0 ),
  117. mMediaTimeControlVolume( 100 ),
  118. mMediaTimeControlSeekSeconds( 0 ),
  119. mGluiMediaTimeControlWindowFlag( true ),
  120. mGluiMediaBrowserControlWindowFlag( true ),
  121. mMediaBrowserControlBackButtonFlag( true ),
  122. mMediaBrowserControlForwardButtonFlag( true ),
  123. mHomeWebUrl( "http://www.google.com/" )
  124. {
  125. // debugging spam
  126. std::cout << std::endl << "             GLUT version: " << "3.7.6" << std::endl; // no way to get real version from GLUT
  127. std::cout << std::endl << "             GLUI version: " << GLUI_Master.get_version() << std::endl;
  128. std::cout << std::endl << "Media Plugin Test version: " << mVersionMajor << "." << mVersionMinor << "." << mVersionPatch << std::endl;
  129. // bookmark title
  130. mBookmarks.push_back( std::pair< std::string, std::string >( "--- Bookmarks ---", "" ) );
  131. // insert hardcoded URLs here as required for testing
  132. //mBookmarks.push_back( std::pair< std::string, std::string >( "description", "url" ) );
  133. // read bookmarks from file.
  134. // note: uses command in ./CmakeLists.txt which copies bookmmarks file from source directory 
  135. //       to app directory (WITHOUT build configuration dir) (this is cwd in Windows within MSVC)
  136. //  For example, test_appsllplugintest and not test_appsllplugintestRelease
  137. //  This may need to be changed for Mac/Linux builds.
  138. // See https://jira.lindenlab.com/browse/DEV-31350 for large list of media URLs from AGNI
  139. const std::string bookmarks_filename( "bookmarks.txt" );
  140. std::ifstream file_handle( bookmarks_filename.c_str() );
  141. if ( file_handle.is_open() )
  142. {
  143. std::cout << "Reading bookmarks for test" << std::endl;
  144. while( ! file_handle.eof() )
  145. {
  146. std::string line;
  147. std::getline( file_handle, line );
  148. if ( file_handle.eof() )
  149. break;
  150. if ( line.substr( 0, 1 ) != "#" )
  151. {
  152. size_t comma_pos = line.find_first_of( ',' );
  153. if ( comma_pos != std::string::npos )
  154. {
  155. std::string description = line.substr( 0, comma_pos );
  156. std::string url = line.substr( comma_pos + 1 );
  157. mBookmarks.push_back( std::pair< std::string, std::string >( description, url ) );
  158. }
  159. else
  160. {
  161. mBookmarks.push_back( std::pair< std::string, std::string >( line, line ) );
  162. };
  163. };
  164. };
  165. std::cout << "Read " << mBookmarks.size() << " bookmarks" << std::endl;
  166. }
  167. else
  168. {
  169. std::cout << "Unable to read bookmarks from file: " << bookmarks_filename << std::endl;
  170. };
  171. // initialize linden lab APR module
  172. ll_init_apr();
  173. // Set up llerror logging 
  174. {
  175. LLError::initForApplication(".");
  176. LLError::setDefaultLevel(LLError::LEVEL_INFO);
  177. //LLError::setTagLevel("Plugin", LLError::LEVEL_DEBUG);
  178. }
  179. // lots of randomness in this app
  180. srand( ( unsigned int )time( 0 ) );
  181. // build GUI
  182. makeChrome();
  183. // OpenGL initialilzation
  184. glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
  185. glClearDepth( 1.0f );
  186. glEnable( GL_DEPTH_TEST );
  187. glEnable( GL_COLOR_MATERIAL );
  188. glColorMaterial( GL_FRONT, GL_AMBIENT_AND_DIFFUSE );
  189. glDepthFunc( GL_LEQUAL );
  190. glEnable( GL_TEXTURE_2D );
  191. glDisable( GL_BLEND );
  192. glColor3f( 1.0f, 1.0f, 1.0f );
  193. glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
  194. glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 );
  195. // start with a sane view
  196. resetView();
  197. // initial media panel
  198. const int num_initial_panels = 1;
  199. for( int i = 0; i < num_initial_panels; ++i )
  200. {
  201. //addMediaPanel( mBookmarks[ rand() % ( mBookmarks.size() - 1 ) + 1 ].second );
  202. addMediaPanel( mHomeWebUrl );
  203. };
  204. }
  205. ////////////////////////////////////////////////////////////////////////////////
  206. //
  207. LLMediaPluginTest::~LLMediaPluginTest()
  208. {
  209. // delete all media panels
  210. for( int i = 0; i < (int)mMediaPanels.size(); ++i )
  211. {
  212. remMediaPanel( mMediaPanels[ i ] );
  213. };
  214. }
  215. ////////////////////////////////////////////////////////////////////////////////
  216. //
  217. void LLMediaPluginTest::reshape( int width, int height )
  218. {
  219. // update viewport (the active window inside the chrome)
  220. int viewport_x, viewport_y;
  221. int viewport_height, viewport_width;
  222. GLUI_Master.get_viewport_area( &viewport_x, &viewport_y, &viewport_width, &viewport_height );
  223. mViewportAspect = (float)( viewport_width ) / (float)( viewport_height );
  224. glViewport( viewport_x, viewport_y, viewport_width, viewport_height );
  225. // save these as we'll need them later
  226. mWindowWidth = width;
  227. mWindowHeight = height;
  228. // adjust size of URL bar so it doesn't get clipped
  229. mUrlEdit->set_w( mWindowWidth - 360 );
  230. // GLUI requires this
  231. if ( glutGetWindow() != mAppWindow )
  232. glutSetWindow( mAppWindow );
  233. // trigger re-display
  234. glutPostRedisplay();
  235. };
  236. ////////////////////////////////////////////////////////////////////////////////
  237. //
  238. void LLMediaPluginTest::bindTexture(GLuint texture, GLint row_length, GLint alignment)
  239. {
  240. glEnable( GL_TEXTURE_2D );
  241. glBindTexture( GL_TEXTURE_2D, texture );
  242. glPixelStorei( GL_UNPACK_ROW_LENGTH, row_length );
  243. glPixelStorei( GL_UNPACK_ALIGNMENT, alignment );
  244. }
  245. ////////////////////////////////////////////////////////////////////////////////
  246. //
  247. bool LLMediaPluginTest::checkGLError(const char *name)
  248. {
  249. bool result = false;
  250. GLenum error = glGetError();
  251. if(error != GL_NO_ERROR)
  252. {
  253. // For some reason, glGenTextures is returning GL_INVALID_VALUE...
  254. std::cout << name << " ERROR 0x" << std::hex << error << std::dec << std::endl;
  255. result = true;
  256. }
  257. return result;
  258. }
  259. ////////////////////////////////////////////////////////////////////////////////
  260. //
  261. void LLMediaPluginTest::drawGeometry( int panel )
  262. {
  263. // texture coordinates for each panel
  264. GLfloat non_opengl_texture_coords[ 8 ] = { 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f };
  265. GLfloat opengl_texture_coords[ 8 ] =     { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f };
  266. GLfloat *texture_coords = mMediaPanels[ panel ]->mAppTextureCoordsOpenGL?opengl_texture_coords:non_opengl_texture_coords;
  267. // base coordinates for each panel
  268. GLfloat base_vertex_pos[ 8 ] = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f };
  269. // calculate posiitons
  270. const int num_panels = (int)mMediaPanels.size();
  271. const int num_rows = (int)sqrt( (float)num_panels );
  272. const int num_cols = num_panels / num_rows;
  273. const int panel_x = ( panel / num_rows );
  274. const int panel_y = ( panel % num_rows );
  275. const float spacing = 0.1f;
  276. const GLfloat offset_x = num_cols * ( 1.0 + spacing ) / 2;
  277. const GLfloat offset_y = num_rows * ( 1.0 + spacing ) / 2;
  278. // Adjust for media aspect ratios
  279. {
  280. float aspect = 1.0f;
  281. if(mMediaPanels[ panel ]->mMediaHeight != 0)
  282. {
  283. aspect = (float)mMediaPanels[ panel ]->mMediaWidth / (float)mMediaPanels[ panel ]->mMediaHeight;
  284. }
  285. if(aspect > 1.0f)
  286. {
  287. // media is wider than it is high -- adjust the top and bottom in
  288. for( int corner = 0; corner < 4; ++corner )
  289. {
  290. float temp = base_vertex_pos[corner * 2 + 1];
  291. if(temp < 0.5f)
  292. temp += 0.5 - (0.5f / aspect);
  293. else
  294. temp -= 0.5 - (0.5f / aspect);
  295. base_vertex_pos[corner * 2 + 1] = temp;
  296. }
  297. }
  298. else if(aspect < 1.0f)
  299. {
  300. // media is higher than it is wide -- adjust the left and right sides in
  301. for( int corner = 0; corner < 4; ++corner )
  302. {
  303. float temp = base_vertex_pos[corner * 2];
  304. if(temp < 0.5f)
  305. temp += 0.5f - (0.5f * aspect);
  306. else
  307. temp -= 0.5f - (0.5f * aspect);
  308. base_vertex_pos[corner * 2] = temp;
  309. }
  310. }
  311. }
  312. glBegin( GL_QUADS );
  313. for( int corner = 0; corner < 4; ++corner )
  314. {
  315. glTexCoord2f( texture_coords[ corner * 2 ], texture_coords[ corner * 2 + 1 ] );
  316. GLfloat x = base_vertex_pos[ corner * 2 ] + panel_x * ( 1.0 + spacing ) - offset_x + spacing / 2.0f;
  317. GLfloat y = base_vertex_pos[ corner * 2 + 1 ] + panel_y * ( 1.0 + spacing ) - offset_y + spacing / 2.0f;
  318. glVertex3f( x, y, 0.0f );
  319. };
  320. glEnd();
  321. }
  322. //////////////////////////////////////////////////////////////////////////////
  323. //
  324. void LLMediaPluginTest::startPanelHighlight( float red, float green, float blue, float line_width )
  325. {
  326. glPushAttrib( GL_ALL_ATTRIB_BITS );
  327. glEnable( GL_POLYGON_OFFSET_FILL );
  328. glPolygonOffset( -2.5f, -2.5f );
  329. glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
  330. glLineWidth( line_width );
  331. glColor3f( red, green, blue );
  332. glDisable( GL_TEXTURE_2D );
  333. }
  334. //////////////////////////////////////////////////////////////////////////////
  335. //
  336. void LLMediaPluginTest::endPanelHighlight()
  337. {
  338. glPopAttrib();
  339. }
  340. ////////////////////////////////////////////////////////////////////////////////
  341. //
  342. void LLMediaPluginTest::draw( int draw_type )
  343. {
  344. for( int panel = 0; panel < (int)mMediaPanels.size(); ++panel )
  345. {
  346. // drawing pick texture
  347. if ( draw_type == DrawTypePickTexture )
  348. {
  349. // only bother with pick if we have something to render
  350. // Actually, we need to pick even if we're not ready to render.  
  351. // Otherwise you can't select and remove a panel which has gone bad.
  352. //if ( mMediaPanels[ panel ]->mReadyToRender )
  353. {
  354. glMatrixMode( GL_TEXTURE );
  355. glPushMatrix();
  356. // pick texture is a power of 2 so no need to scale
  357. glLoadIdentity();
  358. // bind to media texture
  359. glLoadIdentity();
  360. bindTexture( mMediaPanels[ panel ]->mPickTextureHandle );
  361. glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
  362. glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
  363. // draw geometry using pick texture
  364. drawGeometry( panel );
  365. glMatrixMode( GL_TEXTURE );
  366. glPopMatrix();
  367. };
  368. }
  369. else
  370. if ( draw_type == DrawTypeMediaTexture )
  371. {
  372. bool texture_valid = false;
  373. bool plugin_exited = false;
  374. if(mMediaPanels[ panel ]->mMediaSource)
  375. {
  376. texture_valid = mMediaPanels[ panel ]->mMediaSource->textureValid();
  377. plugin_exited = mMediaPanels[ panel ]->mMediaSource->isPluginExited();
  378. }
  379. // save texture matrix (changes for each panel)
  380. glMatrixMode( GL_TEXTURE );
  381. glPushMatrix();
  382. // only process texture if the media is ready to draw
  383. // (we still want to draw the geometry)
  384. if ( mMediaPanels[ panel ]->mReadyToRender && texture_valid )
  385. {
  386. // bind to media texture
  387. bindTexture( mMediaPanels[ panel ]->mMediaTextureHandle );
  388. if ( mFuzzyMedia )
  389. {
  390. glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
  391. glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
  392. }
  393. else
  394. {
  395. glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
  396. glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
  397. }
  398. // scale to fit panel
  399. glScalef( mMediaPanels[ panel ]->mTextureScaleX,
  400. mMediaPanels[ panel ]->mTextureScaleY,
  401. 1.0f );
  402. };
  403. float intensity = plugin_exited?0.25f:1.0f;
  404. // highlight the selected panel
  405. if ( mSelectedPanel && ( mMediaPanels[ panel ]->mId == mSelectedPanel->mId ) )
  406. {
  407. startPanelHighlight( intensity, intensity, 0.0f, 5.0f );
  408. drawGeometry( panel );
  409. endPanelHighlight();
  410. }
  411. else
  412. // this panel not able to render yet since it
  413. // doesn't have enough information
  414. if ( !mMediaPanels[ panel ]->mReadyToRender )
  415. {
  416. startPanelHighlight( intensity, 0.0f, 0.0f, 2.0f );
  417. drawGeometry( panel );
  418. endPanelHighlight();
  419. }
  420. else
  421. // just display a border around the media 
  422. {
  423. startPanelHighlight( 0.0f, intensity, 0.0f, 2.0f );
  424. drawGeometry( panel );
  425. endPanelHighlight();
  426. };
  427. if ( mMediaPanels[ panel ]->mReadyToRender && texture_valid )
  428. {
  429. // draw visual geometry
  430. drawGeometry( panel );
  431. }
  432. // restore texture matrix (changes for each panel)
  433. glMatrixMode( GL_TEXTURE );
  434. glPopMatrix();
  435. };
  436. };
  437. }
  438. ////////////////////////////////////////////////////////////////////////////////
  439. //
  440. void LLMediaPluginTest::display()
  441. {
  442. // GLUI requires this
  443. if ( glutGetWindow() != mAppWindow )
  444. glutSetWindow( mAppWindow );
  445. // start with a clean slate
  446. glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
  447. glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
  448. // set up OpenGL view
  449. glMatrixMode( GL_PROJECTION );
  450. glLoadIdentity();
  451. glFrustum( -mViewportAspect * 0.04f, mViewportAspect * 0.04f, -0.04f, 0.04f, 0.1f, 50.0f );
  452. glMatrixMode( GL_MODELVIEW );
  453. glLoadIdentity();
  454. glTranslatef( 0.0, 0.0, 0.0f );
  455. glTranslatef( mViewPos[ 0 ], mViewPos[ 1 ], -mViewPos[ 2 ] );
  456. glMultMatrixf( mViewRotation );
  457. // draw pick texture
  458. draw( DrawTypePickTexture );
  459. // read colors and get coordinate values
  460. glReadPixels( mCurMouseX, mCurMouseY, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, mPixelReadColor );
  461. // clear the pick render (otherwise it may depth-fight with the textures rendered later)
  462. glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
  463. // draw visible geometry
  464. draw( DrawTypeMediaTexture );
  465. glutSwapBuffers();
  466. }
  467. ////////////////////////////////////////////////////////////////////////////////
  468. //
  469. void LLMediaPluginTest::idle()
  470. {
  471. // checkGLError("LLMediaPluginTest::idle");
  472. // GLUI requires this
  473. if ( glutGetWindow() != mAppWindow )
  474. glutSetWindow( mAppWindow );
  475. // random creation/destruction of panels enabled?
  476. const time_t panel_timeout_time = 5;
  477. if ( mRandomPanelCount )
  478. {
  479. // time for a change
  480. static time_t last_panel_time = 0;
  481. if ( time( NULL ) - last_panel_time > panel_timeout_time )
  482. {
  483. if ( rand() % 2 == 0 )
  484. {
  485. if ( mMediaPanels.size() < 16 )
  486. {
  487. std::cout << "Randomly adding new panel" << std::endl;
  488. addMediaPanel( mBookmarks[ rand() % ( mBookmarks.size() - 1 ) + 1 ].second );
  489. };
  490. }
  491. else
  492. {
  493. if ( mMediaPanels.size() > 0 )
  494. {
  495. std::cout << "Deleting selected panel" << std::endl;
  496. remMediaPanel( mSelectedPanel );
  497. };
  498. };
  499. time( &last_panel_time );
  500. };
  501. };
  502. // random selection of bookmarks enabled?
  503. const time_t bookmark_timeout_time = 5;
  504. if ( mRandomBookmarks )
  505. {
  506. // time for a change
  507. static time_t last_bookmark_time = 0;
  508. if ( time( NULL ) - last_bookmark_time > bookmark_timeout_time )
  509. {
  510. // go to a different random bookmark on each panel
  511. for( int panel = 0; panel < (int)mMediaPanels.size(); ++panel )
  512. {
  513. std::string uri = mBookmarks[ rand() % ( mBookmarks.size() - 1 ) + 1 ].second;
  514. std::cout << "Random: navigating to : " << uri << std::endl;
  515. std::string mime_type = mimeTypeFromUrl( uri );
  516. if ( mime_type != mMediaPanels[ panel ]->mMimeType )
  517. {
  518. replaceMediaPanel( mMediaPanels[ panel ], uri );
  519. }
  520. else
  521. {
  522. mMediaPanels[ panel ]->mMediaSource->loadURI( uri );
  523. mMediaPanels[ panel ]->mMediaSource->start();
  524. };
  525. };
  526. time( &last_bookmark_time );
  527. };
  528. };
  529. // update UI
  530. if ( mSelectedPanel )
  531. {
  532. // set volume based on slider if we have time media
  533. //if ( mGluiMediaTimeControlWindowFlag )
  534. //{
  535. // mSelectedPanel->mMediaSource->setVolume( (float)mMediaTimeControlVolume / 100.0f );
  536. //};
  537. // NOTE: it is absurd that we need cache the state of GLUI controls
  538. //       but enabling/disabling controls drags framerate from 500+
  539. //  down to 15. Not a problem for plugin system - only this test
  540. // enable/disable time based UI controls based on type of plugin
  541. if ( mSelectedPanel->mMediaSource->pluginSupportsMediaTime() )
  542. {
  543. if ( ! mGluiMediaTimeControlWindowFlag )
  544. {
  545. mGluiMediaTimeControlWindow->enable();
  546. mGluiMediaTimeControlWindowFlag = true;
  547. };
  548. }
  549. else
  550. {
  551. if ( mGluiMediaTimeControlWindowFlag )
  552. {
  553. mGluiMediaTimeControlWindow->disable();
  554. mGluiMediaTimeControlWindowFlag = false;
  555. };
  556. };
  557. // enable/disable browser based UI controls based on type of plugin
  558. if ( mSelectedPanel->mMediaSource->pluginSupportsMediaBrowser() )
  559. {
  560. if ( ! mGluiMediaBrowserControlWindowFlag )
  561. {
  562. mGluiMediaBrowserControlWindow->enable();
  563. mGluiMediaBrowserControlWindowFlag = true;
  564. };
  565. }
  566. else
  567. {
  568. if ( mGluiMediaBrowserControlWindowFlag )
  569. {
  570. mGluiMediaBrowserControlWindow->disable();
  571. mGluiMediaBrowserControlWindowFlag = false;
  572. };
  573. };
  574. // enable/disable browser back button depending on browser history
  575. if ( mSelectedPanel->mMediaSource->getHistoryBackAvailable()  )
  576. {
  577. if ( ! mMediaBrowserControlBackButtonFlag )
  578. {
  579. mMediaBrowserControlBackButton->enable();
  580. mMediaBrowserControlBackButtonFlag = true;
  581. };
  582. }
  583. else
  584. {
  585. if ( mMediaBrowserControlBackButtonFlag )
  586. {
  587. mMediaBrowserControlBackButton->disable();
  588. mMediaBrowserControlBackButtonFlag = false;
  589. };
  590. };
  591. // enable/disable browser forward button depending on browser history
  592. if ( mSelectedPanel->mMediaSource->getHistoryForwardAvailable()  )
  593. {
  594. if ( ! mMediaBrowserControlForwardButtonFlag )
  595. {
  596. mMediaBrowserControlForwardButton->enable();
  597. mMediaBrowserControlForwardButtonFlag = true;
  598. };
  599. }
  600. else
  601. {
  602. if ( mMediaBrowserControlForwardButtonFlag )
  603. {
  604. mMediaBrowserControlForwardButton->disable();
  605. mMediaBrowserControlForwardButtonFlag = false;
  606. };
  607. };
  608. // NOTE: This is *very* slow and not worth optimising
  609. updateStatusBar();
  610. };
  611. // update all the panels
  612. for( int panel_index = 0; panel_index < (int)mMediaPanels.size(); ++panel_index )
  613. {
  614. mediaPanel *panel = mMediaPanels[ panel_index ];
  615. // call plugins idle function so it can potentially update itself
  616. panel->mMediaSource->idle();
  617. // update each media panel
  618. updateMediaPanel( panel );
  619. LLRect dirty_rect;
  620. if ( ! panel->mMediaSource->textureValid() )
  621. {
  622. //std::cout << "texture invalid, skipping update..." << std::endl;
  623. }
  624. else
  625. if ( panel && 
  626.  ( panel->mMediaWidth != panel->mMediaSource->getWidth() ||
  627.    panel->mMediaHeight != panel->mMediaSource->getHeight() ) )
  628. {
  629. //std::cout << "Resize in progress, skipping update..." << std::endl;
  630. }
  631. else
  632. if ( panel->mMediaSource->getDirty( &dirty_rect ) )
  633. {
  634. const unsigned char* pixels = panel->mMediaSource->getBitsData();
  635. if ( pixels && isTexture(panel->mMediaTextureHandle))
  636. {
  637. int x_offset = dirty_rect.mLeft;
  638. int y_offset = dirty_rect.mBottom;
  639. int width = dirty_rect.mRight - dirty_rect.mLeft;
  640. int height = dirty_rect.mTop - dirty_rect.mBottom;
  641. if((dirty_rect.mRight <= panel->mTextureWidth) && (dirty_rect.mTop <= panel->mTextureHeight))
  642. {
  643. // Offset the pixels pointer properly
  644. pixels += ( y_offset * panel->mMediaSource->getTextureDepth() * panel->mMediaSource->getBitsWidth() );
  645. pixels += ( x_offset * panel->mMediaSource->getTextureDepth() );
  646. // set up texture
  647. bindTexture( panel->mMediaTextureHandle, panel->mMediaSource->getBitsWidth() );
  648. if ( mFuzzyMedia )
  649. {
  650. glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
  651. glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
  652. }
  653. else
  654. {
  655. glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
  656. glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
  657. };
  658. checkGLError("glTexParameteri");
  659. if(panel->mMediaSource->getTextureFormatSwapBytes())
  660. {
  661. glPixelStorei(GL_UNPACK_SWAP_BYTES, 1);
  662. checkGLError("glPixelStorei");
  663. }
  664. // draw portion that changes into texture
  665. glTexSubImage2D( GL_TEXTURE_2D, 0, 
  666. x_offset, 
  667. y_offset,
  668. width, 
  669. height,
  670. panel->mMediaSource->getTextureFormatPrimary(), 
  671. panel->mMediaSource->getTextureFormatType(), 
  672. pixels );
  673. if(checkGLError("glTexSubImage2D"))
  674. {
  675. std::cerr << "    panel ID=" << panel->mId << std::endl;
  676. std::cerr << "    texture size = " << panel->mTextureWidth << " x " << panel->mTextureHeight << std::endl;
  677. std::cerr << "    media size = " << panel->mMediaWidth << " x " << panel->mMediaHeight << std::endl;
  678. std::cerr << "    dirty rect = " << dirty_rect.mLeft << ", " << dirty_rect.mBottom << ", " << dirty_rect.mRight << ", " << dirty_rect.mTop << std::endl;
  679. std::cerr << "    texture width = " << panel->mMediaSource->getBitsWidth() << std::endl;
  680. std::cerr << "    format primary = 0x" << std::hex << panel->mMediaSource->getTextureFormatPrimary() << std::dec << std::endl;
  681. std::cerr << "    format type = 0x" << std::hex << panel->mMediaSource->getTextureFormatType() << std::dec << std::endl;
  682. std::cerr << "    pixels = " << (void*)pixels << std::endl;
  683. }
  684. if(panel->mMediaSource->getTextureFormatSwapBytes())
  685. {
  686. glPixelStorei(GL_UNPACK_SWAP_BYTES, 0);
  687. checkGLError("glPixelStorei");
  688. }
  689. panel->mMediaSource->resetDirty();
  690. panel->mReadyToRender = true;
  691. }
  692. else
  693. {
  694. std::cerr << "dirty rect is outside current media size, skipping update" << std::endl;
  695. }
  696. };
  697. };
  698. };
  699. // GLUI requires this
  700. if ( glutGetWindow() != mAppWindow )
  701. glutSetWindow( mAppWindow );
  702. // trigger re-display
  703. glutPostRedisplay();
  704. }
  705. ////////////////////////////////////////////////////////////////////////////////
  706. //
  707. void LLMediaPluginTest::windowPosToTexturePos( int window_x, int window_y, 
  708.    int& media_x, int& media_y, 
  709.    int& id )
  710. {
  711. if ( ! mSelectedPanel )
  712. {
  713. media_x = 0;
  714. media_y = 0;
  715. id = 0;
  716. return;
  717. };
  718. // record cursor poisiton for a readback next frame
  719. mCurMouseX = window_x;
  720. // OpenGL app == coordinate system this way
  721. // NOTE: unrelated to settings in plugin - this
  722. // is just for this app
  723. mCurMouseY = mWindowHeight - window_y;  
  724. // extract x (0..1023, y (0..1023) and id (0..15) from RGB components
  725. unsigned long pixel_read_color_bits = ( mPixelReadColor[ 0 ] << 16 ) | ( mPixelReadColor[ 1 ] << 8 ) | mPixelReadColor[ 2 ];
  726. int texture_x = pixel_read_color_bits & 0x3ff;
  727. int texture_y = ( pixel_read_color_bits >> 10 ) & 0x3ff;
  728. id = ( pixel_read_color_bits >> 20 ) & 0x0f;
  729. // scale to size of media (1024 because we use 10 bits for X and Y from 24)
  730. media_x = (int)( ( (float)mSelectedPanel->mMediaWidth * (float)texture_x ) / 1024.0f );
  731. media_y = (int)( ( (float)mSelectedPanel->mMediaHeight * (float)texture_y ) / 1024.0f );
  732. // we assume the plugin uses an inverted coordinate scheme like OpenGL
  733. // if not, the plugin code inverts the Y coordinate for us - we don't need to
  734. media_y = mSelectedPanel->mMediaHeight - media_y;
  735. if ( media_x > 0 && media_y > 0 )
  736. {
  737. //std::cout << "      mouse coords: " << mCurMouseX << " x " << mCurMouseY << " and id = " << id  << std::endl;
  738. //std::cout << "raw texture coords: " << texture_x << " x " << texture_y << " and id = " << id  << std::endl;
  739. //std::cout << "      media coords: " << media_x << " x " << media_y << " and id = " << id  << std::endl;
  740. //std::cout << std::endl;
  741. };
  742. }
  743. ////////////////////////////////////////////////////////////////////////////////
  744. //
  745. void LLMediaPluginTest::selectPanelById( int id )
  746. {
  747. for( int panel = 0; panel < (int)mMediaPanels.size(); ++panel )
  748. {
  749. if ( mMediaPanels[ panel ]->mId == id )
  750. {
  751. selectPanel(mMediaPanels[ panel ]);
  752. return;
  753. };
  754. };
  755. }
  756. ////////////////////////////////////////////////////////////////////////////////
  757. //
  758. void LLMediaPluginTest::selectPanel( mediaPanel* panel )
  759. {
  760. if( mSelectedPanel == panel )
  761. return;
  762. // turn off volume before we delete it
  763. if( mSelectedPanel && mSelectedPanel->mMediaSource )
  764. {
  765. mSelectedPanel->mMediaSource->setVolume( 0.0f );
  766. mSelectedPanel->mMediaSource->setPriority( LLPluginClassMedia::PRIORITY_LOW );
  767. };
  768. mSelectedPanel = panel;
  769. if( mSelectedPanel && mSelectedPanel->mMediaSource )
  770. {
  771. mSelectedPanel->mMediaSource->setVolume( (float)mMediaTimeControlVolume / 100.0f );
  772. mSelectedPanel->mMediaSource->setPriority( LLPluginClassMedia::PRIORITY_NORMAL );
  773. if(!mSelectedPanel->mStartUrl.empty())
  774. {
  775. mUrlEdit->set_text(const_cast<char*>(mSelectedPanel->mStartUrl.c_str()) );
  776. }
  777. };
  778. }
  779. ////////////////////////////////////////////////////////////////////////////////
  780. //
  781. mediaPanel*  LLMediaPluginTest::findMediaPanel( LLPluginClassMedia* source )
  782. {
  783. mediaPanel *result = NULL;
  784. for( int panel = 0; panel < (int)mMediaPanels.size(); ++panel )
  785. {
  786. if ( mMediaPanels[ panel ]->mMediaSource == source )
  787. {
  788. result = mMediaPanels[ panel ];
  789. }
  790. }
  791. return result;
  792. }
  793. ////////////////////////////////////////////////////////////////////////////////
  794. //
  795. void LLMediaPluginTest::navigateToNewURI( std::string uri )
  796. {
  797. if ( uri.length() )
  798. {
  799. std::string mime_type = mimeTypeFromUrl( uri );
  800. if ( !mSelectedPanel->mMediaSource->isPluginExited() && (mime_type == mSelectedPanel->mMimeType) )
  801. {
  802. std::cout << "MIME type is the same" << std::endl;
  803. mSelectedPanel->mMediaSource->loadURI( uri );
  804. mSelectedPanel->mMediaSource->start();
  805. mBookmarkList->do_selection( 0 );
  806. }
  807. else
  808. {
  809. std::cout << "MIME type changed or plugin had exited" << std::endl;
  810. replaceMediaPanel( mSelectedPanel, uri );
  811. mBookmarkList->do_selection( 0 );
  812. }
  813. };
  814. }
  815. ////////////////////////////////////////////////////////////////////////////////
  816. //
  817. void LLMediaPluginTest::initUrlHistory( std::string uris )
  818. {
  819. if ( uris.length() > 0 )
  820. {
  821. std::cout << "init URL : " << uris << std::endl;
  822. LLSD historySD;
  823. char *cstr, *p;
  824. cstr = new char[uris.size()+1];
  825. strcpy(cstr, uris.c_str());
  826. const char *DELIMS = " ,;";
  827. p = strtok(cstr, DELIMS);
  828. while (p != NULL) {
  829. historySD.insert(0, p);
  830. p = strtok(NULL, DELIMS);
  831. }
  832. mSelectedPanel->mMediaSource->initializeUrlHistory(historySD);
  833. delete[] cstr;
  834. }
  835. }
  836. ////////////////////////////////////////////////////////////////////////////////
  837. //
  838. void LLMediaPluginTest::gluiCallback( int control_id )
  839. {
  840. if ( control_id == mIdBookmarks )
  841. {
  842. std::string uri = mBookmarks[ mSelBookmark ].second;
  843. navigateToNewURI( uri );
  844. }
  845. else
  846.     if ( control_id == mIdUrlEdit)
  847. {
  848. std::string uri = mUrlEdit->get_text();
  849. navigateToNewURI( uri );
  850. }
  851. else
  852. if ( control_id == mIdUrlInitHistoryEdit )
  853. {
  854. std::string uri = mUrlInitHistoryEdit->get_text();
  855. initUrlHistory( uri );
  856. }
  857. else
  858. if ( control_id == mIdControlAddPanel )
  859. {
  860. addMediaPanel( mBookmarks[ rand() % ( mBookmarks.size() - 1 ) + 1 ].second );
  861. }
  862. else
  863. if ( control_id == mIdControlRemPanel )
  864. {
  865. remMediaPanel( mSelectedPanel );
  866. }
  867. else
  868. if ( control_id == mIdDisableTimeout )
  869. {
  870. // Set the "disable timeout" flag for all active plugins.
  871. for( int i = 0; i < (int)mMediaPanels.size(); ++i )
  872. {
  873. mMediaPanels[ i ]->mMediaSource->setDisableTimeout(mDisableTimeout);
  874. }
  875. }
  876. else
  877. if ( control_id == mIdControlCrashPlugin )
  878. {
  879. // send message to plugin and ask it to crash
  880. // (switch out for ReleaseCandidate version :) )
  881. if(mSelectedPanel && mSelectedPanel->mMediaSource)
  882. {
  883. mSelectedPanel->mMediaSource->crashPlugin();
  884. }
  885. }
  886. else
  887. if ( control_id == mIdControlHangPlugin )
  888. {
  889. // send message to plugin and ask it to hang
  890. // (switch out for ReleaseCandidate version :) )
  891. if(mSelectedPanel && mSelectedPanel->mMediaSource)
  892. {
  893. mSelectedPanel->mMediaSource->hangPlugin();
  894. }
  895. }
  896. else
  897. if ( control_id == mIdControlExitApp )
  898. {
  899. // text for exiting plugin system cleanly
  900. delete this; // clean up
  901. exit( 0 );
  902. }
  903. else
  904. if ( control_id == mIdMediaTimeControlPlay )
  905. {
  906. if ( mSelectedPanel )
  907. {
  908. mSelectedPanel->mMediaSource->setLoop( false );
  909. mSelectedPanel->mMediaSource->start();
  910. };
  911. }
  912. else
  913. if ( control_id == mIdMediaTimeControlLoop )
  914. {
  915. if ( mSelectedPanel )
  916. {
  917. mSelectedPanel->mMediaSource->setLoop( true );
  918. mSelectedPanel->mMediaSource->start();
  919. };
  920. }
  921. else
  922. if ( control_id == mIdMediaTimeControlPause )
  923. {
  924. if ( mSelectedPanel )
  925. mSelectedPanel->mMediaSource->pause();
  926. }
  927. else
  928. if ( control_id == mIdMediaTimeControlStop )
  929. {
  930. if ( mSelectedPanel )
  931. {
  932. mSelectedPanel->mMediaSource->stop();
  933. };
  934. }
  935. else
  936. if ( control_id == mIdMediaTimeControlSeek )
  937. {
  938. if ( mSelectedPanel )
  939. {
  940. // get value from spinner
  941. float seconds_to_seek = mMediaTimeControlSeekSeconds;
  942. mSelectedPanel->mMediaSource->seek( seconds_to_seek );
  943. mSelectedPanel->mMediaSource->start();
  944. };
  945. }
  946. else
  947. if ( control_id == mIdMediaTimeControlRewind )
  948. {
  949. if ( mSelectedPanel )
  950. {
  951. mSelectedPanel->mMediaSource->setLoop( false );
  952. mSelectedPanel->mMediaSource->start(-2.0f);
  953. };
  954. }
  955. else
  956. if ( control_id == mIdMediaTimeControlFastForward )
  957. {
  958. if ( mSelectedPanel )
  959. {
  960. mSelectedPanel->mMediaSource->setLoop( false );
  961. mSelectedPanel->mMediaSource->start(2.0f);
  962. };
  963. }
  964. else
  965. if ( control_id == mIdMediaBrowserControlBack )
  966. {
  967. if ( mSelectedPanel )
  968. mSelectedPanel->mMediaSource->browse_back();
  969. }
  970. else
  971. if ( control_id == mIdMediaBrowserControlStop )
  972. {
  973. if ( mSelectedPanel )
  974. mSelectedPanel->mMediaSource->browse_stop();
  975. }
  976. else
  977. if ( control_id == mIdMediaBrowserControlForward )
  978. {
  979. if ( mSelectedPanel )
  980. mSelectedPanel->mMediaSource->browse_forward();
  981. }
  982. else
  983. if ( control_id == mIdMediaBrowserControlHome )
  984. {
  985. if ( mSelectedPanel )
  986. mSelectedPanel->mMediaSource->loadURI( mHomeWebUrl );
  987. }
  988. else
  989. if ( control_id == mIdMediaBrowserControlReload )
  990. {
  991. if ( mSelectedPanel )
  992. mSelectedPanel->mMediaSource->browse_reload( true );
  993. }
  994. else
  995. if ( control_id == mIdMediaBrowserControlClearCache )
  996. {
  997. if ( mSelectedPanel )
  998. mSelectedPanel->mMediaSource->clear_cache();
  999. }
  1000. else
  1001. if ( control_id == mIdMediaBrowserControlClearCookies )
  1002. {
  1003. if ( mSelectedPanel )
  1004. mSelectedPanel->mMediaSource->clear_cookies();
  1005. }
  1006. else
  1007. if ( control_id == mIdMediaBrowserControlEnableCookies )
  1008. {
  1009. if ( mSelectedPanel )
  1010. {
  1011. if ( mMediaBrowserControlEnableCookies )
  1012. {
  1013. mSelectedPanel->mMediaSource->enable_cookies( true );
  1014. }
  1015. else
  1016. {
  1017. mSelectedPanel->mMediaSource->enable_cookies( false );
  1018. }
  1019. };
  1020. };
  1021. }
  1022. ////////////////////////////////////////////////////////////////////////////////
  1023. //
  1024. void LLMediaPluginTest::keyboard( int key )
  1025. {
  1026. //if ( key == 'a' || key == 'A' )
  1027. // addMediaPanel( mBookmarks[ rand() % ( mBookmarks.size() - 1 ) + 1 ].second );
  1028. //else
  1029. //if ( key == 'r' || key == 'R' )
  1030. // remMediaPanel( mSelectedPanel );
  1031. //else
  1032. //if ( key == 'd' || key == 'D' )
  1033. // dumpPanelInfo();
  1034. //else
  1035. if ( key == 27 )
  1036. {
  1037. std::cout << "Application finished - exiting..." << std::endl;
  1038. delete this;
  1039. exit( 0 );
  1040. };
  1041. mSelectedPanel->mMediaSource->keyEvent( LLPluginClassMedia::KEY_EVENT_DOWN, key, 0 , LLSD());
  1042. mSelectedPanel->mMediaSource->keyEvent( LLPluginClassMedia::KEY_EVENT_UP, key, 0, LLSD());
  1043. };
  1044. ////////////////////////////////////////////////////////////////////////////////
  1045. //
  1046. void LLMediaPluginTest::mouseButton( int button, int state, int x, int y )
  1047. {
  1048. if ( button == GLUT_LEFT_BUTTON )
  1049. {
  1050. if ( state == GLUT_DOWN )
  1051. {
  1052. int media_x, media_y, id;
  1053. windowPosToTexturePos( x, y, media_x, media_y, id );
  1054. if ( mSelectedPanel )
  1055. mSelectedPanel->mMediaSource->mouseEvent( LLPluginClassMedia::MOUSE_EVENT_DOWN, 0, media_x, media_y, 0 );
  1056. }
  1057. else
  1058. if ( state == GLUT_UP )
  1059. {
  1060. int media_x, media_y, id;
  1061. windowPosToTexturePos( x, y, media_x, media_y, id );
  1062. // only select a panel if we're on a panel
  1063. // (HACK: strictly speaking this rules out clicking on 
  1064. // the origin of a panel but that's very unlikely)
  1065. if ( media_x > 0 && media_y > 0 )
  1066. {
  1067. selectPanelById( id );
  1068. if ( mSelectedPanel )
  1069. mSelectedPanel->mMediaSource->mouseEvent( LLPluginClassMedia::MOUSE_EVENT_UP, 0, media_x, media_y, 0 );
  1070. };
  1071. };
  1072. };
  1073. }
  1074. ////////////////////////////////////////////////////////////////////////////////
  1075. //
  1076. void LLMediaPluginTest::mousePassive( int x, int y )
  1077. {
  1078. int media_x, media_y, id;
  1079. windowPosToTexturePos( x, y, media_x, media_y, id );
  1080. if ( mSelectedPanel )
  1081. mSelectedPanel->mMediaSource->mouseEvent( LLPluginClassMedia::MOUSE_EVENT_MOVE, 0, media_x, media_y, 0 );
  1082. }
  1083. ////////////////////////////////////////////////////////////////////////////////
  1084. //
  1085. void LLMediaPluginTest::mouseMove( int x, int y )
  1086. {
  1087. int media_x, media_y, id;
  1088. windowPosToTexturePos( x, y, media_x, media_y, id );
  1089. if ( mSelectedPanel )
  1090. mSelectedPanel->mMediaSource->mouseEvent( LLPluginClassMedia::MOUSE_EVENT_MOVE, 0, media_x, media_y, 0 );
  1091. }
  1092. ////////////////////////////////////////////////////////////////////////////////
  1093. //
  1094. void LLMediaPluginTest::makeChrome()
  1095. {
  1096. // IDs used by GLUI
  1097. int start_id = 0x1000;
  1098. // right side window - geometry manipulators
  1099. #if __APPLE__
  1100. // the Apple GLUT implementation doesn't seem to set the graphic offset of subwindows correctly when they overlap in certain ways.
  1101. // Use a separate controls window in this case.
  1102. // GLUI window at right containing manipulation controls and other buttons
  1103. int x = glutGet(GLUT_WINDOW_X) + glutGet(GLUT_WINDOW_WIDTH) + 4;
  1104. int y = glutGet(GLUT_WINDOW_Y);
  1105. GLUI* right_glui_window = GLUI_Master.create_glui( "", 0, x, y );
  1106. #else
  1107. GLUI* right_glui_window = GLUI_Master.create_glui_subwindow( mAppWindow, GLUI_SUBWINDOW_RIGHT );
  1108. #endif
  1109. mViewRotationCtrl = right_glui_window->add_rotation( "Rotation", mViewRotation );
  1110. mViewTranslationCtrl = right_glui_window->add_translation( "Translate", GLUI_TRANSLATION_XY, mViewPos );
  1111. mViewTranslationCtrl->set_speed( 0.01f );
  1112. mViewScaleCtrl = right_glui_window->add_translation( "Scale", GLUI_TRANSLATION_Z, &mViewPos[ 2 ] );
  1113. mViewScaleCtrl->set_speed( 0.05f );
  1114. right_glui_window->set_main_gfx_window( mAppWindow );
  1115. // right side window - app controls
  1116. mIdControlAddPanel = start_id++;
  1117. right_glui_window->add_statictext( "" );
  1118. right_glui_window->add_separator();
  1119. right_glui_window->add_statictext( "" );
  1120. right_glui_window->add_button( "Add panel", mIdControlAddPanel, gluiCallbackWrapper );
  1121. right_glui_window->add_statictext( "" );
  1122. mIdControlRemPanel = start_id++;
  1123. right_glui_window->add_button( "Rem panel", mIdControlRemPanel, gluiCallbackWrapper );
  1124. right_glui_window->add_statictext( "" );
  1125. right_glui_window->add_separator();
  1126. right_glui_window->add_statictext( "" );
  1127. mIdControlCrashPlugin = start_id++;
  1128. right_glui_window->add_button( "Crash plugin", mIdControlCrashPlugin, gluiCallbackWrapper );
  1129. mIdControlHangPlugin = start_id++;
  1130. right_glui_window->add_button( "Hang plugin", mIdControlHangPlugin, gluiCallbackWrapper );
  1131. right_glui_window->add_statictext( "" );
  1132. right_glui_window->add_separator();
  1133. right_glui_window->add_statictext( "" );
  1134. mIdControlExitApp = start_id++;
  1135. right_glui_window->add_button( "Exit app", mIdControlExitApp, gluiCallbackWrapper );
  1136. //// top window - holds bookmark UI
  1137. mIdBookmarks = start_id++;
  1138. mSelBookmark = 0;
  1139. GLUI* glui_window_top = GLUI_Master.create_glui_subwindow( mAppWindow, GLUI_SUBWINDOW_TOP );
  1140. mBookmarkList = glui_window_top->add_listbox( "", &mSelBookmark, mIdBookmarks, gluiCallbackWrapper );
  1141. // only add the first 50 bookmarks - list can be very long sometimes (30,000+)
  1142. // when testing list of media URLs from AGNI for example
  1143. for( unsigned int each = 0; each < mBookmarks.size() && each < 50; ++each )
  1144. mBookmarkList->add_item( each, const_cast< char* >( mBookmarks[ each ].first.c_str() ) );
  1145. glui_window_top->set_main_gfx_window( mAppWindow );
  1146. glui_window_top->add_column( false );
  1147. mIdUrlEdit = start_id++;
  1148. mUrlEdit = glui_window_top->add_edittext( "Url:", GLUI_EDITTEXT_TEXT, 0, mIdUrlEdit, gluiCallbackWrapper );
  1149. mUrlEdit->set_w( 600 );
  1150. GLUI* glui_window_top2 = GLUI_Master.create_glui_subwindow( mAppWindow, GLUI_SUBWINDOW_TOP );
  1151. mIdUrlInitHistoryEdit = start_id++;
  1152. mUrlInitHistoryEdit = glui_window_top2->add_edittext( "Init History (separate by commas or semicolons):",
  1153. GLUI_EDITTEXT_TEXT, 0, mIdUrlInitHistoryEdit, gluiCallbackWrapper );
  1154. mUrlInitHistoryEdit->set_w( 800 );
  1155. // top window - media controls for "time" media types (e.g. movies)
  1156. mGluiMediaTimeControlWindow = GLUI_Master.create_glui_subwindow( mAppWindow, GLUI_SUBWINDOW_TOP );
  1157. mGluiMediaTimeControlWindow->set_main_gfx_window( mAppWindow );
  1158. mIdMediaTimeControlPlay = start_id++;
  1159. mGluiMediaTimeControlWindow->add_button( "PLAY", mIdMediaTimeControlPlay, gluiCallbackWrapper );
  1160. mGluiMediaTimeControlWindow->add_column( false );
  1161. mIdMediaTimeControlLoop = start_id++;
  1162. mGluiMediaTimeControlWindow->add_button( "LOOP", mIdMediaTimeControlLoop, gluiCallbackWrapper );
  1163. mGluiMediaTimeControlWindow->add_column( false );
  1164. mIdMediaTimeControlPause = start_id++;
  1165. mGluiMediaTimeControlWindow->add_button( "PAUSE", mIdMediaTimeControlPause, gluiCallbackWrapper );
  1166. mGluiMediaTimeControlWindow->add_column( false );
  1167. GLUI_Button  *button;
  1168. mIdMediaTimeControlRewind = start_id++;
  1169. button = mGluiMediaTimeControlWindow->add_button( "<<", mIdMediaTimeControlRewind, gluiCallbackWrapper );
  1170. button->set_w(30);
  1171. mGluiMediaTimeControlWindow->add_column( false );
  1172. mIdMediaTimeControlFastForward = start_id++;
  1173. button = mGluiMediaTimeControlWindow->add_button( ">>", mIdMediaTimeControlFastForward, gluiCallbackWrapper );
  1174. button->set_w(30);
  1175. mGluiMediaTimeControlWindow->add_column( true );
  1176. mIdMediaTimeControlStop = start_id++;
  1177. mGluiMediaTimeControlWindow->add_button( "STOP", mIdMediaTimeControlStop, gluiCallbackWrapper );
  1178. mGluiMediaTimeControlWindow->add_column( false );
  1179. mIdMediaTimeControlVolume = start_id++;
  1180. GLUI_Spinner* spinner = mGluiMediaTimeControlWindow->add_spinner( "Volume", 2, &mMediaTimeControlVolume, mIdMediaTimeControlVolume, gluiCallbackWrapper);
  1181. spinner->set_float_limits( 0, 100 );
  1182. mGluiMediaTimeControlWindow->add_column( true );
  1183. mIdMediaTimeControlSeekSeconds = start_id++;
  1184. spinner = mGluiMediaTimeControlWindow->add_spinner( "", 2, &mMediaTimeControlSeekSeconds, mIdMediaTimeControlSeekSeconds, gluiCallbackWrapper);
  1185. spinner->set_float_limits( 0, 200 );
  1186. spinner->set_w( 32 );
  1187. spinner->set_speed( 0.025f );
  1188. mGluiMediaTimeControlWindow->add_column( false );
  1189. mIdMediaTimeControlSeek = start_id++;
  1190. mGluiMediaTimeControlWindow->add_button( "SEEK", mIdMediaTimeControlSeek, gluiCallbackWrapper );
  1191. mGluiMediaTimeControlWindow->add_column( false );
  1192. // top window - media controls for "browser" media types (e.g. web browser)
  1193. mGluiMediaBrowserControlWindow = GLUI_Master.create_glui_subwindow( mAppWindow, GLUI_SUBWINDOW_TOP );
  1194. mGluiMediaBrowserControlWindow->set_main_gfx_window( mAppWindow );
  1195. mIdMediaBrowserControlBack = start_id++;
  1196. mMediaBrowserControlBackButton = mGluiMediaBrowserControlWindow->add_button( "BACK", mIdMediaBrowserControlBack, gluiCallbackWrapper );
  1197. mGluiMediaBrowserControlWindow->add_column( false );
  1198. mIdMediaBrowserControlStop = start_id++;
  1199. mGluiMediaBrowserControlWindow->add_button( "STOP", mIdMediaBrowserControlStop, gluiCallbackWrapper );
  1200. mGluiMediaBrowserControlWindow->add_column( false );
  1201. mIdMediaBrowserControlForward = start_id++;
  1202. mMediaBrowserControlForwardButton = mGluiMediaBrowserControlWindow->add_button( "FORWARD", mIdMediaBrowserControlForward, gluiCallbackWrapper );
  1203. mGluiMediaBrowserControlWindow->add_column( false );
  1204. mIdMediaBrowserControlHome = start_id++;
  1205. mGluiMediaBrowserControlWindow->add_button( "HOME", mIdMediaBrowserControlHome, gluiCallbackWrapper );
  1206. mGluiMediaBrowserControlWindow->add_column( false );
  1207. mIdMediaBrowserControlReload = start_id++;
  1208. mGluiMediaBrowserControlWindow->add_button( "RELOAD", mIdMediaBrowserControlReload, gluiCallbackWrapper );
  1209. mGluiMediaBrowserControlWindow->add_column( false );
  1210. mIdMediaBrowserControlClearCache = start_id++;
  1211. mGluiMediaBrowserControlWindow->add_button( "CLEAR CACHE", mIdMediaBrowserControlClearCache, gluiCallbackWrapper );
  1212. mGluiMediaBrowserControlWindow->add_column( false );
  1213. mIdMediaBrowserControlClearCookies = start_id++;
  1214. mGluiMediaBrowserControlWindow->add_button( "CLEAR COOKIES", mIdMediaBrowserControlClearCookies, gluiCallbackWrapper );
  1215. mGluiMediaBrowserControlWindow->add_column( false );
  1216. mIdMediaBrowserControlEnableCookies = start_id++;
  1217. mMediaBrowserControlEnableCookies = 0;
  1218. mGluiMediaBrowserControlWindow->add_checkbox( "Enable Cookies", &mMediaBrowserControlEnableCookies, mIdMediaBrowserControlEnableCookies, gluiCallbackWrapper );
  1219. // top window - misc controls
  1220. GLUI* glui_window_misc_control = GLUI_Master.create_glui_subwindow( mAppWindow, GLUI_SUBWINDOW_TOP );
  1221. mIdRandomPanelCount = start_id++;
  1222. mRandomPanelCount = 0;
  1223. glui_window_misc_control->add_checkbox( "Randomize panel count", &mRandomPanelCount, mIdRandomPanelCount, gluiCallbackWrapper );
  1224. glui_window_misc_control->set_main_gfx_window( mAppWindow );
  1225. glui_window_misc_control->add_column( true );
  1226. mIdRandomBookmarks = start_id++;
  1227. mRandomBookmarks = 0;
  1228. glui_window_misc_control->add_checkbox( "Randomize bookmarks", &mRandomBookmarks, mIdRandomBookmarks, gluiCallbackWrapper );
  1229. glui_window_misc_control->set_main_gfx_window( mAppWindow );
  1230. glui_window_misc_control->add_column( true );
  1231. mIdDisableTimeout = start_id++;
  1232. mDisableTimeout = 0;
  1233. glui_window_misc_control->add_checkbox( "Disable plugin timeout", &mDisableTimeout, mIdDisableTimeout, gluiCallbackWrapper );
  1234. glui_window_misc_control->set_main_gfx_window( mAppWindow );
  1235. // bottom window - status
  1236. mBottomGLUIWindow = GLUI_Master.create_glui_subwindow( mAppWindow, GLUI_SUBWINDOW_BOTTOM );
  1237. mStatusText = mBottomGLUIWindow->add_statictext( "" );
  1238. mBottomGLUIWindow->set_main_gfx_window( mAppWindow );
  1239. }
  1240. ////////////////////////////////////////////////////////////////////////////////
  1241. //
  1242. void LLMediaPluginTest::resetView()
  1243. {
  1244. mViewRotationCtrl->reset();
  1245. mViewScaleCtrl->set_x( 0.0f );
  1246. mViewScaleCtrl->set_y( 0.0f );
  1247. mViewScaleCtrl->set_z( 3.0f );
  1248. mViewTranslationCtrl->set_x( 0.0f );
  1249. mViewTranslationCtrl->set_y( 0.0f );
  1250. mViewTranslationCtrl->set_z( 0.0f );
  1251. }
  1252. ////////////////////////////////////////////////////////////////////////////////
  1253. //
  1254. void LLMediaPluginTest::makePickTexture( int id, GLuint* texture_handle, unsigned char** texture_pixels )
  1255. {
  1256. int pick_texture_width = 1024;
  1257. int pick_texture_height = 1024;
  1258. int pick_texture_depth = 3;
  1259. unsigned char* ptr = new unsigned char[ pick_texture_width * pick_texture_height * pick_texture_depth ];
  1260. for( int y = 0; y < pick_texture_height; ++y )
  1261. {
  1262. for( int x = 0; x < pick_texture_width * pick_texture_depth ; x += pick_texture_depth )
  1263. {
  1264. unsigned long bits = 0L;
  1265. bits |= ( id << 20 ) | ( y << 10 ) | ( x / 3 );
  1266. unsigned char r_component = ( bits >> 16 ) & 0xff;
  1267. unsigned char g_component = ( bits >> 8 ) & 0xff;
  1268. unsigned char b_component = bits & 0xff;
  1269. ptr[ y * pick_texture_width * pick_texture_depth + x + 0 ] = r_component;
  1270. ptr[ y * pick_texture_width * pick_texture_depth + x + 1 ] = g_component;
  1271. ptr[ y * pick_texture_width * pick_texture_depth + x + 2 ] = b_component;
  1272. };
  1273. };
  1274. glGenTextures( 1, texture_handle );
  1275. checkGLError("glGenTextures");
  1276. std::cout << "glGenTextures returned " << *texture_handle << std::endl;
  1277. bindTexture( *texture_handle );
  1278. glTexImage2D( GL_TEXTURE_2D, 0,
  1279. GL_RGB,
  1280. pick_texture_width, pick_texture_height,
  1281. 0, GL_RGB, GL_UNSIGNED_BYTE, ptr );
  1282. *texture_pixels = ptr;
  1283. }
  1284. ////////////////////////////////////////////////////////////////////////////////
  1285. //
  1286. std::string LLMediaPluginTest::mimeTypeFromUrl( std::string& url )
  1287. {
  1288. // default to web 
  1289. std::string mime_type = "text/html";
  1290. // we may need a more advanced MIME type accessor later :-)
  1291. if ( url.find( ".mov" ) != std::string::npos ) // Movies
  1292. mime_type = "video/quicktime";
  1293. else
  1294. if ( url.find( ".txt" ) != std::string::npos ) // Apple Text descriptors
  1295. mime_type = "video/quicktime";
  1296. else
  1297. if ( url.find( ".mp3" ) != std::string::npos ) // Apple Text descriptors
  1298. mime_type = "video/quicktime";
  1299. else
  1300. if ( url.find( "example://" ) != std::string::npos ) // Example plugin
  1301. mime_type = "example/example";
  1302. return mime_type;
  1303. }
  1304. ////////////////////////////////////////////////////////////////////////////////
  1305. //
  1306. std::string LLMediaPluginTest::pluginNameFromMimeType( std::string& mime_type )
  1307. {
  1308. #if LL_DARWIN
  1309. std::string plugin_name( "media_plugin_null.dylib" );
  1310. if ( mime_type == "video/quicktime" )
  1311. plugin_name = "media_plugin_quicktime.dylib";
  1312. else
  1313. if ( mime_type == "text/html" )
  1314. plugin_name = "media_plugin_webkit.dylib";
  1315. #elif LL_WINDOWS
  1316. std::string plugin_name( "media_plugin_null.dll" );
  1317. if ( mime_type == "video/quicktime" )
  1318. plugin_name = "media_plugin_quicktime.dll";
  1319. else
  1320. if ( mime_type == "text/html" )
  1321. plugin_name = "media_plugin_webkit.dll";
  1322. else
  1323. if ( mime_type == "example/example" )
  1324. plugin_name = "media_plugin_example.dll";
  1325. #elif LL_LINUX
  1326. std::string plugin_name( "libmedia_plugin_null.so" );
  1327. if ( mime_type == "video/quicktime" )
  1328. plugin_name = "libmedia_plugin_quicktime.so";
  1329. else
  1330. if ( mime_type == "text/html" )
  1331. plugin_name = "libmedia_plugin_webkit.so";
  1332. #endif
  1333. return plugin_name;
  1334. }
  1335. ////////////////////////////////////////////////////////////////////////////////
  1336. //
  1337. void LLMediaPluginTest::addMediaPanel( std::string url )
  1338. {
  1339. // Get the plugin filename using the URL
  1340. std::string mime_type = mimeTypeFromUrl( url );
  1341. std::string plugin_name = pluginNameFromMimeType( mime_type );
  1342. // create a random size for the new media
  1343. int media_width;
  1344. int media_height;
  1345. getRandomMediaSize( media_width, media_height, mime_type );
  1346. // make a new plugin
  1347. LLPluginClassMedia* media_source = new LLPluginClassMedia(this);
  1348. // tell the plugin what size we asked for
  1349. media_source->setSize( media_width, media_height );
  1350. // Use the launcher start and initialize the plugin 
  1351. #if LL_DARWIN || LL_LINUX
  1352. std::string launcher_name( "SLPlugin" );
  1353. #elif LL_WINDOWS
  1354. std::string launcher_name( "SLPlugin.exe" );
  1355. #endif
  1356. // for this test app, use the cwd as the user data path (ugh).
  1357. #if LL_WINDOWS
  1358. std::string user_data_path = ".\";
  1359. #else
  1360.         char cwd[ FILENAME_MAX ];
  1361. if (NULL == getcwd( cwd, FILENAME_MAX - 1 ))
  1362. {
  1363. std::cerr << "Couldn't get cwd - probably too long - failing to init." << std::endl;
  1364. return;
  1365. }
  1366. std::string user_data_path = std::string( cwd ) + "/";
  1367. #endif
  1368. media_source->init( launcher_name, plugin_name, false, user_data_path );
  1369. media_source->setDisableTimeout(mDisableTimeout);
  1370. // make a new panel and save parameters
  1371. mediaPanel* panel = new mediaPanel;
  1372. panel->mMediaSource = media_source;
  1373. panel->mStartUrl = url;
  1374. panel->mMimeType = mime_type;
  1375. panel->mMediaWidth = media_width;
  1376. panel->mMediaHeight = media_height;
  1377. panel->mTextureWidth = 0;
  1378. panel->mTextureHeight = 0;
  1379. panel->mTextureScaleX = 0;
  1380. panel->mTextureScaleY = 0;
  1381. panel->mMediaTextureHandle = 0;
  1382. panel->mPickTextureHandle = 0;
  1383. panel->mAppTextureCoordsOpenGL = false; // really need an 'undefined' state here too
  1384. panel->mReadyToRender = false;
  1385. // look through current media panels to find an unused index number
  1386. bool id_exists = true;
  1387. for( int nid = 0; nid < mMaxPanels; ++nid )
  1388. {
  1389. // does this id exist already?
  1390. id_exists = false;
  1391. for( int pid = 0; pid < (int)mMediaPanels.size(); ++pid )
  1392. {
  1393. if ( nid == mMediaPanels[ pid ]->mId )
  1394. {
  1395. id_exists = true;
  1396. break;
  1397. };
  1398. };
  1399. // id wasn't found so we can use it
  1400. if ( ! id_exists )
  1401. {
  1402. panel->mId = nid; 
  1403. break;
  1404. };
  1405. };
  1406. // if we get here and this flag is set, there is no room for any more panels
  1407. if ( id_exists )
  1408. {
  1409. std::cout << "No room for any more panels" << std::endl;
  1410. }
  1411. else
  1412. {
  1413. // now we have the ID we can use it to make the 
  1414. // pick texture (id is baked into texture pixels)
  1415. makePickTexture( panel->mId, &panel->mPickTextureHandle, &panel->mPickTexturePixels );
  1416. // save this in the list of panels
  1417. mMediaPanels.push_back( panel );
  1418. // select the panel that was just created
  1419. selectPanel( panel );
  1420. // load and start the URL
  1421. panel->mMediaSource->loadURI( url );
  1422. panel->mMediaSource->start();
  1423. std::cout << "Adding new media panel for " << url << "(" << media_width << "x" << media_height << ") with index " << panel->mId << " - total panels = " << mMediaPanels.size() << std::endl;
  1424. }
  1425. }
  1426. ////////////////////////////////////////////////////////////////////////////////
  1427. //
  1428. void LLMediaPluginTest::updateMediaPanel( mediaPanel* panel )
  1429. {
  1430. // checkGLError("LLMediaPluginTest::updateMediaPanel");
  1431. if ( ! panel ) 
  1432. return;
  1433. if(!panel->mMediaSource || !panel->mMediaSource->textureValid())
  1434. {
  1435. panel->mReadyToRender = false;
  1436. return;
  1437. }
  1438. // take a reference copy of the plugin values since they 
  1439. // might change during this lifetime of this function
  1440. int plugin_media_width = panel->mMediaSource->getWidth();
  1441. int plugin_media_height = panel->mMediaSource->getHeight();
  1442. int plugin_texture_width = panel->mMediaSource->getBitsWidth();
  1443. int plugin_texture_height = panel->mMediaSource->getBitsHeight();
  1444. // If the texture isn't created or the media or texture dimensions changed AND
  1445. // the sizes are valid then we need to delete the old media texture (if necessary) 
  1446. // then make a new one.
  1447. if ((panel->mMediaTextureHandle == 0 ||
  1448.  panel->mMediaWidth != plugin_media_width ||
  1449.  panel->mMediaHeight != plugin_media_height ||  
  1450.  panel->mTextureWidth != plugin_texture_width ||
  1451.  panel->mTextureHeight != plugin_texture_height) &&
  1452. ( plugin_media_width > 0 && plugin_media_height > 0 && 
  1453.   plugin_texture_width > 0 && plugin_texture_height > 0 ) )
  1454. {
  1455. std::cout << "Valid media size (" <<  plugin_media_width << " x " << plugin_media_height 
  1456. << ") and texture size (" <<  plugin_texture_width << " x " << plugin_texture_height 
  1457. << ") for panel with ID=" << panel->mId << " - making texture" << std::endl;
  1458. // delete old GL texture
  1459. if ( isTexture( panel->mMediaTextureHandle ) )
  1460. {
  1461. std::cerr << "updateMediaPanel: deleting texture " << panel->mMediaTextureHandle << std::endl;
  1462. glDeleteTextures( 1, &panel->mMediaTextureHandle );
  1463. panel->mMediaTextureHandle = 0;
  1464. }
  1465. std::cerr << "before: pick texture is " << panel->mPickTextureHandle << ", media texture is " << panel->mMediaTextureHandle << std::endl;
  1466. // make a GL texture based on the dimensions the plugin told us
  1467. GLuint new_texture = 0;
  1468. glGenTextures( 1, &new_texture );
  1469. checkGLError("glGenTextures");
  1470. std::cout << "glGenTextures returned " << new_texture << std::endl;
  1471. panel->mMediaTextureHandle = new_texture;
  1472. bindTexture( panel->mMediaTextureHandle );
  1473. std::cout << "Setting texture size to " << plugin_texture_width << " x " << plugin_texture_height << std::endl;
  1474. glTexImage2D( GL_TEXTURE_2D, 0,
  1475. GL_RGB,
  1476. plugin_texture_width, plugin_texture_height,
  1477. 0, GL_RGB, GL_UNSIGNED_BYTE,
  1478. 0 );
  1479. std::cerr << "after: pick texture is " << panel->mPickTextureHandle << ", media texture is " << panel->mMediaTextureHandle << std::endl;
  1480. };
  1481. // update our record of the media and texture dimensions
  1482. // NOTE: do this after we we check for sizes changes
  1483. panel->mMediaWidth = plugin_media_width;
  1484. panel->mMediaHeight = plugin_media_height;
  1485. panel->mTextureWidth = plugin_texture_width;
  1486. panel->mTextureHeight = plugin_texture_height;
  1487. if ( plugin_texture_width > 0 )
  1488. {
  1489. panel->mTextureScaleX = (double)panel->mMediaWidth / (double)panel->mTextureWidth;
  1490. };
  1491. if ( plugin_texture_height > 0 )
  1492. {
  1493. panel->mTextureScaleY = (double)panel->mMediaHeight / (double)panel->mTextureHeight;
  1494. };
  1495. // update the flag which tells us if the media source uses OprnGL coords or not.
  1496. panel->mAppTextureCoordsOpenGL = panel->mMediaSource->getTextureCoordsOpenGL();
  1497. // Check to see if we have enough to render this panel.
  1498. // If we do, set a flag that the display functions use so 
  1499. // they only render a panel with media if it's ready.
  1500. if ( panel->mMediaWidth < 0 ||
  1501.  panel->mMediaHeight < 0 ||
  1502.  panel->mTextureWidth < 1 ||
  1503.  panel->mTextureHeight < 1 ||
  1504.  panel->mMediaTextureHandle == 0 )
  1505. {
  1506. panel->mReadyToRender = false;
  1507. };
  1508. }
  1509. ////////////////////////////////////////////////////////////////////////////////
  1510. //
  1511. void LLMediaPluginTest::replaceMediaPanel( mediaPanel* panel, std::string url )
  1512. {
  1513. // no media panels so we can't change anything - have to add
  1514. if ( mMediaPanels.size() == 0 ) 
  1515. return;
  1516. // sanity check
  1517. if ( ! panel ) 
  1518. return;
  1519. int index;
  1520. for(index = 0; index < (int)mMediaPanels.size(); index++)
  1521. {
  1522. if(mMediaPanels[index] == panel)
  1523. break;
  1524. }
  1525. if(index >= (int)mMediaPanels.size())
  1526. {
  1527. // panel isn't in mMediaPanels
  1528. return;
  1529. }
  1530. std::cout << "Replacing media panel with index " << panel->mId << std::endl;
  1531. int panel_id = panel->mId;
  1532. if(mSelectedPanel == panel)
  1533. mSelectedPanel = NULL;
  1534. delete panel;
  1535. // Get the plugin filename using the URL
  1536. std::string mime_type = mimeTypeFromUrl( url );
  1537. std::string plugin_name = pluginNameFromMimeType( mime_type );
  1538. // create a random size for the new media
  1539. int media_width;
  1540. int media_height;
  1541. getRandomMediaSize( media_width, media_height, mime_type );
  1542. // make a new plugin
  1543. LLPluginClassMedia* media_source = new LLPluginClassMedia(this);
  1544. // tell the plugin what size we asked for
  1545. media_source->setSize( media_width, media_height );
  1546. // Use the launcher start and initialize the plugin 
  1547. #if LL_DARWIN || LL_LINUX
  1548. std::string launcher_name( "SLPlugin" );
  1549. #elif LL_WINDOWS
  1550. std::string launcher_name( "SLPlugin.exe" );
  1551. #endif
  1552. // for this test app, use the cwd as the user data path (ugh).
  1553. #if LL_WINDOWS
  1554. std::string user_data_path = ".\";
  1555. #else
  1556.         char cwd[ FILENAME_MAX ];
  1557. if (NULL == getcwd( cwd, FILENAME_MAX - 1 ))
  1558. {
  1559. std::cerr << "Couldn't get cwd - probably too long - failing to init." << std::endl;
  1560. return;
  1561. }
  1562. std::string user_data_path = std::string( cwd ) + "/";
  1563. #endif
  1564. media_source->init( launcher_name, plugin_name, false, user_data_path );
  1565. media_source->setDisableTimeout(mDisableTimeout);
  1566. // make a new panel and save parameters
  1567. panel = new mediaPanel;
  1568. panel->mMediaSource = media_source;
  1569. panel->mStartUrl = url;
  1570. panel->mMimeType = mime_type;
  1571. panel->mMediaWidth = media_width;
  1572. panel->mMediaHeight = media_height;
  1573. panel->mTextureWidth = 0;
  1574. panel->mTextureHeight = 0;
  1575. panel->mTextureScaleX = 0;
  1576. panel->mTextureScaleY = 0;
  1577. panel->mMediaTextureHandle = 0;
  1578. panel->mPickTextureHandle = 0;
  1579. panel->mAppTextureCoordsOpenGL = false; // really need an 'undefined' state here too
  1580. panel->mReadyToRender = false;
  1581. panel->mId = panel_id; 
  1582. // Replace the entry in the panels array
  1583. mMediaPanels[index] = panel;
  1584. // now we have the ID we can use it to make the 
  1585. // pick texture (id is baked into texture pixels)
  1586. makePickTexture( panel->mId, &panel->mPickTextureHandle, &panel->mPickTexturePixels );
  1587. // select the panel that was just created
  1588. selectPanel( panel );
  1589. // load and start the URL
  1590. panel->mMediaSource->loadURI( url );
  1591. panel->mMediaSource->start();
  1592. }
  1593. ////////////////////////////////////////////////////////////////////////////////
  1594. //
  1595. void LLMediaPluginTest::getRandomMediaSize( int& width, int& height, std::string mime_type )
  1596. {
  1597. // Make a new media source with a random size which we'll either 
  1598. // directly or the media plugin will tell us what it wants later.
  1599. // Use a random size so we can test support for weird media sizes.
  1600. // (Almost everything else will get filled in later once the
  1601. // plugin responds)
  1602. // NB. Do we need to enforce that width is on 4 pixel boundary?
  1603. width = ( ( rand() % 170 ) + 30 ) * 4;
  1604. height = ( ( rand() % 170 ) + 30 ) * 4;
  1605. // adjust this random size if it's a browser so we get 
  1606. // a more useful size for testing.. 
  1607. if ( mime_type == "text/html" || mime_type == "example/example"  )
  1608. {
  1609. width = ( ( rand() % 100 ) + 100 ) * 4;
  1610. height = ( width * ( ( rand() % 400 ) + 1000 ) ) / 1000;
  1611. };
  1612. }
  1613. ////////////////////////////////////////////////////////////////////////////////
  1614. //
  1615. void LLMediaPluginTest::remMediaPanel( mediaPanel* panel )
  1616. {
  1617. // always leave one panel
  1618. if ( mMediaPanels.size() == 1 ) 
  1619. return;
  1620. // sanity check - don't think this can happen but see above for a case where it might...
  1621. if ( ! panel ) 
  1622. return;
  1623. std::cout << "Removing media panel with index " << panel->mId << " - total panels = " << mMediaPanels.size() - 1 << std::endl;
  1624. if(mSelectedPanel == panel)
  1625. mSelectedPanel = NULL;
  1626. delete panel;
  1627. // remove from storage list
  1628. for( int i = 0; i < (int)mMediaPanels.size(); ++i )
  1629. {
  1630. if ( mMediaPanels[ i ] == panel )
  1631. {
  1632. mMediaPanels.erase( mMediaPanels.begin() + i );
  1633. break;
  1634. };
  1635. };
  1636. // select the first panel 
  1637. selectPanel( mMediaPanels[ 0 ] );
  1638. }
  1639. ////////////////////////////////////////////////////////////////////////////////
  1640. //
  1641. void LLMediaPluginTest::updateStatusBar()
  1642. {
  1643. if ( ! mSelectedPanel )
  1644. return;
  1645. // cache results - this is a very slow function
  1646. static int cached_id = -1;
  1647. static int cached_media_width = -1;
  1648. static int cached_media_height = -1;
  1649. static int cached_texture_width = -1;
  1650. static int cached_texture_height = -1;
  1651. static bool cached_supports_browser_media = true;
  1652. static bool cached_supports_time_media = false;
  1653. static int cached_movie_time = -1;
  1654. static std::string cached_plugin_version = "";
  1655. if ( 
  1656.  cached_id == mSelectedPanel->mId &&
  1657.  cached_media_width == mSelectedPanel->mMediaWidth &&
  1658.  cached_media_height  == mSelectedPanel->mMediaHeight &&
  1659.  cached_texture_width == mSelectedPanel->mTextureWidth &&
  1660.  cached_texture_height == mSelectedPanel->mTextureHeight &&
  1661.  cached_supports_browser_media == mSelectedPanel->mMediaSource->pluginSupportsMediaBrowser() && 
  1662.  cached_supports_time_media == mSelectedPanel->mMediaSource->pluginSupportsMediaTime() &&
  1663.  cached_plugin_version == mSelectedPanel->mMediaSource->getPluginVersion() &&
  1664.  cached_movie_time == (int)mSelectedPanel->mMediaSource->getCurrentTime()
  1665.    )
  1666. {
  1667. // nothing changed so don't spend time in this shitty function
  1668. return;
  1669. };
  1670. std::ostringstream stream( "" );
  1671. stream.str( "" );
  1672. stream.clear();
  1673. stream << "Id: ";
  1674. stream << std::setw( 2 ) << std::setfill( '0' );
  1675. stream << mSelectedPanel->mId;
  1676. stream << " | ";
  1677. stream << "Media: ";
  1678. stream << std::setw( 3 ) << std::setfill( '0' );
  1679. stream << mSelectedPanel->mMediaWidth;
  1680. stream << " x ";
  1681. stream << std::setw( 3 ) << std::setfill( '0' );
  1682. stream << mSelectedPanel->mMediaHeight;
  1683. stream << " | ";
  1684. stream << "Texture: ";
  1685. stream << std::setw( 4 ) << std::setfill( '0' );
  1686. stream << mSelectedPanel->mTextureWidth;
  1687. stream << " x ";
  1688. stream << std::setw( 4 ) << std::setfill( '0' );
  1689. stream << mSelectedPanel->mTextureHeight;
  1690. stream << " | ";
  1691. if ( mSelectedPanel->mMediaSource->pluginSupportsMediaBrowser() )
  1692. stream << "BROWSER";
  1693. else
  1694. if ( mSelectedPanel->mMediaSource->pluginSupportsMediaTime() )
  1695. stream << "TIME   ";
  1696. stream << " | ";
  1697. stream << mSelectedPanel->mMediaSource->getPluginVersion();
  1698. stream << " | ";
  1699. if ( mSelectedPanel->mMediaSource->pluginSupportsMediaTime() )
  1700. {
  1701. stream << std::setw( 3 ) << std::setfill( '0' );
  1702. stream << (int)mSelectedPanel->mMediaSource->getCurrentTime();
  1703. stream << " / ";
  1704. stream << std::setw( 3 ) << std::setfill( '0' );
  1705. stream << (int)mSelectedPanel->mMediaSource->getDuration();
  1706. stream << " @ ";
  1707. stream << (int)mSelectedPanel->mMediaSource->getCurrentPlayRate();
  1708. stream << " | ";
  1709. };
  1710. glutSetWindow( mBottomGLUIWindow->get_glut_window_id() );
  1711. mStatusText->set_text( const_cast< char*>( stream.str().c_str() ) );
  1712. glutSetWindow( mAppWindow );
  1713. // caching
  1714. cached_id = mSelectedPanel->mId;
  1715. cached_media_width = mSelectedPanel->mMediaWidth;
  1716. cached_media_height = mSelectedPanel->mMediaHeight;
  1717. cached_texture_width = mSelectedPanel->mTextureWidth;
  1718. cached_texture_height = mSelectedPanel->mTextureHeight;
  1719. cached_supports_browser_media = mSelectedPanel->mMediaSource->pluginSupportsMediaBrowser();
  1720. cached_supports_time_media = mSelectedPanel->mMediaSource->pluginSupportsMediaTime();
  1721. cached_plugin_version = mSelectedPanel->mMediaSource->getPluginVersion();
  1722. cached_movie_time = (int)mSelectedPanel->mMediaSource->getCurrentTime();
  1723. }
  1724. ////////////////////////////////////////////////////////////////////////////////
  1725. //
  1726. void LLMediaPluginTest::dumpPanelInfo()
  1727. {
  1728. std::cout << std::endl << "===== Media Panels =====" << std::endl;
  1729. for( int i = 0; i < (int)mMediaPanels.size(); ++i )
  1730. {
  1731. std::cout << std::setw( 2 ) << std::setfill( '0' );
  1732. std::cout << i + 1 << "> ";
  1733. std::cout << "Id: ";
  1734. std::cout << std::setw( 2 ) << std::setfill( '0' );
  1735. std::cout << mMediaPanels[ i ]->mId;
  1736. std::cout << " | ";
  1737. std::cout << "Media: ";
  1738. std::cout << std::setw( 3 ) << std::setfill( '0' );
  1739. std::cout << mMediaPanels[ i ]->mMediaWidth;
  1740. std::cout << " x ";
  1741. std::cout << std::setw( 3 ) << std::setfill( '0' );
  1742. std::cout << mMediaPanels[ i ]->mMediaHeight;
  1743. std::cout << " | ";
  1744. std::cout << "Texture: ";
  1745. std::cout << std::setw( 4 ) << std::setfill( '0' );
  1746. std::cout << mMediaPanels[ i ]->mTextureWidth;
  1747. std::cout << " x ";
  1748. std::cout << std::setw( 4 ) << std::setfill( '0' );
  1749. std::cout << mMediaPanels[ i ]->mTextureHeight;
  1750. std::cout << " | ";
  1751. if ( mMediaPanels[ i ] == mSelectedPanel )
  1752. std::cout << "(selected)";
  1753. std::cout << std::endl;
  1754. };
  1755. std::cout << "========================" << std::endl;
  1756. }
  1757. ////////////////////////////////////////////////////////////////////////////////
  1758. //
  1759. void LLMediaPluginTest::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
  1760. {
  1761. // Uncomment this to make things much, much quieter.
  1762. // return;
  1763. switch(event)
  1764. {
  1765. case MEDIA_EVENT_CONTENT_UPDATED:
  1766. // too spammy -- don't log these
  1767. // std::cerr <<  "Media event:  MEDIA_EVENT_CONTENT_UPDATED " << std::endl;
  1768. break;
  1769. case MEDIA_EVENT_TIME_DURATION_UPDATED:
  1770. // too spammy -- don't log these
  1771. // std::cerr <<  "Media event:  MEDIA_EVENT_TIME_DURATION_UPDATED, time is " << self->getCurrentTime() << " of " << self->getDuration() << std::endl;
  1772. break;
  1773. case MEDIA_EVENT_SIZE_CHANGED:
  1774. std::cerr <<  "Media event:  MEDIA_EVENT_SIZE_CHANGED " << std::endl;
  1775. break;
  1776. case MEDIA_EVENT_CURSOR_CHANGED:
  1777. std::cerr <<  "Media event:  MEDIA_EVENT_CURSOR_CHANGED, new cursor is " << self->getCursorName() << std::endl;
  1778. break;
  1779. case MEDIA_EVENT_NAVIGATE_BEGIN:
  1780. std::cerr <<  "Media event:  MEDIA_EVENT_NAVIGATE_BEGIN " << std::endl;
  1781. break;
  1782. case MEDIA_EVENT_NAVIGATE_COMPLETE:
  1783. std::cerr <<  "Media event:  MEDIA_EVENT_NAVIGATE_COMPLETE, result string is: " << self->getNavigateResultString() << std::endl;
  1784. break;
  1785. case MEDIA_EVENT_PROGRESS_UPDATED:
  1786. std::cerr <<  "Media event:  MEDIA_EVENT_PROGRESS_UPDATED, loading at " << self->getProgressPercent() << "%" << std::endl;
  1787. break;
  1788. case MEDIA_EVENT_STATUS_TEXT_CHANGED:
  1789. std::cerr <<  "Media event:  MEDIA_EVENT_STATUS_TEXT_CHANGED, new status text is: " << self->getStatusText() << std::endl;
  1790. break;
  1791. case MEDIA_EVENT_NAME_CHANGED:
  1792. std::cerr <<  "Media event:  MEDIA_EVENT_NAME_CHANGED, new name is: " << self->getMediaName() << std::endl;
  1793. glutSetWindowTitle( self->getMediaName().c_str() );
  1794. break;
  1795. case MEDIA_EVENT_LOCATION_CHANGED:
  1796. {
  1797. std::cerr <<  "Media event:  MEDIA_EVENT_LOCATION_CHANGED, new uri is: " << self->getLocation() << std::endl;
  1798. mediaPanel* panel = findMediaPanel(self);
  1799. if(panel != NULL)
  1800. {
  1801. panel->mStartUrl = self->getLocation();
  1802. if(panel == mSelectedPanel)
  1803. {
  1804. mUrlEdit->set_text(const_cast<char*>(panel->mStartUrl.c_str()) );
  1805. }
  1806. }
  1807. }
  1808. break;
  1809. case MEDIA_EVENT_CLICK_LINK_HREF:
  1810. std::cerr <<  "Media event:  MEDIA_EVENT_CLICK_LINK_HREF, uri is " << self->getClickURL() << std::endl;
  1811. break;
  1812. case MEDIA_EVENT_CLICK_LINK_NOFOLLOW:
  1813. std::cerr <<  "Media event:  MEDIA_EVENT_CLICK_LINK_NOFOLLOW, uri is " << self->getClickURL() << std::endl;
  1814. break;
  1815. case MEDIA_EVENT_PLUGIN_FAILED:
  1816. std::cerr <<  "Media event:  MEDIA_EVENT_PLUGIN_FAILED" << std::endl;
  1817. break;
  1818. case MEDIA_EVENT_PLUGIN_FAILED_LAUNCH:
  1819. std::cerr <<  "Media event:  MEDIA_EVENT_PLUGIN_FAILED_LAUNCH" << std::endl;
  1820. break;
  1821. }
  1822. }
  1823. ////////////////////////////////////////////////////////////////////////////////
  1824. //
  1825. static void gluiCallbackWrapper( int control_id )
  1826. {
  1827. if ( gApplication )
  1828. gApplication->gluiCallback( control_id );
  1829. }
  1830. ////////////////////////////////////////////////////////////////////////////////
  1831. //
  1832. void glutReshape( int width, int height )
  1833. {
  1834. if ( gApplication )
  1835. gApplication->reshape( width, height );
  1836. };
  1837. ////////////////////////////////////////////////////////////////////////////////
  1838. //
  1839. void glutDisplay()
  1840. {
  1841. if ( gApplication )
  1842. gApplication->display();
  1843. };
  1844. ////////////////////////////////////////////////////////////////////////////////
  1845. //
  1846. void glutIdle(int update_ms)
  1847. {
  1848. GLUI_Master.set_glutTimerFunc( update_ms, glutIdle, update_ms);
  1849. if ( gApplication )
  1850. gApplication->idle();
  1851. };
  1852. ////////////////////////////////////////////////////////////////////////////////
  1853. //
  1854. void glutKeyboard( unsigned char key, int x, int y )
  1855. {
  1856. if ( gApplication )
  1857. gApplication->keyboard( key );
  1858. };
  1859. ////////////////////////////////////////////////////////////////////////////////
  1860. //
  1861. void glutMousePassive( int x, int y )
  1862. {
  1863. if ( gApplication )
  1864. gApplication->mousePassive( x, y );
  1865. }
  1866. ////////////////////////////////////////////////////////////////////////////////
  1867. //
  1868. void glutMouseMove( int x , int y )
  1869. {
  1870. if ( gApplication )
  1871. gApplication->mouseMove( x, y );
  1872. }
  1873. ////////////////////////////////////////////////////////////////////////////////
  1874. //
  1875. void glutMouseButton( int button, int state, int x, int y )
  1876. {
  1877. if ( gApplication )
  1878. gApplication->mouseButton( button, state, x, y );
  1879. }
  1880. ////////////////////////////////////////////////////////////////////////////////
  1881. //
  1882. int main( int argc, char* argv[] )
  1883. {
  1884. #if LL_DARWIN
  1885. // Set the current working directory to <application bundle>/Contents/Resources/
  1886. CFURLRef resources_url = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle());
  1887. if(resources_url != NULL)
  1888. {
  1889. CFStringRef resources_string = CFURLCopyFileSystemPath(resources_url, kCFURLPOSIXPathStyle);
  1890. CFRelease(resources_url);
  1891. if(resources_string != NULL)
  1892. {
  1893. char buffer[PATH_MAX] = "";
  1894. if(CFStringGetCString(resources_string, buffer, sizeof(buffer), kCFStringEncodingUTF8))
  1895. {
  1896. chdir(buffer);
  1897. }
  1898. CFRelease(resources_string);
  1899. }
  1900. }
  1901. #endif
  1902. glutInit( &argc, argv );
  1903. glutInitDisplayMode( GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGB );
  1904. const int app_window_x = 80;
  1905. const int app_window_y = 0;
  1906. const int app_window_width = 960;
  1907. const int app_window_height = 960;
  1908. glutInitWindowPosition( app_window_x, app_window_y );
  1909. glutInitWindowSize( app_window_width, app_window_height );
  1910. int app_window_handle = glutCreateWindow( "LLMediaPluginTest" );
  1911. glutDisplayFunc( glutDisplay );
  1912. GLUI_Master.set_glutReshapeFunc( glutReshape );
  1913. GLUI_Master.set_glutKeyboardFunc( glutKeyboard );
  1914. GLUI_Master.set_glutMouseFunc( glutMouseButton );
  1915. glutPassiveMotionFunc( glutMousePassive );
  1916. glutMotionFunc( glutMouseMove );
  1917. glutSetWindow( app_window_handle );
  1918. gApplication = new LLMediaPluginTest( app_window_handle, app_window_width, app_window_height );
  1919. // update at approximately 60hz
  1920. int update_ms = 1000 / 60;
  1921. GLUI_Master.set_glutTimerFunc( update_ms, glutIdle, update_ms);
  1922. glutMainLoop();
  1923. delete gApplication;
  1924. }