diff --git a/.cvsignore b/.cvsignore index 1158bb2..334a01f 100644 --- a/.cvsignore +++ b/.cvsignore @@ -1,9 +1 @@ -gstreamer-logo.svg -hi128-phonon-gstreamer.png -hi16-phonon-gstreamer.png -hi22-phonon-gstreamer.png -hi32-phonon-gstreamer.png -hi48-phonon-gstreamer.png -hi64-phonon-gstreamer.png -phonon-4.3.80.tar.bz2 -phonon-4.4.0.tgz +phonon-4.4.1.tar.bz2 diff --git a/phonon-4.3.50-fix-decodebin-usage.patch b/phonon-4.3.50-fix-decodebin-usage.patch deleted file mode 100644 index 4b9bdcf..0000000 --- a/phonon-4.3.50-fix-decodebin-usage.patch +++ /dev/null @@ -1,27 +0,0 @@ -Index: gstreamer/mediaobject.cpp -=================================================================== ---- gstreamer/mediaobject.cpp (revision 1040729) -+++ gstreamer/mediaobject.cpp (working copy) -@@ -484,7 +484,7 @@ - gst_object_ref (GST_OBJECT (m_pipeline)); - gst_object_sink (GST_OBJECT (m_pipeline)); - -- m_decodebin = gst_element_factory_make ("decodebin", NULL); -+ m_decodebin = gst_element_factory_make ("decodebin2", NULL); - g_signal_connect (m_decodebin, "new-decoded-pad", G_CALLBACK (&cb_newpad), this); - g_signal_connect (m_decodebin, "unknown-type", G_CALLBACK (&cb_unknown_type), this); - g_signal_connect (m_decodebin, "no-more-pads", G_CALLBACK (&cb_no_more_pads), this); -Index: gstreamer/gsthelper.cpp -=================================================================== ---- gstreamer/gsthelper.cpp (revision 1040694) -+++ gstreamer/gsthelper.cpp (working copy) -@@ -121,7 +121,7 @@ - { - GstElement *playbin = 0; - //init playbin and add to our pipeline -- playbin = gst_element_factory_make("playbin", NULL); -+ playbin = gst_element_factory_make("playbin2", NULL); - - //Create an identity element to redirect sound - GstElement *audioSinkBin = gst_bin_new (NULL); - diff --git a/phonon-4.3.80-pulse-devicemove-rejig.patch b/phonon-4.3.80-pulse-devicemove-rejig.patch deleted file mode 100644 index 4eff732..0000000 --- a/phonon-4.3.80-pulse-devicemove-rejig.patch +++ /dev/null @@ -1,454 +0,0 @@ -diff --git a/phonon/audiooutput.cpp b/phonon/audiooutput.cpp -index e99c394..ddbf360 100644 ---- a/phonon/audiooutput.cpp -+++ b/phonon/audiooutput.cpp -@@ -99,7 +99,9 @@ void AudioOutputPrivate::init(Phonon::Category c) - - category = c; - streamUuid = QUuid::createUuid().toString(); -- PulseSupport::getInstance()->setStreamPropList(category, streamUuid); -+ PulseSupport *pulse = PulseSupport::getInstance(); -+ pulse->setStreamPropList(category, streamUuid); -+ q->connect(pulse, SIGNAL(usingDevice(QString,int)), SLOT(_k_deviceChanged(QString,int))); - - createBackendObject(); - -@@ -232,14 +234,14 @@ bool AudioOutput::setOutputDevice(const AudioOutputDevice &newAudioOutputDevice) - { - K_D(AudioOutput); - if (!newAudioOutputDevice.isValid()) { -- d->outputDeviceOverridden = false; -+ d->outputDeviceOverridden = d->forceMove = false; - const int newIndex = GlobalConfig().audioOutputDeviceFor(d->category); - if (newIndex == d->device.index()) { - return true; - } - d->device = AudioOutputDevice::fromIndex(newIndex); - } else { -- d->outputDeviceOverridden = true; -+ d->outputDeviceOverridden = d->forceMove = true; - if (d->device == newAudioOutputDevice) { - return true; - } -@@ -272,7 +274,10 @@ void AudioOutputPrivate::setupBackendObject() - pINTERFACE_CALL(setVolume(pow(volume, VOLTAGE_TO_LOUDNESS_EXPONENT))); - - // if the output device is not available and the device was not explicitly set -- if (!callSetOutputDevice(this, device) && !outputDeviceOverridden) { -+ // There is no need to set the output device initially if PA is used as -+ // we know it will not work (stream doesn't exist yet) and that this will be -+ // handled by _k_deviceChanged() -+ if (!PulseSupport::getInstance()->isActive() && !callSetOutputDevice(this, device) && !outputDeviceOverridden) { - // fall back in the preference list of output devices - QList deviceList = GlobalConfig().audioOutputDeviceListFor(category, GlobalConfig::AdvancedDevicesFromSettings | GlobalConfig::HideUnavailableDevices); - if (deviceList.isEmpty()) { -@@ -316,6 +321,9 @@ void AudioOutputPrivate::_k_revertFallback() - - void AudioOutputPrivate::_k_audioDeviceFailed() - { -+ if (PulseSupport::getInstance()->isActive()) -+ return; -+ - pDebug() << Q_FUNC_INFO; - // outputDeviceIndex identifies a failing device - // fall back in the preference list of output devices -@@ -338,7 +346,14 @@ void AudioOutputPrivate::_k_audioDeviceFailed() - - void AudioOutputPrivate::_k_deviceListChanged() - { -+ if (PulseSupport::getInstance()->isActive()) -+ return; -+ - pDebug() << Q_FUNC_INFO; -+ // Check to see if we have an override and do not change to a higher priority device if the overridden device is still present. -+ if (outputDeviceOverridden && device.property("available").toBool()) { -+ return; -+ } - // let's see if there's a usable device higher in the preference list - QList deviceList = GlobalConfig().audioOutputDeviceListFor(category, GlobalConfig::AdvancedDevicesFromSettings); - DeviceChangeType changeType = HigherPreferenceChange; -@@ -365,6 +380,36 @@ void AudioOutputPrivate::_k_deviceListChanged() - } - } - -+void AudioOutputPrivate::_k_deviceChanged(QString inStreamUuid, int deviceIndex) -+{ -+ // Note that this method is only used by PulseAudio at present. -+ if (inStreamUuid == streamUuid) { -+ // 1. Check to see if we are overridden. If we are, and devices do not match, -+ // then try and apply our own device as the output device. -+ // We only do this the first time -+ if (outputDeviceOverridden && forceMove) { -+ forceMove = false; -+ const AudioOutputDevice ¤tDevice = AudioOutputDevice::fromIndex(deviceIndex); -+ if (currentDevice != device) { -+ if (!callSetOutputDevice(this, device)) { -+ // What to do if we are overridden and cannot change to our preferred device? -+ } -+ } -+ } -+ // 2. If we are not overridden, then we need to update our perception of what -+ // device we are using. If the devices do not match, something lower in the -+ // stack is overriding our preferences (e.g. a per-application stream preference, -+ // specific application move, priority list changed etc. etc.) -+ else if (!outputDeviceOverridden) { -+ const AudioOutputDevice ¤tDevice = AudioOutputDevice::fromIndex(deviceIndex); -+ if (currentDevice != device) { -+ // The device is not what we think it is, so lets say what is happening. -+ handleAutomaticDeviceChange(currentDevice, SoundSystemChange); -+ } -+ } -+ } -+} -+ - static struct - { - int first; -@@ -409,6 +454,27 @@ void AudioOutputPrivate::handleAutomaticDeviceChange(const AudioOutputDevice &de - g_lastFallback.second = 0; - } - break; -+ case SoundSystemChange: -+ { -+#ifndef QT_NO_PHONON_PLATFORMPLUGIN -+ if (device1.property("available").toBool()) { -+ const QString text = AudioOutput::tr("Switching to the audio playback device %1
" -+ "which has higher preference or is specifically configured for this stream.").arg(device2.name()); -+ Platform::notification("AudioDeviceFallback", text, -+ QStringList(AudioOutput::tr("Revert back to device '%1'").arg(device1.name())), -+ q, SLOT(_k_revertFallback())); -+ } else { -+ const QString &text = -+ AudioOutput::tr("The audio playback device %1 does not work.
" -+ "Falling back to %2.").arg(device1.name()).arg(device2.name()); -+ Platform::notification("AudioDeviceFallback", text); -+ } -+#endif //QT_NO_PHONON_PLATFORMPLUGIN -+ //outputDeviceOverridden = true; -+ g_lastFallback.first = 0; -+ g_lastFallback.second = 0; -+ } -+ break; - } - } - -diff --git a/phonon/audiooutput.h b/phonon/audiooutput.h -index 4edf135..513a863 100644 ---- a/phonon/audiooutput.h -+++ b/phonon/audiooutput.h -@@ -169,6 +169,7 @@ namespace Phonon - Q_PRIVATE_SLOT(k_func(), void _k_revertFallback()) - Q_PRIVATE_SLOT(k_func(), void _k_audioDeviceFailed()) - Q_PRIVATE_SLOT(k_func(), void _k_deviceListChanged()) -+ Q_PRIVATE_SLOT(k_func(), void _k_deviceChanged(QString streamUuid, int device)) - }; - } //namespace Phonon - -diff --git a/phonon/audiooutput_p.h b/phonon/audiooutput_p.h -index 0a90c3d..01dc48f 100644 ---- a/phonon/audiooutput_p.h -+++ b/phonon/audiooutput_p.h -@@ -59,6 +59,7 @@ class AudioOutputPrivate : public AbstractAudioOutputPrivate - #endif - deviceBeforeFallback(-1), - outputDeviceOverridden(false), -+ forceMove(false), - muted(false) - { - } -@@ -67,7 +68,8 @@ class AudioOutputPrivate : public AbstractAudioOutputPrivate - - enum DeviceChangeType { - FallbackChange, -- HigherPreferenceChange -+ HigherPreferenceChange, -+ SoundSystemChange - }; - void handleAutomaticDeviceChange(const AudioOutputDevice &newDev, DeviceChangeType type); - -@@ -75,6 +77,7 @@ class AudioOutputPrivate : public AbstractAudioOutputPrivate - void _k_revertFallback(); - void _k_audioDeviceFailed(); - void _k_deviceListChanged(); -+ void _k_deviceChanged(QString streamUuid, int deviceIndex); - - private: - QString name; -@@ -87,6 +90,7 @@ class AudioOutputPrivate : public AbstractAudioOutputPrivate - Category category; - int deviceBeforeFallback; - bool outputDeviceOverridden; -+ bool forceMove; - bool muted; - }; - } //namespace Phonon -diff --git a/phonon/pulsesupport.cpp b/phonon/pulsesupport.cpp -index f102177..9d3dd82 100644 ---- a/phonon/pulsesupport.cpp -+++ b/phonon/pulsesupport.cpp -@@ -145,13 +145,11 @@ static QMap s_outputDeviceIndexes; - static QMap s_outputDevices; - static QMap > s_outputDevicePriorities; // prio, device - static QMap s_outputStreamIndexMap; --static QMap s_outputStreamMoveQueue; - - static QMap s_captureDeviceIndexes; - static QMap s_captureDevices; - static QMap > s_captureDevicePriorities; // prio, device - static QMap s_captureStreamIndexMap; --static QMap s_captureStreamMoveQueue; - - static void createGenericDevices() - { -@@ -378,80 +376,6 @@ static void ext_device_manager_read_cb(pa_context *c, const pa_ext_device_manage - } - #endif - --static void set_output_device(QString streamUuid) --{ -- // If we only have one device, bail. This will be true if we are not using module-device-manager -- if (s_outputDevices.size() < 2) -- return; -- -- if (!s_outputStreamMoveQueue.contains(streamUuid)) -- return; -- -- if (!s_outputStreamIndexMap.contains(streamUuid)) -- return; -- -- if (s_outputStreamIndexMap[streamUuid] == PA_INVALID_INDEX) -- return; -- -- int device = s_outputStreamMoveQueue[streamUuid]; -- if (!s_outputDevices.contains(device)) -- return; -- -- // We don't remove the uuid from the s_captureStreamMoveQueue -- // as an application may reuse the phonon AudioOutput object -- -- uint32_t pulse_device_index = s_outputDevices[device].pulseIndex; -- uint32_t pulse_stream_index = s_outputStreamIndexMap[streamUuid]; -- -- const QVariant var = s_outputDevices[device].properties["name"]; -- logMessage(QString("Moving Pulse Sink Input %1 to '%2' (Pulse Sink %3)").arg(pulse_stream_index).arg(var.toString()).arg(pulse_device_index)); -- -- /// @todo Find a way to move the stream without saving it... We don't want to pollute the stream restore db. -- pa_operation* o; -- if (!(o = pa_context_move_sink_input_by_index(s_context, pulse_stream_index, pulse_device_index, NULL, NULL))) { -- logMessage(QString("pa_context_move_sink_input_by_index() failed")); -- return; -- } -- pa_operation_unref(o); --} -- --static void set_capture_device(QString streamUuid) --{ -- // If we only have one device, bail. This will be true if we are not using module-device-manager -- if (s_captureDevices.size() < 2) -- return; -- -- if (!s_captureStreamMoveQueue.contains(streamUuid)) -- return; -- -- if (!s_captureStreamIndexMap.contains(streamUuid)) -- return; -- -- if (s_captureStreamIndexMap[streamUuid] == PA_INVALID_INDEX) -- return; -- -- int device = s_captureStreamMoveQueue[streamUuid]; -- if (!s_captureDevices.contains(device)) -- return; -- -- // We don't remove the uuid from the s_captureStreamMoveQueue -- // as an application may reuse the phonon AudioCapture object (when it exists!) -- -- uint32_t pulse_device_index = s_captureDevices[device].pulseIndex; -- uint32_t pulse_stream_index = s_captureStreamIndexMap[streamUuid]; -- -- const QVariant var = s_captureDevices[device].properties["name"]; -- logMessage(QString("Moving Pulse Source Output %1 to '%2' (Pulse Sink %3)").arg(pulse_stream_index).arg(var.toString()).arg(pulse_device_index)); -- -- /// @todo Find a way to move the stream without saving it... We don't want to pollute the stream restore db. -- pa_operation* o; -- if (!(o = pa_context_move_source_output_by_index(s_context, pulse_stream_index, pulse_device_index, NULL, NULL))) { -- logMessage(QString("pa_context_move_source_output_by_index() failed")); -- return; -- } -- pa_operation_unref(o); --} -- - void sink_input_cb(pa_context *c, const pa_sink_input_info *i, int eol, void *userdata) { - Q_UNUSED(userdata); - Q_ASSERT(c); -@@ -474,8 +398,25 @@ void sink_input_cb(pa_context *c, const pa_sink_input_info *i, int eol, void *us - if ((t = pa_proplist_gets(i->proplist, "phonon.streamid"))) { - logMessage(QString("Found PulseAudio stream index %1 for Phonon Output Stream %2").arg(i->index).arg(t)); - s_outputStreamIndexMap[QString(t)] = i->index; -- // Process any pending moves... -- set_output_device(QString(t)); -+ -+ // Find the sink's phonon index and notify whoever cares... -+ if (PA_INVALID_INDEX != i->sink) { -+ bool found = false; -+ int device; -+ QMap::iterator it; -+ for (it = s_outputDevices.begin(); it != s_outputDevices.end(); ++it) { -+ if ((*it).pulseIndex == i->sink) { -+ found = true; -+ device = it.key(); -+ break; -+ } -+ } -+ if (found) { -+ // OK so we just emit our signal -+ logMessage(QString("Letting the rest of phonon know about this")); -+ s_instance->emitUsingDevice(QString(t), device); -+ } -+ } - } - } - -@@ -501,8 +442,25 @@ void source_output_cb(pa_context *c, const pa_source_output_info *i, int eol, vo - if ((t = pa_proplist_gets(i->proplist, "phonon.streamid"))) { - logMessage(QString("Found PulseAudio stream index %1 for Phonon Capture Stream %2").arg(i->index).arg(t)); - s_captureStreamIndexMap[QString(t)] = i->index; -- // Process any pending moves... -- set_capture_device(QString(t)); -+ -+ // Find the source's phonon index and notify whoever cares... -+ if (PA_INVALID_INDEX != i->source) { -+ bool found = false; -+ int device; -+ QMap::iterator it; -+ for (it = s_captureDevices.begin(); it != s_captureDevices.end(); ++it) { -+ if ((*it).pulseIndex == i->source) { -+ found = true; -+ device = it.key(); -+ break; -+ } -+ } -+ if (found) { -+ // OK so we just emit our signal -+ logMessage(QString("Letting the rest of phonon know about this")); -+ s_instance->emitUsingDevice(QString(t), device); -+ } -+ } - } - } - -@@ -520,7 +478,6 @@ static void subscribe_cb(pa_context *c, pa_subscription_event_type_t t, uint32_t - } else { - logMessage(QString("Removing Phonon Output Stream %1 (it's gone!)").arg(phononid)); - s_outputStreamIndexMap.remove(phononid); -- s_outputStreamMoveQueue.remove(phononid); - } - } - } else { -@@ -543,7 +500,6 @@ static void subscribe_cb(pa_context *c, pa_subscription_event_type_t t, uint32_t - } else { - logMessage(QString("Removing Phonon Capture Stream %1 (it's gone!)").arg(phononid)); - s_captureStreamIndexMap.remove(phononid); -- s_captureStreamMoveQueue.remove(phononid); - } - } - } else { -@@ -933,6 +889,11 @@ void PulseSupport::emitObjectDescriptionChanged(ObjectDescriptionType type) - emit objectDescriptionChanged(type); - } - -+void PulseSupport::emitUsingDevice(QString streamUuid, int device) -+{ -+ emit usingDevice(streamUuid, device); -+} -+ - bool PulseSupport::setOutputDevice(QString streamUuid, int device) { - #ifndef HAVE_PULSEAUDIO - Q_UNUSED(streamUuid); -@@ -949,13 +910,24 @@ bool PulseSupport::setOutputDevice(QString streamUuid, int device) { - const QVariant var = s_outputDevices[device].properties["name"]; - logMessage(QString("Attempting to set Output Device to '%1' for Output Stream %2").arg(var.toString()).arg(streamUuid)); - -- s_outputStreamMoveQueue[streamUuid] = device; - // Attempt to look up the pulse stream index. - if (s_outputStreamIndexMap.contains(streamUuid) && s_outputStreamIndexMap[streamUuid] != PA_INVALID_INDEX) { - logMessage(QString("... Found in map. Moving now")); -- set_output_device(streamUuid); -+ -+ uint32_t pulse_device_index = s_outputDevices[device].pulseIndex; -+ uint32_t pulse_stream_index = s_outputStreamIndexMap[streamUuid]; -+ -+ logMessage(QString("Moving Pulse Sink Input %1 to '%2' (Pulse Sink %3)").arg(pulse_stream_index).arg(var.toString()).arg(pulse_device_index)); -+ -+ /// @todo Find a way to move the stream without saving it... We don't want to pollute the stream restore db. -+ pa_operation* o; -+ if (!(o = pa_context_move_sink_input_by_index(s_context, pulse_stream_index, pulse_device_index, NULL, NULL))) { -+ logMessage(QString("pa_context_move_sink_input_by_index() failed")); -+ return false; -+ } -+ pa_operation_unref(o); - } else { -- logMessage(QString("... Not found in map. Saving move for when the stream appears")); -+ logMessage(QString("... Not found in map. We will be notified of the device when the stream appears and we can process any moves needed then")); - } - return true; - #endif -@@ -977,13 +949,24 @@ bool PulseSupport::setCaptureDevice(QString streamUuid, int device) { - const QVariant var = s_captureDevices[device].properties["name"]; - logMessage(QString("Attempting to set Capture Device to '%1' for Capture Stream %2").arg(var.toString()).arg(streamUuid)); - -- s_captureStreamMoveQueue[streamUuid] = device; - // Attempt to look up the pulse stream index. - if (s_captureStreamIndexMap.contains(streamUuid) && s_captureStreamIndexMap[streamUuid] == PA_INVALID_INDEX) { - logMessage(QString("... Found in map. Moving now")); -- set_capture_device(streamUuid); -+ -+ uint32_t pulse_device_index = s_captureDevices[device].pulseIndex; -+ uint32_t pulse_stream_index = s_captureStreamIndexMap[streamUuid]; -+ -+ logMessage(QString("Moving Pulse Source Output %1 to '%2' (Pulse Sink %3)").arg(pulse_stream_index).arg(var.toString()).arg(pulse_device_index)); -+ -+ /// @todo Find a way to move the stream without saving it... We don't want to pollute the stream restore db. -+ pa_operation* o; -+ if (!(o = pa_context_move_source_output_by_index(s_context, pulse_stream_index, pulse_device_index, NULL, NULL))) { -+ logMessage(QString("pa_context_move_source_output_by_index() failed")); -+ return false; -+ } -+ pa_operation_unref(o); - } else { -- logMessage(QString("... Not found in map. Saving move for when the stream appears")); -+ logMessage(QString("... Not found in map. We will be notified of the device when the stream appears and we can process any moves needed then")); - } - return true; - #endif -@@ -996,9 +979,7 @@ void PulseSupport::clearStreamCache(QString streamUuid) { - #else - logMessage(QString("Clearing stream cache for stream %1").arg(streamUuid)); - s_outputStreamIndexMap.remove(streamUuid); -- s_outputStreamMoveQueue.remove(streamUuid); - s_captureStreamIndexMap.remove(streamUuid); -- s_captureStreamMoveQueue.remove(streamUuid); - #endif - } - -diff --git a/phonon/pulsesupport.h b/phonon/pulsesupport.h -index bba5fd5..c38bece 100644 ---- a/phonon/pulsesupport.h -+++ b/phonon/pulsesupport.h -@@ -54,6 +54,7 @@ namespace Phonon - - void setStreamPropList(Category category, QString streamUuid); - void emitObjectDescriptionChanged(ObjectDescriptionType); -+ void emitUsingDevice(QString streamUuid, int device); - - bool setOutputDevice(QString streamUuid, int device); - bool setCaptureDevice(QString streamUuid, int device); -@@ -61,6 +62,8 @@ namespace Phonon - - signals: - void objectDescriptionChanged(ObjectDescriptionType); -+ void usingDevice(QString streamUuid, int device); -+ - private: - PulseSupport(); - ~PulseSupport(); diff --git a/phonon-4.4.0-eventloop.patch b/phonon-4.4.0-eventloop.patch deleted file mode 100644 index a20b5e8..0000000 --- a/phonon-4.4.0-eventloop.patch +++ /dev/null @@ -1,327 +0,0 @@ -diff --git a/phonon/pulsesupport.cpp b/phonon/pulsesupport.cpp -index d0387c3..a3733ad 100644 ---- a/phonon/pulsesupport.cpp -+++ b/phonon/pulsesupport.cpp -@@ -135,7 +135,6 @@ static bool s_pulseActive = false; - - static pa_glib_mainloop *s_mainloop = NULL; - static pa_context *s_context = NULL; --static QEventLoop *s_connectionEventloop = NULL; - - - -@@ -179,31 +178,25 @@ static void createGenericDevices() - } - - #ifdef HAVE_PULSEAUDIO_DEVICE_MANAGER --static void ext_device_manager_subscribe_cb(pa_context *, void *); - static void ext_device_manager_read_cb(pa_context *c, const pa_ext_device_manager_info *info, int eol, void *userdata) { - Q_ASSERT(c); - Q_ASSERT(userdata); - -- // If this is our first iteration, set things up properly -- if (s_connectionEventloop) { -- logMessage("Exiting connection event loop (PulseAudio server found)"); -- s_connectionEventloop->exit(0); -- s_connectionEventloop = NULL; -- s_pulseActive = true; -- -- pa_operation *o; -- pa_ext_device_manager_set_subscribe_cb(c, ext_device_manager_subscribe_cb, NULL); -- if ((o = pa_ext_device_manager_subscribe(c, 1, NULL, NULL))) -- pa_operation_unref(o); -- } -+ PulseUserData *u = reinterpret_cast(userdata); - - if (eol < 0) { - logMessage(QString("Failed to initialize device manager extension: %1").arg(pa_strerror(pa_context_errno(c)))); -+ logMessage("Falling back to single device mode"); - createGenericDevices(); -+ delete u; -+ -+ // If this is our probe phase, exit now -+ if (s_context != c) -+ pa_context_disconnect(c); -+ - return; - } - -- PulseUserData *u = reinterpret_cast(userdata); - if (eol) { - // We're done reading the data, so order it by priority and copy it into the - // static variables where it can then be accessed by those classes that need it. -@@ -289,6 +282,8 @@ static void ext_device_manager_read_cb(pa_context *c, const pa_ext_device_manage - } - - if (s_instance) { -+ // This wont be emitted durring the connection probe phase -+ // which is intensional - if (output_changed) - s_instance->emitObjectDescriptionChanged(AudioOutputDeviceType); - if (capture_changed) -@@ -323,6 +318,11 @@ static void ext_device_manager_read_cb(pa_context *c, const pa_ext_device_manage - } - } - } -+ -+ // If this is our probe phase, exit now as we're finished reading -+ // our device info and can exit and reconnect -+ if (s_context != c) -+ pa_context_disconnect(c); - } - - if (!info) -@@ -374,6 +374,19 @@ static void ext_device_manager_read_cb(pa_context *c, const pa_ext_device_manage - } - } - } -+ -+static void ext_device_manager_subscribe_cb(pa_context *c, void *) { -+ Q_ASSERT(c); -+ -+ pa_operation *o; -+ PulseUserData *u = new PulseUserData; -+ if (!(o = pa_ext_device_manager_read(c, ext_device_manager_read_cb, u))) { -+ logMessage(QString("pa_ext_device_manager_read() failed.")); -+ delete u; -+ return; -+ } -+ pa_operation_unref(o); -+} - #endif - - void sink_input_cb(pa_context *c, const pa_sink_input_info *i, int eol, void *userdata) { -@@ -515,49 +528,6 @@ static void subscribe_cb(pa_context *c, pa_subscription_event_type_t t, uint32_t - } - - --static void ext_device_manager_subscribe_cb(pa_context *c, void *) { -- Q_ASSERT(c); -- -- pa_operation *o; --#ifdef HAVE_PULSEAUDIO_DEVICE_MANAGER -- PulseUserData *u = new PulseUserData; /** @todo Make some object to receive the info... */ -- if (!(o = pa_ext_device_manager_read(c, ext_device_manager_read_cb, u))) { -- // We need to deal with failure on first iteration -- if (s_connectionEventloop) { -- logMessage("Entering connection eventloop (initialisation failed)"); -- s_connectionEventloop->exit(0); -- s_connectionEventloop = NULL; -- } -- logMessage(QString("pa_ext_device_manager_read() failed")); -- return; -- } -- pa_operation_unref(o); --#else -- // If we do not have Device Manager support. We just bail out now -- // and say we are active with our single "devices" for playback and capture -- s_pulseActive = true; -- logMessage("Entering connection eventloop (successfully detected PulseAudio)"); -- if (s_connectionEventloop) { -- s_connectionEventloop->exit(0); -- s_connectionEventloop = NULL; -- } -- createGenericDevices(); --#endif -- -- -- // Register for the stream changes... -- pa_context_set_subscribe_callback(c, subscribe_cb, NULL); -- -- if (!(o = pa_context_subscribe(c, (pa_subscription_mask_t) -- (PA_SUBSCRIPTION_MASK_SINK_INPUT| -- PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT), NULL, NULL))) { -- logMessage(QString("pa_context_subscribe() failed")); -- return; -- } -- pa_operation_unref(o); --} -- -- - static const char* statename(pa_context_state_t state) - { - switch (state) -@@ -581,32 +551,68 @@ static void context_state_callback(pa_context *c, void *) - Q_ASSERT(c); - - logMessage(QString("context_state_callback %1").arg(statename(pa_context_get_state(c)))); -- switch (pa_context_get_state(c)) { -- case PA_CONTEXT_UNCONNECTED: -- case PA_CONTEXT_CONNECTING: -- case PA_CONTEXT_AUTHORIZING: -- case PA_CONTEXT_SETTING_NAME: -- break; -+ pa_context_state_t state = pa_context_get_state(c); -+ if (state == PA_CONTEXT_READY) { -+ // We've connected to PA, so it is active -+ s_pulseActive = true; - -- case PA_CONTEXT_READY: -- // Attempt to load things up -- ext_device_manager_subscribe_cb(c, NULL); -- break; -+ // Attempt to load things up -+ pa_operation *o; -+ -+ // 1. Register for the stream changes (except during probe) -+ if (s_context == c) { -+ pa_context_set_subscribe_callback(c, subscribe_cb, NULL); - -- case PA_CONTEXT_FAILED: -- s_pulseActive = false; -- if (s_connectionEventloop) { -- logMessage("Entering connection eventloop (connection failed)"); -- s_connectionEventloop->exit(0); -- s_connectionEventloop = NULL; -+ if (!(o = pa_context_subscribe(c, (pa_subscription_mask_t) -+ (PA_SUBSCRIPTION_MASK_SINK_INPUT| -+ PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT), NULL, NULL))) { -+ logMessage(QString("pa_context_subscribe() failed")); -+ return; - } -- break; -+ pa_operation_unref(o); -+ } - -- case PA_CONTEXT_TERMINATED: -- default: -- s_pulseActive = false; -- /// @todo Deal with reconnection... -- break; -+#ifdef HAVE_PULSEAUDIO_DEVICE_MANAGER -+ // 2a. Attempt to initialise Device Manager info (except during probe) -+ if (s_context == c) { -+ pa_ext_device_manager_set_subscribe_cb(c, ext_device_manager_subscribe_cb, NULL); -+ if (!(o = pa_ext_device_manager_subscribe(c, 1, NULL, NULL))) { -+ logMessage(QString("pa_ext_device_manager_subscribe() failed")); -+ return; -+ } -+ pa_operation_unref(o); -+ } -+ -+ // 3. Attempt to read info from Device Manager -+ PulseUserData *u = new PulseUserData; -+ if (!(o = pa_ext_device_manager_read(c, ext_device_manager_read_cb, u))) { -+ logMessage(QString("pa_ext_device_manager_read() failed. Attempting to continue without device manager support")); -+ createGenericDevices(); -+ delete u; -+ -+ // If this is our probe phase, exit immediately -+ if (s_context != c) -+ pa_context_disconnect(c); -+ -+ return; -+ } -+ pa_operation_unref(o); -+ -+#else -+ // If we know do not have Device Manager support, we just create our dummy devices now -+ createGenericDevices(); -+ -+ // If this is our probe phase, exit immediately -+ if (s_context != c) -+ pa_context_disconnect(c); -+#endif -+ } else if (!PA_CONTEXT_IS_GOOD(state)) { -+ /// @todo Deal with reconnection... -+ //logMessage("Connection to PulseAudio lost"); -+ -+ // If this is our probe phase, exit our context immediately -+ if (s_context != c) -+ pa_context_disconnect(c); - } - } - #endif // HAVE_PULSEAUDIO -@@ -645,27 +651,67 @@ PulseSupport::PulseSupport() - - // To allow for easy debugging, give an easy way to disable this pulseaudio check - QString pulseenv = qgetenv("PHONON_PULSEAUDIO_DISABLE"); -- if (pulseenv.toInt()) -+ if (pulseenv.toInt()) { -+ logMessage("PulseAudio support disabled: PHONON_PULSEAUDIO_DISABLE is set"); -+ return; -+ } -+ -+ // First of all conenct to PA via simple/blocking means and if that succeeds, -+ // use a fully async integrated mainloop method to connect and get proper support. -+ pa_mainloop *p_test_mainloop; -+ if (!(p_test_mainloop = pa_mainloop_new())) { -+ logMessage("PulseAudio support disabled: Unable to create mainloop"); -+ return; -+ } -+ -+ pa_context *p_test_context; -+ if (!(p_test_context = pa_context_new(pa_mainloop_get_api(p_test_mainloop), "libphonon-probe"))) { -+ logMessage("PulseAudio support disabled: Unable to create context"); -+ pa_mainloop_free(p_test_mainloop); -+ return; -+ } -+ -+ logMessage("Probing for PulseAudio..."); -+ // (cg) Convert to PA_CONTEXT_NOFLAGS when PulseAudio 0.9.19 is required -+ if (pa_context_connect(p_test_context, NULL, static_cast(0), NULL) < 0) { -+ logMessage(QString("PulseAudio support disabled: %1").arg(pa_strerror(pa_context_errno(p_test_context)))); -+ pa_context_disconnect(p_test_context); -+ pa_context_unref(p_test_context); -+ pa_mainloop_free(p_test_mainloop); - return; -+ } -+ -+ pa_context_set_state_callback(p_test_context, &context_state_callback, NULL); -+ for (;;) { -+ pa_mainloop_iterate(p_test_mainloop, 1, NULL); - -+ if (!PA_CONTEXT_IS_GOOD(pa_context_get_state(p_test_context))) { -+ logMessage("PulseAudio probe complete."); -+ break; -+ } -+ } -+ pa_context_disconnect(p_test_context); -+ pa_context_unref(p_test_context); -+ pa_mainloop_free(p_test_mainloop); -+ -+ if (!s_pulseActive) { -+ logMessage("PulseAudio support is not available."); -+ return; -+ } -+ -+ // If we're still here, PA is available. -+ logMessage("PulseAudio support enabled"); -+ -+ // Now we connect for real using a proper main loop that we can forget -+ // all about processing. - s_mainloop = pa_glib_mainloop_new(NULL); - Q_ASSERT(s_mainloop); - pa_mainloop_api *api = pa_glib_mainloop_get_api(s_mainloop); - -- // We create a simple event loop to allow the glib loop -- // to iterate until we've connected or not to the server. -- s_connectionEventloop = new QEventLoop; -- -- // XXX I don't want to show up in the client list. All I want to know is the list of sources -- // and sinks... - s_context = pa_context_new(api, "libphonon"); - // (cg) Convert to PA_CONTEXT_NOFLAGS when PulseAudio 0.9.19 is required -- if (pa_context_connect(s_context, NULL, static_cast(0), 0) >= 0) { -- pa_context_set_state_callback(s_context, &context_state_callback, s_connectionEventloop); -- // Now we block until we connect or otherwise... -- logMessage("Entering connection eventloop..."); -- s_connectionEventloop->exec(); -- } -+ if (pa_context_connect(s_context, NULL, static_cast(0), 0) >= 0) -+ pa_context_set_state_callback(s_context, &context_state_callback, NULL); - #endif - } - -@@ -681,11 +727,6 @@ PulseSupport::~PulseSupport() - pa_glib_mainloop_free(s_mainloop); - s_mainloop = NULL; - } -- -- if (s_connectionEventloop) { -- delete s_connectionEventloop; -- s_connectionEventloop = NULL; -- } - #endif - } - diff --git a/phonon.spec b/phonon.spec index c70ed6d..e6c48b2 100644 --- a/phonon.spec +++ b/phonon.spec @@ -1,14 +1,12 @@ -%define tar_ver 4.4 - Summary: Multimedia framework api Name: phonon -Version: 4.4.0 -Release: 3%{?dist} +Version: 4.4.1 +Release: 1%{?dist} Group: System Environment/Libraries License: LGPLv2+ URL: http://phonon.kde.org/ -Source0: ftp://ftp.kde.org/pub/kde/stable/phonon/4.4.0/phonon-%{version}.tgz +Source0: ftp://ftp.kde.org/pub/kde/stable/phonon/%{version}/phonon-%{version}.tar.bz2 ## FIXME: update to point to http://gitorious.org/phonon Source1: phonon_snapshot.sh BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) @@ -22,14 +20,10 @@ Source15: hi64-phonon-gstreamer.png Source16: hi128-phonon-gstreamer.png ## Mandriva/upstreamable patches -Patch51: phonon-4.3.50-fix-decodebin-usage.patch Patch52: phonon-4.3.50-gstreamer-fix-seekable-query-failed.patch Patch53: phonon-4.3.50-phonon-allow-stop-empty-source.patch -Patch57: phonon-4.3.80-pulse-devicemove-rejig.patch ## Upstream patches -# https://bugs.kde.org/show_bug.cgi?id=228324#c23 -Patch100: phonon-4.4.0-eventloop.patch BuildRequires: automoc4 >= 0.9.86 BuildRequires: cmake >= 2.6.0 @@ -84,14 +78,10 @@ Provides: %{name}-backend-gst = %{version}-%{release} %prep -%setup -q -n phonon%{!?snap:-%{?tar_ver}%{!?tar_ver:%{version}}} +%setup -q -%patch51 -p0 -b .fix-decodebin-usage %patch52 -p1 -b .gstreamer-fix-seekable-query-failed %patch53 -p1 -b .phonon-allow-stop-empty-source -%patch57 -p1 -b .pulse-devicemove-rejig - -%patch100 -p1 -b .eventloop %build @@ -197,6 +187,9 @@ gtk-update-icon-cache %{_kde4_iconsdir}/hicolor &> /dev/null ||: %changelog +* Thu Apr 22 2010 Rex Dieter - 4.4.1-1 +- phonon-4.4.1 + * Thu Apr 01 2010 Rex Dieter - 4.4.0-3 - add minimal pulseaudio runtime dep diff --git a/sources b/sources index e9f9fad..68556d9 100644 --- a/sources +++ b/sources @@ -1,8 +1 @@ -8e3924f417fea67f72b2105faed2119c gstreamer-logo.svg -60de9d7e1cddd019f09fd036f0e5413a hi128-phonon-gstreamer.png -7ca265e0cf75b3b4c81e1490d3dba3be hi16-phonon-gstreamer.png -0a9f69d901aded140d4fed969c22e14f hi22-phonon-gstreamer.png -12db12c009b722a6dc141f78feb7e330 hi32-phonon-gstreamer.png -86c34a1b81d44980b1381f94ed6b7a23 hi48-phonon-gstreamer.png -153505c71ec021b0a3bd4b74f2492e93 hi64-phonon-gstreamer.png -80544b876cf0e0af05f2303b3f534351 phonon-4.4.0.tgz +5a1444f009a77054f16fea38c08e6cb5 phonon-4.4.1.tar.bz2