aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--linden/indra/media_plugins/base/media_plugin_base.cpp57
-rw-r--r--linden/indra/media_plugins/base/media_plugin_base.h45
-rw-r--r--linden/indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h6
-rw-r--r--linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp35
-rw-r--r--linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h2
-rw-r--r--linden/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp78
-rw-r--r--linden/indra/media_plugins/quicktime/CMakeLists.txt8
-rw-r--r--linden/indra/media_plugins/quicktime/media_plugin_quicktime.cpp170
-rw-r--r--linden/indra/media_plugins/webkit/media_plugin_webkit.cpp53
-rw-r--r--linden/indra/newview/llviewerparcelmedia.cpp7
10 files changed, 358 insertions, 103 deletions
diff --git a/linden/indra/media_plugins/base/media_plugin_base.cpp b/linden/indra/media_plugins/base/media_plugin_base.cpp
index 1919419..4d5e374 100644
--- a/linden/indra/media_plugins/base/media_plugin_base.cpp
+++ b/linden/indra/media_plugins/base/media_plugin_base.cpp
@@ -2,6 +2,8 @@
2 * @file media_plugin_base.cpp 2 * @file media_plugin_base.cpp
3 * @brief Media plugin base class for LLMedia API plugin system 3 * @brief Media plugin base class for LLMedia API plugin system
4 * 4 *
5 * All plugins should be a subclass of MediaPluginBase.
6 *
5 * $LicenseInfo:firstyear=2008&license=viewergpl$ 7 * $LicenseInfo:firstyear=2008&license=viewergpl$
6 * 8 *
7 * Copyright (c) 2008-2009, Linden Research, Inc. 9 * Copyright (c) 2008-2009, Linden Research, Inc.
@@ -36,7 +38,10 @@
36 38
37// TODO: Make sure that the only symbol exported from this library is LLPluginInitEntryPoint 39// TODO: Make sure that the only symbol exported from this library is LLPluginInitEntryPoint
38//////////////////////////////////////////////////////////////////////////////// 40////////////////////////////////////////////////////////////////////////////////
39// 41/// Media plugin constructor.
42///
43/// @param[in] host_send_func Function for sending messages from plugin to plugin loader shell
44/// @param[in] host_user_data Message data for messages from plugin to plugin loader shell
40 45
41MediaPluginBase::MediaPluginBase( 46MediaPluginBase::MediaPluginBase(
42 LLPluginInstance::sendMessageFunction host_send_func, 47 LLPluginInstance::sendMessageFunction host_send_func,
@@ -54,6 +59,12 @@ MediaPluginBase::MediaPluginBase(
54 mStatus = STATUS_NONE; 59 mStatus = STATUS_NONE;
55} 60}
56 61
62/**
63 * Converts current media status enum value into string (STATUS_LOADING into "loading", etc.)
64 *
65 * @return Media status string ("loading", "playing", "paused", etc)
66 *
67 */
57std::string MediaPluginBase::statusString() 68std::string MediaPluginBase::statusString()
58{ 69{
59 std::string result; 70 std::string result;
@@ -65,6 +76,7 @@ std::string MediaPluginBase::statusString()
65 case STATUS_ERROR: result = "error"; break; 76 case STATUS_ERROR: result = "error"; break;
66 case STATUS_PLAYING: result = "playing"; break; 77 case STATUS_PLAYING: result = "playing"; break;
67 case STATUS_PAUSED: result = "paused"; break; 78 case STATUS_PAUSED: result = "paused"; break;
79 case STATUS_DONE: result = "done"; break;
68 default: 80 default:
69 // keep the empty string 81 // keep the empty string
70 break; 82 break;
@@ -73,6 +85,12 @@ std::string MediaPluginBase::statusString()
73 return result; 85 return result;
74} 86}
75 87
88/**
89 * Set media status.
90 *
91 * @param[in] status Media status (STATUS_LOADING, STATUS_PLAYING, STATUS_PAUSED, etc)
92 *
93 */
76void MediaPluginBase::setStatus(EStatus status) 94void MediaPluginBase::setStatus(EStatus status)
77{ 95{
78 if(mStatus != status) 96 if(mStatus != status)
@@ -83,6 +101,13 @@ void MediaPluginBase::setStatus(EStatus status)
83} 101}
84 102
85 103
104/**
105 * Receive message from plugin loader shell.
106 *
107 * @param[in] message_string Message string
108 * @param[in] user_data Message data
109 *
110 */
86void MediaPluginBase::staticReceiveMessage(const char *message_string, void **user_data) 111void MediaPluginBase::staticReceiveMessage(const char *message_string, void **user_data)
87{ 112{
88 MediaPluginBase *self = (MediaPluginBase*)*user_data; 113 MediaPluginBase *self = (MediaPluginBase*)*user_data;
@@ -100,12 +125,27 @@ void MediaPluginBase::staticReceiveMessage(const char *message_string, void **us
100 } 125 }
101} 126}
102 127
128/**
129 * Send message to plugin loader shell.
130 *
131 * @param[in] message Message data being sent to plugin loader shell
132 *
133 */
103void MediaPluginBase::sendMessage(const LLPluginMessage &message) 134void MediaPluginBase::sendMessage(const LLPluginMessage &message)
104{ 135{
105 std::string output = message.generate(); 136 std::string output = message.generate();
106 mHostSendFunction(output.c_str(), &mHostUserData); 137 mHostSendFunction(output.c_str(), &mHostUserData);
107} 138}
108 139
140/**
141 * Notifies plugin loader shell that part of display area needs to be redrawn.
142 *
143 * @param[in] left Left X coordinate of area to redraw (0,0 is at top left corner)
144 * @param[in] top Top Y coordinate of area to redraw (0,0 is at top left corner)
145 * @param[in] right Right X-coordinate of area to redraw (0,0 is at top left corner)
146 * @param[in] bottom Bottom Y-coordinate of area to redraw (0,0 is at top left corner)
147 *
148 */
109void MediaPluginBase::setDirty(int left, int top, int right, int bottom) 149void MediaPluginBase::setDirty(int left, int top, int right, int bottom)
110{ 150{
111 LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "updated"); 151 LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "updated");
@@ -118,6 +158,10 @@ void MediaPluginBase::setDirty(int left, int top, int right, int bottom)
118 sendMessage(message); 158 sendMessage(message);
119} 159}
120 160
161/**
162 * Sends "media_status" message to plugin loader shell ("loading", "playing", "paused", etc.)
163 *
164 */
121void MediaPluginBase::sendStatus() 165void MediaPluginBase::sendStatus()
122{ 166{
123 LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "media_status"); 167 LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "media_status");
@@ -141,6 +185,17 @@ extern "C"
141 LLSYMEXPORT int LLPluginInitEntryPoint(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data); 185 LLSYMEXPORT int LLPluginInitEntryPoint(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data);
142} 186}
143 187
188/**
189 * Plugin initialization and entry point. Establishes communication channel for messages between plugin and plugin loader shell. TODO:DOC - Please check!
190 *
191 * @param[in] host_send_func Function for sending messages from plugin to plugin loader shell
192 * @param[in] host_user_data Message data for messages from plugin to plugin loader shell
193 * @param[out] plugin_send_func Function for plugin to receive messages from plugin loader shell
194 * @param[out] plugin_user_data Pointer to plugin instance
195 *
196 * @return int, where 0=success
197 *
198 */
144LLSYMEXPORT int 199LLSYMEXPORT int
145LLPluginInitEntryPoint(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data) 200LLPluginInitEntryPoint(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data)
146{ 201{
diff --git a/linden/indra/media_plugins/base/media_plugin_base.h b/linden/indra/media_plugins/base/media_plugin_base.h
index 4872706..24198af 100644
--- a/linden/indra/media_plugins/base/media_plugin_base.h
+++ b/linden/indra/media_plugins/base/media_plugin_base.h
@@ -41,14 +41,17 @@ class MediaPluginBase
41{ 41{
42public: 42public:
43 MediaPluginBase(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); 43 MediaPluginBase(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data);
44 /** Media plugin destructor. */
44 virtual ~MediaPluginBase() {} 45 virtual ~MediaPluginBase() {}
45 46
47 /** Handle received message from plugin loader shell. */
46 virtual void receiveMessage(const char *message_string) = 0; 48 virtual void receiveMessage(const char *message_string) = 0;
47 49
48 static void staticReceiveMessage(const char *message_string, void **user_data); 50 static void staticReceiveMessage(const char *message_string, void **user_data);
49 51
50protected: 52protected:
51 53
54 /** Plugin status. */
52 typedef enum 55 typedef enum
53 { 56 {
54 STATUS_NONE, 57 STATUS_NONE,
@@ -57,12 +60,16 @@ protected:
57 STATUS_ERROR, 60 STATUS_ERROR,
58 STATUS_PLAYING, 61 STATUS_PLAYING,
59 STATUS_PAUSED, 62 STATUS_PAUSED,
63 STATUS_DONE
60 } EStatus; 64 } EStatus;
61 65
66 /** Plugin shared memory. */
62 class SharedSegmentInfo 67 class SharedSegmentInfo
63 { 68 {
64 public: 69 public:
70 /** Shared memory address. */
65 void *mAddress; 71 void *mAddress;
72 /** Shared memory size. */
66 size_t mSize; 73 size_t mSize;
67 }; 74 };
68 75
@@ -71,42 +78,56 @@ protected:
71 std::string statusString(); 78 std::string statusString();
72 void setStatus(EStatus status); 79 void setStatus(EStatus status);
73 80
74 // The quicktime plugin overrides this to add current time and duration to the message... 81 /// Note: The quicktime plugin overrides this to add current time and duration to the message.
75 virtual void setDirty(int left, int top, int right, int bottom); 82 virtual void setDirty(int left, int top, int right, int bottom);
76 83
84 /** Map of shared memory names to shared memory. */
77 typedef std::map<std::string, SharedSegmentInfo> SharedSegmentMap; 85 typedef std::map<std::string, SharedSegmentInfo> SharedSegmentMap;
78 86
79 87
88 /** Function to send message from plugin to plugin loader shell. */
80 LLPluginInstance::sendMessageFunction mHostSendFunction; 89 LLPluginInstance::sendMessageFunction mHostSendFunction;
90 /** Message data being sent to plugin loader shell by mHostSendFunction. */
81 void *mHostUserData; 91 void *mHostUserData;
92 /** Flag to delete plugin instance (self). */
82 bool mDeleteMe; 93 bool mDeleteMe;
94 /** Pixel array to display. TODO:DOC are pixels always 24-bit RGB format, aligned on 32-bit boundary? Also: calling this a pixel array may be misleading since 1 pixel > 1 char. */
83 unsigned char* mPixels; 95 unsigned char* mPixels;
96 /** TODO:DOC what's this for -- does a texture have its own piece of shared memory? updated on size_change_request, cleared on shm_remove */
84 std::string mTextureSegmentName; 97 std::string mTextureSegmentName;
98 /** Width of plugin display in pixels. */
85 int mWidth; 99 int mWidth;
100 /** Height of plugin display in pixels. */
86 int mHeight; 101 int mHeight;
102 /** Width of plugin texture. */
87 int mTextureWidth; 103 int mTextureWidth;
104 /** Height of plugin texture. */
88 int mTextureHeight; 105 int mTextureHeight;
106 /** Pixel depth (pixel size in bytes). */
89 int mDepth; 107 int mDepth;
108 /** Current status of plugin. */
90 EStatus mStatus; 109 EStatus mStatus;
110 /** Map of shared memory segments. */
91 SharedSegmentMap mSharedSegments; 111 SharedSegmentMap mSharedSegments;
92 112
93}; 113};
94 114
95// The plugin must define this function to create its instance. 115/** The plugin <b>must</b> define this function to create its instance.
116 * It should look something like this:
117 * @code
118 * {
119 * MediaPluginFoo *self = new MediaPluginFoo(host_send_func, host_user_data);
120 * *plugin_send_func = MediaPluginFoo::staticReceiveMessage;
121 * *plugin_user_data = (void*)self;
122 *
123 * return 0;
124 * }
125 * @endcode
126 */
96int init_media_plugin( 127int init_media_plugin(
97 LLPluginInstance::sendMessageFunction host_send_func, 128 LLPluginInstance::sendMessageFunction host_send_func,
98 void *host_user_data, 129 void *host_user_data,
99 LLPluginInstance::sendMessageFunction *plugin_send_func, 130 LLPluginInstance::sendMessageFunction *plugin_send_func,
100 void **plugin_user_data); 131 void **plugin_user_data);
101 132
102// It should look something like this:
103/*
104{
105 MediaPluginFoo *self = new MediaPluginFoo(host_send_func, host_user_data);
106 *plugin_send_func = MediaPluginFoo::staticReceiveMessage;
107 *plugin_user_data = (void*)self;
108
109 return 0;
110}
111*/
112 133
diff --git a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h
index e31d4a3..04976b9 100644
--- a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h
+++ b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h
@@ -35,10 +35,16 @@
35 35
36#include <cstdio> 36#include <cstdio>
37 37
38extern "C" {
39#include <sys/types.h>
40#include <unistd.h>
41}
42
38///////////////////////////////////////////////////////////////////////// 43/////////////////////////////////////////////////////////////////////////
39// Debug/Info/Warning macros. 44// Debug/Info/Warning macros.
40#define MSGMODULEFOO "(media plugin)" 45#define MSGMODULEFOO "(media plugin)"
41#define STDERRMSG(...) do{\ 46#define STDERRMSG(...) do{\
47 fprintf(stderr, " pid:%d: ", (int)getpid());\
42 fprintf(stderr, MSGMODULEFOO " %s:%d: ", __FUNCTION__, __LINE__);\ 48 fprintf(stderr, MSGMODULEFOO " %s:%d: ", __FUNCTION__, __LINE__);\
43 fprintf(stderr, __VA_ARGS__);\ 49 fprintf(stderr, __VA_ARGS__);\
44 fputc('\n',stderr);\ 50 fputc('\n',stderr);\
diff --git a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp
index 25e96d4..ef8ff58 100644
--- a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp
+++ b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp
@@ -52,7 +52,7 @@ GST_DEBUG_CATEGORY_STATIC (gst_slvideo_debug);
52#define SLV_ALLCAPS GST_VIDEO_CAPS_RGBx SLV_SIZECAPS 52#define SLV_ALLCAPS GST_VIDEO_CAPS_RGBx SLV_SIZECAPS
53 53
54static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ( 54static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE (
55 (gchar*)"sink", 55 "sink",
56 GST_PAD_SINK, 56 GST_PAD_SINK,
57 GST_PAD_ALWAYS, 57 GST_PAD_ALWAYS,
58 GST_STATIC_CAPS (SLV_ALLCAPS) 58 GST_STATIC_CAPS (SLV_ALLCAPS)
@@ -106,11 +106,10 @@ gst_slvideo_show_frame (GstBaseSink * bsink, GstBuffer * buf)
106 106
107 slvideo = GST_SLVIDEO(bsink); 107 slvideo = GST_SLVIDEO(bsink);
108 108
109#if 0 109 DEBUGMSG("transferring a frame of %dx%d <- %p (%d)",
110 fprintf(stderr, "\n\ntransferring a frame of %dx%d <- %p (%d)\n\n", 110 slvideo->width, slvideo->height, GST_BUFFER_DATA(buf),
111 slvideo->width, slvideo->height, GST_BUFFER_DATA(buf), 111 slvideo->format);
112 slvideo->format); 112
113#endif
114 if (GST_BUFFER_DATA(buf)) 113 if (GST_BUFFER_DATA(buf))
115 { 114 {
116 // copy frame and frame info into neutral territory 115 // copy frame and frame info into neutral territory
@@ -335,7 +334,7 @@ gst_slvideo_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size,
335#define MAXDEPTHHACK 4 334#define MAXDEPTHHACK 4
336 335
337 GST_OBJECT_LOCK(slvideo); 336 GST_OBJECT_LOCK(slvideo);
338 if (slvideo->resize_forced) 337 if (slvideo->resize_forced_always) // app is giving us a fixed size to work with
339 { 338 {
340 gint slwantwidth, slwantheight; 339 gint slwantwidth, slwantheight;
341 slwantwidth = slvideo->resize_try_width; 340 slwantwidth = slvideo->resize_try_width;
@@ -384,6 +383,8 @@ gst_slvideo_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size,
384 } 383 }
385 } 384 }
386 385
386 GST_OBJECT_UNLOCK(slvideo);
387
387 if (!made_bufferdata_ptr) // need to fallback to malloc at original size 388 if (!made_bufferdata_ptr) // need to fallback to malloc at original size
388 { 389 {
389 GST_BUFFER_SIZE(newbuf) = width * height * MAXDEPTHHACK; 390 GST_BUFFER_SIZE(newbuf) = width * height * MAXDEPTHHACK;
@@ -392,8 +393,6 @@ gst_slvideo_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size,
392 llgst_buffer_set_caps (GST_BUFFER_CAST(newbuf), caps); 393 llgst_buffer_set_caps (GST_BUFFER_CAST(newbuf), caps);
393 } 394 }
394 395
395 GST_OBJECT_UNLOCK(slvideo);
396
397 *buf = GST_BUFFER_CAST(newbuf); 396 *buf = GST_BUFFER_CAST(newbuf);
398 397
399 return GST_FLOW_OK; 398 return GST_FLOW_OK;
@@ -457,7 +456,7 @@ gst_slvideo_init (GstSLVideo * filter,
457 filter->retained_frame_format = SLV_PF_UNKNOWN; 456 filter->retained_frame_format = SLV_PF_UNKNOWN;
458 GstCaps *caps = llgst_caps_from_string (SLV_ALLCAPS); 457 GstCaps *caps = llgst_caps_from_string (SLV_ALLCAPS);
459 llgst_caps_replace (&filter->caps, caps); 458 llgst_caps_replace (&filter->caps, caps);
460 filter->resize_forced = false; 459 filter->resize_forced_always = false;
461 filter->resize_try_width = -1; 460 filter->resize_try_width = -1;
462 filter->resize_try_height = -1; 461 filter->resize_try_height = -1;
463 GST_OBJECT_UNLOCK(filter); 462 GST_OBJECT_UNLOCK(filter);
@@ -498,12 +497,12 @@ gst_slvideo_get_property (GObject * object, guint prop_id,
498static gboolean 497static gboolean
499plugin_init (GstPlugin * plugin) 498plugin_init (GstPlugin * plugin)
500{ 499{
501 DEBUGMSG("\n\n\nPLUGIN INIT\n\n\n"); 500 DEBUGMSG("PLUGIN INIT");
502 501
503 GST_DEBUG_CATEGORY_INIT (gst_slvideo_debug, (gchar*)"private-slvideo-plugin", 502 GST_DEBUG_CATEGORY_INIT (gst_slvideo_debug, (gchar*)"private-slvideo-plugin",
504 0, (gchar*)"Second Life Video Sink"); 503 0, (gchar*)"Second Life Video Sink");
505 504
506 return llgst_element_register (plugin, (gchar*)"private-slvideo", 505 return llgst_element_register (plugin, "private-slvideo",
507 GST_RANK_NONE, GST_TYPE_SLVIDEO); 506 GST_RANK_NONE, GST_TYPE_SLVIDEO);
508} 507}
509 508
@@ -519,14 +518,14 @@ void gst_slvideo_init_class (void)
519 // this macro quietly refers to PACKAGE internally 518 // this macro quietly refers to PACKAGE internally
520 static GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, 519 static GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
521 GST_VERSION_MINOR, 520 GST_VERSION_MINOR,
522 (gchar*)"private-slvideoplugin", 521 "private-slvideoplugin",
523 (gchar*)"SL Video sink plugin", 522 "SL Video sink plugin",
524 plugin_init, (gchar*)"0.1", (gchar*)GST_LICENSE_UNKNOWN, 523 plugin_init, "0.1", GST_LICENSE_UNKNOWN,
525 (gchar*)"Second Life", 524 "Second Life",
526 (gchar*)"http://www.secondlife.com/"); 525 "http://www.secondlife.com/");
527#undef PACKAGE 526#undef PACKAGE
528 ll_gst_plugin_register_static (&gst_plugin_desc); 527 ll_gst_plugin_register_static (&gst_plugin_desc);
529 DEBUGMSG(stderr, "\n\n\nCLASS INIT\n\n\n"); 528 DEBUGMSG("CLASS INIT");
530} 529}
531 530
532#endif // LL_GSTREAMER010_ENABLED 531#endif // LL_GSTREAMER010_ENABLED
diff --git a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h
index f6d55b8..8cdc72d 100644
--- a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h
+++ b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h
@@ -88,7 +88,7 @@ struct _GstSLVideo
88 int retained_frame_width, retained_frame_height; 88 int retained_frame_width, retained_frame_height;
89 SLVPixelFormat retained_frame_format; 89 SLVPixelFormat retained_frame_format;
90 // sticky resize info 90 // sticky resize info
91 bool resize_forced; 91 bool resize_forced_always;
92 int resize_try_width; 92 int resize_try_width;
93 int resize_try_height; 93 int resize_try_height;
94}; 94};
diff --git a/linden/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp b/linden/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp
index 77b7c13..5b3152d 100644
--- a/linden/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp
+++ b/linden/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp
@@ -104,7 +104,7 @@ private:
104 void mouseUp( int x, int y ); 104 void mouseUp( int x, int y );
105 void mouseMove( int x, int y ); 105 void mouseMove( int x, int y );
106 106
107 bool sizeChanged(); 107 void sizeChanged();
108 108
109 static bool mDoneInit; 109 static bool mDoneInit;
110 110
@@ -114,13 +114,16 @@ private:
114 114
115 int mDepth; 115 int mDepth;
116 116
117 // media natural size 117 // media NATURAL size
118 int mNaturalWidth; 118 int mNaturalWidth;
119 int mNaturalHeight; 119 int mNaturalHeight;
120 int mNaturalRowbytes; 120 // media current size
121 // previous media natural size so we can detect changes 121 int mCurrentWidth;
122 int mPreviousNaturalWidth; 122 int mCurrentHeight;
123 int mPreviousNaturalHeight; 123 int mCurrentRowbytes;
124 // previous media size so we can detect changes
125 int mPreviousWidth;
126 int mPreviousHeight;
124 // desired render size from host 127 // desired render size from host
125 int mWidth; 128 int mWidth;
126 int mHeight; 129 int mHeight;
@@ -148,7 +151,7 @@ MediaPluginGStreamer010::MediaPluginGStreamer010(
148 void *host_user_data ) : 151 void *host_user_data ) :
149 MediaPluginBase(host_send_func, host_user_data), 152 MediaPluginBase(host_send_func, host_user_data),
150 mBusWatchID ( 0 ), 153 mBusWatchID ( 0 ),
151 mNaturalRowbytes ( 4 ), 154 mCurrentRowbytes ( 4 ),
152 mTextureFormatPrimary ( GL_RGBA ), 155 mTextureFormatPrimary ( GL_RGBA ),
153 mTextureFormatType ( GL_UNSIGNED_INT_8_8_8_8_REV ), 156 mTextureFormatType ( GL_UNSIGNED_INT_8_8_8_8_REV ),
154 mSeekWanted(false), 157 mSeekWanted(false),
@@ -194,6 +197,7 @@ MediaPluginGStreamer010::processGSTEvents(GstBus *bus,
194 } 197 }
195 else 198 else
196 { 199 {
200 // TODO: grok 'duration' message type
197 DEBUGMSG("Got GST message type: %s", 201 DEBUGMSG("Got GST message type: %s",
198 LLGST_MESSAGE_TYPE_NAME (message)); 202 LLGST_MESSAGE_TYPE_NAME (message));
199 } 203 }
@@ -428,8 +432,8 @@ MediaPluginGStreamer010::update(int milliseconds)
428 { 432 {
429 DEBUGMSG("NEW FRAME READY"); 433 DEBUGMSG("NEW FRAME READY");
430 434
431 if (mVideoSink->retained_frame_width != mNaturalWidth || 435 if (mVideoSink->retained_frame_width != mCurrentWidth ||
432 mVideoSink->retained_frame_height != mNaturalHeight) 436 mVideoSink->retained_frame_height != mCurrentHeight)
433 // *TODO: also check for change in format 437 // *TODO: also check for change in format
434 { 438 {
435 // just resize container, don't consume frame 439 // just resize container, don't consume frame
@@ -456,39 +460,38 @@ MediaPluginGStreamer010::update(int milliseconds)
456 460
457 GST_OBJECT_UNLOCK(mVideoSink); 461 GST_OBJECT_UNLOCK(mVideoSink);
458 462
459 mNaturalRowbytes = neww * newd; 463 mCurrentRowbytes = neww * newd;
460 DEBUGMSG("video container resized to %dx%d", 464 DEBUGMSG("video container resized to %dx%d",
461 neww, newh); 465 neww, newh);
462 466
463 mDepth = newd; 467 mDepth = newd;
464 mNaturalWidth = neww; 468 mCurrentWidth = neww;
465 mNaturalHeight = newh; 469 mCurrentHeight = newh;
466 sizeChanged(); 470 sizeChanged();
467 return true; 471 return true;
468 } 472 }
469 473
470 if (mPixels && 474 if (mPixels &&
471 mNaturalHeight <= mHeight && 475 mCurrentHeight <= mHeight &&
472 mNaturalWidth <= mWidth && 476 mCurrentWidth <= mWidth &&
473 !mTextureSegmentName.empty()) 477 !mTextureSegmentName.empty())
474 { 478 {
475
476 // we're gonna totally consume this frame - reset 'ready' flag 479 // we're gonna totally consume this frame - reset 'ready' flag
477 mVideoSink->retained_frame_ready = FALSE; 480 mVideoSink->retained_frame_ready = FALSE;
478 int destination_rowbytes = mWidth * mDepth; 481 int destination_rowbytes = mWidth * mDepth;
479 for (int row=0; row<mNaturalHeight; ++row) 482 for (int row=0; row<mCurrentHeight; ++row)
480 { 483 {
481 memcpy(&mPixels 484 memcpy(&mPixels
482 [destination_rowbytes * row], 485 [destination_rowbytes * row],
483 &mVideoSink->retained_frame_data 486 &mVideoSink->retained_frame_data
484 [mNaturalRowbytes * row], 487 [mCurrentRowbytes * row],
485 mNaturalRowbytes); 488 mCurrentRowbytes);
486 } 489 }
487 490
488 GST_OBJECT_UNLOCK(mVideoSink); 491 GST_OBJECT_UNLOCK(mVideoSink);
489 DEBUGMSG("NEW FRAME REALLY TRULY CONSUMED, TELLING HOST"); 492 DEBUGMSG("NEW FRAME REALLY TRULY CONSUMED, TELLING HOST");
490 493
491 setDirty(0,0,mNaturalWidth,mNaturalHeight); 494 setDirty(0,0,mCurrentWidth,mCurrentHeight);
492 } 495 }
493 else 496 else
494 { 497 {
@@ -835,27 +838,35 @@ MediaPluginGStreamer010::startup()
835} 838}
836 839
837 840
838bool 841void
839MediaPluginGStreamer010::sizeChanged() 842MediaPluginGStreamer010::sizeChanged()
840{ 843{
841 // the shared writing space has possibly changed size/location/whatever 844 // the shared writing space has possibly changed size/location/whatever
842 845
843 // Check to see whether the movie's natural size has updated 846 // Check to see whether the movie's NATURAL size has been set yet
844 if (mNaturalWidth != mPreviousNaturalWidth || 847 if (1 == mNaturalWidth &&
845 mNaturalHeight != mPreviousNaturalHeight) 848 1 == mNaturalHeight)
846 { 849 {
847 mPreviousNaturalWidth = mNaturalWidth; 850 mNaturalWidth = mCurrentWidth;
848 mPreviousNaturalHeight = mNaturalHeight; 851 mNaturalHeight = mCurrentHeight;
852 DEBUGMSG("Media NATURAL size better detected as %dx%d",
853 mNaturalWidth, mNaturalHeight);
854 }
855
856 // if the size has changed then the shm has changed and the app needs telling
857 if (mCurrentWidth != mPreviousWidth ||
858 mCurrentHeight != mPreviousHeight)
859 {
860 mPreviousWidth = mCurrentWidth;
861 mPreviousHeight = mCurrentHeight;
849 862
850 LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_request"); 863 LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_request");
851 message.setValue("name", mTextureSegmentName); 864 message.setValue("name", mTextureSegmentName);
852 message.setValueS32("width", mNaturalWidth); 865 message.setValueS32("width", mNaturalWidth);
853 message.setValueS32("height", mNaturalHeight); 866 message.setValueS32("height", mNaturalHeight);
854 DEBUGMSG("<--- Sending size change request to application with name: '%s' - size is %d x %d", mTextureSegmentName.c_str(), mNaturalWidth, mNaturalHeight); 867 DEBUGMSG("<--- Sending size change request to application with name: '%s' - natural size is %d x %d", mTextureSegmentName.c_str(), mNaturalWidth, mNaturalHeight);
855 sendMessage(message); 868 sendMessage(message);
856 } 869 }
857
858 return true;
859} 870}
860 871
861 872
@@ -940,10 +951,12 @@ void MediaPluginGStreamer010::receiveMessage(const char *message_string)
940 // lame to have to decide this now, it depends on the movie. Oh well. 951 // lame to have to decide this now, it depends on the movie. Oh well.
941 mDepth = 4; 952 mDepth = 4;
942 953
954 mCurrentWidth = 1;
955 mCurrentHeight = 1;
956 mPreviousWidth = 1;
957 mPreviousHeight = 1;
943 mNaturalWidth = 1; 958 mNaturalWidth = 1;
944 mNaturalHeight = 1; 959 mNaturalHeight = 1;
945 mPreviousNaturalWidth = 1;
946 mPreviousNaturalHeight = 1;
947 mWidth = 1; 960 mWidth = 1;
948 mHeight = 1; 961 mHeight = 1;
949 mTextureWidth = 1; 962 mTextureWidth = 1;
@@ -984,7 +997,6 @@ void MediaPluginGStreamer010::receiveMessage(const char *message_string)
984 INFOMSG("MediaPluginGStreamer010::receiveMessage: shared memory added, name: %s, size: %d, address: %p", name.c_str(), int(info.mSize), info.mAddress); 997 INFOMSG("MediaPluginGStreamer010::receiveMessage: shared memory added, name: %s, size: %d, address: %p", name.c_str(), int(info.mSize), info.mAddress);
985 998
986 mSharedSegments.insert(SharedSegmentMap::value_type(name, info)); 999 mSharedSegments.insert(SharedSegmentMap::value_type(name, info));
987
988 } 1000 }
989 else if(message_name == "shm_remove") 1001 else if(message_name == "shm_remove")
990 { 1002 {
@@ -1063,7 +1075,7 @@ void MediaPluginGStreamer010::receiveMessage(const char *message_string)
1063 INFOMSG("**** = REAL RESIZE REQUEST FROM APP"); 1075 INFOMSG("**** = REAL RESIZE REQUEST FROM APP");
1064 1076
1065 GST_OBJECT_LOCK(mVideoSink); 1077 GST_OBJECT_LOCK(mVideoSink);
1066 mVideoSink->resize_forced = true; 1078 mVideoSink->resize_forced_always = true;
1067 mVideoSink->resize_try_width = texture_width; 1079 mVideoSink->resize_try_width = texture_width;
1068 mVideoSink->resize_try_height = texture_height; 1080 mVideoSink->resize_try_height = texture_height;
1069 GST_OBJECT_UNLOCK(mVideoSink); 1081 GST_OBJECT_UNLOCK(mVideoSink);
diff --git a/linden/indra/media_plugins/quicktime/CMakeLists.txt b/linden/indra/media_plugins/quicktime/CMakeLists.txt
index db11c9a..f0b8f0d 100644
--- a/linden/indra/media_plugins/quicktime/CMakeLists.txt
+++ b/linden/indra/media_plugins/quicktime/CMakeLists.txt
@@ -56,6 +56,14 @@ add_dependencies(media_plugin_quicktime
56 ${LLCOMMON_LIBRARIES} 56 ${LLCOMMON_LIBRARIES}
57) 57)
58 58
59if (WINDOWS)
60 set_target_properties(
61 media_plugin_quicktime
62 PROPERTIES
63 LINK_FLAGS "/MANIFEST:NO"
64 )
65endif (WINDOWS)
66
59if (QUICKTIME) 67if (QUICKTIME)
60 68
61 add_definitions(-DLL_QUICKTIME_ENABLED=1) 69 add_definitions(-DLL_QUICKTIME_ENABLED=1)
diff --git a/linden/indra/media_plugins/quicktime/media_plugin_quicktime.cpp b/linden/indra/media_plugins/quicktime/media_plugin_quicktime.cpp
index 51cc8dd..6c8c41d 100644
--- a/linden/indra/media_plugins/quicktime/media_plugin_quicktime.cpp
+++ b/linden/indra/media_plugins/quicktime/media_plugin_quicktime.cpp
@@ -49,6 +49,7 @@
49 #include "Movies.h" 49 #include "Movies.h"
50 #include "QDoffscreen.h" 50 #include "QDoffscreen.h"
51 #include "FixMath.h" 51 #include "FixMath.h"
52 #include "QTLoadLibraryUtils.h"
52#endif 53#endif
53 54
54// TODO: Make sure that the only symbol exported from this library is LLPluginInitEntryPoint 55// TODO: Make sure that the only symbol exported from this library is LLPluginInitEntryPoint
@@ -72,11 +73,14 @@ private:
72 int mCurVolume; 73 int mCurVolume;
73 bool mMediaSizeChanging; 74 bool mMediaSizeChanging;
74 bool mIsLooping; 75 bool mIsLooping;
76 std::string mMovieTitle;
77 bool mReceivedTitle;
75 const int mMinWidth; 78 const int mMinWidth;
76 const int mMaxWidth; 79 const int mMaxWidth;
77 const int mMinHeight; 80 const int mMinHeight;
78 const int mMaxHeight; 81 const int mMaxHeight;
79 F64 mPlayRate; 82 F64 mPlayRate;
83 std::string mNavigateURL;
80 84
81 enum ECommand { 85 enum ECommand {
82 COMMAND_NONE, 86 COMMAND_NONE,
@@ -175,6 +179,11 @@ private:
175 setStatus(STATUS_ERROR); 179 setStatus(STATUS_ERROR);
176 return; 180 return;
177 }; 181 };
182
183 mNavigateURL = url;
184 LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_begin");
185 message.setValue("uri", mNavigateURL);
186 sendMessage(message);
178 187
179 // do pre-roll actions (typically fired for streaming movies but not always) 188 // do pre-roll actions (typically fired for streaming movies but not always)
180 PrePrerollMovie( mMovieHandle, 0, getPlayRate(), moviePrePrerollCompleteCallback, ( void * )this ); 189 PrePrerollMovie( mMovieHandle, 0, getPlayRate(), moviePrePrerollCompleteCallback, ( void * )this );
@@ -199,6 +208,9 @@ private:
199 208
200 bool unload() 209 bool unload()
201 { 210 {
211 // new movie and have to get title again
212 mReceivedTitle = false;
213
202 if ( mMovieHandle ) 214 if ( mMovieHandle )
203 { 215 {
204 StopMovie( mMovieHandle ); 216 StopMovie( mMovieHandle );
@@ -382,11 +394,18 @@ private:
382 394
383 static void moviePrePrerollCompleteCallback( Movie movie, OSErr preroll_err, void *ref ) 395 static void moviePrePrerollCompleteCallback( Movie movie, OSErr preroll_err, void *ref )
384 { 396 {
385 //MediaPluginQuickTime* self = ( MediaPluginQuickTime* )ref; 397 MediaPluginQuickTime* self = ( MediaPluginQuickTime* )ref;
386 398
387 // TODO: 399 // TODO:
388 //LLMediaEvent event( self ); 400 //LLMediaEvent event( self );
389 //self->mEventEmitter.update( &LLMediaObserver::onMediaPreroll, event ); 401 //self->mEventEmitter.update( &LLMediaObserver::onMediaPreroll, event );
402
403 // Send a "navigate complete" event.
404 LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_complete");
405 message.setValue("uri", self->mNavigateURL);
406 message.setValueS32("result_code", 200);
407 message.setValue("result_string", "OK");
408 self->sendMessage(message);
390 }; 409 };
391 410
392 411
@@ -400,7 +419,7 @@ private:
400 { 419 {
401 if ( mCommand == COMMAND_PLAY ) 420 if ( mCommand == COMMAND_PLAY )
402 { 421 {
403 if ( mStatus == STATUS_LOADED || mStatus == STATUS_PAUSED || mStatus == STATUS_PLAYING ) 422 if ( mStatus == STATUS_LOADED || mStatus == STATUS_PAUSED || mStatus == STATUS_PLAYING || mStatus == STATUS_DONE )
404 { 423 {
405 long state = GetMovieLoadState( mMovieHandle ); 424 long state = GetMovieLoadState( mMovieHandle );
406 425
@@ -426,7 +445,7 @@ private:
426 else 445 else
427 if ( mCommand == COMMAND_STOP ) 446 if ( mCommand == COMMAND_STOP )
428 { 447 {
429 if ( mStatus == STATUS_PLAYING || mStatus == STATUS_PAUSED ) 448 if ( mStatus == STATUS_PLAYING || mStatus == STATUS_PAUSED || mStatus == STATUS_DONE )
430 { 449 {
431 if ( GetMovieLoadState( mMovieHandle ) >= kMovieLoadStatePlaythroughOK ) 450 if ( GetMovieLoadState( mMovieHandle ) >= kMovieLoadStatePlaythroughOK )
432 { 451 {
@@ -508,11 +527,17 @@ private:
508 if ( ! mMovieController ) 527 if ( ! mMovieController )
509 return; 528 return;
510 529
511 // service QuickTime 530 // this wasn't required in 1.xx viewer but we have to manually
512 // Calling it this way doesn't have good behavior on Windows... 531 // work the Windows message pump now
513// MoviesTask( mMovieHandle, milliseconds ); 532 #if defined( LL_WINDOWS )
514 // This was the original, but I think using both MoviesTask and MCIdle is redundant. Trying with only MCIdle. 533 MSG msg;
515// MoviesTask( mMovieHandle, 0 ); 534 while ( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) )
535 {
536 GetMessage( &msg, NULL, 0, 0 );
537 TranslateMessage( &msg );
538 DispatchMessage( &msg );
539 };
540 #endif
516 541
517 MCIdle( mMovieController ); 542 MCIdle( mMovieController );
518 543
@@ -525,11 +550,14 @@ private:
525 // update state machine 550 // update state machine
526 processState(); 551 processState();
527 552
528 // special code for looping - need to rewind at the end of the movie 553 // see if title arrived and if so, update member variable with contents
529 if ( mIsLooping ) 554 checkTitle();
555
556 // QT call to see if we are at the end - can't do with controller
557 if ( IsMovieDone( mMovieHandle ) )
530 { 558 {
531 // QT call to see if we are at the end - can't do with controller 559 // special code for looping - need to rewind at the end of the movie
532 if ( IsMovieDone( mMovieHandle ) ) 560 if ( mIsLooping )
533 { 561 {
534 // go back to start 562 // go back to start
535 rewind(); 563 rewind();
@@ -542,8 +570,16 @@ private:
542 // set the volume 570 // set the volume
543 MCDoAction( mMovieController, mcActionSetVolume, (void*)mCurVolume ); 571 MCDoAction( mMovieController, mcActionSetVolume, (void*)mCurVolume );
544 }; 572 };
545 }; 573 }
546 }; 574 else
575 {
576 if(mStatus == STATUS_PLAYING)
577 {
578 setStatus(STATUS_DONE);
579 }
580 }
581 }
582
547 }; 583 };
548 584
549 int getDataWidth() const 585 int getDataWidth() const
@@ -586,6 +622,19 @@ private:
586 }; 622 };
587 }; 623 };
588 624
625 F64 getLoadedDuration()
626 {
627 TimeValue duration;
628 if(GetMaxLoadedTimeInMovie( mMovieHandle, &duration ) != noErr)
629 {
630 // If GetMaxLoadedTimeInMovie returns an error, return the full duration of the movie.
631 duration = GetMovieDuration( mMovieHandle );
632 }
633 TimeValue scale = GetMovieTimeScale( mMovieHandle );
634
635 return (F64)duration / (F64)scale;
636 };
637
589 F64 getDuration() 638 F64 getDuration()
590 { 639 {
591 TimeValue duration = GetMovieDuration( mMovieHandle ); 640 TimeValue duration = GetMovieDuration( mMovieHandle );
@@ -643,6 +692,77 @@ private:
643 { 692 {
644 }; 693 };
645 694
695 ////////////////////////////////////////////////////////////////////////////////
696 // Grab movie title into mMovieTitle - should be called repeatedly
697 // until it returns true since movie title takes a while to become
698 // available.
699 const bool getMovieTitle()
700 {
701 // grab meta data from movie
702 QTMetaDataRef media_data_ref;
703 OSErr result = QTCopyMovieMetaData( mMovieHandle, &media_data_ref );
704 if ( noErr != result )
705 return false;
706
707 // look up "Display Name" in meta data
708 OSType meta_data_key = kQTMetaDataCommonKeyDisplayName;
709 QTMetaDataItem item = kQTMetaDataItemUninitialized;
710 result = QTMetaDataGetNextItem( media_data_ref, kQTMetaDataStorageFormatWildcard,
711 0, kQTMetaDataKeyFormatCommon,
712 (const UInt8 *)&meta_data_key,
713 sizeof( meta_data_key ), &item );
714 if ( noErr != result )
715 return false;
716
717 // find the size of the title
718 ByteCount size;
719 result = QTMetaDataGetItemValue( media_data_ref, item, NULL, 0, &size );
720 if ( noErr != result || size <= 0 /*|| size > 1024 FIXME: arbitrary limit */ )
721 return false;
722
723 // allocate some space and grab it
724 UInt8* item_data = new UInt8( size + 1 );
725 memset( item_data, 0, ( size + 1 ) * sizeof( UInt8* ) );
726 result = QTMetaDataGetItemValue( media_data_ref, item, item_data, size, NULL );
727 if ( noErr != result )
728 {
729 delete [] item_data;
730 return false;
731 };
732
733 // save it
734 if ( strlen( (char*)item_data ) )
735 mMovieTitle = std::string( (char* )item_data );
736 else
737 mMovieTitle = "";
738
739 // clean up
740 delete [] item_data;
741
742 return true;
743 };
744
745 // called regularly to see if title changed
746 void checkTitle()
747 {
748 // we did already receive title so keep checking
749 if ( ! mReceivedTitle )
750 {
751 // grab title from movie meta data
752 if ( getMovieTitle() )
753 {
754 // pass back to host application
755 LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text");
756 message.setValue("name", mMovieTitle );
757 sendMessage( message );
758
759 // stop looking once we find a title for this movie.
760 // TODO: this may to be reset if movie title changes
761 // during playback but this is okay for now
762 mReceivedTitle = true;
763 };
764 };
765 };
646}; 766};
647 767
648MediaPluginQuickTime::MediaPluginQuickTime( 768MediaPluginQuickTime::MediaPluginQuickTime(
@@ -664,6 +784,8 @@ MediaPluginQuickTime::MediaPluginQuickTime(
664 mCurVolume = 0x99; 784 mCurVolume = 0x99;
665 mMediaSizeChanging = false; 785 mMediaSizeChanging = false;
666 mIsLooping = false; 786 mIsLooping = false;
787 mMovieTitle = std::string();
788 mReceivedTitle = false;
667 mCommand = COMMAND_NONE; 789 mCommand = COMMAND_NONE;
668 mPlayRate = 0.0f; 790 mPlayRate = 0.0f;
669 mStatus = STATUS_NONE; 791 mStatus = STATUS_NONE;
@@ -700,22 +822,29 @@ void MediaPluginQuickTime::receiveMessage(const char *message_string)
700 versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION; 822 versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION;
701 versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION; 823 versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION;
702 // Normally a plugin would only specify one of these two subclasses, but this is a demo... 824 // Normally a plugin would only specify one of these two subclasses, but this is a demo...
703// versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER] = LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER_VERSION;
704 versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME] = LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME_VERSION; 825 versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME] = LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME_VERSION;
705 message.setValueLLSD("versions", versions); 826 message.setValueLLSD("versions", versions);
706 827
707 #ifdef LL_WINDOWS 828 #ifdef LL_WINDOWS
708 if ( InitializeQTML( 0L ) != noErr ) 829
830 // QuickTime 7.6.4 has an issue (that was not present in 7.6.2) with initializing QuickTime
831 // according to this article: http://lists.apple.com/archives/QuickTime-API/2009/Sep/msg00097.html
832 // The solution presented there appears to work.
833 QTLoadLibrary("qtcf.dll");
834
835 // main initialization for QuickTime - only required on Windows
836 OSErr result = InitializeQTML( 0L );
837 if ( result != noErr )
709 { 838 {
710 //TODO: If no QT on Windows, this fails - respond accordingly. 839 //TODO: If no QT on Windows, this fails - respond accordingly.
711 //return false;
712 } 840 }
713 else 841 else
714 { 842 {
715// std::cerr << "QuickTime initialized" << std::endl; 843 //std::cerr << "QuickTime initialized" << std::endl;
716 }; 844 };
717 #endif 845 #endif
718 846
847 // required for both Windows and Mac
719 EnterMovies(); 848 EnterMovies();
720 849
721 std::string plugin_version = "QuickTime media plugin, QuickTime version "; 850 std::string plugin_version = "QuickTime media plugin, QuickTime version ";
@@ -773,10 +902,7 @@ void MediaPluginQuickTime::receiveMessage(const char *message_string)
773 else if(message_name == "shm_added") 902 else if(message_name == "shm_added")
774 { 903 {
775 SharedSegmentInfo info; 904 SharedSegmentInfo info;
776 U64 address_lo = message_in.getValueU32("address"); 905 info.mAddress = message_in.getValuePointer("address");
777 U64 address_hi = message_in.hasValue("address_1") ? message_in.getValueU32("address_1") : 0;
778 info.mAddress = (void*)((address_lo) |
779 (address_hi * (U64(1)<<31)));
780 info.mSize = (size_t)message_in.getValueS32("size"); 906 info.mSize = (size_t)message_in.getValueS32("size");
781 std::string name = message_in.getValue("name"); 907 std::string name = message_in.getValue("name");
782 908
diff --git a/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp b/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp
index f115c28..91efdae 100644
--- a/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp
+++ b/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp
@@ -75,6 +75,8 @@ public:
75 75
76private: 76private:
77 77
78 std::string mProfileDir;
79
78 enum 80 enum
79 { 81 {
80 INIT_STATE_UNINITIALIZED, // Browser instance hasn't been set up yet 82 INIT_STATE_UNINITIALIZED, // Browser instance hasn't been set up yet
@@ -95,6 +97,12 @@ private:
95 int mLastMouseY; 97 int mLastMouseY;
96 bool mFirstFocus; 98 bool mFirstFocus;
97 99
100 void setInitState(int state)
101 {
102// std::cerr << "changing init state to " << state << std::endl;
103 mInitState = state;
104 }
105
98 //////////////////////////////////////////////////////////////////////////////// 106 ////////////////////////////////////////////////////////////////////////////////
99 // 107 //
100 void update(int milliseconds) 108 void update(int milliseconds)
@@ -186,7 +194,6 @@ private:
186#else 194#else
187 std::string component_dir = application_dir; 195 std::string component_dir = application_dir;
188#endif 196#endif
189 std::string profileDir = application_dir + "/" + "browser_profile"; // cross platform?
190 197
191 // window handle - needed on Windows and must be app window. 198 // window handle - needed on Windows and must be app window.
192#if LL_WINDOWS 199#if LL_WINDOWS
@@ -198,7 +205,7 @@ private:
198#endif 205#endif
199 206
200 // main browser initialization 207 // main browser initialization
201 bool result = LLQtWebKit::getInstance()->init( application_dir, component_dir, profileDir, native_window_handle ); 208 bool result = LLQtWebKit::getInstance()->init( application_dir, component_dir, mProfileDir, native_window_handle );
202 if ( result ) 209 if ( result )
203 { 210 {
204 // create single browser window 211 // create single browser window
@@ -208,13 +215,15 @@ private:
208 // Enable plugins 215 // Enable plugins
209 LLQtWebKit::getInstance()->enablePlugins(true); 216 LLQtWebKit::getInstance()->enablePlugins(true);
210#elif LL_DARWIN 217#elif LL_DARWIN
211 // Disable plugins 218 // Enable plugins
212 LLQtWebKit::getInstance()->enablePlugins(false); 219 LLQtWebKit::getInstance()->enablePlugins(true);
213#elif LL_LINUX 220#elif LL_LINUX
214 // Disable plugins 221 // Enable plugins
215 LLQtWebKit::getInstance()->enablePlugins(false); 222 LLQtWebKit::getInstance()->enablePlugins(true);
216#endif 223#endif
217 224 // Enable cookies
225 LLQtWebKit::getInstance()->enableCookies( true );
226
218 // tell LLQtWebKit about the size of the browser window 227 // tell LLQtWebKit about the size of the browser window
219 LLQtWebKit::getInstance()->setSize( mBrowserWindowId, mWidth, mHeight ); 228 LLQtWebKit::getInstance()->setSize( mBrowserWindowId, mWidth, mHeight );
220 229
@@ -227,11 +236,11 @@ private:
227 // don't flip bitmap 236 // don't flip bitmap
228 LLQtWebKit::getInstance()->flipWindow( mBrowserWindowId, true ); 237 LLQtWebKit::getInstance()->flipWindow( mBrowserWindowId, true );
229 238
230 // Set the background color to black - mostly for initial login page 239 // set background color to be black - mostly for initial login page
231 LLQtWebKit::getInstance()->setBackgroundColor( mBrowserWindowId, 0x00, 0x00, 0x00 ); 240 LLQtWebKit::getInstance()->setBackgroundColor( mBrowserWindowId, 0x00, 0x00, 0x00 );
232 241
233 // Set state _before_ starting the navigate, since onNavigateBegin might get called before this call returns. 242 // Set state _before_ starting the navigate, since onNavigateBegin might get called before this call returns.
234 mInitState = INIT_STATE_NAVIGATING; 243 setInitState(INIT_STATE_NAVIGATING);
235 244
236 // Don't do this here -- it causes the dreaded "white flash" when loading a browser instance. 245 // Don't do this here -- it causes the dreaded "white flash" when loading a browser instance.
237 // FIXME: Re-added this because navigating to a "page" initializes things correctly - especially 246 // FIXME: Re-added this because navigating to a "page" initializes things correctly - especially
@@ -285,7 +294,7 @@ private:
285 { 294 {
286 if(mInitState == INIT_STATE_WAIT_REDRAW) 295 if(mInitState == INIT_STATE_WAIT_REDRAW)
287 { 296 {
288 mInitState = INIT_STATE_RUNNING; 297 setInitState(INIT_STATE_RUNNING);
289 } 298 }
290 299
291 // flag that an update is required 300 // flag that an update is required
@@ -307,7 +316,7 @@ private:
307 316
308 if(mInitState == INIT_STATE_NAVIGATE_COMPLETE) 317 if(mInitState == INIT_STATE_NAVIGATE_COMPLETE)
309 { 318 {
310 mInitState = INIT_STATE_WAIT_REDRAW; 319 setInitState(INIT_STATE_WAIT_REDRAW);
311 } 320 }
312 321
313 } 322 }
@@ -330,7 +339,7 @@ private:
330 } 339 }
331 else if(mInitState == INIT_STATE_NAVIGATING) 340 else if(mInitState == INIT_STATE_NAVIGATING)
332 { 341 {
333 mInitState = INIT_STATE_NAVIGATE_COMPLETE; 342 setInitState(INIT_STATE_NAVIGATE_COMPLETE);
334 } 343 }
335 344
336 } 345 }
@@ -495,7 +504,16 @@ private:
495 { 504 {
496// std::cerr << "unicode input, code = 0x" << std::hex << (unsigned long)(wstr[i]) << std::dec << std::endl; 505// std::cerr << "unicode input, code = 0x" << std::hex << (unsigned long)(wstr[i]) << std::dec << std::endl;
497 506
498 LLQtWebKit::getInstance()->unicodeInput(mBrowserWindowId, wstr[i], modifiers); 507 if(wstr[i] == 32)
508 {
509 // For some reason, the webkit plugin really wants the space bar to come in through the key-event path, not the unicode path.
510 LLQtWebKit::getInstance()->keyEvent( mBrowserWindowId, LLQtWebKit::KE_KEY_DOWN, 32, modifiers);
511 LLQtWebKit::getInstance()->keyEvent( mBrowserWindowId, LLQtWebKit::KE_KEY_UP, 32, modifiers);
512 }
513 else
514 {
515 LLQtWebKit::getInstance()->unicodeInput(mBrowserWindowId, wstr[i], modifiers);
516 }
499 } 517 }
500 518
501 checkEditState(); 519 checkEditState();
@@ -576,6 +594,9 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)
576 { 594 {
577 if(message_name == "init") 595 if(message_name == "init")
578 { 596 {
597 std::string user_data_path = message_in.getValue("user_data_path"); // n.b. always has trailing platform-specific dir-delimiter
598 mProfileDir = user_data_path + "browser_profile";
599
579 LLPluginMessage message("base", "init_response"); 600 LLPluginMessage message("base", "init_response");
580 LLSD versions = LLSD::emptyMap(); 601 LLSD versions = LLSD::emptyMap();
581 versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION; 602 versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION;
@@ -611,7 +632,11 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)
611 } 632 }
612 else if(message_name == "cleanup") 633 else if(message_name == "cleanup")
613 { 634 {
614 // TODO: clean up here 635 // DTOR most likely won't be called but the recent change to the way this process
636 // is (not) killed means we see this message and can do what we need to here.
637 // Note: this cleanup is ultimately what writes cookies to the disk
638 LLQtWebKit::getInstance()->remObserver( mBrowserWindowId, this );
639 LLQtWebKit::getInstance()->reset();
615 } 640 }
616 else if(message_name == "shm_added") 641 else if(message_name == "shm_added")
617 { 642 {
diff --git a/linden/indra/newview/llviewerparcelmedia.cpp b/linden/indra/newview/llviewerparcelmedia.cpp
index c7f0c4b..d4ebbd9 100644
--- a/linden/indra/newview/llviewerparcelmedia.cpp
+++ b/linden/indra/newview/llviewerparcelmedia.cpp
@@ -193,6 +193,9 @@ void LLViewerParcelMedia::play(LLParcel* parcel)
193 S32 media_width = parcel->getMediaWidth(); 193 S32 media_width = parcel->getMediaWidth();
194 S32 media_height = parcel->getMediaHeight(); 194 S32 media_height = parcel->getMediaHeight();
195 195
196 // Debug print
197 // LL_DEBUGS("Media") << "Play media type : " << mime_type << ", url : " << media_url << LL_ENDL;
198
196 if(sMediaImpl) 199 if(sMediaImpl)
197 { 200 {
198 // If the url and mime type are the same, call play again 201 // If the url and mime type are the same, call play again
@@ -221,7 +224,7 @@ void LLViewerParcelMedia::play(LLParcel* parcel)
221 224
222 sMediaImpl = LLViewerMedia::newMediaImpl(media_url, placeholder_texture_id, 225 sMediaImpl = LLViewerMedia::newMediaImpl(media_url, placeholder_texture_id,
223 media_width, media_height, media_auto_scale, 226 media_width, media_height, media_auto_scale,
224 media_loop); 227 media_loop, mime_type);
225 } 228 }
226 } 229 }
227 else 230 else
@@ -229,7 +232,7 @@ void LLViewerParcelMedia::play(LLParcel* parcel)
229 // There is no media impl, make a new one 232 // There is no media impl, make a new one
230 sMediaImpl = LLViewerMedia::newMediaImpl(media_url, placeholder_texture_id, 233 sMediaImpl = LLViewerMedia::newMediaImpl(media_url, placeholder_texture_id,
231 media_width, media_height, media_auto_scale, 234 media_width, media_height, media_auto_scale,
232 media_loop); 235 media_loop, mime_type);
233 } 236 }
234 237
235 238