parent
d6afb7bd12
commit
ff15ad1dfe
@ -1,9 +1 @@
|
|||||||
gstreamer-logo.svg
|
phonon-4.4.1.tar.bz2
|
||||||
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
|
|
||||||
|
@ -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);
|
|
||||||
|
|
@ -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<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 ¤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("<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();
|
|
@ -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<PulseUserData*>(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<PulseUserData*>(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<pa_context_flags_t>(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<pa_context_flags_t>(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<pa_context_flags_t>(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
|
|
||||||
}
|
|
||||||
|
|
@ -1,8 +1 @@
|
|||||||
8e3924f417fea67f72b2105faed2119c gstreamer-logo.svg
|
5a1444f009a77054f16fea38c08e6cb5 phonon-4.4.1.tar.bz2
|
||||||
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
|
|
||||||
|
Loading…
Reference in new issue