diff -Nru phonon-backend-gstreamer-4.7.0really4.6.2/.gitignore phonon-backend-gstreamer-4.7.0really4.6.3/.gitignore --- phonon-backend-gstreamer-4.7.0really4.6.2/.gitignore 2012-08-09 15:20:06.000000000 +0000 +++ phonon-backend-gstreamer-4.7.0really4.6.3/.gitignore 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -*.swp -build diff -Nru phonon-backend-gstreamer-4.7.0really4.6.2/CMakeLists.txt phonon-backend-gstreamer-4.7.0really4.6.3/CMakeLists.txt --- phonon-backend-gstreamer-4.7.0really4.6.2/CMakeLists.txt 2012-08-09 15:20:06.000000000 +0000 +++ phonon-backend-gstreamer-4.7.0really4.6.3/CMakeLists.txt 2013-01-31 23:42:39.000000000 +0000 @@ -10,7 +10,7 @@ set(PHONON_GST_MAJOR_VERSION "4") set(PHONON_GST_MINOR_VERSION "6") -set(PHONON_GST_PATCH_VERSION "2") +set(PHONON_GST_PATCH_VERSION "3") set(PHONON_GST_VERSION "${PHONON_GST_MAJOR_VERSION}.${PHONON_GST_MINOR_VERSION}.${PHONON_GST_PATCH_VERSION}") add_definitions(-DPHONON_GST_VERSION="${PHONON_GST_VERSION}") diff -Nru phonon-backend-gstreamer-4.7.0really4.6.2/cmake/FindPhonon.cmake phonon-backend-gstreamer-4.7.0really4.6.3/cmake/FindPhonon.cmake --- phonon-backend-gstreamer-4.7.0really4.6.2/cmake/FindPhonon.cmake 2012-08-09 15:20:06.000000000 +0000 +++ phonon-backend-gstreamer-4.7.0really4.6.3/cmake/FindPhonon.cmake 2013-01-31 23:42:39.000000000 +0000 @@ -1,14 +1,20 @@ # Find Phonon -# Copyright (c) 2010, Harald Sitter +# Copyright (c) 2010-2013, Harald Sitter # Copyright (c) 2011, Alexander Neundorf # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. find_package(Phonon NO_MODULE) -if(PHONON_FOUND) + +if(PHONON_BUILDSYSTEM_DIR) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PHONON_BUILDSYSTEM_DIR}) + # Prevent double-include of internals, and make sure they are included + # In Phonon <4.7 the internals were auto-included, in >=4.7 they are not. + if(NOT COMMAND phonon_add_executable) + include(${PHONON_BUILDSYSTEM_DIR}/FindPhononInternal.cmake ) + endif() endif() include(FindPackageHandleStandardArgs) diff -Nru phonon-backend-gstreamer-4.7.0really4.6.2/debian/changelog phonon-backend-gstreamer-4.7.0really4.6.3/debian/changelog --- phonon-backend-gstreamer-4.7.0really4.6.2/debian/changelog 2012-08-14 08:42:01.000000000 +0000 +++ phonon-backend-gstreamer-4.7.0really4.6.3/debian/changelog 2013-03-13 00:11:11.000000000 +0000 @@ -1,3 +1,15 @@ +phonon-backend-gstreamer (4:4.7.0really4.6.3-0ubuntu1~ubuntu12.10.1~ppa1) quantal; urgency=low + + * No-change backport to quantal + + -- Micah Gersten Tue, 12 Mar 2013 19:11:11 -0500 + +phonon-backend-gstreamer (4:4.7.0really4.6.3-0ubuntu1) raring; urgency=low + + * New upstream release + + -- Harald Sitter Mon, 04 Feb 2013 14:30:52 +0100 + phonon-backend-gstreamer (4:4.7.0really4.6.2-0ubuntu1) quantal; urgency=low * New upstream release diff -Nru phonon-backend-gstreamer-4.7.0really4.6.2/gstreamer/audiodataoutput.cpp phonon-backend-gstreamer-4.7.0really4.6.3/gstreamer/audiodataoutput.cpp --- phonon-backend-gstreamer-4.7.0really4.6.2/gstreamer/audiodataoutput.cpp 2012-08-09 15:20:06.000000000 +0000 +++ phonon-backend-gstreamer-4.7.0really4.6.3/gstreamer/audiodataoutput.cpp 2013-01-31 23:42:39.000000000 +0000 @@ -146,10 +146,12 @@ int nBlockToSend = (that->m_pendingData.size() + gstBufferSize) / (dataSize * that->m_channels); if (nBlockToSend == 0) { // add data to pending buffer + const int prevPendingSize = that->m_pendingData.size(); for (quint32 i = 0; i < gstBufferSize ; ++i) { #warning should be QBA, so we can work with append(buffer, size) that->m_pendingData.append(gstBufferData[i]); } + Q_ASSERT(prevPendingSize + gstBufferSize == that->m_pendingData.size()); return; } @@ -157,6 +159,9 @@ // 1) I empty the stored data if (that->m_pendingData.size() != 0) { + // Since pendingData is a concatenation of buffers it must share its + // attribute of being a multiple of channelCount + Q_ASSERT((that->m_pendingData.size() % that->m_channels) == 0); for (int i = 0; i < that->m_pendingData.size(); i += that->m_channels) { for (int j = 0; j < that->m_channels; ++j) { that->m_channelBuffers[j].append(that->m_pendingData[i+j]); diff -Nru phonon-backend-gstreamer-4.7.0really4.6.2/gstreamer/audiooutput.cpp phonon-backend-gstreamer-4.7.0really4.6.3/gstreamer/audiooutput.cpp --- phonon-backend-gstreamer-4.7.0really4.6.2/gstreamer/audiooutput.cpp 2012-08-09 15:20:06.000000000 +0000 +++ phonon-backend-gstreamer-4.7.0really4.6.3/gstreamer/audiooutput.cpp 2013-01-31 23:42:39.000000000 +0000 @@ -47,35 +47,34 @@ { static int count = 0; m_name = "AudioOutput" + QString::number(count++); - if (m_backend->isValid()) { - m_audioBin = gst_bin_new (NULL); - gst_object_ref (GST_OBJECT (m_audioBin)); - gst_object_sink (GST_OBJECT (m_audioBin)); - - m_conv = gst_element_factory_make ("audioconvert", NULL); - - // Get category from parent - Phonon::Category category = Phonon::NoCategory; - if (Phonon::AudioOutput *audioOutput = qobject_cast(parent)) - category = audioOutput->category(); - - m_audioSink = m_backend->deviceManager()->createAudioSink(category); - m_volumeElement = gst_element_factory_make ("volume", NULL); - GstElement *queue = gst_element_factory_make ("queue", NULL); - GstElement *audioresample = gst_element_factory_make ("audioresample", NULL); - - if (queue && m_audioBin && m_conv && audioresample && m_audioSink && m_volumeElement) { - gst_bin_add_many(GST_BIN(m_audioBin), queue, m_conv, - audioresample, m_volumeElement, m_audioSink, NULL); - - if (gst_element_link_many(queue, m_conv, audioresample, m_volumeElement, - m_audioSink, NULL)) { - // Add ghost sink for audiobin - GstPad *audiopad = gst_element_get_static_pad (queue, "sink"); - gst_element_add_pad (m_audioBin, gst_ghost_pad_new ("sink", audiopad)); - gst_object_unref (audiopad); - m_isValid = true; // Initialization ok, accept input - } + + m_audioBin = gst_bin_new (NULL); + gst_object_ref (GST_OBJECT (m_audioBin)); + gst_object_sink (GST_OBJECT (m_audioBin)); + + m_conv = gst_element_factory_make ("audioconvert", NULL); + + // Get category from parent + Phonon::Category category = Phonon::NoCategory; + if (Phonon::AudioOutput *audioOutput = qobject_cast(parent)) + category = audioOutput->category(); + + m_audioSink = m_backend->deviceManager()->createAudioSink(category); + m_volumeElement = gst_element_factory_make ("volume", NULL); + GstElement *queue = gst_element_factory_make ("queue", NULL); + GstElement *audioresample = gst_element_factory_make ("audioresample", NULL); + + if (queue && m_audioBin && m_conv && audioresample && m_audioSink && m_volumeElement) { + gst_bin_add_many(GST_BIN(m_audioBin), queue, m_conv, + audioresample, m_volumeElement, m_audioSink, NULL); + + if (gst_element_link_many(queue, m_conv, audioresample, m_volumeElement, + m_audioSink, NULL)) { + // Add ghost sink for audiobin + GstPad *audiopad = gst_element_get_static_pad (queue, "sink"); + gst_element_add_pad (m_audioBin, gst_ghost_pad_new ("sink", audiopad)); + gst_object_unref (audiopad); + m_isValid = true; // Initialization ok, accept input } } } diff -Nru phonon-backend-gstreamer-4.7.0really4.6.2/gstreamer/backend.cpp phonon-backend-gstreamer-4.7.0really4.6.3/gstreamer/backend.cpp --- phonon-backend-gstreamer-4.7.0really4.6.2/gstreamer/backend.cpp 2012-08-09 15:20:06.000000000 +0000 +++ phonon-backend-gstreamer-4.7.0really4.6.3/gstreamer/backend.cpp 2013-01-31 23:42:39.000000000 +0000 @@ -82,7 +82,7 @@ int argc = sizeof(args) / sizeof(*args); char **argv = const_cast(args); GError *err = 0; - bool wasInit = gst_init_check(&argc, &argv, &err); //init gstreamer: must be called before any gst-related functions + bool wasInit = gst_init_check(&argc, &argv, &err); //init gstreamer: must be called before any gst-related functions if (err) g_error_free(err); @@ -109,11 +109,13 @@ logMessage(QString("Using %0").arg(versionString)); g_free(versionString); } - if (!m_isValid) - qWarning("Phonon::GStreamer::Backend: Failed to initialize GStreamer"); - m_deviceManager = new DeviceManager(this); - m_effectManager = new EffectManager(this); + if (!isValid()) { + qWarning("Phonon::GStreamer::Backend: Failed to initialize GStreamer"); + } else { + m_deviceManager = new DeviceManager(this); + m_effectManager = new EffectManager(this); + } } Backend::~Backend() @@ -132,6 +134,10 @@ QObject *Backend::createObject(BackendInterface::Class c, QObject *parent, const QList &args) { // Return nothing if dependencies are not met + if (!isValid()) { + warning() << "Backend class" << c << "is not going to be created because GStreamer init failed."; + return 0; + } switch (c) { case MediaObjectClass: diff -Nru phonon-backend-gstreamer-4.7.0really4.6.2/gstreamer/backend.h phonon-backend-gstreamer-4.7.0really4.6.3/gstreamer/backend.h --- phonon-backend-gstreamer-4.7.0really4.6.2/gstreamer/backend.h 2012-08-09 15:20:06.000000000 +0000 +++ phonon-backend-gstreamer-4.7.0really4.6.3/gstreamer/backend.h 2013-01-31 23:42:39.000000000 +0000 @@ -52,8 +52,6 @@ QObject *createObject(BackendInterface::Class, QObject *parent, const QList &args); - bool isValid() const; - bool supportsVideo() const; QStringList availableMimeTypes() const; QList objectDescriptionIndexes(ObjectDescriptionType type) const; @@ -74,6 +72,9 @@ void objectDescriptionChanged(ObjectDescriptionType); private: + bool isValid() const; + bool supportsVideo() const; + DeviceManager *m_deviceManager; EffectManager *m_effectManager; DebugLevel m_debugLevel; diff -Nru phonon-backend-gstreamer-4.7.0really4.6.2/gstreamer/debug.cpp phonon-backend-gstreamer-4.7.0really4.6.3/gstreamer/debug.cpp --- phonon-backend-gstreamer-4.7.0really4.6.2/gstreamer/debug.cpp 2012-08-09 15:20:06.000000000 +0000 +++ phonon-backend-gstreamer-4.7.0really4.6.3/gstreamer/debug.cpp 2013-01-31 23:42:39.000000000 +0000 @@ -173,7 +173,7 @@ : m_label( label ) , m_color( s_colorIndex ) { - if( !debugEnabled() ) + if( !debugEnabled() || DEBUG_INFO < s_debugLevel) return; #if QT_VERSION >= 0x040700 @@ -193,7 +193,7 @@ Block::~Block() { - if( !debugEnabled() ) + if( !debugEnabled() || DEBUG_INFO < s_debugLevel) return; #if QT_VERSION >= 0x040700 diff -Nru phonon-backend-gstreamer-4.7.0really4.6.2/gstreamer/devicemanager.cpp phonon-backend-gstreamer-4.7.0really4.6.3/gstreamer/devicemanager.cpp --- phonon-backend-gstreamer-4.7.0really4.6.2/gstreamer/devicemanager.cpp 2012-08-09 15:20:06.000000000 +0000 +++ phonon-backend-gstreamer-4.7.0really4.6.3/gstreamer/devicemanager.cpp 2013-01-31 23:42:39.000000000 +0000 @@ -130,8 +130,7 @@ m_videoSinkWidget = settings.value(QLatin1String("videomode"), "Auto").toByteArray().toLower(); } - if (m_backend->isValid()) - updateDeviceList(); + updateDeviceList(); } DeviceManager::~DeviceManager() @@ -205,70 +204,67 @@ { GstElement *sink = 0; - if (m_backend && m_backend->isValid()) + if (m_audioSink == "auto") //this is the default value { - if (m_audioSink == "auto") //this is the default value - { - //### TODO : get equivalent KDE settings here - - if (!qgetenv("GNOME_DESKTOP_SESSION_ID").isEmpty()) { - sink = createGNOMEAudioSink(category); - if (canOpenDevice(sink)) + //### TODO : get equivalent KDE settings here + + if (!qgetenv("GNOME_DESKTOP_SESSION_ID").isEmpty()) { + sink = createGNOMEAudioSink(category); + if (canOpenDevice(sink)) m_backend->logMessage("AudioOutput using gconf audio sink"); - else if (sink) { - gst_object_unref(sink); - sink = 0; - } + else if (sink) { + gst_object_unref(sink); + sink = 0; } + } - if (!sink) { - sink = gst_element_factory_make ("alsasink", NULL); - if (canOpenDevice(sink)) + if (!sink) { + sink = gst_element_factory_make ("alsasink", NULL); + if (canOpenDevice(sink)) m_backend->logMessage("AudioOutput using alsa audio sink"); - else if (sink) { - gst_object_unref(sink); - sink = 0; - } + else if (sink) { + gst_object_unref(sink); + sink = 0; } + } - if (!sink) { - sink = gst_element_factory_make ("autoaudiosink", NULL); - if (canOpenDevice(sink)) + if (!sink) { + sink = gst_element_factory_make ("autoaudiosink", NULL); + if (canOpenDevice(sink)) m_backend->logMessage("AudioOutput using auto audio sink"); - else if (sink) { - gst_object_unref(sink); - sink = 0; - } + else if (sink) { + gst_object_unref(sink); + sink = 0; } + } - if (!sink) { - sink = gst_element_factory_make ("osssink", NULL); - if (canOpenDevice(sink)) + if (!sink) { + sink = gst_element_factory_make ("osssink", NULL); + if (canOpenDevice(sink)) m_backend->logMessage("AudioOutput using oss audio sink"); - else if (sink) { - gst_object_unref(sink); - sink = 0; - } + else if (sink) { + gst_object_unref(sink); + sink = 0; } - } else if (m_audioSink == "fake") { - //do nothing as a fakesink will be created by default - } else if (!m_audioSink.isEmpty()) { //Use a custom sink - sink = gst_element_factory_make (m_audioSink, NULL); - if (canOpenDevice(sink)) + } + } else if (m_audioSink == "fake") { + //do nothing as a fakesink will be created by default + } else if (!m_audioSink.isEmpty()) { //Use a custom sink + sink = gst_element_factory_make (m_audioSink, NULL); + if (canOpenDevice(sink)) m_backend->logMessage(QString("AudioOutput using %0").arg(QString::fromUtf8(m_audioSink))); - else { - if (sink) { - gst_object_unref(sink); - sink = 0; - } - if ("pulsesink" == m_audioSink) { - // We've tried to use PulseAudio support, but the GST plugin - // doesn't exits. Let's try again, but not use PA support this time. + else { + if (sink) { + gst_object_unref(sink); + sink = 0; + } + if ("pulsesink" == m_audioSink) { + // We've tried to use PulseAudio support, but the GST plugin + // doesn't exits. Let's try again, but not use PA support this time. m_backend->logMessage("PulseAudio support failed. Falling back to 'auto'"); - PulseSupport::getInstance()->enable(false); - m_audioSink = "auto"; - sink = createAudioSink(); - } + PulseSupport::getInstance()->enable(false); + m_audioSink = "auto"; + sink = createAudioSink(); } } } diff -Nru phonon-backend-gstreamer-4.7.0really4.6.2/gstreamer/glrenderer.cpp phonon-backend-gstreamer-4.7.0really4.6.3/gstreamer/glrenderer.cpp --- phonon-backend-gstreamer-4.7.0really4.6.2/gstreamer/glrenderer.cpp 2012-08-09 15:20:06.000000000 +0000 +++ phonon-backend-gstreamer-4.7.0really4.6.3/gstreamer/glrenderer.cpp 2013-01-31 23:42:39.000000000 +0000 @@ -292,7 +292,7 @@ const float tx_array[] = { 0, 0, 1, 0, 1, 1, 0, 1}; const QRectF r = drawFrameRect(); - const float v_array[] = { r.left(), r.top(), r.right(), r.top(), r.right(), r.bottom(), r.left(), r.bottom() }; + const qreal v_array[] = { r.left(), r.top(), r.right(), r.top(), r.right(), r.bottom(), r.left(), r.bottom() }; glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, m_texture[0]); diff -Nru phonon-backend-gstreamer-4.7.0really4.6.2/gstreamer/gstreamer.desktop.cmake phonon-backend-gstreamer-4.7.0really4.6.3/gstreamer/gstreamer.desktop.cmake --- phonon-backend-gstreamer-4.7.0really4.6.2/gstreamer/gstreamer.desktop.cmake 2012-08-09 15:20:06.000000000 +0000 +++ phonon-backend-gstreamer-4.7.0really4.6.3/gstreamer/gstreamer.desktop.cmake 2013-01-31 23:42:39.000000000 +0000 @@ -1,7 +1,7 @@ [Desktop Entry] Type=Service X-KDE-ServiceTypes=PhononBackend -MimeType=application/x-annodex;video/quicktime;video/x-quicktime;audio/x-m4a;application/x-quicktimeplayer;video/mkv;video/msvideo;video/x-msvideo;video/x-flic;audio/x-aiff;audio/aiff;audio/x-pn-aiff;audio/x-realaudio;audio/basic;audio/x-basic;audio/x-pn-au;audio/x-8svx;audio/8svx;audio/x-16sv;audio/168sv;image/x-ilbm;image/ilbm;video/x-anim;video/anim;image/png;image/x-png;video/mng;video/x-mng;audio/x-ogg;audio/x-speex+ogg;application/ogg;application/ogg;audio/vnd.rn-realaudio;audio/x-pn-realaudio-plugin;audio/x-real-audio;application/vnd.rn-realmedia;video/mpeg;video/x-mpeg;audio/x-wav;audio/wav;audio/x-pn-wav;audio/x-pn-windows-acm;audio/mpeg2;audio/x-mpeg2;audio/mpeg3;audio/x-mpeg3;audio/mpeg;audio/x-mpeg;x-mpegurl;audio/x-mpegurl;audio/mp3;audio/mpeg;audio/x-ape; +MimeType=application/x-annodex;video/quicktime;video/x-quicktime;audio/x-m4a;application/x-quicktimeplayer;video/mkv;video/msvideo;video/x-msvideo;video/x-flic;audio/x-aiff;audio/aiff;audio/x-pn-aiff;audio/x-realaudio;audio/basic;audio/x-basic;audio/x-pn-au;audio/x-8svx;audio/8svx;audio/x-16sv;audio/168sv;image/x-ilbm;image/ilbm;video/x-anim;video/anim;image/png;image/x-png;video/mng;video/x-mng;audio/x-ogg;audio/x-speex+ogg;application/ogg;audio/vnd.rn-realaudio;audio/x-pn-realaudio-plugin;audio/x-real-audio;application/vnd.rn-realmedia;video/mpeg;video/x-mpeg;audio/x-wav;audio/wav;audio/x-pn-wav;audio/x-pn-windows-acm;audio/mpeg2;audio/x-mpeg2;audio/mpeg3;audio/x-mpeg3;audio/mpeg;audio/x-mpeg;audio/x-mpegurl;audio/mp3;audio/x-ape; X-KDE-Library=phonon_gstreamer X-KDE-PhononBackendInfo-InterfaceVersion=1 X-KDE-PhononBackendInfo-Version=@PHONON_GST_VERSION@ @@ -38,6 +38,7 @@ Name[lt]=GStreamer Name[lv]=GStreamer Name[mai]=GStreamer +Name[mr]=जी-स्ट्रीमर Name[nb]=GStreamer Name[nds]=GStreamer Name[nl]=GStreamer @@ -92,6 +93,7 @@ Comment[ku]=Binesaza Phonon GStreamer Comment[lt]=Phonon GStreamer galinė sąsaja Comment[lv]=Phonon GStreamer aizmugure +Comment[mr]=फोनोन जी-स्ट्रीमर बॅकएन्ड Comment[nb]=Phonon-motor for GStreamer Comment[nds]=GStreamer-Hülpprogramm för Phonon Comment[nl]=GStreamer-backend (Phonon) diff -Nru phonon-backend-gstreamer-4.7.0really4.6.2/gstreamer/mediaobject.cpp phonon-backend-gstreamer-4.7.0really4.6.3/gstreamer/mediaobject.cpp --- phonon-backend-gstreamer-4.7.0really4.6.2/gstreamer/mediaobject.cpp 2012-08-09 15:20:06.000000000 +0000 +++ phonon-backend-gstreamer-4.7.0really4.6.3/gstreamer/mediaobject.cpp 2013-01-31 23:42:39.000000000 +0000 @@ -88,47 +88,42 @@ static int count = 0; m_name = "MediaObject" + QString::number(count++); - if (!m_backend->isValid()) { - setError(tr("Cannot start playback. \n\nCheck your GStreamer installation and make sure you " - "\nhave libgstreamer-plugins-base installed."), Phonon::FatalError); - } else { - m_root = this; - m_pipeline = new Pipeline(this); - m_isValid = true; - GlobalSubtitles::instance()->register_(this); - - connect(m_pipeline, SIGNAL(aboutToFinish()), - this, SLOT(handleAboutToFinish()), Qt::DirectConnection); - connect(m_pipeline, SIGNAL(eos()), - this, SLOT(handleEndOfStream())); - connect(m_pipeline, SIGNAL(warning(QString)), - this, SLOT(logWarning(QString))); - connect(m_pipeline, SIGNAL(durationChanged(qint64)), - this, SLOT(handleDurationChange(qint64))); - connect(m_pipeline, SIGNAL(buffering(int)), - this, SIGNAL(bufferStatus(int))); - connect(m_pipeline, SIGNAL(stateChanged(GstState,GstState)), - this, SLOT(handleStateChange(GstState,GstState))); - connect(m_pipeline, SIGNAL(errorMessage(QString,Phonon::ErrorType)), - this, SLOT(setError(QString,Phonon::ErrorType))); - connect(m_pipeline, SIGNAL(metaDataChanged(QMultiMap)), - this, SIGNAL(metaDataChanged(QMultiMap))); - connect(m_pipeline, SIGNAL(availableMenusChanged(QList)), - this, SIGNAL(availableMenusChanged(QList))); - connect(m_pipeline, SIGNAL(videoAvailabilityChanged(bool)), - this, SIGNAL(hasVideoChanged(bool))); - connect(m_pipeline, SIGNAL(seekableChanged(bool)), - this, SIGNAL(seekableChanged(bool))); - connect(m_pipeline, SIGNAL(streamChanged()), - this, SLOT(handleStreamChange())); - - connect(m_pipeline, SIGNAL(textTagChanged(int)), - this, SLOT(getSubtitleInfo(int))); - connect(m_pipeline, SIGNAL(trackCountChanged(int)), - this, SLOT(handleTrackCountChange(int))); + m_root = this; + m_pipeline = new Pipeline(this); + m_isValid = true; + GlobalSubtitles::instance()->register_(this); + + connect(m_pipeline, SIGNAL(aboutToFinish()), + this, SLOT(handleAboutToFinish()), Qt::DirectConnection); + connect(m_pipeline, SIGNAL(eos()), + this, SLOT(handleEndOfStream())); + connect(m_pipeline, SIGNAL(warning(QString)), + this, SLOT(logWarning(QString))); + connect(m_pipeline, SIGNAL(durationChanged(qint64)), + this, SLOT(handleDurationChange(qint64))); + connect(m_pipeline, SIGNAL(buffering(int)), + this, SIGNAL(bufferStatus(int))); + connect(m_pipeline, SIGNAL(stateChanged(GstState,GstState)), + this, SLOT(handleStateChange(GstState,GstState))); + connect(m_pipeline, SIGNAL(errorMessage(QString,Phonon::ErrorType)), + this, SLOT(setError(QString,Phonon::ErrorType))); + connect(m_pipeline, SIGNAL(metaDataChanged(QMultiMap)), + this, SIGNAL(metaDataChanged(QMultiMap))); + connect(m_pipeline, SIGNAL(availableMenusChanged(QList)), + this, SIGNAL(availableMenusChanged(QList))); + connect(m_pipeline, SIGNAL(videoAvailabilityChanged(bool)), + this, SIGNAL(hasVideoChanged(bool))); + connect(m_pipeline, SIGNAL(seekableChanged(bool)), + this, SIGNAL(seekableChanged(bool))); + connect(m_pipeline, SIGNAL(streamChanged()), + this, SLOT(handleStreamChange())); + + connect(m_pipeline, SIGNAL(textTagChanged(int)), + this, SLOT(getSubtitleInfo(int))); + connect(m_pipeline, SIGNAL(trackCountChanged(int)), + this, SLOT(handleTrackCountChange(int))); - connect(m_tickTimer, SIGNAL(timeout()), SLOT(emitTick())); - } + connect(m_tickTimer, SIGNAL(timeout()), SLOT(emitTick())); } MediaObject::~MediaObject() @@ -378,9 +373,6 @@ */ void MediaObject::setSource(const MediaSource &source) { - if (!isValid()) - return; - DEBUG_BLOCK; if (source.type() == Phonon::MediaSource::Invalid) { @@ -453,9 +445,6 @@ void MediaObject::seek(qint64 time) { - if (!isValid()) - return; - DEBUG_BLOCK; if (m_waitingForNextSource) { @@ -861,23 +850,42 @@ m_aboutToFinishLock.lock(); m_handlingAboutToFinish = true; emit aboutToFinish(); - // Three seconds should be more than enough for any application to get their act together. - // Any longer than that and they have bigger issues. If Phonon does no supply a next source - // within 3 seconds, treat as if there is no next source to come, and finish the current source. + // As our signal gets emitted queued we need to wait here until either a + // new source or a timeout is reached. + // If we got a new source in time -> hooray + gapless + // If we did not get a new source in time -> boooh + stop() if (!m_skipGapless) { - if (m_aboutToFinishWait.wait(&m_aboutToFinishLock, 3000)) { - debug() << "Finally got a source"; - if (m_skipGapless) { // Was explicitly set by stateChange interrupt - debug() << "...oh, no, just got aborted, skipping EOS"; - m_skippingEOS = false; - } - } else { - warning() << "aboutToFinishWait timed out!"; - m_skippingEOS = false; - } + // Dynamic lock timeout is our friend. + // Instead of simply waiting for a fixed amount of ms for the next source, we wait for the + // most sensible amount of time. This is whatever amount of time is remaining to play + // minus a 0.5 seconds safety delta (time values not precise etc.). + // A source for which we have no time or for which the remaining time is < 0.5 seconds is + // immediately unlocked again. Otherwise the consumer has as much time as gst gave us to + // set a new source. + // This in particular prevents pointless excessive locking on sources which have a totalTime + // < whatever fixed lock value we have (so that we'd lock longer than what we are playing). + // An issue apparent with notification-like sounds, that are rather short and do not need + // gapless transitioning. As outlined in https://bugs.kde.org/show_bug.cgi?id=307530 + unsigned long timeout = 0; + if (totalTime() <= 0 || (remainingTime() - 500 <= 0)) + timeout = 0; + else + timeout = remainingTime() - 500; + + debug() << "waiting for" << timeout; + if (m_aboutToFinishWait.wait(&m_aboutToFinishLock, timeout)) { + debug() << "Finally got a source"; + if (m_skipGapless) { // Was explicitly set by stateChange interrupt + debug() << "...oh, no, just got aborted, skipping EOS"; + m_skippingEOS = false; + } + } else { + warning() << "aboutToFinishWait timed out!"; + m_skippingEOS = false; + } } else { - debug() << "Skipping gapless audio"; - m_skippingEOS = false; + debug() << "Skipping gapless audio"; + m_skippingEOS = false; } m_handlingAboutToFinish = false; m_aboutToFinishLock.unlock(); diff -Nru phonon-backend-gstreamer-4.7.0really4.6.2/gstreamer/pipeline.cpp phonon-backend-gstreamer-4.7.0really4.6.3/gstreamer/pipeline.cpp --- phonon-backend-gstreamer-4.7.0really4.6.2/gstreamer/pipeline.cpp 2012-08-09 15:20:06.000000000 +0000 +++ phonon-backend-gstreamer-4.7.0really4.6.3/gstreamer/pipeline.cpp 2013-01-31 23:42:39.000000000 +0000 @@ -842,11 +842,18 @@ g_signal_connect(phononSrc, "seek-data", G_CALLBACK(cb_seekAppSrc), that->m_reader); that->m_reader->start(); } else { - if (that->currentSource().type() == MediaSource::Url && - that->currentSource().mrl().scheme().startsWith("http")) { + if (that->currentSource().type() == MediaSource::Url + && that->currentSource().mrl().scheme().startsWith(QLatin1String("http")) + // Check whether this property exists. + // Setting it on a source other than souphttpsrc (which supports it) may break playback. + && g_object_class_find_property(G_OBJECT_GET_CLASS(phononSrc), "user-agent")) { QString userAgent = QCoreApplication::applicationName() + '/' + QCoreApplication::applicationVersion(); userAgent += QString(" (Phonon/%0; Phonon-GStreamer/%1)").arg(PHONON_VERSION_STR).arg(PHONON_GST_VERSION); g_object_set(phononSrc, "user-agent", userAgent.toUtf8().constData(), NULL); + } else if (that->currentSource().type() == MediaSource::Disc && + !that->currentSource().deviceName().isEmpty()) { + debug() << "setting device prop to" << that->currentSource().deviceName(); + g_object_set(phononSrc, "device", that->currentSource().deviceName().toUtf8().constData(), NULL); } } gst_object_unref(that->m_pipeline); diff -Nru phonon-backend-gstreamer-4.7.0really4.6.2/gstreamer/volumefadereffect.cpp phonon-backend-gstreamer-4.7.0really4.6.3/gstreamer/volumefadereffect.cpp --- phonon-backend-gstreamer-4.7.0really4.6.2/gstreamer/volumefadereffect.cpp 2012-08-09 15:20:06.000000000 +0000 +++ phonon-backend-gstreamer-4.7.0really4.6.3/gstreamer/volumefadereffect.cpp 2013-01-31 23:42:39.000000000 +0000 @@ -84,7 +84,7 @@ void VolumeFaderEffect::slotSetVolume(qreal volume) { float gstVolume = m_fadeFromVolume + (volume * (m_fadeToVolume - m_fadeFromVolume)); - setVolume(gstVolume); + setVolumeInternal(gstVolume); } Phonon::VolumeFaderEffect::FadeCurve VolumeFaderEffect::fadeCurve() const @@ -115,13 +115,14 @@ void VolumeFaderEffect::fadeTo(float targetVolume, int fadeTime) { + abortFade(); m_fadeToVolume = targetVolume; g_object_get(G_OBJECT(m_effectElement), "volume", &m_fadeFromVolume, NULL); // Don't call QTimeLine::setDuration() with zero. // It is not supported and breaks fading. if (fadeTime <= 0) { - setVolume(targetVolume); + setVolumeInternal(targetVolume); return; } @@ -131,6 +132,17 @@ void VolumeFaderEffect::setVolume(float v) { + abortFade(); + setVolumeInternal(v); +} + +void VolumeFaderEffect::abortFade() +{ + m_fadeTimeline->stop(); +} + +void VolumeFaderEffect::setVolumeInternal(float v) +{ g_object_set(G_OBJECT(m_effectElement), "volume", (gdouble)v, NULL); debug() << "Fading to" << v; } diff -Nru phonon-backend-gstreamer-4.7.0really4.6.2/gstreamer/volumefadereffect.h phonon-backend-gstreamer-4.7.0really4.6.3/gstreamer/volumefadereffect.h --- phonon-backend-gstreamer-4.7.0really4.6.2/gstreamer/volumefadereffect.h 2012-08-09 15:20:06.000000000 +0000 +++ phonon-backend-gstreamer-4.7.0really4.6.3/gstreamer/volumefadereffect.h 2013-01-31 23:42:39.000000000 +0000 @@ -31,32 +31,38 @@ { namespace Gstreamer { - class VolumeFaderEffect : public Effect, public VolumeFaderInterface - { - Q_OBJECT - Q_INTERFACES(Phonon::VolumeFaderInterface) - - public: - VolumeFaderEffect(Backend *backend, QObject *parent = 0); - ~VolumeFaderEffect(); - - GstElement* createEffectBin(); - GstElement *audioElement() { return m_effectBin; } - - // VolumeFaderInterface: - float volume() const; - Phonon::VolumeFaderEffect::FadeCurve fadeCurve() const; - void setFadeCurve(Phonon::VolumeFaderEffect::FadeCurve fadeCurve); - void fadeTo(float volume, int fadeTime); - void setVolume(float v); - - Phonon::VolumeFaderEffect::FadeCurve m_fadeCurve; - gdouble m_fadeFromVolume; - gdouble m_fadeToVolume; - QTimeLine *m_fadeTimeline; - private slots: - void slotSetVolume(qreal v); - }; +class VolumeFaderEffect : public Effect, public VolumeFaderInterface +{ + Q_OBJECT + Q_INTERFACES(Phonon::VolumeFaderInterface) + +public: + explicit VolumeFaderEffect(Backend *backend, QObject *parent = 0); + ~VolumeFaderEffect(); + + GstElement* createEffectBin(); + GstElement *audioElement() { return m_effectBin; } + + // VolumeFaderInterface: + float volume() const; + Phonon::VolumeFaderEffect::FadeCurve fadeCurve() const; + void setFadeCurve(Phonon::VolumeFaderEffect::FadeCurve fadeCurve); + void fadeTo(float volume, int fadeTime); + void setVolume(float v); + +private slots: + void slotSetVolume(qreal v); + +private: + void abortFade(); + inline void setVolumeInternal(float v); + + Phonon::VolumeFaderEffect::FadeCurve m_fadeCurve; + gdouble m_fadeFromVolume; + gdouble m_fadeToVolume; + QTimeLine *m_fadeTimeline; + +}; }} //namespace Phonon::Gstreamer #endif //QT_NO_PHONON_VOLUMEFADEREFFECT QT_END_NAMESPACE