diff options
Diffstat (limited to 'linden/indra/newview/llviewermedia.cpp')
-rw-r--r-- | linden/indra/newview/llviewermedia.cpp | 1451 |
1 files changed, 985 insertions, 466 deletions
diff --git a/linden/indra/newview/llviewermedia.cpp b/linden/indra/newview/llviewermedia.cpp index 6bcf8ce..5c01b25 100644 --- a/linden/indra/newview/llviewermedia.cpp +++ b/linden/indra/newview/llviewermedia.cpp | |||
@@ -33,687 +33,1206 @@ | |||
33 | #include "llviewerprecompiledheaders.h" | 33 | #include "llviewerprecompiledheaders.h" |
34 | 34 | ||
35 | #include "llviewermedia.h" | 35 | #include "llviewermedia.h" |
36 | 36 | #include "llviewermediafocus.h" | |
37 | #include "llhoverview.h" | ||
37 | #include "llmimetypes.h" | 38 | #include "llmimetypes.h" |
38 | #include "llviewercontrol.h" | 39 | #include "llviewercontrol.h" |
39 | #include "llviewerimage.h" | 40 | #include "llviewerimage.h" |
40 | #include "llviewerwindow.h" | 41 | #include "llviewerwindow.h" |
41 | #include "llviewerimagelist.h" | 42 | #include "llviewerimagelist.h" |
42 | #include "viewerversion.h" | 43 | //#include "viewerversion.h" |
44 | |||
45 | #include "llpluginclassmedia.h" | ||
43 | 46 | ||
44 | #include "llevent.h" // LLSimpleListener | 47 | #include "llevent.h" // LLSimpleListener |
45 | #include "llmediamanager.h" | ||
46 | #include "lluuid.h" | 48 | #include "lluuid.h" |
49 | #include "llkeyboard.h" | ||
47 | 50 | ||
48 | #include <boost/bind.hpp> // for SkinFolder listener | ||
49 | #include <boost/signal.hpp> | ||
50 | 51 | ||
52 | // Merov: Temporary definitions while porting the new viewer media code to Snowglobe | ||
53 | const int LEFT_BUTTON = 0; | ||
54 | const int RIGHT_BUTTON = 1; | ||
51 | 55 | ||
52 | // Implementation functions not exported into header file | 56 | // Move this to its own file. |
53 | class LLViewerMediaImpl | 57 | |
54 | : public LLMediaObserver | 58 | LLViewerMediaEventEmitter::~LLViewerMediaEventEmitter() |
55 | { | 59 | { |
56 | public: | 60 | observerListType::iterator iter = mObservers.begin(); |
57 | LLViewerMediaImpl() | ||
58 | : mMediaSource( NULL ), | ||
59 | mMovieImageID(), | ||
60 | mMovieImageHasMips(false) | ||
61 | { } | ||
62 | |||
63 | void destroyMediaSource(); | ||
64 | |||
65 | void play(const std::string& media_url, | ||
66 | const std::string& mime_type, | ||
67 | const LLUUID& placeholder_texture_id, | ||
68 | S32 media_width, S32 media_height, U8 media_auto_scale, | ||
69 | U8 media_loop); | ||
70 | |||
71 | void stop(); | ||
72 | void pause(); | ||
73 | void start(); | ||
74 | void seek(F32 time); | ||
75 | void setVolume(F32 volume); | ||
76 | LLMediaBase::EStatus getStatus(); | ||
77 | |||
78 | /*virtual*/ void onMediaSizeChange(const EventType& event_in); | ||
79 | /*virtual*/ void onMediaContentsChange(const EventType& event_in); | ||
80 | |||
81 | void updateMovieImage(const LLUUID& image_id, BOOL active); | ||
82 | void updateImagesMediaStreams(); | ||
83 | LLUUID getMediaTextureID(); | ||
84 | |||
85 | // Internally set our desired browser user agent string, including | ||
86 | // the Second Life version and skin name. Used because we can | ||
87 | // switch skins without restarting the app. | ||
88 | static void updateBrowserUserAgent(); | ||
89 | |||
90 | // Callback for when the SkinCurrent control is changed to | ||
91 | // switch the user agent string to indicate the new skin. | ||
92 | static bool handleSkinCurrentChanged(const LLSD& newvalue); | ||
93 | 61 | ||
94 | public: | 62 | while( iter != mObservers.end() ) |
63 | { | ||
64 | LLViewerMediaObserver *self = *iter; | ||
65 | iter++; | ||
66 | remObserver(self); | ||
67 | } | ||
68 | } | ||
95 | 69 | ||
96 | // a single media url with some data and an impl. | 70 | /////////////////////////////////////////////////////////////////////////////// |
97 | LLMediaBase* mMediaSource; | 71 | // |
98 | LLUUID mMovieImageID; | 72 | bool LLViewerMediaEventEmitter::addObserver( LLViewerMediaObserver* observer ) |
99 | bool mMovieImageHasMips; | 73 | { |
100 | std::string mMediaURL; | 74 | if ( ! observer ) |
101 | std::string mMimeType; | 75 | return false; |
102 | private: | ||
103 | void initializePlaceholderImage(LLViewerImage *placeholder_image, LLMediaBase *media_source); | ||
104 | }; | ||
105 | 76 | ||
106 | static LLViewerMediaImpl sViewerMediaImpl; | 77 | if ( std::find( mObservers.begin(), mObservers.end(), observer ) != mObservers.end() ) |
78 | return false; | ||
107 | 79 | ||
108 | ////////////////////////////////////////////////////////////////////////////////////////// | 80 | mObservers.push_back( observer ); |
81 | observer->mEmitters.push_back( this ); | ||
109 | 82 | ||
110 | void LLViewerMediaImpl::destroyMediaSource() | 83 | return true; |
84 | } | ||
85 | |||
86 | /////////////////////////////////////////////////////////////////////////////// | ||
87 | // | ||
88 | bool LLViewerMediaEventEmitter::remObserver( LLViewerMediaObserver* observer ) | ||
89 | { | ||
90 | if ( ! observer ) | ||
91 | return false; | ||
92 | |||
93 | mObservers.remove( observer ); | ||
94 | observer->mEmitters.remove(this); | ||
95 | |||
96 | return true; | ||
97 | } | ||
98 | |||
99 | /////////////////////////////////////////////////////////////////////////////// | ||
100 | // | ||
101 | void LLViewerMediaEventEmitter::emitEvent( LLPluginClassMedia* media, LLPluginClassMediaOwner::EMediaEvent event ) | ||
111 | { | 102 | { |
112 | LLMediaManager* mgr = LLMediaManager::getInstance(); | 103 | observerListType::iterator iter = mObservers.begin(); |
113 | if ( mMediaSource ) | 104 | |
105 | while( iter != mObservers.end() ) | ||
114 | { | 106 | { |
115 | bool was_playing = LLViewerMedia::isMediaPlaying(); | 107 | LLViewerMediaObserver *self = *iter; |
116 | mMediaSource->remObserver(this); | 108 | ++iter; |
117 | mgr->destroySource( mMediaSource ); | 109 | self->handleMediaEvent( media, event ); |
110 | } | ||
111 | } | ||
118 | 112 | ||
119 | // Restore the texture | 113 | // Move this to its own file. |
120 | updateMovieImage(LLUUID::null, was_playing); | 114 | LLViewerMediaObserver::~LLViewerMediaObserver() |
115 | { | ||
116 | std::list<LLViewerMediaEventEmitter *>::iterator iter = mEmitters.begin(); | ||
121 | 117 | ||
118 | while( iter != mEmitters.end() ) | ||
119 | { | ||
120 | LLViewerMediaEventEmitter *self = *iter; | ||
121 | iter++; | ||
122 | self->remObserver( this ); | ||
122 | } | 123 | } |
123 | mMediaSource = NULL; | ||
124 | } | 124 | } |
125 | 125 | ||
126 | void LLViewerMediaImpl::play(const std::string& media_url, | 126 | |
127 | const std::string& mime_type, | 127 | // Move this to its own file. |
128 | const LLUUID& placeholder_texture_id, | 128 | // helper class that tries to download a URL from a web site and calls a method |
129 | S32 media_width, S32 media_height, U8 media_auto_scale, | 129 | // on the Panel Land Media and to discover the MIME type |
130 | U8 media_loop) | 130 | class LLMimeDiscoveryResponder : public LLHTTPClient::Responder |
131 | { | 131 | { |
132 | // first stop any previously playing media | 132 | LOG_CLASS(LLMimeDiscoveryResponder); |
133 | stop(); | 133 | public: |
134 | LLMimeDiscoveryResponder( viewer_media_t media_impl) | ||
135 | : mMediaImpl(media_impl), | ||
136 | mInitialized(false) | ||
137 | {} | ||
138 | |||
134 | 139 | ||
135 | // Save this first, as init/load below may fire events | ||
136 | mMovieImageID = placeholder_texture_id; | ||
137 | 140 | ||
138 | // If the mime_type passed in is different than the cached one, and | 141 | virtual void completedHeader(U32 status, const std::string& reason, const LLSD& content) |
139 | // Auto-discovery is turned OFF, replace the cached mime_type with the new one. | 142 | { |
140 | if(mime_type != mMimeType && | 143 | std::string media_type = content["content-type"].asString(); |
141 | ! gSavedSettings.getBOOL("AutoMimeDiscovery")) | 144 | std::string::size_type idx1 = media_type.find_first_of(";"); |
145 | std::string mime_type = media_type.substr(0, idx1); | ||
146 | completeAny(status, mime_type); | ||
147 | } | ||
148 | |||
149 | virtual void error( U32 status, const std::string& reason ) | ||
142 | { | 150 | { |
143 | mMimeType = mime_type; | 151 | // completeAny(status, "none/none"); |
144 | } | 152 | } |
145 | LLURI url(media_url); | ||
146 | std::string scheme = url.scheme() != "" ? url.scheme() : "http"; | ||
147 | 153 | ||
148 | LLMediaManager* mgr = LLMediaManager::getInstance(); | 154 | void completeAny(U32 status, const std::string& mime_type) |
149 | mMediaSource = mgr->createSourceFromMimeType(scheme, mMimeType ); | ||
150 | if ( !mMediaSource ) | ||
151 | { | 155 | { |
152 | if (mMimeType != "none/none") | 156 | if(!mInitialized && ! mime_type.empty()) |
153 | { | 157 | { |
154 | llwarns << "media source create failed " << media_url | 158 | if (mMediaImpl->initializeMedia(mime_type)) |
155 | << " type " << mMimeType | 159 | { |
156 | << llendl; | 160 | mInitialized = true; |
161 | mMediaImpl->play(); | ||
162 | } | ||
157 | } | 163 | } |
158 | return; | ||
159 | } | 164 | } |
160 | 165 | ||
161 | // Store the URL and Mime Type | 166 | public: |
162 | mMediaURL = media_url; | 167 | viewer_media_t mMediaImpl; |
168 | bool mInitialized; | ||
169 | }; | ||
170 | typedef std::list<LLViewerMediaImpl*> impl_list; | ||
171 | static impl_list sViewerMediaImplList; | ||
172 | |||
173 | ////////////////////////////////////////////////////////////////////////////////////////// | ||
174 | // LLViewerMedia | ||
163 | 175 | ||
164 | if ((media_width != 0) && (media_height != 0)) | 176 | ////////////////////////////////////////////////////////////////////////////////////////// |
177 | // static | ||
178 | viewer_media_t LLViewerMedia::newMediaImpl(const std::string& media_url, | ||
179 | const LLUUID& texture_id, | ||
180 | S32 media_width, S32 media_height, U8 media_auto_scale, | ||
181 | U8 media_loop, | ||
182 | std::string mime_type) | ||
183 | { | ||
184 | LLViewerMediaImpl* media_impl = getMediaImplFromTextureID(texture_id); | ||
185 | if(media_impl == NULL || texture_id.isNull()) | ||
165 | { | 186 | { |
166 | mMediaSource->setRequestedMediaSize(media_width, media_height); | 187 | // Create the media impl |
188 | media_impl = new LLViewerMediaImpl(media_url, texture_id, media_width, media_height, media_auto_scale, media_loop, mime_type); | ||
189 | sViewerMediaImplList.push_back(media_impl); | ||
167 | } | 190 | } |
168 | 191 | else | |
169 | mMediaSource->setLooping(media_loop); | 192 | { |
170 | mMediaSource->setAutoScaled(media_auto_scale); | 193 | media_impl->stop(); |
171 | mMediaSource->addObserver( this ); | 194 | media_impl->mTextureId = texture_id; |
172 | mMediaSource->navigateTo( media_url ); | 195 | media_impl->mMediaURL = media_url; |
173 | mMediaSource->addCommand(LLMediaBase::COMMAND_START); | 196 | media_impl->mMediaWidth = media_width; |
197 | media_impl->mMediaHeight = media_height; | ||
198 | media_impl->mMediaAutoScale = media_auto_scale; | ||
199 | media_impl->mMediaLoop = media_loop; | ||
200 | if(! media_url.empty()) | ||
201 | media_impl->navigateTo(media_url, mime_type, true); | ||
202 | } | ||
203 | return media_impl; | ||
174 | } | 204 | } |
175 | 205 | ||
176 | void LLViewerMediaImpl::stop() | 206 | ////////////////////////////////////////////////////////////////////////////////////////// |
207 | // static | ||
208 | void LLViewerMedia::removeMedia(LLViewerMediaImpl* media) | ||
177 | { | 209 | { |
178 | destroyMediaSource(); | 210 | impl_list::iterator iter = sViewerMediaImplList.begin(); |
211 | impl_list::iterator end = sViewerMediaImplList.end(); | ||
212 | |||
213 | for(; iter != end; iter++) | ||
214 | { | ||
215 | if(media == *iter) | ||
216 | { | ||
217 | sViewerMediaImplList.erase(iter); | ||
218 | return; | ||
219 | } | ||
220 | } | ||
179 | } | 221 | } |
180 | 222 | ||
181 | void LLViewerMediaImpl::pause() | 223 | ////////////////////////////////////////////////////////////////////////////////////////// |
224 | // static | ||
225 | LLViewerMediaImpl* LLViewerMedia::getMediaImplFromTextureID(const LLUUID& texture_id) | ||
182 | { | 226 | { |
183 | if(mMediaSource) | 227 | impl_list::iterator iter = sViewerMediaImplList.begin(); |
228 | impl_list::iterator end = sViewerMediaImplList.end(); | ||
229 | |||
230 | for(; iter != end; iter++) | ||
184 | { | 231 | { |
185 | mMediaSource->addCommand(LLMediaBase::COMMAND_PAUSE); | 232 | LLViewerMediaImpl* media_impl = *iter; |
233 | if(media_impl->getMediaTextureID() == texture_id) | ||
234 | { | ||
235 | return media_impl; | ||
236 | } | ||
186 | } | 237 | } |
238 | return NULL; | ||
187 | } | 239 | } |
188 | 240 | ||
189 | void LLViewerMediaImpl::start() | 241 | ////////////////////////////////////////////////////////////////////////////////////////// |
242 | // static | ||
243 | std::string LLViewerMedia::getCurrentUserAgent() | ||
190 | { | 244 | { |
191 | if(mMediaSource) | 245 | // Don't include version, channel, or skin -- MC |
246 | |||
247 | // Don't use user-visible string to avoid | ||
248 | // punctuation and strange characters. | ||
249 | //std::string skin_name = gSavedSettings.getString("SkinCurrent"); | ||
250 | |||
251 | // Just in case we need to check browser differences in A/B test | ||
252 | // builds. | ||
253 | //std::string channel = gSavedSettings.getString("VersionChannelName"); | ||
254 | |||
255 | // append our magic version number string to the browser user agent id | ||
256 | // See the HTTP 1.0 and 1.1 specifications for allowed formats: | ||
257 | // http://www.ietf.org/rfc/rfc1945.txt section 10.15 | ||
258 | // http://www.ietf.org/rfc/rfc2068.txt section 3.8 | ||
259 | // This was also helpful: | ||
260 | // http://www.mozilla.org/build/revised-user-agent-strings.html | ||
261 | std::ostringstream codec; | ||
262 | codec << "SecondLife/"; | ||
263 | codec << "C64 Basic V2"; | ||
264 | //codec << ViewerVersion::getImpMajorVersion() << "." << ViewerVersion::getImpMinorVersion() << "." << ViewerVersion::getImpPatchVersion() << " " << ViewerVersion::getImpTestVersion(); | ||
265 | //codec << " (" << channel << "; " << skin_name << " skin)"; | ||
266 | // llinfos << codec.str() << llendl; | ||
267 | |||
268 | return codec.str(); | ||
269 | } | ||
270 | |||
271 | ////////////////////////////////////////////////////////////////////////////////////////// | ||
272 | // static | ||
273 | void LLViewerMedia::updateBrowserUserAgent() | ||
274 | { | ||
275 | std::string user_agent = getCurrentUserAgent(); | ||
276 | |||
277 | impl_list::iterator iter = sViewerMediaImplList.begin(); | ||
278 | impl_list::iterator end = sViewerMediaImplList.end(); | ||
279 | |||
280 | for(; iter != end; iter++) | ||
192 | { | 281 | { |
193 | mMediaSource->addCommand(LLMediaBase::COMMAND_START); | 282 | LLViewerMediaImpl* pimpl = *iter; |
283 | if(pimpl->mMediaSource && pimpl->mMediaSource->pluginSupportsMediaBrowser()) | ||
284 | { | ||
285 | pimpl->mMediaSource->setBrowserUserAgent(user_agent); | ||
286 | } | ||
194 | } | 287 | } |
288 | |||
195 | } | 289 | } |
196 | 290 | ||
197 | void LLViewerMediaImpl::seek(F32 time) | 291 | ////////////////////////////////////////////////////////////////////////////////////////// |
292 | // static | ||
293 | bool LLViewerMedia::handleSkinCurrentChanged(const LLSD& /*newvalue*/) | ||
198 | { | 294 | { |
199 | if(mMediaSource) | 295 | // gSavedSettings is already updated when this function is called. |
296 | updateBrowserUserAgent(); | ||
297 | return true; | ||
298 | } | ||
299 | |||
300 | ////////////////////////////////////////////////////////////////////////////////////////// | ||
301 | // static | ||
302 | bool LLViewerMedia::textureHasMedia(const LLUUID& texture_id) | ||
303 | { | ||
304 | impl_list::iterator iter = sViewerMediaImplList.begin(); | ||
305 | impl_list::iterator end = sViewerMediaImplList.end(); | ||
306 | |||
307 | for(; iter != end; iter++) | ||
200 | { | 308 | { |
201 | mMediaSource->seek(time); | 309 | LLViewerMediaImpl* pimpl = *iter; |
310 | if(pimpl->getMediaTextureID() == texture_id) | ||
311 | { | ||
312 | return true; | ||
313 | } | ||
202 | } | 314 | } |
315 | return false; | ||
203 | } | 316 | } |
204 | 317 | ||
205 | void LLViewerMediaImpl::setVolume(F32 volume) | 318 | ////////////////////////////////////////////////////////////////////////////////////////// |
319 | // static | ||
320 | void LLViewerMedia::setVolume(F32 volume) | ||
206 | { | 321 | { |
207 | if(mMediaSource) | 322 | impl_list::iterator iter = sViewerMediaImplList.begin(); |
323 | impl_list::iterator end = sViewerMediaImplList.end(); | ||
324 | |||
325 | for(; iter != end; iter++) | ||
208 | { | 326 | { |
209 | mMediaSource->setVolume( volume); | 327 | LLViewerMediaImpl* pimpl = *iter; |
328 | pimpl->setVolume(volume); | ||
210 | } | 329 | } |
211 | } | 330 | } |
212 | 331 | ||
213 | LLMediaBase::EStatus LLViewerMediaImpl::getStatus() | 332 | ////////////////////////////////////////////////////////////////////////////////////////// |
333 | // static | ||
334 | void LLViewerMedia::updateMedia() | ||
214 | { | 335 | { |
215 | if (mMediaSource) | 336 | impl_list::iterator iter = sViewerMediaImplList.begin(); |
337 | impl_list::iterator end = sViewerMediaImplList.end(); | ||
338 | |||
339 | for(; iter != end; iter++) | ||
216 | { | 340 | { |
217 | return mMediaSource->getStatus(); | 341 | LLViewerMediaImpl* pimpl = *iter; |
342 | pimpl->update(); | ||
218 | } | 343 | } |
219 | else | 344 | } |
345 | |||
346 | ////////////////////////////////////////////////////////////////////////////////////////// | ||
347 | // static | ||
348 | void LLViewerMedia::cleanupClass() | ||
349 | { | ||
350 | // This is no longer necessary, since the list is no longer smart pointers. | ||
351 | #if 0 | ||
352 | while(!sViewerMediaImplList.empty()) | ||
220 | { | 353 | { |
221 | return LLMediaBase::STATUS_UNKNOWN; | 354 | sViewerMediaImplList.pop_back(); |
222 | } | 355 | } |
356 | #endif | ||
223 | } | 357 | } |
224 | 358 | ||
225 | ////////////////////////////////////////////////////////////////////////////////////////// | 359 | ////////////////////////////////////////////////////////////////////////////////////////// |
226 | // static | 360 | // LLViewerMediaImpl |
227 | void LLViewerMediaImpl::updateMovieImage(const LLUUID& uuid, BOOL active) | 361 | ////////////////////////////////////////////////////////////////////////////////////////// |
362 | LLViewerMediaImpl::LLViewerMediaImpl(const std::string& media_url, | ||
363 | const LLUUID& texture_id, | ||
364 | S32 media_width, | ||
365 | S32 media_height, | ||
366 | U8 media_auto_scale, | ||
367 | U8 media_loop, | ||
368 | const std::string& mime_type) | ||
369 | : | ||
370 | mMediaSource( NULL ), | ||
371 | mMovieImageHasMips(false), | ||
372 | mTextureId(texture_id), | ||
373 | mMediaWidth(media_width), | ||
374 | mMediaHeight(media_height), | ||
375 | mMediaAutoScale(media_auto_scale), | ||
376 | mMediaLoop(media_loop), | ||
377 | mMediaURL(media_url), | ||
378 | mMimeType(mime_type), | ||
379 | mNeedsNewTexture(true), | ||
380 | mSuspendUpdates(false), | ||
381 | mVisible(true) | ||
382 | { | ||
383 | createMediaSource(); | ||
384 | } | ||
385 | |||
386 | ////////////////////////////////////////////////////////////////////////////////////////// | ||
387 | LLViewerMediaImpl::~LLViewerMediaImpl() | ||
228 | { | 388 | { |
229 | // IF the media image hasn't changed, do nothing | 389 | if( gEditMenuHandler == this ) |
230 | if (mMovieImageID == uuid) | ||
231 | { | 390 | { |
232 | return; | 391 | gEditMenuHandler = NULL; |
233 | } | 392 | } |
234 | // If we have changed media uuid, restore the old one | 393 | |
235 | if (!mMovieImageID.isNull()) | 394 | destroyMediaSource(); |
395 | LLViewerMedia::removeMedia(this); | ||
396 | } | ||
397 | |||
398 | ////////////////////////////////////////////////////////////////////////////////////////// | ||
399 | bool LLViewerMediaImpl::initializeMedia(const std::string& mime_type) | ||
400 | { | ||
401 | if((mMediaSource == NULL) || (mMimeType != mime_type)) | ||
236 | { | 402 | { |
237 | LLViewerImage* oldImage = LLViewerImage::getImage( mMovieImageID ); | 403 | if(! initializePlugin(mime_type)) |
238 | if (oldImage) | ||
239 | { | 404 | { |
240 | oldImage->reinit(mMovieImageHasMips); | 405 | LL_WARNS("Plugin") << "plugin intialization failed for mime type: " << mime_type << LL_ENDL; |
241 | oldImage->mIsMediaTexture = FALSE; | 406 | LLSD args; |
407 | args["MIME_TYPE"] = mime_type; | ||
408 | LLNotifications::instance().add("NoPlugin", args); | ||
409 | |||
410 | return false; | ||
242 | } | 411 | } |
243 | mMovieImageID.setNull(); | ||
244 | } | 412 | } |
245 | // If the movie is playing, set the new media image | 413 | |
246 | if (active && !uuid.isNull()) | 414 | // play(); |
415 | return (mMediaSource != NULL); | ||
416 | } | ||
417 | |||
418 | ////////////////////////////////////////////////////////////////////////////////////////// | ||
419 | void LLViewerMediaImpl::createMediaSource() | ||
420 | { | ||
421 | if(! mMediaURL.empty()) | ||
247 | { | 422 | { |
248 | LLViewerImage* viewerImage = LLViewerImage::getImage( uuid ); | 423 | navigateTo(mMediaURL, mMimeType, true); |
249 | if( viewerImage ) | 424 | } |
250 | { | 425 | else if(! mMimeType.empty()) |
251 | mMovieImageID = uuid; | 426 | { |
252 | // Can't use mipmaps for movies because they don't update the full image | 427 | initializeMedia(mMimeType); |
253 | mMovieImageHasMips = viewerImage->getUseMipMaps(); | ||
254 | viewerImage->reinit(FALSE); | ||
255 | viewerImage->mIsMediaTexture = TRUE; | ||
256 | } | ||
257 | } | 428 | } |
429 | |||
258 | } | 430 | } |
259 | 431 | ||
432 | ////////////////////////////////////////////////////////////////////////////////////////// | ||
433 | void LLViewerMediaImpl::destroyMediaSource() | ||
434 | { | ||
435 | mNeedsNewTexture = true; | ||
436 | if(! mMediaSource) | ||
437 | { | ||
438 | return; | ||
439 | } | ||
440 | // Restore the texture | ||
441 | updateMovieImage(LLUUID::null, false); | ||
442 | delete mMediaSource; | ||
443 | mMediaSource = NULL; | ||
444 | } | ||
260 | 445 | ||
261 | ////////////////////////////////////////////////////////////////////////////////////////// | 446 | ////////////////////////////////////////////////////////////////////////////////////////// |
262 | // static | 447 | void LLViewerMediaImpl::setMediaType(const std::string& media_type) |
263 | void LLViewerMediaImpl::updateImagesMediaStreams() | ||
264 | { | 448 | { |
265 | LLMediaManager::updateClass(); | 449 | mMimeType = media_type; |
266 | } | 450 | } |
267 | 451 | ||
268 | void LLViewerMediaImpl::initializePlaceholderImage(LLViewerImage *placeholder_image, LLMediaBase *media_source) | 452 | ////////////////////////////////////////////////////////////////////////////////////////// |
453 | /*static*/ | ||
454 | LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height) | ||
269 | { | 455 | { |
270 | int media_width = media_source->getMediaWidth(); | 456 | std::string plugin_basename = LLMIMETypes::implType(media_type); |
271 | int media_height = media_source->getMediaHeight(); | ||
272 | //int media_rowspan = media_source->getMediaRowSpan(); | ||
273 | 457 | ||
274 | // if width & height are invalid, don't bother doing anything | 458 | if(plugin_basename.empty()) |
275 | if ( media_width < 1 || media_height < 1 ) | 459 | { |
276 | return; | 460 | LL_WARNS("Media") << "Couldn't find plugin for media type " << media_type << LL_ENDL; |
461 | } | ||
462 | else | ||
463 | { | ||
464 | std::string launcher_name = gDirUtilp->getLLPluginLauncher(); | ||
465 | std::string plugin_name = gDirUtilp->getLLPluginFilename(plugin_basename); | ||
466 | std::string user_data_path = gDirUtilp->getOSUserAppDir(); | ||
467 | user_data_path += gDirUtilp->getDirDelimiter(); | ||
468 | |||
469 | // Fix for EXT-5960 - make browser profile specific to user (cache, cookies etc.) | ||
470 | // If the linden username returned is blank, that can only mean we are | ||
471 | // at the login page displaying login Web page or Web browser test via Develop menu. | ||
472 | // In this case we just use whatever gDirUtilp->getOSUserAppDir() gives us (this | ||
473 | // is what we always used before this change) | ||
474 | std::string linden_user_dir = gDirUtilp->getLindenUserDir(true); | ||
475 | if ( ! linden_user_dir.empty() ) | ||
476 | { | ||
477 | // gDirUtilp->getLindenUserDir() is whole path, not just Linden name | ||
478 | user_data_path = linden_user_dir; | ||
479 | user_data_path += gDirUtilp->getDirDelimiter(); | ||
480 | } | ||
277 | 481 | ||
278 | llinfos << "initializing media placeholder" << llendl; | 482 | // See if the plugin executable exists |
279 | llinfos << "movie image id " << mMovieImageID << llendl; | 483 | llstat s; |
484 | if(LLFile::stat(launcher_name, &s)) | ||
485 | { | ||
486 | LL_WARNS("Media") << "Couldn't find launcher at " << launcher_name << LL_ENDL; | ||
487 | } | ||
488 | else if(LLFile::stat(plugin_name, &s)) | ||
489 | { | ||
490 | LL_WARNS("Media") << "Couldn't find plugin at " << plugin_name << LL_ENDL; | ||
491 | } | ||
492 | else | ||
493 | { | ||
494 | LLPluginClassMedia* media_source = new LLPluginClassMedia(owner); | ||
495 | media_source->setSize(default_width, default_height); | ||
496 | media_source->setUserDataPath(user_data_path); | ||
497 | media_source->setLanguageCode(LLUI::getLanguage()); | ||
280 | 498 | ||
281 | int texture_width = LLMediaManager::textureWidthFromMediaWidth( media_width ); | 499 | // collect 'cookies enabled' setting from prefs and send to embedded browser |
282 | int texture_height = LLMediaManager::textureHeightFromMediaHeight( media_height ); | 500 | bool cookies_enabled = gSavedSettings.getBOOL( "BrowserCookiesEnabled" ); |
283 | int texture_depth = media_source->getMediaDepth(); | 501 | media_source->enable_cookies( cookies_enabled ); |
284 | 502 | ||
285 | // MEDIAOPT: check to see if size actually changed before doing work | 503 | // collect 'plugins enabled' setting from prefs and send to embedded browser |
286 | placeholder_image->destroyGLTexture(); | 504 | bool plugins_enabled = gSavedSettings.getBOOL( "BrowserPluginsEnabled" ); |
287 | // MEDIAOPT: apparently just calling setUseMipMaps(FALSE) doesn't work? | 505 | media_source->setPluginsEnabled( plugins_enabled ); |
288 | placeholder_image->reinit(FALSE); // probably not needed | ||
289 | 506 | ||
290 | // MEDIAOPT: seems insane that we actually have to make an imageraw then | 507 | // collect 'javascript enabled' setting from prefs and send to embedded browser |
291 | // immediately discard it | 508 | bool javascript_enabled = gSavedSettings.getBOOL( "BrowserJavascriptEnabled" ); |
292 | LLPointer<LLImageRaw> raw = new LLImageRaw(texture_width, texture_height, texture_depth); | 509 | media_source->setJavascriptEnabled( javascript_enabled ); |
293 | raw->clear(0x0f, 0x0f, 0x0f, 0xff); | ||
294 | int discard_level = 0; | ||
295 | 510 | ||
296 | // ask media source for correct GL image format constants | 511 | if (media_source->init(launcher_name, plugin_name, gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins"))) |
297 | placeholder_image->setExplicitFormat(media_source->getTextureFormatInternal(), | 512 | { |
298 | media_source->getTextureFormatPrimary(), | 513 | return media_source; |
299 | media_source->getTextureFormatType()); | 514 | } |
515 | else | ||
516 | { | ||
517 | LL_WARNS("Media") << "Failed to init plugin. Destroying." << LL_ENDL; | ||
518 | delete media_source; | ||
519 | } | ||
520 | } | ||
521 | } | ||
300 | 522 | ||
301 | placeholder_image->createGLTexture(discard_level, raw); | 523 | LL_WARNS("Plugin") << "plugin intialization failed for mime type: " << media_type << LL_ENDL; |
524 | LLSD args; | ||
525 | args["MIME_TYPE"] = media_type; | ||
526 | LLNotifications::instance().add("NoPlugin", args); | ||
302 | 527 | ||
303 | // placeholder_image->setExplicitFormat() | 528 | return NULL; |
304 | placeholder_image->setUseMipMaps(FALSE); | 529 | } |
305 | 530 | ||
306 | // MEDIAOPT: set this dynamically on play/stop | 531 | ////////////////////////////////////////////////////////////////////////////////////////// |
307 | placeholder_image->mIsMediaTexture = true; | 532 | bool LLViewerMediaImpl::initializePlugin(const std::string& media_type) |
308 | } | 533 | { |
534 | if(mMediaSource) | ||
535 | { | ||
536 | // Save the previous media source's last set size before destroying it. | ||
537 | mMediaWidth = mMediaSource->getSetWidth(); | ||
538 | mMediaHeight = mMediaSource->getSetHeight(); | ||
539 | } | ||
540 | |||
541 | // Always delete the old media impl first. | ||
542 | destroyMediaSource(); | ||
543 | |||
544 | // and unconditionally set the mime type | ||
545 | mMimeType = media_type; | ||
309 | 546 | ||
547 | LLPluginClassMedia* media_source = newSourceFromMediaType(media_type, this, mMediaWidth, mMediaHeight); | ||
548 | |||
549 | if (media_source) | ||
550 | { | ||
551 | media_source->setDisableTimeout(gSavedSettings.getBOOL("DebugPluginDisableTimeout")); | ||
552 | media_source->setLoop(mMediaLoop); | ||
553 | media_source->setAutoScale(mMediaAutoScale); | ||
554 | media_source->setBrowserUserAgent(LLViewerMedia::getCurrentUserAgent()); | ||
555 | |||
556 | mMediaSource = media_source; | ||
557 | return true; | ||
558 | } | ||
310 | 559 | ||
560 | return false; | ||
561 | } | ||
311 | 562 | ||
312 | // virtual | 563 | void LLViewerMediaImpl::setSize(int width, int height) |
313 | void LLViewerMediaImpl::onMediaContentsChange(const EventType& event_in) | 564 | { |
565 | mMediaWidth = width; | ||
566 | mMediaHeight = height; | ||
567 | if(mMediaSource) | ||
568 | { | ||
569 | mMediaSource->setSize(width, height); | ||
570 | } | ||
571 | } | ||
572 | |||
573 | ////////////////////////////////////////////////////////////////////////////////////////// | ||
574 | void LLViewerMediaImpl::play() | ||
314 | { | 575 | { |
315 | LLMediaBase* media_source = event_in.getSubject(); | 576 | // first stop any previously playing media |
316 | LLViewerImage* placeholder_image = gImageList.getImage( mMovieImageID ); | 577 | // stop(); |
317 | if ((placeholder_image) && (placeholder_image->getHasGLTexture())) | 578 | |
579 | // mMediaSource->addObserver( this ); | ||
580 | if(mMediaSource == NULL) | ||
318 | { | 581 | { |
319 | if (placeholder_image->getUseMipMaps()) | 582 | if(!initializePlugin(mMimeType)) |
320 | { | 583 | { |
321 | // bad image! NO MIPMAPS! | 584 | // Plugin failed initialization... should assert or something |
322 | initializePlaceholderImage(placeholder_image, media_source); | 585 | return; |
323 | } | 586 | } |
587 | } | ||
588 | |||
589 | // updateMovieImage(mTextureId, true); | ||
324 | 590 | ||
325 | U8* data = media_source->getMediaData(); | 591 | mMediaSource->loadURI( mMediaURL ); |
326 | S32 x_pos = 0; | 592 | if(/*mMediaSource->pluginSupportsMediaTime()*/ true) |
327 | S32 y_pos = 0; | 593 | { |
328 | S32 width = media_source->getMediaWidth(); | 594 | start(); |
329 | S32 height = media_source->getMediaHeight(); | ||
330 | S32 data_width = media_source->getMediaDataWidth(); | ||
331 | S32 data_height = media_source->getMediaDataHeight(); | ||
332 | placeholder_image->setSubImage(data, data_width, data_height, | ||
333 | x_pos, y_pos, width, height); | ||
334 | } | 595 | } |
335 | } | 596 | } |
336 | 597 | ||
598 | ////////////////////////////////////////////////////////////////////////////////////////// | ||
599 | void LLViewerMediaImpl::stop() | ||
600 | { | ||
601 | if(mMediaSource) | ||
602 | { | ||
603 | mMediaSource->stop(); | ||
604 | // destroyMediaSource(); | ||
605 | } | ||
606 | } | ||
337 | 607 | ||
338 | // virtual | 608 | ////////////////////////////////////////////////////////////////////////////////////////// |
339 | void LLViewerMediaImpl::onMediaSizeChange(const EventType& event_in) | 609 | void LLViewerMediaImpl::pause() |
340 | { | 610 | { |
341 | LLMediaBase* media_source = event_in.getSubject(); | 611 | if(mMediaSource) |
342 | LLViewerImage* placeholder_image = gImageList.getImage( mMovieImageID ); | ||
343 | if (placeholder_image) | ||
344 | { | 612 | { |
345 | initializePlaceholderImage(placeholder_image, media_source); | 613 | mMediaSource->pause(); |
346 | } | 614 | } |
347 | else | 615 | } |
616 | |||
617 | ////////////////////////////////////////////////////////////////////////////////////////// | ||
618 | void LLViewerMediaImpl::start() | ||
619 | { | ||
620 | if(mMediaSource) | ||
348 | { | 621 | { |
349 | llinfos << "no placeholder image" << llendl; | 622 | mMediaSource->start(); |
350 | } | 623 | } |
351 | } | 624 | } |
352 | 625 | ||
626 | ////////////////////////////////////////////////////////////////////////////////////////// | ||
627 | void LLViewerMediaImpl::seek(F32 time) | ||
628 | { | ||
629 | if(mMediaSource) | ||
630 | { | ||
631 | mMediaSource->seek(time); | ||
632 | } | ||
633 | } | ||
353 | 634 | ||
354 | // Get the image we're using | 635 | ////////////////////////////////////////////////////////////////////////////////////////// |
636 | void LLViewerMediaImpl::setVolume(F32 volume) | ||
637 | { | ||
638 | if(mMediaSource) | ||
639 | { | ||
640 | mMediaSource->setVolume(volume); | ||
641 | } | ||
642 | } | ||
355 | 643 | ||
356 | /* | 644 | ////////////////////////////////////////////////////////////////////////////////////////// |
357 | // update media stream if required | 645 | void LLViewerMediaImpl::focus(bool focus) |
358 | LLMediaEngine* media_engine = LLMediaEngine::getInstance(); | 646 | { |
359 | if (media_engine) | 647 | if (mMediaSource) |
360 | { | 648 | { |
361 | if ( media_engine->update() ) | 649 | // call focus just for the hell of it, even though this apopears to be a nop |
362 | { | 650 | mMediaSource->focus(focus); |
363 | LLUUID media_uuid = media_engine->getImageUUID(); | 651 | if (focus) |
364 | updateMovieImage(media_uuid, TRUE); | ||
365 | if (!media_uuid.isNull()) | ||
366 | { | ||
367 | LLViewerImage* viewerImage = getImage( media_uuid ); | ||
368 | if( viewerImage ) | ||
369 | { | ||
370 | LLMediaBase* renderer = media_engine->getMediaRenderer(); | ||
371 | if ((renderer->getTextureWidth() != viewerImage->getWidth()) || | ||
372 | (renderer->getTextureHeight() != viewerImage->getHeight()) || | ||
373 | (renderer->getTextureDepth() != viewerImage->getComponents()) || | ||
374 | (viewerImage->getHasGLTexture() == FALSE)) | ||
375 | { | ||
376 | // destroy existing GL image | ||
377 | viewerImage->destroyGLTexture(); | ||
378 | |||
379 | // set new size | ||
380 | viewerImage->setSize( renderer->getTextureWidth(), | ||
381 | renderer->getTextureHeight(), | ||
382 | renderer->getTextureDepth() ); | ||
383 | |||
384 | LLPointer<LLImageRaw> raw = new LLImageRaw(renderer->getTextureWidth(), | ||
385 | renderer->getTextureHeight(), | ||
386 | renderer->getTextureDepth()); | ||
387 | raw->clear(0x7f,0x7f,0x7f,0xff); | ||
388 | viewerImage->createGLTexture(0, raw); | ||
389 | } | ||
390 | |||
391 | // Set the explicit format the instance wants | ||
392 | viewerImage->setExplicitFormat(renderer->getTextureFormatInternal(), | ||
393 | renderer->getTextureFormatPrimary(), | ||
394 | renderer->getTextureFormatType(), | ||
395 | renderer->getTextureFormatSwapBytes()); | ||
396 | // This should be redundant, but just in case: | ||
397 | viewerImage->setUseMipMaps(FALSE); | ||
398 | |||
399 | LLImageRaw* rawImage = media_engine->getImageRaw(); | ||
400 | if ( rawImage ) | ||
401 | { | ||
402 | viewerImage->setSubImage(rawImage, 0, 0, | ||
403 | renderer->getMediaWidth(), | ||
404 | renderer->getMediaHeight()); | ||
405 | } | ||
406 | } | ||
407 | else | ||
408 | { | ||
409 | llwarns << "MediaEngine update unable to get viewer image for GL texture" << llendl; | ||
410 | } | ||
411 | } | ||
412 | } | ||
413 | else | ||
414 | { | 652 | { |
415 | LLUUID media_uuid = media_engine->getImageUUID(); | 653 | // spoof a mouse click to *actually* pass focus |
416 | updateMovieImage(media_uuid, FALSE); | 654 | // Don't do this anymore -- it actually clicks through now. |
655 | // mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_DOWN, 1, 1, 0); | ||
656 | // mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_UP, 1, 1, 0); | ||
417 | } | 657 | } |
418 | } | 658 | } |
419 | */ | 659 | } |
420 | |||
421 | 660 | ||
422 | LLUUID LLViewerMediaImpl::getMediaTextureID() | 661 | ////////////////////////////////////////////////////////////////////////////////////////// |
662 | void LLViewerMediaImpl::mouseDown(S32 x, S32 y) | ||
423 | { | 663 | { |
424 | return mMovieImageID; | 664 | scaleMouse(&x, &y); |
665 | mLastMouseX = x; | ||
666 | mLastMouseY = y; | ||
667 | if (mMediaSource) | ||
668 | { | ||
669 | mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_DOWN, LEFT_BUTTON, x, y, 0); | ||
670 | } | ||
425 | } | 671 | } |
426 | 672 | ||
427 | // static | 673 | ////////////////////////////////////////////////////////////////////////////////////////// |
428 | void LLViewerMediaImpl::updateBrowserUserAgent() | 674 | void LLViewerMediaImpl::mouseUp(S32 x, S32 y) |
429 | { | 675 | { |
430 | // Don't use user-visible string to avoid | 676 | scaleMouse(&x, &y); |
431 | // punctuation and strange characters. | 677 | mLastMouseX = x; |
432 | std::string skin_name = gSavedSettings.getString("SkinCurrent"); | 678 | mLastMouseY = y; |
433 | 679 | if (mMediaSource) | |
434 | // Just in case we need to check browser differences in A/B test | 680 | { |
435 | // builds. | 681 | mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_UP, LEFT_BUTTON, x, y, 0); |
436 | std::string channel = gSavedSettings.getString("VersionChannelName"); | 682 | } |
437 | |||
438 | // append our magic version number string to the browser user agent id | ||
439 | // See the HTTP 1.0 and 1.1 specifications for allowed formats: | ||
440 | // http://www.ietf.org/rfc/rfc1945.txt section 10.15 | ||
441 | // http://www.ietf.org/rfc/rfc2068.txt section 3.8 | ||
442 | // This was also helpful: | ||
443 | // http://www.mozilla.org/build/revised-user-agent-strings.html | ||
444 | std::ostringstream codec; | ||
445 | codec << "SecondLife/"; | ||
446 | codec << ViewerVersion::getLLMajorVersion() << "." << ViewerVersion::getLLMinorVersion() << "." << ViewerVersion::getLLPatchVersion() << "." << ViewerVersion::getLLBuildVersion(); | ||
447 | codec << " (" << channel << "; " << skin_name << " skin)"; | ||
448 | llinfos << codec.str() << llendl; | ||
449 | LLMediaManager::setBrowserUserAgent( codec.str() ); | ||
450 | } | 683 | } |
451 | 684 | ||
452 | // static | 685 | ////////////////////////////////////////////////////////////////////////////////////////// |
453 | bool LLViewerMediaImpl::handleSkinCurrentChanged(const LLSD& /*newvalue*/) | 686 | void LLViewerMediaImpl::mouseMove(S32 x, S32 y) |
454 | { | 687 | { |
455 | // gSavedSettings is already updated when this function is called. | 688 | scaleMouse(&x, &y); |
456 | updateBrowserUserAgent(); | 689 | mLastMouseX = x; |
457 | return true; | 690 | mLastMouseY = y; |
691 | if (mMediaSource) | ||
692 | { | ||
693 | mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_MOVE, LEFT_BUTTON, x, y, 0); | ||
694 | } | ||
458 | } | 695 | } |
459 | 696 | ||
460 | ////////////////////////////////////////////////////////////////////////////////////////// | 697 | ////////////////////////////////////////////////////////////////////////////////////////// |
461 | // Wrapper class | 698 | void LLViewerMediaImpl::mouseLeftDoubleClick(S32 x, S32 y) |
699 | { | ||
700 | scaleMouse(&x, &y); | ||
701 | mLastMouseX = x; | ||
702 | mLastMouseY = y; | ||
703 | if (mMediaSource) | ||
704 | { | ||
705 | mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_DOUBLE_CLICK, LEFT_BUTTON, x, y, 0); | ||
706 | } | ||
707 | } | ||
708 | |||
462 | ////////////////////////////////////////////////////////////////////////////////////////// | 709 | ////////////////////////////////////////////////////////////////////////////////////////// |
710 | void LLViewerMediaImpl::onMouseCaptureLost() | ||
711 | { | ||
712 | if (mMediaSource) | ||
713 | { | ||
714 | mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_UP, LEFT_BUTTON, mLastMouseX, mLastMouseY, 0); | ||
715 | } | ||
716 | } | ||
463 | 717 | ||
718 | ////////////////////////////////////////////////////////////////////////////////////////// | ||
719 | BOOL LLViewerMediaImpl::handleMouseUp(S32 x, S32 y, MASK mask) | ||
720 | { | ||
721 | // NOTE: this is called when the mouse is released when we have capture. | ||
722 | // Due to the way mouse coordinates are mapped to the object, we can't use the x and y coordinates that come in with the event. | ||
723 | |||
724 | if(hasMouseCapture()) | ||
725 | { | ||
726 | // Release the mouse -- this will also send a mouseup to the media | ||
727 | gFocusMgr.setMouseCapture( FALSE ); | ||
728 | } | ||
464 | 729 | ||
730 | return TRUE; | ||
731 | } | ||
465 | ////////////////////////////////////////////////////////////////////////////////////////// | 732 | ////////////////////////////////////////////////////////////////////////////////////////// |
466 | // The viewer takes a long time to load the start screen. Part of the problem | 733 | void LLViewerMediaImpl::navigateHome() |
467 | // is media initialization -- in particular, QuickTime loads many DLLs and | ||
468 | // hits the disk heavily. So we initialize only the browser component before | ||
469 | // the login screen, then do the rest later when we have a progress bar. JC | ||
470 | // static | ||
471 | void LLViewerMedia::initBrowser() | ||
472 | { | 734 | { |
473 | LLMediaManagerData* init_data = new LLMediaManagerData; | 735 | if(mMediaSource) |
474 | buildMediaManagerData( init_data ); | 736 | { |
475 | LLMediaManager::initBrowser( init_data ); | 737 | mMediaSource->loadURI( mHomeURL ); |
476 | delete init_data; | 738 | } |
477 | |||
478 | // We use a custom user agent with viewer version and skin name. | ||
479 | LLViewerMediaImpl::updateBrowserUserAgent(); | ||
480 | } | 739 | } |
481 | 740 | ||
482 | ////////////////////////////////////////////////////////////////////////////////////////// | 741 | ////////////////////////////////////////////////////////////////////////////////////////// |
483 | // static | 742 | void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mime_type, bool rediscover_type) |
484 | void LLViewerMedia::initClass() | ||
485 | { | 743 | { |
486 | // *TODO: This looks like a memory leak to me. JC | 744 | if(rediscover_type) |
487 | LLMediaManagerData* init_data = new LLMediaManagerData; | 745 | { |
488 | buildMediaManagerData( init_data ); | ||
489 | LLMediaManager::initClass( init_data ); | ||
490 | delete init_data; | ||
491 | 746 | ||
492 | LLMediaManager* mm = LLMediaManager::getInstance(); | 747 | LLURI uri(url); |
493 | LLMIMETypes::mime_info_map_t::const_iterator it; | 748 | std::string scheme = uri.scheme(); |
494 | for (it = LLMIMETypes::sMap.begin(); it != LLMIMETypes::sMap.end(); ++it) | 749 | |
750 | if(scheme.empty() || "http" == scheme || "https" == scheme) | ||
751 | { | ||
752 | LLHTTPClient::getHeaderOnly( url, new LLMimeDiscoveryResponder(this)); | ||
753 | } | ||
754 | else if("data" == scheme || "file" == scheme || "about" == scheme) | ||
755 | { | ||
756 | // FIXME: figure out how to really discover the type for these schemes | ||
757 | // We use "data" internally for a text/html url for loading the login screen | ||
758 | if(initializeMedia("text/html")) | ||
759 | { | ||
760 | mMediaSource->loadURI( url ); | ||
761 | } | ||
762 | } | ||
763 | else | ||
764 | { | ||
765 | // This catches 'rtsp://' urls | ||
766 | if(initializeMedia(scheme)) | ||
767 | { | ||
768 | mMediaSource->loadURI( url ); | ||
769 | } | ||
770 | } | ||
771 | } | ||
772 | else if (mMediaSource) | ||
495 | { | 773 | { |
496 | const std::string& mime_type = it->first; | 774 | mMediaSource->loadURI( url ); |
497 | const LLMIMETypes::LLMIMEInfo& info = it->second; | ||
498 | mm->addMimeTypeImplNameMap( mime_type, info.mImpl ); | ||
499 | } | 775 | } |
500 | 776 | else if(initializeMedia(mime_type) && mMediaSource) | |
501 | LLMediaBase *impl = mm->createSourceFromMimeType("http", "audio/mpeg"); | 777 | { |
502 | if (impl) | 778 | mMediaSource->loadURI( url ); |
779 | } | ||
780 | else | ||
503 | { | 781 | { |
504 | U32 level = gSavedSettings.getU32("MediaDebugLevel"); | 782 | LL_WARNS("Media") << "Couldn't navigate to: " << url << " as there is no media type for: " << mime_type << LL_ENDL; |
505 | impl->setDebugLevel( (LLMediaBase::EDebugLevel)level ); | 783 | return; |
506 | } | 784 | } |
785 | mMediaURL = url; | ||
786 | |||
507 | } | 787 | } |
508 | 788 | ||
509 | ////////////////////////////////////////////////////////////////////////////////////////// | 789 | ////////////////////////////////////////////////////////////////////////////////////////// |
510 | // static | 790 | void LLViewerMediaImpl::navigateStop() |
511 | void LLViewerMedia::buildMediaManagerData( LLMediaManagerData* init_data ) | 791 | { |
512 | { | 792 | if(mMediaSource) |
513 | // std::string executable_dir = std::string( arg0 ).substr( 0, std::string( arg0 ).find_last_of("\\/") ); | 793 | { |
514 | // std::string component_dir = std::string( executable_dir ).substr( 0, std::string( executable_dir ).find_last_of("\\/") ); | 794 | mMediaSource->browse_stop(); |
515 | // component_dir = std::string( component_dir ).substr( 0, std::string( component_dir ).find_last_of("\\/") ); | 795 | } |
516 | // component_dir = std::string( component_dir ).substr( 0, std::string( component_dir ).find_last_of("\\/") ); | ||
517 | // component_dir += "\\newview\\app_settings\\mozilla"; | ||
518 | |||
519 | |||
520 | #if LL_DARWIN | ||
521 | // For Mac OS, we store both the shared libraries and the runtime files (chrome/, plugins/, etc) in | ||
522 | // Second Life.app/Contents/MacOS/. This matches the way Firefox is distributed on the Mac. | ||
523 | std::string component_dir(gDirUtilp->getExecutableDir()); | ||
524 | #elif LL_WINDOWS | ||
525 | std::string component_dir( gDirUtilp->getExpandedFilename( LL_PATH_APP_SETTINGS, "" ) ); | ||
526 | component_dir += gDirUtilp->getDirDelimiter(); | ||
527 | #ifdef LL_DEBUG | ||
528 | component_dir += "mozilla_debug"; | ||
529 | #else // LL_DEBUG | ||
530 | component_dir += "mozilla"; | ||
531 | #endif // LL_DEBUG | ||
532 | #elif LL_LINUX | ||
533 | std::string component_dir( gDirUtilp->getExpandedFilename( LL_PATH_APP_SETTINGS, "" ) ); | ||
534 | component_dir += gDirUtilp->getDirDelimiter(); | ||
535 | |||
536 | #if LINUX64 | ||
537 | component_dir += "mozilla-runtime-linux-x86_64"; | ||
538 | #else | ||
539 | component_dir += "mozilla-runtime-linux-i686"; | ||
540 | #endif | ||
541 | |||
542 | #elif LL_SOLARIS | ||
543 | std::string component_dir( gDirUtilp->getExpandedFilename( LL_PATH_APP_SETTINGS, "" ) ); | ||
544 | component_dir += gDirUtilp->getDirDelimiter(); | ||
545 | #ifdef __sparc | ||
546 | component_dir += "mozilla-solaris-sparc"; | ||
547 | #else | ||
548 | component_dir += "mozilla-solaris-i686"; | ||
549 | #endif | ||
550 | #else | ||
551 | std::string component_dir( gDirUtilp->getExpandedFilename( LL_PATH_APP_SETTINGS, "" ) ); | ||
552 | component_dir += gDirUtilp->getDirDelimiter(); | ||
553 | component_dir += "mozilla"; | ||
554 | #endif | ||
555 | |||
556 | std::string application_dir = gDirUtilp->getExecutableDir(); | ||
557 | 796 | ||
558 | init_data->setBrowserApplicationDir( application_dir ); | 797 | } |
559 | std::string profile_dir = gDirUtilp->getExpandedFilename( LL_PATH_MOZILLA_PROFILE, "" ); | ||
560 | init_data->setBrowserProfileDir( profile_dir ); | ||
561 | init_data->setBrowserComponentDir( component_dir ); | ||
562 | std::string profile_name("Second Life"); | ||
563 | init_data->setBrowserProfileName( profile_name ); | ||
564 | init_data->setBrowserParentWindow( gViewerWindow->getMediaWindow() ); | ||
565 | 798 | ||
566 | // Users can change skins while client is running, so make sure | 799 | ////////////////////////////////////////////////////////////////////////////////////////// |
567 | // we pick up on changes. | 800 | bool LLViewerMediaImpl::handleKeyHere(KEY key, MASK mask) |
568 | gSavedSettings.getControl("SkinCurrent")->getSignal()->connect( | 801 | { |
569 | boost::bind( LLViewerMediaImpl::handleSkinCurrentChanged, _1 ) ); | 802 | bool result = false; |
803 | |||
804 | if (mMediaSource) | ||
805 | { | ||
806 | // FIXME: THIS IS SO WRONG. | ||
807 | // Menu keys should be handled by the menu system and not passed to UI elements, but this is how LLTextEditor and LLLineEditor do it... | ||
808 | if( MASK_CONTROL & mask ) | ||
809 | { | ||
810 | if( 'C' == key ) | ||
811 | { | ||
812 | mMediaSource->copy(); | ||
813 | result = true; | ||
814 | } | ||
815 | else | ||
816 | if( 'V' == key ) | ||
817 | { | ||
818 | mMediaSource->paste(); | ||
819 | result = true; | ||
820 | } | ||
821 | else | ||
822 | if( 'X' == key ) | ||
823 | { | ||
824 | mMediaSource->cut(); | ||
825 | result = true; | ||
826 | } | ||
827 | } | ||
828 | |||
829 | if(!result) | ||
830 | { | ||
831 | |||
832 | LLSD native_key_data = gViewerWindow->getWindow()->getNativeKeyData(); | ||
833 | |||
834 | result = mMediaSource->keyEvent(LLPluginClassMedia::KEY_EVENT_DOWN ,key, mask, native_key_data); | ||
835 | // Since the viewer internal event dispatching doesn't give us key-up events, simulate one here. | ||
836 | (void)mMediaSource->keyEvent(LLPluginClassMedia::KEY_EVENT_UP ,key, mask, native_key_data); | ||
837 | } | ||
838 | } | ||
839 | |||
840 | return result; | ||
841 | } | ||
570 | 842 | ||
843 | ////////////////////////////////////////////////////////////////////////////////////////// | ||
844 | bool LLViewerMediaImpl::handleUnicodeCharHere(llwchar uni_char) | ||
845 | { | ||
846 | bool result = false; | ||
847 | |||
848 | if (mMediaSource) | ||
849 | { | ||
850 | // only accept 'printable' characters, sigh... | ||
851 | if (uni_char >= 32 // discard 'control' characters | ||
852 | && uni_char != 127) // SDL thinks this is 'delete' - yuck. | ||
853 | { | ||
854 | LLSD native_key_data = gViewerWindow->getWindow()->getNativeKeyData(); | ||
855 | |||
856 | mMediaSource->textInput(wstring_to_utf8str(LLWString(1, uni_char)), gKeyboard->currentMask(FALSE), native_key_data); | ||
857 | } | ||
858 | } | ||
859 | |||
860 | return result; | ||
571 | } | 861 | } |
572 | 862 | ||
573 | ////////////////////////////////////////////////////////////////////////////////////////// | 863 | ////////////////////////////////////////////////////////////////////////////////////////// |
574 | // static | 864 | bool LLViewerMediaImpl::canNavigateForward() |
575 | void LLViewerMedia::cleanupClass() | ||
576 | { | 865 | { |
577 | stop() ; | 866 | BOOL result = FALSE; |
578 | LLMediaManager::cleanupClass(); | 867 | if (mMediaSource) |
868 | { | ||
869 | result = mMediaSource->getHistoryForwardAvailable(); | ||
870 | } | ||
871 | return result; | ||
579 | } | 872 | } |
580 | 873 | ||
581 | // static | 874 | ////////////////////////////////////////////////////////////////////////////////////////// |
582 | void LLViewerMedia::play(const std::string& media_url, | 875 | bool LLViewerMediaImpl::canNavigateBack() |
583 | const std::string& mime_type, | ||
584 | const LLUUID& placeholder_texture_id, | ||
585 | S32 media_width, S32 media_height, U8 media_auto_scale, | ||
586 | U8 media_loop) | ||
587 | { | 876 | { |
588 | sViewerMediaImpl.play(media_url, mime_type, placeholder_texture_id, | 877 | BOOL result = FALSE; |
589 | media_width, media_height, media_auto_scale, media_loop); | 878 | if (mMediaSource) |
879 | { | ||
880 | result = mMediaSource->getHistoryBackAvailable(); | ||
881 | } | ||
882 | return result; | ||
590 | } | 883 | } |
591 | 884 | ||
592 | // static | 885 | |
593 | void LLViewerMedia::stop() | 886 | ////////////////////////////////////////////////////////////////////////////////////////// |
887 | void LLViewerMediaImpl::updateMovieImage(const LLUUID& uuid, BOOL active) | ||
594 | { | 888 | { |
595 | sViewerMediaImpl.stop(); | 889 | // IF the media image hasn't changed, do nothing |
890 | if (mTextureId == uuid) | ||
891 | { | ||
892 | return; | ||
893 | } | ||
894 | // If we have changed media uuid, restore the old one | ||
895 | if (!mTextureId.isNull()) | ||
896 | { | ||
897 | LLViewerImage* oldImage = LLViewerImage::getImage( mTextureId ); | ||
898 | if (oldImage) | ||
899 | { | ||
900 | oldImage->reinit(mMovieImageHasMips); | ||
901 | oldImage->mIsMediaTexture = FALSE; | ||
902 | } | ||
903 | } | ||
904 | // If the movie is playing, set the new media image | ||
905 | if (active && !uuid.isNull()) | ||
906 | { | ||
907 | LLViewerImage* viewerImage = LLViewerImage::getImage( uuid ); | ||
908 | if( viewerImage ) | ||
909 | { | ||
910 | mTextureId = uuid; | ||
911 | // Can't use mipmaps for movies because they don't update the full image | ||
912 | mMovieImageHasMips = viewerImage->getUseMipMaps(); | ||
913 | viewerImage->reinit(FALSE); | ||
914 | viewerImage->mIsMediaTexture = TRUE; | ||
915 | } | ||
916 | } | ||
596 | } | 917 | } |
597 | 918 | ||
598 | // static | 919 | ////////////////////////////////////////////////////////////////////////////////////////// |
599 | void LLViewerMedia::pause() | 920 | void LLViewerMediaImpl::update() |
600 | { | 921 | { |
601 | sViewerMediaImpl.pause(); | 922 | if(mMediaSource == NULL) |
923 | { | ||
924 | return; | ||
925 | } | ||
926 | |||
927 | mMediaSource->idle(); | ||
928 | |||
929 | if(mMediaSource->isPluginExited()) | ||
930 | { | ||
931 | destroyMediaSource(); | ||
932 | return; | ||
933 | } | ||
934 | |||
935 | if(!mMediaSource->textureValid()) | ||
936 | { | ||
937 | return; | ||
938 | } | ||
939 | |||
940 | if(mSuspendUpdates || !mVisible) | ||
941 | { | ||
942 | return; | ||
943 | } | ||
944 | |||
945 | LLViewerImage* placeholder_image = updatePlaceholderImage(); | ||
946 | |||
947 | if(placeholder_image) | ||
948 | { | ||
949 | LLRect dirty_rect; | ||
950 | if(mMediaSource->getDirty(&dirty_rect)) | ||
951 | { | ||
952 | // Constrain the dirty rect to be inside the texture | ||
953 | S32 x_pos = llmax(dirty_rect.mLeft, 0); | ||
954 | S32 y_pos = llmax(dirty_rect.mBottom, 0); | ||
955 | S32 width = llmin(dirty_rect.mRight, placeholder_image->getWidth()) - x_pos; | ||
956 | S32 height = llmin(dirty_rect.mTop, placeholder_image->getHeight()) - y_pos; | ||
957 | |||
958 | if(width > 0 && height > 0) | ||
959 | { | ||
960 | |||
961 | U8* data = mMediaSource->getBitsData(); | ||
962 | |||
963 | // Offset the pixels pointer to match x_pos and y_pos | ||
964 | data += ( x_pos * mMediaSource->getTextureDepth() * mMediaSource->getBitsWidth() ); | ||
965 | data += ( y_pos * mMediaSource->getTextureDepth() ); | ||
966 | |||
967 | placeholder_image->setSubImage( | ||
968 | data, | ||
969 | mMediaSource->getBitsWidth(), | ||
970 | mMediaSource->getBitsHeight(), | ||
971 | x_pos, | ||
972 | y_pos, | ||
973 | width, | ||
974 | height, | ||
975 | TRUE); // force a fast update (i.e. don't call analyzeAlpha, etc.) | ||
976 | |||
977 | } | ||
978 | |||
979 | mMediaSource->resetDirty(); | ||
980 | } | ||
981 | } | ||
602 | } | 982 | } |
603 | 983 | ||
604 | // static | 984 | |
605 | void LLViewerMedia::start() | 985 | ////////////////////////////////////////////////////////////////////////////////////////// |
986 | void LLViewerMediaImpl::updateImagesMediaStreams() | ||
606 | { | 987 | { |
607 | sViewerMediaImpl.start(); | ||
608 | } | 988 | } |
609 | 989 | ||
610 | // static | 990 | |
611 | void LLViewerMedia::seek(F32 time) | 991 | ////////////////////////////////////////////////////////////////////////////////////////// |
992 | LLViewerImage* LLViewerMediaImpl::updatePlaceholderImage() | ||
612 | { | 993 | { |
613 | sViewerMediaImpl.seek(time); | 994 | if(mTextureId.isNull()) |
995 | { | ||
996 | // The code that created this instance will read from the plugin's bits. | ||
997 | return NULL; | ||
998 | } | ||
999 | |||
1000 | LLViewerImage* placeholder_image = gImageList.getImage( mTextureId ); | ||
1001 | |||
1002 | if (mNeedsNewTexture | ||
1003 | || placeholder_image->getUseMipMaps() | ||
1004 | || ! placeholder_image->mIsMediaTexture | ||
1005 | || placeholder_image->getWidth() != mMediaSource->getTextureWidth() | ||
1006 | || placeholder_image->getHeight() != mMediaSource->getTextureHeight()) | ||
1007 | { | ||
1008 | llinfos << "initializing media placeholder" << llendl; | ||
1009 | llinfos << "movie image id " << mTextureId << llendl; | ||
1010 | |||
1011 | int texture_width = mMediaSource->getTextureWidth(); | ||
1012 | int texture_height = mMediaSource->getTextureHeight(); | ||
1013 | int texture_depth = mMediaSource->getTextureDepth(); | ||
1014 | |||
1015 | // MEDIAOPT: check to see if size actually changed before doing work | ||
1016 | placeholder_image->destroyGLTexture(); | ||
1017 | // MEDIAOPT: apparently just calling setUseMipMaps(FALSE) doesn't work? | ||
1018 | placeholder_image->reinit(FALSE); // probably not needed | ||
1019 | |||
1020 | // MEDIAOPT: seems insane that we actually have to make an imageraw then | ||
1021 | // immediately discard it | ||
1022 | LLPointer<LLImageRaw> raw = new LLImageRaw(texture_width, texture_height, texture_depth); | ||
1023 | raw->clear(0x0f, 0x0f, 0x0f, 0xff); | ||
1024 | int discard_level = 0; | ||
1025 | |||
1026 | // ask media source for correct GL image format constants | ||
1027 | placeholder_image->setExplicitFormat(mMediaSource->getTextureFormatInternal(), | ||
1028 | mMediaSource->getTextureFormatPrimary(), | ||
1029 | mMediaSource->getTextureFormatType(), | ||
1030 | mMediaSource->getTextureFormatSwapBytes()); | ||
1031 | |||
1032 | placeholder_image->createGLTexture(discard_level, raw); | ||
1033 | |||
1034 | // placeholder_image->setExplicitFormat() | ||
1035 | placeholder_image->setUseMipMaps(FALSE); | ||
1036 | |||
1037 | // MEDIAOPT: set this dynamically on play/stop | ||
1038 | placeholder_image->mIsMediaTexture = true; | ||
1039 | mNeedsNewTexture = false; | ||
1040 | } | ||
1041 | |||
1042 | return placeholder_image; | ||
614 | } | 1043 | } |
615 | 1044 | ||
616 | // static | 1045 | |
617 | void LLViewerMedia::setVolume(F32 volume) | 1046 | ////////////////////////////////////////////////////////////////////////////////////////// |
1047 | LLUUID LLViewerMediaImpl::getMediaTextureID() | ||
618 | { | 1048 | { |
619 | sViewerMediaImpl.setVolume(volume); | 1049 | return mTextureId; |
620 | } | 1050 | } |
621 | 1051 | ||
622 | // static | 1052 | ////////////////////////////////////////////////////////////////////////////////////////// |
623 | LLMediaBase::EStatus LLViewerMedia::getStatus() | 1053 | void LLViewerMediaImpl::setVisible(bool visible) |
624 | { | 1054 | { |
625 | return sViewerMediaImpl.getStatus(); | 1055 | mVisible = visible; |
1056 | |||
1057 | if(mVisible) | ||
1058 | { | ||
1059 | if(mMediaSource && mMediaSource->isPluginExited()) | ||
1060 | { | ||
1061 | destroyMediaSource(); | ||
1062 | } | ||
1063 | |||
1064 | if(!mMediaSource) | ||
1065 | { | ||
1066 | createMediaSource(); | ||
1067 | } | ||
1068 | } | ||
1069 | |||
1070 | if(mMediaSource) | ||
1071 | { | ||
1072 | mMediaSource->setPriority(mVisible?LLPluginClassMedia::PRIORITY_NORMAL:LLPluginClassMedia::PRIORITY_HIDDEN); | ||
1073 | } | ||
626 | } | 1074 | } |
627 | 1075 | ||
628 | ////////////////////////////////////////////////////////////////////////////////////////// | 1076 | ////////////////////////////////////////////////////////////////////////////////////////// |
629 | // static | 1077 | void LLViewerMediaImpl::mouseCapture() |
630 | LLUUID LLViewerMedia::getMediaTextureID() | ||
631 | { | 1078 | { |
632 | return sViewerMediaImpl.getMediaTextureID(); | 1079 | gFocusMgr.setMouseCapture(this); |
633 | } | 1080 | } |
634 | 1081 | ||
635 | ////////////////////////////////////////////////////////////////////////////////////////// | 1082 | ////////////////////////////////////////////////////////////////////////////////////////// |
636 | // static | 1083 | void LLViewerMediaImpl::getTextureSize(S32 *texture_width, S32 *texture_height) |
637 | bool LLViewerMedia::getMediaSize(S32 *media_width, S32 *media_height) | ||
638 | { | 1084 | { |
639 | // make sure we're valid | 1085 | if(mMediaSource && mMediaSource->textureValid()) |
1086 | { | ||
1087 | S32 real_texture_width = mMediaSource->getBitsWidth(); | ||
1088 | S32 real_texture_height = mMediaSource->getBitsHeight(); | ||
640 | 1089 | ||
641 | if ( sViewerMediaImpl.mMediaSource != NULL ) | 1090 | { |
1091 | // The "texture width" coming back from the plugin may not be a power of two (thanks to webkit). | ||
1092 | // It will be the correct "data width" to pass to setSubImage | ||
1093 | int i; | ||
1094 | |||
1095 | for(i = 1; i < real_texture_width; i <<= 1) | ||
1096 | ; | ||
1097 | *texture_width = i; | ||
1098 | |||
1099 | for(i = 1; i < real_texture_height; i <<= 1) | ||
1100 | ; | ||
1101 | *texture_height = i; | ||
1102 | } | ||
1103 | |||
1104 | } | ||
1105 | else | ||
642 | { | 1106 | { |
643 | *media_width = sViewerMediaImpl.mMediaSource->getMediaWidth(); | 1107 | *texture_width = 0; |
644 | *media_height = sViewerMediaImpl.mMediaSource->getMediaHeight(); | 1108 | *texture_height = 0; |
645 | return true; | ||
646 | } | 1109 | } |
647 | return false; | 1110 | } |
1111 | ////////////////////////////////////////////////////////////////////////////////////////// | ||
1112 | void LLViewerMediaImpl::scaleMouse(S32 *mouse_x, S32 *mouse_y) | ||
1113 | { | ||
1114 | #if 0 | ||
1115 | S32 media_width, media_height; | ||
1116 | S32 texture_width, texture_height; | ||
1117 | getMediaSize( &media_width, &media_height ); | ||
1118 | getTextureSize( &texture_width, &texture_height ); | ||
1119 | S32 y_delta = texture_height - media_height; | ||
1120 | |||
1121 | *mouse_y -= y_delta; | ||
1122 | #endif | ||
648 | } | 1123 | } |
649 | 1124 | ||
650 | ////////////////////////////////////////////////////////////////////////////////////////// | 1125 | ////////////////////////////////////////////////////////////////////////////////////////// |
651 | // static | 1126 | bool LLViewerMediaImpl::isMediaPlaying() |
652 | bool LLViewerMedia::getTextureSize(S32 *texture_width, S32 *texture_height) | ||
653 | { | 1127 | { |
654 | if ( sViewerMediaImpl.mMediaSource != NULL ) | 1128 | bool result = false; |
1129 | |||
1130 | if(mMediaSource) | ||
655 | { | 1131 | { |
656 | S32 media_width = sViewerMediaImpl.mMediaSource->getMediaWidth(); | 1132 | EMediaStatus status = mMediaSource->getStatus(); |
657 | S32 media_height = sViewerMediaImpl.mMediaSource->getMediaHeight(); | 1133 | if(status == MEDIA_PLAYING || status == MEDIA_LOADING) |
658 | *texture_width = LLMediaManager::textureWidthFromMediaWidth( media_width ); | 1134 | result = true; |
659 | *texture_height = LLMediaManager::textureHeightFromMediaHeight( media_height ); | ||
660 | return true; | ||
661 | } | 1135 | } |
662 | return false; | 1136 | |
1137 | return result; | ||
663 | } | 1138 | } |
1139 | ////////////////////////////////////////////////////////////////////////////////////////// | ||
1140 | bool LLViewerMediaImpl::isMediaPaused() | ||
1141 | { | ||
1142 | bool result = false; | ||
664 | 1143 | ||
1144 | if(mMediaSource) | ||
1145 | { | ||
1146 | if(mMediaSource->getStatus() == MEDIA_PAUSED) | ||
1147 | result = true; | ||
1148 | } | ||
1149 | |||
1150 | return result; | ||
1151 | } | ||
665 | 1152 | ||
666 | ////////////////////////////////////////////////////////////////////////////////////////// | 1153 | ////////////////////////////////////////////////////////////////////////////////////////// |
667 | // static | 1154 | // |
668 | void LLViewerMedia::updateImagesMediaStreams() | 1155 | bool LLViewerMediaImpl::hasMedia() |
669 | { | 1156 | { |
670 | sViewerMediaImpl.updateImagesMediaStreams(); | 1157 | return mMediaSource != NULL; |
671 | } | 1158 | } |
1159 | |||
672 | ////////////////////////////////////////////////////////////////////////////////////////// | 1160 | ////////////////////////////////////////////////////////////////////////////////////////// |
673 | // static | 1161 | void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* self, LLPluginClassMediaOwner::EMediaEvent event) |
674 | bool LLViewerMedia::isMediaPlaying() | ||
675 | { | 1162 | { |
676 | LLMediaBase::EStatus status = sViewerMediaImpl.getStatus(); | 1163 | switch(event) |
677 | return (status == LLMediaBase::STATUS_STARTED ); | 1164 | { |
1165 | case MEDIA_EVENT_PLUGIN_FAILED: | ||
1166 | { | ||
1167 | LLSD args; | ||
1168 | args["PLUGIN"] = LLMIMETypes::implType(mMimeType); | ||
1169 | LLNotifications::instance().add("MediaPluginFailed", args); | ||
1170 | } | ||
1171 | break; | ||
1172 | default: | ||
1173 | break; | ||
1174 | } | ||
1175 | // Just chain the event to observers. | ||
1176 | emitEvent(self, event); | ||
678 | } | 1177 | } |
679 | ////////////////////////////////////////////////////////////////////////////////////////// | 1178 | |
680 | // static | 1179 | //////////////////////////////////////////////////////////////////////////////// |
681 | bool LLViewerMedia::isMediaPaused() | 1180 | // virtual |
1181 | void | ||
1182 | LLViewerMediaImpl::cut() | ||
682 | { | 1183 | { |
683 | LLMediaBase::EStatus status = sViewerMediaImpl.getStatus(); | 1184 | if (mMediaSource) |
684 | return (status == LLMediaBase::STATUS_PAUSED); | 1185 | mMediaSource->cut(); |
685 | } | 1186 | } |
686 | ////////////////////////////////////////////////////////////////////////////////////////// | 1187 | |
687 | // static | 1188 | //////////////////////////////////////////////////////////////////////////////// |
688 | bool LLViewerMedia::hasMedia() | 1189 | // virtual |
1190 | BOOL | ||
1191 | LLViewerMediaImpl::canCut() const | ||
689 | { | 1192 | { |
690 | return sViewerMediaImpl.mMediaSource != NULL; | 1193 | if (mMediaSource) |
1194 | return mMediaSource->canCut(); | ||
1195 | else | ||
1196 | return FALSE; | ||
691 | } | 1197 | } |
692 | 1198 | ||
693 | ////////////////////////////////////////////////////////////////////////////////////////// | 1199 | //////////////////////////////////////////////////////////////////////////////// |
694 | //static | 1200 | // virtual |
695 | bool LLViewerMedia::isActiveMediaTexture(const LLUUID& id) | 1201 | void |
1202 | LLViewerMediaImpl::copy() | ||
696 | { | 1203 | { |
697 | return (id.notNull() | 1204 | if (mMediaSource) |
698 | && id == getMediaTextureID() | 1205 | mMediaSource->copy(); |
699 | && isMediaPlaying()); | ||
700 | } | 1206 | } |
701 | 1207 | ||
702 | ////////////////////////////////////////////////////////////////////////////////////////// | 1208 | //////////////////////////////////////////////////////////////////////////////// |
703 | // static | 1209 | // virtual |
704 | std::string LLViewerMedia::getMediaURL() | 1210 | BOOL |
1211 | LLViewerMediaImpl::canCopy() const | ||
705 | { | 1212 | { |
706 | return sViewerMediaImpl.mMediaURL; | 1213 | if (mMediaSource) |
1214 | return mMediaSource->canCopy(); | ||
1215 | else | ||
1216 | return FALSE; | ||
707 | } | 1217 | } |
708 | ////////////////////////////////////////////////////////////////////////////////////////// | 1218 | |
709 | // static | 1219 | //////////////////////////////////////////////////////////////////////////////// |
710 | std::string LLViewerMedia::getMimeType() | 1220 | // virtual |
1221 | void | ||
1222 | LLViewerMediaImpl::paste() | ||
711 | { | 1223 | { |
712 | return sViewerMediaImpl.mMimeType; | 1224 | if (mMediaSource) |
1225 | mMediaSource->paste(); | ||
713 | } | 1226 | } |
714 | ////////////////////////////////////////////////////////////////////////////////////////// | 1227 | |
715 | // static | 1228 | //////////////////////////////////////////////////////////////////////////////// |
716 | void LLViewerMedia::setMimeType(std::string mime_type) | 1229 | // virtual |
1230 | BOOL | ||
1231 | LLViewerMediaImpl::canPaste() const | ||
717 | { | 1232 | { |
718 | sViewerMediaImpl.mMimeType = mime_type; | 1233 | if (mMediaSource) |
1234 | return mMediaSource->canPaste(); | ||
1235 | else | ||
1236 | return FALSE; | ||
719 | } | 1237 | } |
1238 | |||