diff options
author | Jacek Antonelli | 2008-08-15 23:45:04 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:45:04 -0500 |
commit | 117e22047c5752352342d64e3fb7ce00a4eb8113 (patch) | |
tree | e32de2cfba0dda8705ae528fcd1fbe23ba075685 /linden/indra/llmedia/llmediaimplgstreamer.cpp | |
parent | Second Life viewer sources 1.18.0.6 (diff) | |
download | meta-impy-117e22047c5752352342d64e3fb7ce00a4eb8113.zip meta-impy-117e22047c5752352342d64e3fb7ce00a4eb8113.tar.gz meta-impy-117e22047c5752352342d64e3fb7ce00a4eb8113.tar.bz2 meta-impy-117e22047c5752352342d64e3fb7ce00a4eb8113.tar.xz |
Second Life viewer sources 1.18.1.2
Diffstat (limited to 'linden/indra/llmedia/llmediaimplgstreamer.cpp')
-rw-r--r-- | linden/indra/llmedia/llmediaimplgstreamer.cpp | 715 |
1 files changed, 715 insertions, 0 deletions
diff --git a/linden/indra/llmedia/llmediaimplgstreamer.cpp b/linden/indra/llmedia/llmediaimplgstreamer.cpp new file mode 100644 index 0000000..f8b4c74 --- /dev/null +++ b/linden/indra/llmedia/llmediaimplgstreamer.cpp | |||
@@ -0,0 +1,715 @@ | |||
1 | /** | ||
2 | * @file llmediaimplgstreamer.cpp | ||
3 | * @brief implementation that supports various media through GStreamer. | ||
4 | * | ||
5 | * Copyright (c) 2007-2007, Linden Research, Inc. | ||
6 | * | ||
7 | * Second Life Viewer Source Code | ||
8 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
9 | * to you under the terms of the GNU General Public License, version 2.0 | ||
10 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
11 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
12 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
13 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
14 | * | ||
15 | * There are special exceptions to the terms and conditions of the GPL as | ||
16 | * it is applied to this Source Code. View the full text of the exception | ||
17 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
18 | * online at http://secondlife.com/developers/opensource/flossexception | ||
19 | * | ||
20 | * By copying, modifying or distributing this software, you acknowledge | ||
21 | * that you have read and understood your obligations described above, | ||
22 | * and agree to abide by those obligations. | ||
23 | * | ||
24 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
25 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
26 | * COMPLETENESS OR PERFORMANCE. | ||
27 | */ | ||
28 | |||
29 | #include "linden_common.h" | ||
30 | |||
31 | #if LL_GSTREAMER_ENABLED | ||
32 | |||
33 | extern "C" { | ||
34 | #include <gst/gst.h> | ||
35 | } | ||
36 | |||
37 | #include "llmediaimplgstreamer.h" | ||
38 | |||
39 | #include "llmediaimplgstreamervidplug.h" | ||
40 | |||
41 | #ifdef LL_GST_SOUNDSINK | ||
42 | #include "llmediaimplgstreamersndplug.h" | ||
43 | #endif // LL_GST_SOUNDSINK | ||
44 | |||
45 | #include "llmediaimplgstreamer_syms.h" | ||
46 | |||
47 | #include "llgl.h" | ||
48 | #include "llglheaders.h" // For gl texture modes | ||
49 | |||
50 | /////////////////////////////////////////////////////////////////////////////// | ||
51 | // | ||
52 | LLMediaImplGStreamer:: | ||
53 | LLMediaImplGStreamer () : | ||
54 | mediaData ( NULL ), | ||
55 | ownBuffer ( TRUE ), | ||
56 | mVolume ( 1.0f ), | ||
57 | currentMode ( ModeIdle ), | ||
58 | mPump ( NULL ), | ||
59 | mPlaybin ( NULL ), | ||
60 | mVideoSink ( NULL ) | ||
61 | #ifdef LL_GST_SOUNDSINK | ||
62 | ,mAudioSink ( NULL ) | ||
63 | #endif // LL_GST_SOUNDSINK | ||
64 | { | ||
65 | mMediaDepthBytes = 4; | ||
66 | mTextureDepth = 4; | ||
67 | mTextureFormatInternal = GL_RGB8; | ||
68 | mTextureFormatPrimary = GL_BGRA; | ||
69 | mTextureFormatType = GL_UNSIGNED_INT_8_8_8_8_REV; | ||
70 | } | ||
71 | |||
72 | /////////////////////////////////////////////////////////////////////////////// | ||
73 | // | ||
74 | LLMediaImplGStreamer:: | ||
75 | ~LLMediaImplGStreamer () | ||
76 | { | ||
77 | unload(); | ||
78 | } | ||
79 | |||
80 | void UnloadGStreamer() | ||
81 | { | ||
82 | ungrab_gst_syms(); | ||
83 | } | ||
84 | |||
85 | |||
86 | /////////////////////////////////////////////////////////////////////////////// | ||
87 | // | ||
88 | BOOL | ||
89 | LLMediaImplGStreamer:: | ||
90 | setBuffer ( U8* bufferIn ) | ||
91 | { | ||
92 | // Since we've pointed GStreamer at the old media data buffer | ||
93 | // directly, we need to be somewhat careful deleting it... | ||
94 | U8* oldMediaData = mediaData; | ||
95 | BOOL ownedMediaData = ownBuffer; | ||
96 | |||
97 | if(bufferIn == NULL) | ||
98 | { | ||
99 | // Passing NULL to this function requests that the object | ||
100 | // allocate its own buffer. | ||
101 | mediaData = new unsigned char[ mMediaHeight * mMediaRowbytes ]; | ||
102 | ownBuffer = TRUE; | ||
103 | } | ||
104 | else | ||
105 | { | ||
106 | // Use the supplied buffer. | ||
107 | mediaData = bufferIn; | ||
108 | ownBuffer = FALSE; | ||
109 | } | ||
110 | |||
111 | if(mediaData == NULL) | ||
112 | { | ||
113 | // This is bad - probably out of memory. | ||
114 | llerrs << "LLMediaImplGStreamer::setBuffer: mediaData is NULL" << llendl; | ||
115 | // NOTE: This case doesn't clean up properly. This assert is fatal, so this isn't a huge problem, | ||
116 | // but if this assert is ever removed the code should be fixed to clean up correctly. | ||
117 | return FALSE; | ||
118 | } | ||
119 | |||
120 | // [..] | ||
121 | |||
122 | // Delete the old media data buffer iff we owned it. | ||
123 | if ( ownedMediaData ) | ||
124 | { | ||
125 | if ( oldMediaData ) | ||
126 | { | ||
127 | delete [] oldMediaData; | ||
128 | } | ||
129 | } | ||
130 | |||
131 | return TRUE; | ||
132 | } | ||
133 | |||
134 | /////////////////////////////////////////////////////////////////////////////// | ||
135 | // | ||
136 | BOOL | ||
137 | LLMediaImplGStreamer:: | ||
138 | init () | ||
139 | { | ||
140 | static bool done_init = false; | ||
141 | if (!done_init) | ||
142 | { | ||
143 | // Get symbols! | ||
144 | if (! grab_gst_syms("libgstreamer-0.10.so.0", | ||
145 | "libgstvideo-0.10.so.0", | ||
146 | "libgstaudio-0.10.so.0") ) | ||
147 | { | ||
148 | llwarns << "Couldn't find suitable GStreamer 0.10 support on this system - video playback disabled." << llendl; | ||
149 | return FALSE; | ||
150 | } | ||
151 | |||
152 | if (llgst_segtrap_set_enabled) | ||
153 | llgst_segtrap_set_enabled(FALSE); | ||
154 | else | ||
155 | llwarns << "gst_segtrap_set_enabled() is not available; Second Life automated crash-reporter may cease to function until next restart." << llendl; | ||
156 | |||
157 | if (0 == llgst_init_check(NULL, NULL, NULL)) | ||
158 | { | ||
159 | return FALSE; | ||
160 | } | ||
161 | |||
162 | // Init our custom plugins - only really need do this once. | ||
163 | gst_slvideo_init_class(); | ||
164 | #if 0 | ||
165 | gst_slsound_init_class(); | ||
166 | #endif | ||
167 | |||
168 | done_init = true; | ||
169 | } | ||
170 | |||
171 | // Create a pumpable main-loop for this media | ||
172 | mPump = g_main_loop_new (NULL, FALSE); | ||
173 | if (!mPump) | ||
174 | { | ||
175 | return FALSE; | ||
176 | } | ||
177 | |||
178 | // instantiate a playbin element to do the hard work | ||
179 | mPlaybin = llgst_element_factory_make ("playbin", "play"); | ||
180 | if (!mPlaybin) | ||
181 | { | ||
182 | // todo: cleanup pump | ||
183 | return FALSE; | ||
184 | } | ||
185 | |||
186 | if (NULL == getenv("LL_GSTREAMER_EXTERNAL")) { | ||
187 | // instantiate and connect a custom video sink | ||
188 | mVideoSink = | ||
189 | GST_SLVIDEO(llgst_element_factory_make ("private-slvideo", "slvideo")); | ||
190 | if (!mVideoSink) | ||
191 | { | ||
192 | llwarns << "Could not instantiate private-slvideo element." | ||
193 | << llendl; | ||
194 | // todo: cleanup. | ||
195 | return FALSE; | ||
196 | } | ||
197 | |||
198 | g_object_set(mPlaybin, "video-sink", mVideoSink, NULL); | ||
199 | |||
200 | #ifdef LL_GST_SOUNDSINK | ||
201 | // instantiate and connect a custom audio sink | ||
202 | mAudioSink = | ||
203 | GST_SLSOUND(llgst_element_factory_make ("private-slsound", "slsound")); | ||
204 | if (!mAudioSink) | ||
205 | { | ||
206 | llwarns << "Could not instantiate private-slsound element." | ||
207 | << llendl; | ||
208 | // todo: cleanup. | ||
209 | return FALSE; | ||
210 | } | ||
211 | |||
212 | g_object_set(mPlaybin, "audio-sink", mAudioSink, NULL); | ||
213 | #endif | ||
214 | } | ||
215 | |||
216 | return LLMediaMovieBase::init(); | ||
217 | } | ||
218 | |||
219 | |||
220 | /////////////////////////////////////////////////////////////////////////////// | ||
221 | // | ||
222 | //#define LL_GST_REPORT_STATE_CHANGES | ||
223 | #ifdef LL_GST_REPORT_STATE_CHANGES | ||
224 | static char* get_gst_state_name(GstState state) | ||
225 | { | ||
226 | switch (state) { | ||
227 | case GST_STATE_VOID_PENDING: return "VOID_PENDING"; | ||
228 | case GST_STATE_NULL: return "NULL"; | ||
229 | case GST_STATE_READY: return "READY"; | ||
230 | case GST_STATE_PAUSED: return "PAUSED"; | ||
231 | case GST_STATE_PLAYING: return "PLAYING"; | ||
232 | } | ||
233 | return "(unknown)"; | ||
234 | } | ||
235 | #endif // LL_GST_REPORT_STATE_CHANGES | ||
236 | |||
237 | static gboolean | ||
238 | my_bus_callback (GstBus *bus, | ||
239 | GstMessage *message, | ||
240 | gpointer data) | ||
241 | { | ||
242 | if (GST_MESSAGE_TYPE(message) != GST_MESSAGE_STATE_CHANGED && | ||
243 | GST_MESSAGE_TYPE(message) != GST_MESSAGE_BUFFERING) | ||
244 | { | ||
245 | llinfos << "Got GST message type: " | ||
246 | << LLGST_MESSAGE_TYPE_NAME (message) | ||
247 | << llendl; | ||
248 | } | ||
249 | else | ||
250 | { | ||
251 | lldebugs << "Got GST message type: " | ||
252 | << LLGST_MESSAGE_TYPE_NAME (message) | ||
253 | << llendl; | ||
254 | } | ||
255 | |||
256 | LLMediaImplGStreamer *impl = (LLMediaImplGStreamer*)data; | ||
257 | |||
258 | switch (GST_MESSAGE_TYPE (message)) { | ||
259 | case GST_MESSAGE_BUFFERING: { | ||
260 | // NEEDS GST 0.10.11+ | ||
261 | if (llgst_message_parse_buffering) | ||
262 | { | ||
263 | gint percent = 0; | ||
264 | llgst_message_parse_buffering(message, &percent); | ||
265 | llinfos << "GST buffering: " << percent | ||
266 | << "%" << llendl; | ||
267 | // ModeBuffering seems to do nothing except make | ||
268 | // the UI worse | ||
269 | /*if (percent < 100) impl->setCurrentMode(LLMediaImplGStreamer::ModeBuffering);*/ | ||
270 | } | ||
271 | break; | ||
272 | } | ||
273 | case GST_MESSAGE_STATE_CHANGED: { | ||
274 | GstState old_state; | ||
275 | GstState new_state; | ||
276 | GstState pending_state; | ||
277 | llgst_message_parse_state_changed(message, | ||
278 | &old_state, | ||
279 | &new_state, | ||
280 | &pending_state); | ||
281 | #ifdef LL_GST_REPORT_STATE_CHANGES | ||
282 | // not generally very useful, and rather spammy. | ||
283 | llinfos << "state change (old,<new>,pending): " | ||
284 | << get_gst_state_name(old_state) << ", <" | ||
285 | << get_gst_state_name(new_state) << ">, " | ||
286 | << get_gst_state_name(pending_state) << | ||
287 | llendl; | ||
288 | #endif // LL_GST_REPORT_STATE_CHANGES | ||
289 | |||
290 | switch (new_state) { | ||
291 | case GST_STATE_VOID_PENDING: | ||
292 | impl->setCurrentMode(LLMediaImplGStreamer::ModeNone); | ||
293 | break; | ||
294 | case GST_STATE_NULL: | ||
295 | impl->setCurrentMode(LLMediaImplGStreamer::ModeNone); | ||
296 | break; | ||
297 | case GST_STATE_READY: | ||
298 | impl->setCurrentMode(LLMediaImplGStreamer::ModeStopped); | ||
299 | break; | ||
300 | case GST_STATE_PAUSED: | ||
301 | impl->setCurrentMode(LLMediaImplGStreamer::ModePaused); | ||
302 | break; | ||
303 | case GST_STATE_PLAYING: | ||
304 | impl->setCurrentMode(LLMediaImplGStreamer::ModePlaying); | ||
305 | break; | ||
306 | } | ||
307 | break; | ||
308 | } | ||
309 | case GST_MESSAGE_ERROR: { | ||
310 | GError *err; | ||
311 | gchar *debug; | ||
312 | |||
313 | llgst_message_parse_error (message, &err, &debug); | ||
314 | llinfos << "GST error: " << err->message << llendl; | ||
315 | g_error_free (err); | ||
316 | g_free (debug); | ||
317 | |||
318 | impl->setCurrentMode(LLMediaImplGStreamer::ModeError); | ||
319 | |||
320 | impl->stop(); | ||
321 | |||
322 | break; | ||
323 | } | ||
324 | case GST_MESSAGE_INFO: { | ||
325 | if (llgst_message_parse_info) | ||
326 | { | ||
327 | GError *err; | ||
328 | gchar *debug; | ||
329 | |||
330 | llgst_message_parse_info (message, &err, &debug); | ||
331 | llinfos << "GST info: " << err->message << llendl; | ||
332 | g_error_free (err); | ||
333 | g_free (debug); | ||
334 | } | ||
335 | break; | ||
336 | } | ||
337 | case GST_MESSAGE_WARNING: { | ||
338 | GError *err; | ||
339 | gchar *debug; | ||
340 | |||
341 | llgst_message_parse_warning (message, &err, &debug); | ||
342 | llinfos << "GST warning: " << err->message << llendl; | ||
343 | g_error_free (err); | ||
344 | g_free (debug); | ||
345 | |||
346 | break; | ||
347 | } | ||
348 | case GST_MESSAGE_EOS: | ||
349 | /* end-of-stream */ | ||
350 | llinfos << "GST EOS." << llendl; | ||
351 | impl->setCurrentMode(LLMediaImplGStreamer::ModeStopped);//? | ||
352 | impl->stop(); | ||
353 | break; | ||
354 | default: | ||
355 | /* unhandled message */ | ||
356 | break; | ||
357 | } | ||
358 | |||
359 | /* we want to be notified again the next time there is a message | ||
360 | * on the bus, so returning TRUE (FALSE means we want to stop watching | ||
361 | * for messages on the bus and our callback should not be called again) | ||
362 | */ | ||
363 | return TRUE; | ||
364 | } | ||
365 | |||
366 | BOOL | ||
367 | LLMediaImplGStreamer:: | ||
368 | load ( const LLString& urlIn ) | ||
369 | { | ||
370 | llinfos << "Setting media URI: " << urlIn << llendl; | ||
371 | |||
372 | // set URI | ||
373 | g_object_set (G_OBJECT (mPlaybin), "uri", urlIn.c_str(), NULL); | ||
374 | //g_object_set (G_OBJECT (mPlaybin), "uri", "file:///tmp/movie", NULL); | ||
375 | |||
376 | // get playbin's bus - perhaps this can/should be done at init() | ||
377 | GstBus *bus = llgst_pipeline_get_bus (GST_PIPELINE (mPlaybin)); | ||
378 | if (!bus) | ||
379 | { | ||
380 | return FALSE; | ||
381 | } | ||
382 | llgst_bus_add_watch (bus, my_bus_callback, this); | ||
383 | llgst_object_unref (bus); | ||
384 | |||
385 | if (true) // dummy values | ||
386 | { | ||
387 | const int fixedsize = 2; | ||
388 | mMediaRowbytes = mMediaDepthBytes * fixedsize; | ||
389 | mMediaWidth = fixedsize; | ||
390 | mMediaHeight = fixedsize; | ||
391 | mTextureWidth = fixedsize; | ||
392 | mTextureHeight = fixedsize; | ||
393 | } | ||
394 | |||
395 | BOOL rtn = LLMediaMovieBase::load(urlIn); | ||
396 | llinfos << "load returns " << int(rtn) << llendl; | ||
397 | return rtn; | ||
398 | } | ||
399 | |||
400 | /////////////////////////////////////////////////////////////////////////////// | ||
401 | // | ||
402 | BOOL | ||
403 | LLMediaImplGStreamer:: | ||
404 | unload () | ||
405 | { | ||
406 | if (mPlaybin) | ||
407 | { | ||
408 | llgst_element_set_state (mPlaybin, GST_STATE_NULL); | ||
409 | llgst_object_unref (GST_OBJECT (mPlaybin)); | ||
410 | mPlaybin = NULL; | ||
411 | } | ||
412 | |||
413 | if (mPump) | ||
414 | { | ||
415 | g_main_loop_quit(mPump); | ||
416 | mPump = NULL; | ||
417 | } | ||
418 | |||
419 | if (mediaData) | ||
420 | { | ||
421 | if (ownBuffer) | ||
422 | { | ||
423 | delete mediaData; | ||
424 | mediaData = NULL; | ||
425 | } | ||
426 | } | ||
427 | |||
428 | mVideoSink = NULL; | ||
429 | |||
430 | return TRUE; | ||
431 | } | ||
432 | |||
433 | /////////////////////////////////////////////////////////////////////////////// | ||
434 | // | ||
435 | S32 | ||
436 | LLMediaImplGStreamer:: | ||
437 | updateMedia () | ||
438 | { | ||
439 | //llinfos << "updating media..." << llendl; | ||
440 | if (g_main_context_pending(g_main_loop_get_context(mPump))) | ||
441 | { | ||
442 | g_main_context_iteration(g_main_loop_get_context(mPump), FALSE); | ||
443 | } | ||
444 | |||
445 | if (mVideoSink) | ||
446 | { | ||
447 | GST_OBJECT_LOCK(mVideoSink); | ||
448 | if (mVideoSink->retained_frame_ready) | ||
449 | { | ||
450 | //llinfos << "NEW FRAME " << llendl; | ||
451 | if (mVideoSink->retained_frame_width != mMediaWidth || | ||
452 | mVideoSink->retained_frame_height != mMediaHeight) | ||
453 | // *TODO: also check for change in format | ||
454 | { | ||
455 | // just resize container | ||
456 | mMediaWidth = mVideoSink->retained_frame_width; | ||
457 | mMediaHeight = mVideoSink->retained_frame_height; | ||
458 | mTextureWidth = mMediaWidth; | ||
459 | mTextureHeight = mMediaHeight; | ||
460 | mMediaDepthBytes = mTextureDepth = | ||
461 | SLVPixelFormatBytes[mVideoSink->retained_frame_format]; | ||
462 | if (SLV_PF_RGBX == mVideoSink->retained_frame_format) | ||
463 | { | ||
464 | mTextureFormatPrimary = GL_RGBA; | ||
465 | mTextureFormatType=GL_UNSIGNED_INT_8_8_8_8_REV; | ||
466 | } | ||
467 | else | ||
468 | { | ||
469 | mTextureFormatPrimary = GL_BGRA; | ||
470 | mTextureFormatType=GL_UNSIGNED_INT_8_8_8_8_REV; | ||
471 | } | ||
472 | mMediaRowbytes = mMediaWidth * mMediaDepthBytes; | ||
473 | llinfos << "video container resized to " << | ||
474 | mMediaWidth << "x" << mMediaHeight << llendl; | ||
475 | |||
476 | if (ownBuffer) | ||
477 | { | ||
478 | // we manage the buffer, so we need to realloc | ||
479 | delete[] mediaData; | ||
480 | mediaData = new U8[mMediaRowbytes * | ||
481 | mMediaHeight]; | ||
482 | } | ||
483 | |||
484 | GST_OBJECT_UNLOCK(mVideoSink); | ||
485 | return updateMediaNeedsSizeChange; | ||
486 | } | ||
487 | |||
488 | // we're gonna totally consume this frame - reset 'ready' flag | ||
489 | mVideoSink->retained_frame_ready = FALSE; | ||
490 | memcpy(mediaData, mVideoSink->retained_frame_data, | ||
491 | mMediaRowbytes * mMediaHeight); | ||
492 | |||
493 | GST_OBJECT_UNLOCK(mVideoSink); | ||
494 | return updateMediaNeedsUpdate; | ||
495 | } | ||
496 | else | ||
497 | { | ||
498 | // nothing to do yet. | ||
499 | GST_OBJECT_UNLOCK(mVideoSink); | ||
500 | return updateMediaNoChanges; | ||
501 | } | ||
502 | } | ||
503 | |||
504 | return updateMediaNoChanges; | ||
505 | } | ||
506 | |||
507 | /////////////////////////////////////////////////////////////////////////////// | ||
508 | // | ||
509 | void | ||
510 | LLMediaImplGStreamer:: | ||
511 | setAutoScaled ( BOOL autoScaledIn ) | ||
512 | { | ||
513 | autoScaled = autoScaledIn; | ||
514 | } | ||
515 | |||
516 | /////////////////////////////////////////////////////////////////////////////// | ||
517 | // | ||
518 | BOOL | ||
519 | LLMediaImplGStreamer:: | ||
520 | stop () | ||
521 | { | ||
522 | llinfos << "stopping media..." << llendl; | ||
523 | // todo: error-check this? | ||
524 | llgst_element_set_state(mPlaybin, GST_STATE_READY); | ||
525 | |||
526 | BOOL rtn = LLMediaMovieBase::stop(); | ||
527 | setCurrentMode(LLMediaImplGStreamer::ModeStopped);//? | ||
528 | return rtn; | ||
529 | } | ||
530 | |||
531 | /////////////////////////////////////////////////////////////////////////////// | ||
532 | // | ||
533 | BOOL | ||
534 | LLMediaImplGStreamer:: | ||
535 | play () | ||
536 | { | ||
537 | llinfos << "playing media..." << llendl; | ||
538 | // todo: error-check this? | ||
539 | llgst_element_set_state(mPlaybin, GST_STATE_PLAYING); | ||
540 | |||
541 | return LLMediaMovieBase::play(); | ||
542 | } | ||
543 | |||
544 | /////////////////////////////////////////////////////////////////////////////// | ||
545 | // | ||
546 | BOOL | ||
547 | LLMediaImplGStreamer:: | ||
548 | loop ( S32 howMany ) | ||
549 | { | ||
550 | llinfos << "looping media... " << howMany << llendl; | ||
551 | // todo: implement this | ||
552 | if (!play()) | ||
553 | return FALSE; | ||
554 | |||
555 | return LLMediaMovieBase::loop(howMany); | ||
556 | }; | ||
557 | |||
558 | /////////////////////////////////////////////////////////////////////////////// | ||
559 | // | ||
560 | BOOL | ||
561 | LLMediaImplGStreamer:: | ||
562 | pause () | ||
563 | { | ||
564 | llinfos << "pausing media..." << llendl; | ||
565 | // todo: error-check this? | ||
566 | llgst_element_set_state(mPlaybin, GST_STATE_PAUSED); | ||
567 | |||
568 | return LLMediaMovieBase::pause(); | ||
569 | }; | ||
570 | |||
571 | /////////////////////////////////////////////////////////////////////////////// | ||
572 | // | ||
573 | BOOL | ||
574 | LLMediaImplGStreamer:: | ||
575 | setVolume ( F32 volumeIn ) | ||
576 | { | ||
577 | mVolume = volumeIn; | ||
578 | g_object_set(mPlaybin, "volume", mVolume, NULL); | ||
579 | return TRUE; | ||
580 | } | ||
581 | |||
582 | /////////////////////////////////////////////////////////////////////////////// | ||
583 | // | ||
584 | F32 | ||
585 | LLMediaImplGStreamer:: | ||
586 | getVolume () | ||
587 | { | ||
588 | return mVolume; | ||
589 | } | ||
590 | |||
591 | /////////////////////////////////////////////////////////////////////////////// | ||
592 | // | ||
593 | BOOL | ||
594 | LLMediaImplGStreamer:: | ||
595 | isIdle () const | ||
596 | { | ||
597 | // todo: probably semantically decouple from currentMode | ||
598 | return currentMode == ModeIdle; | ||
599 | } | ||
600 | |||
601 | /////////////////////////////////////////////////////////////////////////////// | ||
602 | // | ||
603 | BOOL | ||
604 | LLMediaImplGStreamer:: | ||
605 | isError () const | ||
606 | { | ||
607 | // todo: probably semantically decouple from currentMode | ||
608 | return currentMode == ModeError; | ||
609 | } | ||
610 | |||
611 | /////////////////////////////////////////////////////////////////////////////// | ||
612 | // | ||
613 | BOOL | ||
614 | LLMediaImplGStreamer:: | ||
615 | isBuffering () const | ||
616 | { | ||
617 | // todo: probably semantically decouple from currentMode | ||
618 | return currentMode == ModeBuffering; | ||
619 | } | ||
620 | |||
621 | /////////////////////////////////////////////////////////////////////////////// | ||
622 | // | ||
623 | BOOL | ||
624 | LLMediaImplGStreamer:: | ||
625 | isLoaded () const | ||
626 | { | ||
627 | // todo: probably semantically decouple from currentMode | ||
628 | //return currentMode == ModeLoaded; | ||
629 | return (mPump != NULL); | ||
630 | } | ||
631 | |||
632 | /////////////////////////////////////////////////////////////////////////////// | ||
633 | // | ||
634 | BOOL | ||
635 | LLMediaImplGStreamer:: | ||
636 | isPlaying () const | ||
637 | { | ||
638 | // todo: probably semantically decouple from currentMode | ||
639 | return currentMode == ModePlaying; | ||
640 | } | ||
641 | |||
642 | /////////////////////////////////////////////////////////////////////////////// | ||
643 | // | ||
644 | BOOL | ||
645 | LLMediaImplGStreamer:: | ||
646 | isLooping () const | ||
647 | { | ||
648 | // todo: probably semantically decouple from currentMode | ||
649 | return currentMode == ModeLooping; | ||
650 | } | ||
651 | |||
652 | /////////////////////////////////////////////////////////////////////////////// | ||
653 | // | ||
654 | BOOL | ||
655 | LLMediaImplGStreamer:: | ||
656 | isPaused () const | ||
657 | { | ||
658 | // todo: probably semantically decouple from currentMode | ||
659 | return currentMode == ModePaused; | ||
660 | } | ||
661 | |||
662 | /////////////////////////////////////////////////////////////////////////////// | ||
663 | // | ||
664 | BOOL | ||
665 | LLMediaImplGStreamer:: | ||
666 | isStopped () const | ||
667 | { | ||
668 | // todo: probably semantically decouple from currentMode | ||
669 | return currentMode == ModeStopped; | ||
670 | } | ||
671 | |||
672 | /////////////////////////////////////////////////////////////////////////////// | ||
673 | // | ||
674 | U8* | ||
675 | LLMediaImplGStreamer:: | ||
676 | getMediaData () | ||
677 | { | ||
678 | return mediaData; | ||
679 | } | ||
680 | |||
681 | /////////////////////////////////////////////////////////////////////////////// | ||
682 | // | ||
683 | BOOL | ||
684 | LLMediaImplGStreamer:: | ||
685 | seek ( F64 time ) | ||
686 | { | ||
687 | // todo: implement this | ||
688 | llinfos << "Tried to seek to time " << time | ||
689 | << " - faking it" << llendl; | ||
690 | return TRUE; | ||
691 | } | ||
692 | |||
693 | /////////////////////////////////////////////////////////////////////////////// | ||
694 | // | ||
695 | F64 | ||
696 | LLMediaImplGStreamer:: | ||
697 | getTime () const | ||
698 | { | ||
699 | // todo: implement this | ||
700 | F64 result = 0; | ||
701 | return result; | ||
702 | } | ||
703 | |||
704 | /////////////////////////////////////////////////////////////////////////////// | ||
705 | // | ||
706 | F64 | ||
707 | LLMediaImplGStreamer:: | ||
708 | getMediaDuration () const | ||
709 | { | ||
710 | // todo: implement this | ||
711 | F64 result = 0; | ||
712 | return result; | ||
713 | } | ||
714 | |||
715 | #endif // LL_GSTREAMER_ENABLED | ||