- phonon-4.3.80-pulse-devicemove-rejig.patch (from mdv)

epel9
Rex Dieter 15 years ago
parent d0d14dd0d0
commit 3dfefd2d3c

@ -0,0 +1,454 @@
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<int> 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<int> 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 &currentDevice = 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 &currentDevice = 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("<html>Switching to the audio playback device <b>%1</b><br/>"
+ "which has higher preference or is specifically configured for this stream.</html>").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("<html>The audio playback device <b>%1</b> does not work.<br/>"
+ "Falling back to <b>%2</b>.</html>").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<QString, int> s_outputDeviceIndexes;
static QMap<int, AudioDevice> s_outputDevices;
static QMap<Phonon::Category, QMap<int, int> > s_outputDevicePriorities; // prio, device
static QMap<QString, uint32_t> s_outputStreamIndexMap;
-static QMap<QString, int> s_outputStreamMoveQueue;
static QMap<QString, int> s_captureDeviceIndexes;
static QMap<int, AudioDevice> s_captureDevices;
static QMap<Phonon::Category, QMap<int, int> > s_captureDevicePriorities; // prio, device
static QMap<QString, uint32_t> s_captureStreamIndexMap;
-static QMap<QString, int> 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<int, AudioDevice>::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<int, AudioDevice>::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();

@ -4,7 +4,7 @@
Summary: Multimedia framework api Summary: Multimedia framework api
Name: phonon Name: phonon
Version: 4.4.0 Version: 4.4.0
Release: 0.2%{?dist} Release: 0.3%{?dist}
Group: System Environment/Libraries Group: System Environment/Libraries
License: LGPLv2+ License: LGPLv2+
URL: http://phonon.kde.org/ URL: http://phonon.kde.org/
@ -32,6 +32,7 @@ Patch1: phonon-4.3.50-xine_pulseaudio.patch
Patch51: phonon-4.3.50-fix-decodebin-usage.patch Patch51: phonon-4.3.50-fix-decodebin-usage.patch
Patch52: phonon-4.3.50-gstreamer-fix-seekable-query-failed.patch Patch52: phonon-4.3.50-gstreamer-fix-seekable-query-failed.patch
Patch53: phonon-4.3.50-phonon-allow-stop-empty-source.patch Patch53: phonon-4.3.50-phonon-allow-stop-empty-source.patch
Patch57: phonon-4.3.80-pulse-devicemove-rejig.patch
## Upstream patches ## Upstream patches
@ -101,6 +102,7 @@ Provides: %{name}-backend-gst = %{version}-%{release}
%patch51 -p0 -b .fix-decodebin-usage %patch51 -p0 -b .fix-decodebin-usage
%patch52 -p1 -b .gstreamer-fix-seekable-query-failed %patch52 -p1 -b .gstreamer-fix-seekable-query-failed
%patch53 -p1 -b .phonon-allow-stop-empty-source %patch53 -p1 -b .phonon-allow-stop-empty-source
%patch57 -p1 -b .pulse-devicemove-rejig
%build %build
@ -206,6 +208,9 @@ gtk-update-icon-cache %{_kde4_iconsdir}/hicolor &> /dev/null ||:
%changelog %changelog
* Fri Mar 12 2010 Rex Dieter <rdieter@fedoraproject.org> - 4.4.0-0.3
- phonon-4.3.80-pulse-devicemove-rejig.patch (from mdv)
* Wed Feb 24 2010 Rex Dieter <rdieter@fedoraproject.org> - 4.4.0-0.2 * Wed Feb 24 2010 Rex Dieter <rdieter@fedoraproject.org> - 4.4.0-0.2
- preliminary phonon-4.4.0 tarball - preliminary phonon-4.4.0 tarball

Loading…
Cancel
Save