31 #include <nsIFileURL.h>
32 #include <nsIInterfaceRequestorUtils.h>
33 #include <nsServiceManagerUtils.h>
34 #include <nsILocalFile.h>
37 #include <nsIRunnable.h>
38 #include <nsIIOService.h>
39 #include <nsIPrefBranch2.h>
40 #include <nsIObserver.h>
41 #include <nsThreadUtils.h>
47 #include <nsIBaseWindow.h>
48 #include <nsIBoxObject.h>
49 #include <nsIDocument.h>
50 #include <nsIDOMAbstractView.h>
51 #include <nsIDOMEvent.h>
52 #include <nsIDocShellTreeItem.h>
53 #include <nsIDocShellTreeOwner.h>
54 #include <nsIDOMDocument.h>
55 #include <nsIDOMDocumentView.h>
56 #include <nsIDOMEventTarget.h>
57 #include <nsIDOMXULElement.h>
58 #include <nsIScriptGlobalObject.h>
59 #include <nsIWebNavigation.h>
60 #include <nsIWidget.h>
70 #include <sbIMediacorePlaybackControl.h>
71 #include <sbIMediacoreManager.h>
72 #include <sbIGStreamerService.h>
73 #include <sbIMediaItem.h>
77 #include <gst/pbutils/missing-plugins.h>
79 #include "nsNetUtil.h"
83 #ifdef MOZ_WIDGET_GTK2
99 #define MAX_FILE_SIZE_FOR_ACCURATE_SEEK (20 * 1024 * 1024)
101 #define EQUALIZER_FACTORY_NAME "equalizer-10bands"
103 #define EQUALIZER_DEFAULT_BAND_COUNT \
104 sbBaseMediacoreMultibandEqualizer::EQUALIZER_BAND_COUNT_DEFAULT
106 #define EQUALIZER_BANDS \
107 sbBaseMediacoreMultibandEqualizer::EQUALIZER_BANDS_10
117 static PRLogModuleInfo* gGStreamerMediacore =
118 PR_NewLogModule(
"sbGStreamerMediacore");
121 if (gGStreamerMediacore) \
122 PR_LOG(gGStreamerMediacore, PR_LOG_WARNING, args)
124 #define TRACE(args) \
125 if (gGStreamerMediacore) \
126 PR_LOG(gGStreamerMediacore, PR_LOG_DEBUG, args)
153 sbIMediacoreMultibandEqualizer,
154 sbIMediacorePlaybackControl,
155 sbIMediacoreVideoWindow,
156 sbIMediacoreVolumeControl,
157 sbIMediacoreVotingParticipant,
158 sbIGStreamerMediacore,
159 sbIMediacoreEventTarget)
164 sbGStreamerMediacore::sbGStreamerMediacore() :
166 mIsVideoSupported(PR_FALSE),
168 mPlatformInterface(nsnull),
170 mReplaygainElement(nsnull),
171 mEqualizerElement(nsnull),
175 mBuffering(PR_FALSE),
177 mMediacoreError(NULL),
178 mTargetState(GST_STATE_NULL),
179 mVideoDisabled(PR_FALSE),
180 mVideoSinkDescription(),
181 mAudioSinkDescription(),
182 mAudioSinkBufferTime(0),
183 mStreamingBufferSize(0),
184 mResourceIsLocal(PR_FALSE),
186 mGaplessDisabled(PR_FALSE),
187 mPlayingGaplessly(PR_FALSE),
188 mAbortingPlayback(PR_FALSE),
189 mHasReachedPlaying(PR_FALSE),
190 mCurrentAudioCaps(NULL),
191 mAudioBinGhostPad(NULL),
196 NS_WARN_IF_FALSE(mBaseEventTarget,
197 "mBaseEventTarget is null, may be out of memory");
203 gst_tag_list_free(
mTags);
211 std::vector<GstElement *>::const_iterator it =
mAudioFilters.begin();
213 gst_object_unref (*it);
216 nsAutoMonitor::DestroyMonitor(
mMonitor);
224 mMonitor = nsAutoMonitor::NewMonitor(
"sbGStreamerMediacore::mMonitor");
225 NS_ENSURE_TRUE(
mMonitor, NS_ERROR_OUT_OF_MEMORY);
228 NS_ENSURE_SUCCESS(rv, rv);
231 NS_ENSURE_SUCCESS(rv, rv);
234 NS_ENSURE_SUCCESS(rv, rv);
237 NS_ENSURE_SUCCESS(rv, rv);
240 NS_ENSURE_SUCCESS(rv, rv);
242 nsCOMPtr<sbIMediacore> core = do_QueryInterface(
244 NS_ENSURE_SUCCESS(rv, rv);
246 #if defined (MOZ_WIDGET_GTK2)
249 #elif defined (XP_WIN)
252 #elif defined (XP_MACOSX)
256 LOG((
"No video backend available for this platform"));
268 NS_ENSURE_SUCCESS (rv, rv);
270 rv =
mPrefs->AddObserver(
"songbird.mediacore",
this, PR_FALSE);
271 NS_ENSURE_SUCCESS(rv, rv);
274 NS_ENSURE_SUCCESS(rv, rv);
285 rv =
mPrefs->GetBoolPref(
"songbird.mediacore.gstreamer.disablevideo",
287 if (rv == NS_ERROR_UNEXPECTED)
290 NS_ENSURE_SUCCESS(rv, rv);
293 const char *VIDEO_SINK_PREF =
"songbird.mediacore.gstreamer.videosink";
294 const char *AUDIO_SINK_PREF =
"songbird.mediacore.gstreamer.audiosink";
296 rv =
mPrefs->GetPrefType(VIDEO_SINK_PREF, &prefType);
297 NS_ENSURE_SUCCESS(rv, rv);
298 if (prefType == nsIPrefBranch::PREF_STRING) {
299 rv =
mPrefs->GetCharPref(VIDEO_SINK_PREF,
301 NS_ENSURE_SUCCESS(rv, rv);
304 rv =
mPrefs->GetPrefType(AUDIO_SINK_PREF, &prefType);
305 NS_ENSURE_SUCCESS(rv, rv);
306 if (prefType == nsIPrefBranch::PREF_STRING) {
307 rv =
mPrefs->GetCharPref(AUDIO_SINK_PREF,
309 NS_ENSURE_SUCCESS(rv, rv);
313 const char *AUDIO_SINK_BUFFERTIME_PREF =
314 "songbird.mediacore.output.buffertime";
316 const char *STREAMING_BUFFERSIZE_PREF =
317 "songbird.mediacore.streaming.buffersize";
320 PRInt64 audioSinkBufferTime = 1000 * 1000;
321 PRInt32 streamingBufferSize = 256 * 1024;
323 rv =
mPrefs->GetPrefType(AUDIO_SINK_BUFFERTIME_PREF, &prefType);
324 NS_ENSURE_SUCCESS(rv, rv);
325 if (prefType == nsIPrefBranch::PREF_INT) {
327 rv =
mPrefs->GetIntPref(AUDIO_SINK_BUFFERTIME_PREF, &time);
328 NS_ENSURE_SUCCESS(rv, rv);
331 if(time >= 100 || time <= 10000) {
333 audioSinkBufferTime = time * 1000;
337 rv =
mPrefs->GetPrefType(STREAMING_BUFFERSIZE_PREF, &prefType);
338 NS_ENSURE_SUCCESS(rv, rv);
339 if (prefType == nsIPrefBranch::PREF_INT) {
340 rv =
mPrefs->GetIntPref(STREAMING_BUFFERSIZE_PREF, &streamingBufferSize);
341 NS_ENSURE_SUCCESS(rv, rv);
343 streamingBufferSize *= 1024;
349 const char *NORMALIZATION_ENABLED_PREF =
350 "songbird.mediacore.normalization.enabled";
351 const char *NORMALIZATION_MODE_PREF =
352 "songbird.mediacore.normalization.preferredGain";
353 PRBool normalizationEnabled = PR_TRUE;
354 rv =
mPrefs->GetPrefType(NORMALIZATION_ENABLED_PREF, &prefType);
355 NS_ENSURE_SUCCESS(rv, rv);
356 if (prefType == nsIPrefBranch::PREF_BOOL) {
357 rv =
mPrefs->GetBoolPref(NORMALIZATION_ENABLED_PREF, &normalizationEnabled);
358 NS_ENSURE_SUCCESS(rv, rv);
361 if (normalizationEnabled) {
371 NS_ENSURE_SUCCESS(rv, rv);
375 nsCString normalizationMode;
376 rv =
mPrefs->GetPrefType(NORMALIZATION_MODE_PREF, &prefType);
377 NS_ENSURE_SUCCESS(rv, rv);
378 if (prefType == nsIPrefBranch::PREF_STRING) {
379 rv =
mPrefs->GetCharPref(NORMALIZATION_MODE_PREF,
380 getter_Copies(normalizationMode));
381 NS_ENSURE_SUCCESS(rv, rv);
384 if (normalizationMode.EqualsLiteral(
"track")) {
394 NS_ENSURE_SUCCESS(rv, rv);
408 sbGStreamerMediacore::aboutToFinishHandler(GstElement *playbin, gpointer
data)
419 if (aSinkDescription && *aSinkDescription)
421 GstElement *sink = gst_parse_bin_from_description (aSinkDescription,
435 nsCOMPtr<nsIFileURL> fileUrl = do_QueryInterface(aURI, &rv);
436 if (rv != NS_ERROR_NO_INTERFACE) {
437 NS_ENSURE_SUCCESS (rv, rv);
439 nsCOMPtr<nsIFile>
file;
440 rv = fileUrl->GetFile(getter_AddRefs(file));
441 NS_ENSURE_SUCCESS(rv, rv);
443 rv = file->GetFileSize(aFileSize);
444 NS_ENSURE_SUCCESS (rv, rv);
472 GstElement *sinkbin = gst_bin_new (
"audiosink-bin");
474 GstPad *targetpad, *ghostpad;
494 gst_bin_add ((GstBin *)sinkbin, audiosink);
496 targetpad = gst_element_get_pad (audiosink,
"sink");
501 std::vector<GstElement *>::const_reverse_iterator it =
mAudioFilters.rbegin(),
503 for ( ; it != end; ++it)
505 GstElement *audioconvert = gst_element_factory_make (
"audioconvert", NULL);
507 GstPad *srcpad, *sinkpad;
509 gst_bin_add_many ((GstBin *)sinkbin, filter, audioconvert, NULL);
511 srcpad = gst_element_get_pad (filter,
"src");
512 sinkpad = gst_element_get_pad (audioconvert,
"sink");
513 gst_pad_link (srcpad, sinkpad);
514 gst_object_unref (srcpad);
515 gst_object_unref (sinkpad);
517 srcpad = gst_element_get_pad (audioconvert,
"src");
518 gst_pad_link (srcpad, targetpad);
519 gst_object_unref (targetpad);
520 gst_object_unref (srcpad);
522 targetpad = gst_element_get_pad (filter,
"sink");
527 ghostpad = gst_ghost_pad_new (
"sink", targetpad);
528 gst_element_add_pad (sinkbin, ghostpad);
532 gst_object_unref (targetpad);
538 sbGStreamerMediacore::currentAudioSetHelper(GObject* obj, GParamSpec* pspec,
548 g_object_get(obj,
"current-audio", ¤t_audio, NULL);
549 NS_ASSERTION(current_audio >= 0,
"current audio is negative");
552 g_signal_emit_by_name(obj,
"get-audio-pad", current_audio, &pad);
556 caps = gst_pad_get_negotiated_caps(pad);
559 gst_caps_unref(caps);
562 g_signal_connect(pad,
"notify::caps",
563 G_CALLBACK(audioCapsSetHelper), core);
565 gst_object_unref(pad);
570 sbGStreamerMediacore::audioCapsSetHelper(GObject* obj, GParamSpec* pspec,
573 GstPad *pad = GST_PAD(obj);
574 GstCaps *caps = gst_pad_get_negotiated_caps(pad);
578 gst_caps_unref (caps);
583 sbGStreamerMediacore::currentVideoSetHelper(GObject* obj, GParamSpec* pspec,
593 g_object_get(obj,
"current-video", ¤t_video, NULL);
594 NS_ASSERTION(current_video >= 0,
"current video is negative");
597 g_signal_emit_by_name(obj,
"get-video-pad", current_video, &pad);
601 caps = gst_pad_get_negotiated_caps(pad);
604 gst_caps_unref(caps);
607 g_signal_connect(pad,
"notify::caps",
608 G_CALLBACK(videoCapsSetHelper), core);
610 gst_object_unref(pad);
615 sbGStreamerMediacore::videoCapsSetHelper(GObject* obj, GParamSpec* pspec,
618 GstPad *pad = GST_PAD(obj);
619 GstCaps *caps = gst_pad_get_negotiated_caps(pad);
623 gst_caps_unref (caps);
630 GstElement *pipeline = NULL;
633 pipeline = (GstElement *)g_object_ref (
mPipeline);
638 gst_element_set_state (pipeline, GST_STATE_NULL);
639 gst_object_unref (pipeline);
647 std::vector<GstElement *>::const_iterator it =
mAudioFilters.begin();
653 parent = (GstElement *)gst_element_get_parent (filter);
655 gst_bin_remove ((GstBin *)parent, filter);
656 gst_object_unref (parent);
672 gst_tag_list_free (
mTags);
701 NS_ENSURE_ARG_POINTER(aPipeline);
703 if (g_object_class_find_property(
704 G_OBJECT_GET_CLASS (aPipeline),
"buffer-size"))
714 const char *aPropertyName, gint64 aPropertyValue)
719 if (g_object_class_find_property(
720 G_OBJECT_GET_CLASS (aElement), aPropertyName))
722 g_object_set (aElement, aPropertyName, aPropertyValue, NULL);
726 if (GST_IS_BIN (aElement)) {
728 GstIterator *it = gst_bin_iterate_sorted ((GstBin *)aElement);
733 switch (gst_iterator_next (it, &data)) {
734 case GST_ITERATOR_OK:
735 child = GST_ELEMENT_CAST (data);
737 aPropertyName, aPropertyValue))
742 gst_object_unref (child);
744 case GST_ITERATOR_DONE:
747 case GST_ITERATOR_RESYNC:
748 gst_iterator_resync (it);
750 case GST_ITERATOR_ERROR:
756 gst_iterator_free (it);
770 NS_ENSURE_SUCCESS (rv, rv);
773 mPipeline = gst_element_factory_make (
"playbin2",
"player");
776 return NS_ERROR_FAILURE;
782 g_object_set(
mPipeline,
"audio-sink", audiosink, NULL);
790 g_object_set(
mPipeline,
"video-sink", videosink, NULL);
802 g_object_set (G_OBJECT(
mPipeline),
"flags", flags, NULL);
804 GstBus *bus = gst_element_get_bus (
mPipeline);
808 g_object_set(
mPipeline,
"auto-flush-bus", FALSE, NULL);
811 NS_ENSURE_SUCCESS (rv, rv);
816 static_cast<sbGStreamerMessageHandler*>(
this));
818 g_object_unref ((GObject *)bus);
821 g_signal_connect (
mPipeline,
"about-to-finish",
822 G_CALLBACK (aboutToFinishHandler),
this);
826 g_signal_connect (
mPipeline,
"notify::current-video",
827 G_CALLBACK (currentVideoSetHelper),
this);
828 g_signal_connect (
mPipeline,
"notify::current-audio",
829 G_CALLBACK (currentAudioSetHelper),
this);
836 GstMessageType msg_type;
837 msg_type = GST_MESSAGE_TYPE(aMessage);
841 TRACE((
"Dropping message due to abort\n"));
846 case GST_MESSAGE_ELEMENT: {
849 if (gst_structure_has_name(aMessage->structure,
"prepare-xwindow-id") ||
850 gst_structure_has_name(aMessage->structure,
"have-ns-view"))
872 nsCOMPtr<sbIMediacoreEvent>
event;
877 getter_AddRefs(event));
878 NS_ENSURE_SUCCESS(rv, );
880 rv = DispatchEvent(event, PR_TRUE, nsnull);
881 NS_ENSURE_SUCCESS(rv, );
886 LOG((
"Handling about-to-finish signal"));
893 LOG((
"Ignoring about-to-finish signal"));
904 nsCOMPtr<sbIMediaItem> item;
905 nsresult rv = sequencer->GetNextItem(getter_AddRefs(item));
906 NS_ENSURE_SUCCESS(rv, );
907 NS_ENSURE_TRUE(item, );
912 NS_ENSURE_SUCCESS(rv, );
914 if(StringBeginsWith(contentURL, NS_LITERAL_STRING(
"file:"))) {
915 rv = sequencer->RequestHandleNextItem(
this);
916 NS_ENSURE_SUCCESS(rv, );
922 gst_tag_list_free (
mTags);
928 nsCOMPtr<nsIURI> itemuri;
929 rv = item->GetContentSrc(getter_AddRefs(itemuri));
930 NS_ENSURE_SUCCESS (rv, );
935 nsCString
uri = NS_ConvertUTF16toUTF8(contentURL);
936 LOG((
"Setting URI to \"%s\"", uri.BeginReading()));
940 g_object_set (G_OBJECT (
mPipeline),
"uri", uri.BeginReading(), NULL);
956 GstTagList *tag_list;
959 LOG((
"Handling tag message"));
960 gst_message_parse_tag(message, &tag_list);
963 GstTagList *newTags = gst_tag_list_merge (
mTags, tag_list,
964 GST_TAG_MERGE_REPLACE);
965 gst_tag_list_free (
mTags);
969 mTags = gst_tag_list_copy (tag_list);
972 gst_tag_list_free(tag_list);
974 if (NS_SUCCEEDED (rv)) {
975 nsCOMPtr<nsISupports> properties = do_QueryInterface(
mProperties, &rv);
976 NS_ENSURE_SUCCESS (rv, );
981 LOG((
"Failed to convert"));
987 if (GST_IS_PIPELINE (message->src))
989 GstState oldstate, newstate, pendingstate;
990 gst_message_parse_state_changed (message,
991 &oldstate, &newstate, &pendingstate);
994 if (pendingstate == GST_STATE_VOID_PENDING && newstate ==
mTargetState) {
995 if (newstate == GST_STATE_PLAYING) {
999 else if (newstate == GST_STATE_PAUSED)
1001 else if (newstate == GST_STATE_NULL)
1020 else if (pendingstate == GST_STATE_VOID_PENDING)
1024 if (newstate == GST_STATE_PAUSED &&
mTargetState == GST_STATE_PLAYING &&
1027 gst_element_set_state (
mPipeline, GST_STATE_PLAYING);
1039 gst_message_parse_buffering (message, &percent);
1040 TRACE((
"Buffering (%u percent done)", percent));
1064 TRACE((
"Buffering complete, setting state to playing"));
1065 gst_element_set_state (
mPipeline, GST_STATE_PLAYING);
1068 TRACE((
"Buffering complete, setting state to paused"));
1072 else if (percent < maxpercent) {
1074 gst_element_get_state (
mPipeline, &cur_state, NULL, 0);
1078 if (!
mBuffering && cur_state == GST_STATE_PLAYING) {
1079 TRACE((
"Buffering... setting to paused"));
1080 gst_element_set_state (
mPipeline, GST_STATE_PAUSED);
1089 double bufferingProgress = (double)percent / (
double)maxpercent;
1099 const gchar *location;
1101 nsCString uriString;
1103 location = gst_structure_get_string (message->structure,
"new-location");
1105 if (location && *location) {
1106 if (strstr (location,
"://") != NULL) {
1108 uriString = location;
1111 TRACE ((
"Resolving redirect to '%s'", location));
1113 rv =
mUri->Resolve(nsDependentCString(location), uriString);
1114 NS_ENSURE_SUCCESS (rv, );
1118 nsCOMPtr<nsIIOService>
ioService = do_GetService(
1119 "@mozilla.org/network/io-service;1", &rv);
1120 NS_ENSURE_SUCCESS (rv, );
1122 nsCOMPtr<nsIURI> finaluri;
1123 rv = ioService->NewURI(uriString, nsnull, nsnull,
1124 getter_AddRefs(finaluri));
1125 NS_ENSURE_SUCCESS (rv, );
1128 rv = finaluri->Equals(
mUri, &isEqual);
1129 NS_ENSURE_SUCCESS (rv, );
1137 rv = SetUri(finaluri);
1138 NS_ENSURE_SUCCESS (rv, );
1146 NS_ENSURE_SUCCESS (rv, );
1152 nsCOMPtr<sbMediacoreError> error;
1153 gchar *debugMessage;
1154 nsString errorMessage;
1156 nsString stringName;
1159 nsTArray<nsString> params;
1161 NS_ASSERTION(NS_IsMainThread(),
"not on main thread");
1166 debugMessage = gst_missing_plugin_message_get_description(message);
1168 stringName = NS_LITERAL_STRING(
"mediacore.error.known_codec_not_found");
1169 params.AppendElement(NS_ConvertUTF8toUTF16(debugMessage));
1170 g_free(debugMessage);
1172 stringName = NS_LITERAL_STRING(
"mediacore.error.codec_not_found");
1176 nsCOMPtr<sbIMediacoreSequencer>
sequencer;
1185 nsCOMPtr<sbIMediaItem> item;
1186 nsresult rv = sequencer->GetCurrentItem(getter_AddRefs(item));
1187 if (NS_SUCCEEDED(rv) && item) {
1188 nsString trackNameProp;
1191 if (NS_SUCCEEDED(rv)) {
1192 nsAutoString stripped (trackNameProp);
1193 CompressWhitespace(stripped);
1194 if (!stripped.IsEmpty()) {
1196 if (NS_SUCCEEDED(rv)) {
1197 params.InsertElementAt(0, trackNameProp);
1198 errorMessage = bundle.
Format(stringName, params);
1212 nsCOMPtr<nsIURI>
uri;
1213 rv = GetUri(getter_AddRefs(uri));
1214 NS_ENSURE_SUCCESS(rv, );
1216 nsCOMPtr<nsIFileURL>
url = do_QueryInterface(uri, &rv);
1217 if (NS_SUCCEEDED(rv))
1219 nsCOMPtr<nsIFile>
file;
1222 rv = url->GetFile(getter_AddRefs(file));
1223 if (NS_SUCCEEDED(rv))
1225 rv = file->GetPath(path);
1227 if (NS_SUCCEEDED(rv)) {
1229 if (NS_SUCCEEDED(rv)) {
1230 params.InsertElementAt(0, path);
1231 errorMessage = bundle.
Format(stringName, params);
1244 rv = uri->GetSpec(temp);
1245 if (NS_SUCCEEDED(rv))
1246 spec = NS_ConvertUTF8toUTF16(temp);
1251 if (NS_SUCCEEDED(rv)) {
1252 params.InsertElementAt(0, spec);
1253 errorMessage = bundle.
Format(stringName, params);
1259 NS_ENSURE_SUCCESS(rv, );
1275 GstElement *pipeline = (GstElement *)g_object_ref (
mPipeline);
1278 gst_element_set_state (pipeline, GST_STATE_NULL);
1279 g_object_unref (pipeline);
1288 GstElement *pipeline = (GstElement *)g_object_ref (
mPipeline);
1294 gst_element_set_state (pipeline, GST_STATE_NULL);
1295 g_object_unref (pipeline);
1300 GError *gerror = NULL;
1301 nsString errormessage;
1302 nsCOMPtr<sbIMediacoreError> error;
1303 nsCOMPtr<sbIMediacoreEvent>
event;
1304 gchar *debugMessage;
1305 nsresult rv = NS_ERROR_UNEXPECTED;
1307 NS_ASSERTION(NS_IsMainThread(),
"not on main thread");
1309 gst_message_parse_error(message, &gerror, &debugMessage);
1314 nsCOMPtr<sbIMediacoreSequencer>
sequencer;
1323 nsCOMPtr<sbIMediaItem> item;
1324 rv = sequencer->GetCurrentItem(getter_AddRefs(item));
1325 if (NS_SUCCEEDED(rv) && item) {
1326 nsString trackNameProp;
1329 if (NS_SUCCEEDED(rv)) {
1330 nsAutoString stripped (trackNameProp);
1331 CompressWhitespace(stripped);
1334 getter_AddRefs(error));
1343 if (NS_FAILED(rv)) {
1345 nsCOMPtr<nsIURI>
uri;
1346 rv = GetUri(getter_AddRefs(uri));
1347 NS_ENSURE_SUCCESS(rv, );
1349 nsCOMPtr<nsIFileURL>
url = do_QueryInterface(uri, &rv);
1350 if (NS_SUCCEEDED(rv))
1352 nsCOMPtr<nsIFile>
file;
1355 rv = url->GetFile(getter_AddRefs(file));
1356 if (NS_SUCCEEDED(rv))
1358 rv = file->GetPath(path);
1360 if (NS_SUCCEEDED(rv))
1363 getter_AddRefs(error));
1376 rv = uri->GetSpec(temp);
1377 if (NS_SUCCEEDED(rv))
1378 spec = NS_ConvertUTF8toUTF16(temp);
1384 getter_AddRefs(error));
1388 NS_ENSURE_SUCCESS(rv, );
1401 nsString errmessage = NS_LITERAL_STRING(
"GStreamer error: ");
1402 errmessage.Append(NS_ConvertUTF8toUTF16(gerror->message));
1403 errmessage.Append(NS_LITERAL_STRING(
" Additional information: "));
1404 errmessage.Append(NS_ConvertUTF8toUTF16(debugMessage));
1406 g_error_free (gerror);
1407 g_free (debugMessage);
1414 GstElement *pipeline = (GstElement *)g_object_ref (
mPipeline);
1417 gst_element_set_state (pipeline, GST_STATE_NULL);
1418 g_object_unref (pipeline);
1426 GError *gerror = NULL;
1427 gchar *debugMessage;
1429 NS_ASSERTION(NS_IsMainThread(),
"not on main thread");
1431 gst_message_parse_warning(message, &gerror, &debugMessage);
1435 nsString warning = NS_LITERAL_STRING(
"GStreamer warning: ");
1436 warning.Append(NS_ConvertUTF8toUTF16(gerror->message));
1437 warning.Append(NS_LITERAL_STRING(
" Additional information: "));
1438 warning.Append(NS_ConvertUTF8toUTF16(debugMessage));
1440 g_error_free (gerror);
1441 g_free (debugMessage);
1452 GstMessageType msg_type;
1453 msg_type = GST_MESSAGE_TYPE(message);
1455 LOG((
"Got message: %s", gst_message_type_get_name(msg_type)));
1458 case GST_MESSAGE_STATE_CHANGED:
1461 case GST_MESSAGE_TAG:
1464 case GST_MESSAGE_ERROR:
1467 case GST_MESSAGE_WARNING:
1470 case GST_MESSAGE_EOS:
1473 case GST_MESSAGE_BUFFERING:
1475 case GST_MESSAGE_ELEMENT: {
1476 if (gst_structure_has_name (message->structure,
"redirect")) {
1478 }
else if (gst_is_missing_plugin_message(message)) {
1484 LOG((
"Got message: %s", gst_message_type_get_name(msg_type)));
1493 PRUint32 videoWidth = 0;
1494 PRUint32 videoHeight = 0;
1496 nsCOMPtr<sbIMediacoreManager> mediacoreManager =
1498 NS_ENSURE_SUCCESS(rv, );
1502 NS_ENSURE_SUCCESS(rv, );
1504 NS_ENSURE_SUCCESS(rv, );
1506 PRUint32 parNum, parDenom;
1508 NS_ENSURE_SUCCESS(rv, );
1509 rv =
mVideoSize->GetParDenominator(&parDenom);
1510 NS_ENSURE_SUCCESS(rv, );
1514 videoWidth = videoWidth * parNum / parDenom;
1518 rv = mediacoreManager->GetPrimaryVideoWindow(PR_TRUE, videoWidth, videoHeight,
1519 getter_AddRefs(videoWindow));
1520 NS_ENSURE_SUCCESS(rv, );
1522 if (videoWindow != NULL) {
1523 nsCOMPtr<nsIDOMXULElement> videoDOMElement;
1524 rv = videoWindow->GetVideoWindow(getter_AddRefs(videoDOMElement));
1525 NS_ENSURE_SUCCESS(rv, );
1529 rv = SetVideoWindow(videoDOMElement);
1530 NS_ENSURE_SUCCESS(rv, );
1541 gint pixelAspectRatioN, pixelAspectRatioD;
1542 gint videoWidth, videoHeight;
1544 s = gst_caps_get_structure(caps, 0);
1546 gst_structure_get_int(s,
"width", &videoWidth);
1547 gst_structure_get_int(s,
"height", &videoHeight);
1550 const GValue* par = gst_structure_get_value(s,
"pixel-aspect-ratio");
1552 pixelAspectRatioN = gst_value_get_fraction_numerator(par);
1553 pixelAspectRatioD = gst_value_get_fraction_denominator(par);
1557 pixelAspectRatioN = pixelAspectRatioD = 1;
1561 int num = videoWidth * pixelAspectRatioN;
1562 int denom = videoHeight * pixelAspectRatioD;
1570 pixelAspectRatioN = pixelAspectRatioD = 0;
1580 nsCOMPtr<nsIRunnable> abort =
1583 NS_DispatchToMainThread(abort);
1589 nsRefPtr<sbVideoBox> videoBox;
1591 NS_ENSURE_TRUE(videoBox, );
1593 nsresult rv = videoBox->Init(videoWidth,
1597 NS_ENSURE_SUCCESS(rv, );
1602 mVideoSize = do_QueryInterface(videoBox, &rv);
1603 NS_ENSURE_SUCCESS(rv, );
1614 nsCOMPtr<nsIRunnable> abort =
1617 NS_DispatchToMainThread(abort);
1628 nsresult rv = Stop();
1629 NS_ENSURE_SUCCESS (rv, );
1633 NS_ENSURE_SUCCESS (rv, );
1639 g_object_set (G_OBJECT (
mPipeline),
"volume", 0.0, NULL);
1646 NS_ENSURE_SUCCESS (rv, );
1659 nsCOMPtr<sbIGStreamerService>
service =
1661 NS_ENSURE_SUCCESS(rv, rv);
1670 return NS_ERROR_NOT_IMPLEMENTED;
1679 LOG ((
"Destroying pipeline on shutdown"));
1684 nsresult rv =
mPrefs->RemoveObserver(
"songbird.mediacore.gstreamer",
this);
1685 NS_ENSURE_SUCCESS(rv, rv);
1708 char band[16] = {0};
1710 GValue freqVal = {0};
1711 g_value_init (&freqVal, G_TYPE_DOUBLE);
1714 PR_snprintf (band, 16,
"band%i::freq",
i);
1721 g_value_unset (&freqVal);
1741 double bandGain = 0;
1746 PR_snprintf (band, 8,
"band%i",
i);
1757 NS_ENSURE_ARG_POINTER(aBandCount);
1775 NS_ENSURE_ARG_POINTER(aBand);
1785 PR_snprintf(band, 8,
"band%i", aBandIndex);
1787 gdouble bandGain = 0.0;
1790 nsresult rv = aBand->Init(aBandIndex,
EQUALIZER_BANDS[aBandIndex], bandGain);
1791 NS_ENSURE_SUCCESS(rv, rv);
1799 NS_ENSURE_ARG_POINTER(aBand);
1807 PRUint32 bandIndex = 0;
1808 nsresult rv = aBand->GetIndex(&bandIndex);
1809 NS_ENSURE_SUCCESS(rv, rv);
1811 double bandGain = 0.0;
1812 rv = aBand->GetGain(&bandGain);
1813 NS_ENSURE_SUCCESS(rv, rv);
1819 PR_snprintf(band, 8,
"band%i", bandIndex);
1845 NS_ENSURE_SUCCESS (rv,rv);
1849 rv = aURI->GetSpec(spec);
1850 NS_ENSURE_SUCCESS(rv, rv);
1853 if (rv == NS_ERROR_NO_INTERFACE) {
1861 LOG((
"Setting URI to \"%s\"", spec.get()));
1864 g_object_set (G_OBJECT (
mPipeline),
"uri", spec.get(), NULL);
1879 return NS_ERROR_NOT_AVAILABLE;
1881 query = gst_query_new_duration(GST_FORMAT_TIME);
1882 res = gst_element_query(
mPipeline, query);
1886 gst_query_parse_duration(query, NULL, &duration);
1888 if ((GstClockTime)duration == GST_CLOCK_TIME_NONE) {
1892 rv = NS_ERROR_NOT_AVAILABLE;
1896 *aDuration = duration / GST_MSECOND;
1901 rv = NS_ERROR_NOT_AVAILABLE;
1903 gst_query_unref (query);
1917 return NS_ERROR_NOT_AVAILABLE;
1919 query = gst_query_new_position(GST_FORMAT_TIME);
1920 res = gst_element_query(
mPipeline, query);
1924 gst_query_parse_position(query, NULL, &position);
1926 if (position == 0 || (GstClockTime)position == GST_CLOCK_TIME_NONE) {
1932 rv = NS_ERROR_NOT_AVAILABLE;
1936 *aPosition = position / GST_MSECOND;
1941 rv = NS_ERROR_NOT_AVAILABLE;
1943 gst_query_unref (query);
1964 position = aPosition * GST_MSECOND;
1977 flags = (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE);
1980 flags = (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT);
1983 ret = gst_element_seek_simple (
mPipeline, GST_FORMAT_TIME,
1989 return NS_ERROR_FAILURE;
1995 ret = gst_element_set_state (
mPipeline, GST_STATE_PAUSED);
1997 if (ret == GST_STATE_CHANGE_FAILURE)
1998 return NS_ERROR_FAILURE;
2001 NS_ENSURE_SUCCESS (rv, rv);
2010 *aIsPlayingAudio = PR_FALSE;
2023 *aIsPlayingVideo = PR_FALSE;
2035 GstStateChangeReturn
ret;
2041 gst_element_get_state (
mPipeline, &curstate, NULL, 0);
2045 if (curstate == GST_STATE_PAUSED && !
mBuffering) {
2048 ret = gst_element_set_state (
mPipeline, GST_STATE_PLAYING);
2055 ret = gst_element_set_state (
mPipeline, GST_STATE_PAUSED);
2058 NS_ENSURE_SUCCESS (rv, rv);
2065 if (ret == GST_STATE_CHANGE_FAILURE)
2067 else if (ret == GST_STATE_CHANGE_NO_PREROLL)
2084 PRBool schemeIsHttp;
2085 nsresult rv =
mUri->SchemeIs(
"http", &schemeIsHttp);
2086 NS_ENSURE_SUCCESS (rv, rv);
2089 double bufferingProgress = 0.0;
2100 GstStateChangeReturn
ret;
2107 ret = gst_element_set_state (
mPipeline, GST_STATE_PAUSED);
2109 if (ret == GST_STATE_CHANGE_FAILURE)
2110 return NS_ERROR_FAILURE;
2124 GstElement *pipeline = (GstElement *)g_object_ref (
mPipeline);
2127 gst_element_set_state (pipeline, GST_STATE_NULL);
2128 g_object_unref (pipeline);
2154 if(!aMute &&
mMute) {
2160 else if(aMute && !
mMute){
2163 g_object_set(
mPipeline,
"volume", 0.0, NULL);
2177 g_object_set(
mPipeline,
"volume", aVolume, NULL);
2187 sbGStreamerMediacore::VoteWithURI(nsIURI *aURI, PRUint32 *_retval)
2189 NS_ENSURE_ARG_POINTER(aURI);
2190 NS_ENSURE_ARG_POINTER(_retval);
2203 sbGStreamerMediacore::VoteWithChannel(
nsIChannel *aChannel, PRUint32 *_retval)
2205 return NS_ERROR_NOT_IMPLEMENTED;
2213 sbGStreamerMediacore::GetFullscreen(PRBool *aFullscreen)
2215 NS_ENSURE_ARG_POINTER(aFullscreen);
2223 return NS_ERROR_NOT_IMPLEMENTED;
2228 sbGStreamerMediacore::SetFullscreen(PRBool aFullscreen)
2236 return NS_ERROR_NOT_IMPLEMENTED;
2241 sbGStreamerMediacore::GetVideoWindow(nsIDOMXULElement **aVideoWindow)
2250 sbGStreamerMediacore::SetVideoWindow(nsIDOMXULElement *aVideoWindow)
2252 NS_ENSURE_ARG_POINTER(aVideoWindow);
2257 nsCOMPtr<nsIBoxObject> boxObject;
2258 nsresult rv = aVideoWindow->GetBoxObject(getter_AddRefs(boxObject));
2259 NS_ENSURE_SUCCESS (rv, rv);
2261 nsCOMPtr<nsIDOMDocument> domDocument;
2262 rv = aVideoWindow->GetOwnerDocument(getter_AddRefs(domDocument));
2263 NS_ENSURE_SUCCESS(rv, rv);
2265 nsCOMPtr<nsIDOMDocumentView> domDocumentView(do_QueryInterface(domDocument));
2266 NS_ENSURE_TRUE(domDocumentView, NS_NOINTERFACE);
2268 nsCOMPtr<nsIDOMAbstractView> domAbstractView;
2269 rv = domDocumentView->GetDefaultView(getter_AddRefs(domAbstractView));
2270 NS_ENSURE_SUCCESS(rv, rv);
2272 nsCOMPtr<nsIWebNavigation> webNavigation(do_GetInterface(domAbstractView));
2273 nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem(do_QueryInterface(webNavigation));
2274 NS_ENSURE_TRUE(docShellTreeItem, NS_NOINTERFACE);
2276 nsCOMPtr<nsIDocShellTreeOwner> docShellTreeOwner;
2277 rv = docShellTreeItem->GetTreeOwner(getter_AddRefs(docShellTreeOwner));
2278 NS_ENSURE_SUCCESS(rv, rv);
2280 nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(docShellTreeOwner);
2281 NS_ENSURE_TRUE(baseWindow, NS_NOINTERFACE);
2283 nsCOMPtr<nsIWidget>
widget;
2284 rv = baseWindow->GetMainWidget(getter_AddRefs(widget));
2285 NS_ENSURE_SUCCESS(rv, rv);
2288 nsCOMPtr<nsIDocument> document(do_QueryInterface(domDocument));
2289 NS_ENSURE_TRUE(document, NS_NOINTERFACE);
2291 mDOMWindow = do_QueryInterface(document->GetScriptGlobalObject());
2295 NS_ENSURE_TRUE(
target, NS_NOINTERFACE);
2296 target->AddEventListener(NS_LITERAL_STRING(
"resize"),
this, PR_FALSE);
2297 target->AddEventListener(NS_LITERAL_STRING(
"unload"),
this, PR_FALSE);
2298 target->AddEventListener(NS_LITERAL_STRING(
"hide"),
this, PR_FALSE);
2300 NS_WARN_IF_FALSE(NS_IsMainThread(),
"Wrong Thread!");
2306 NS_ENSURE_SUCCESS(rv, rv);
2309 NS_ENSURE_SUCCESS(rv, rv);
2320 sbGStreamerMediacore::GetGstreamerVersion(nsAString& aGStreamerVersion)
2322 nsString versionString;
2324 versionString.AppendInt(GST_VERSION_MAJOR);
2325 versionString.AppendLiteral(
".");
2326 versionString.AppendInt(GST_VERSION_MINOR);
2327 versionString.AppendLiteral(
".");
2328 versionString.AppendInt(GST_VERSION_MICRO);
2330 aGStreamerVersion.Assign(versionString);
2344 NS_ERROR_NULL_POINTER;
2352 NS_ERROR_NULL_POINTER;
2360 NS_ERROR_NULL_POINTER;
2369 sbGStreamerMediacore::HandleEvent(
nsIDOMEvent* aEvent)
2371 nsAutoString eventType;
2372 aEvent->GetType(eventType);
2374 if(eventType.EqualsLiteral(
"unload") ||
2375 eventType.EqualsLiteral(
"hide")) {
2379 NS_ENSURE_TRUE(
target, NS_NOINTERFACE);
2380 target->RemoveEventListener(NS_LITERAL_STRING(
"resize"),
this, PR_FALSE);
2381 target->RemoveEventListener(NS_LITERAL_STRING(
"unload"),
this, PR_FALSE);
2382 target->RemoveEventListener(NS_LITERAL_STRING(
"hide"),
this, PR_FALSE);
2390 NS_ENSURE_SUCCESS(rv, rv);
2393 else if(eventType.EqualsLiteral(
"resize") &&
2407 sbGStreamerMediacore::Observe(
nsISupports *aSubject,
2409 const PRUnichar *
aData)
2413 NS_ENSURE_SUCCESS(rv, rv);
2426 gst_object_ref (aElement);
2439 gst_object_unref (aElement);
nsCOMPtr< nsIArray > mProperties
nsString Format(const nsAString &aKey, nsTArray< nsString > &aParams, const nsAString &aDefault=SBVoidString())
sbDeviceFirmwareAutoCheckForUpdate prototype flags
Songbird Variant Utility Definitions.
NS_IMPL_THREADSAFE_RELEASE(sbRequestItem)
#define SBGSTREAMERSERVICE_CONTRACTID
NS_IMPL_THREADSAFE_ADDREF(sbRequestItem)
static void Error(char const *aCategory, nsAString const &aMessage, nsAString const &aSource=nsString(), PRUint32 aLine=0)
const sbCreateProxiedComponent do_ProxiedGetService(const nsCID &aCID, nsresult *error=0)
Songbird String Bundle Definitions.
#define SB_PROPERTY_TRACKNAME
#define SB_PROPERTY_CONTENTURL
const NS_PREFBRANCH_PREFCHANGE_TOPIC_ID
_getSelectedPageStyle s i
Array filter(tab.attributes, function(aAttr){return(_this.xulAttributes.indexOf(aAttr.name) >-1);}).forEach(tab.removeAttribute
_updateTextAndScrollDataForFrame aData