[kdebase-runtime] - pa speakersetup backport (courtesy of coling/mandriva) - hammer rpath from phonon_platform/kde.so
Rex Dieter
rdieter at fedoraproject.org
Fri Oct 15 17:52:46 UTC 2010
commit 57c10a4327c3ad5bd8aed98d349ad2c1f9ea9a0b
Author: Rex Dieter <rdieter at fedoraproject.org>
Date: Fri Oct 15 12:58:48 2010 -0500
- pa speakersetup backport (courtesy of coling/mandriva)
- hammer rpath from phonon_platform/kde.so
kdebase-runtime-4.5-speakersetup.patch | 1318 ++++++++++++++++++++++++++++++++
kdebase-runtime.spec | 19 +-
2 files changed, 1336 insertions(+), 1 deletions(-)
---
diff --git a/kdebase-runtime-4.5-speakersetup.patch b/kdebase-runtime-4.5-speakersetup.patch
new file mode 100644
index 0000000..acd828a
--- /dev/null
+++ b/kdebase-runtime-4.5-speakersetup.patch
@@ -0,0 +1,1318 @@
+Index: runtime/phonon/kcm/testspeakerwidget.cpp
+===================================================================
+--- runtime/phonon/kcm/testspeakerwidget.cpp (revision 0)
++++ runtime/phonon/kcm/testspeakerwidget.cpp (revision 1154776)
+@@ -0,0 +1,194 @@
++/* This file is part of the KDE project
++ Copyright (C) 2010 Colin Guthrie <cguthrie at mandriva.org>
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License version 2
++ as published by the Free Software Foundation.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the Free Software
++ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
++ 02110-1301, USA.
++
++*/
++
++#include "testspeakerwidget.h"
++#include "speakersetup.h"
++#include <stdio.h>
++
++TestSpeakerWidget::TestSpeakerWidget(const pa_channel_position_t pos, ca_context *canberra, SpeakerSetup* ss)
++ : KPushButton(KIcon("preferences-desktop-sound"), "Test", ss)
++ , m_Ss(ss)
++ , m_Pos(pos)
++ , m_Canberra(canberra)
++{
++ setText(_positionName());
++ connect(this, SIGNAL(clicked()), SLOT(clicked()));
++}
++
++void TestSpeakerWidget::clicked()
++{
++ uint32_t sink_index = m_Ss->getCurrentSinkIndex();
++ char dev[64];
++ snprintf(dev, sizeof(dev), "%lu", (unsigned long) sink_index);
++ ca_context_change_device(m_Canberra, dev);
++
++ const char* sound_name = _positionSoundName();
++ ca_proplist* proplist;
++ ca_proplist_create(&proplist);
++
++ ca_proplist_sets(proplist, CA_PROP_MEDIA_ROLE, "test");
++ ca_proplist_sets(proplist, CA_PROP_MEDIA_NAME, _positionName().toAscii().constData());
++ ca_proplist_sets(proplist, CA_PROP_CANBERRA_FORCE_CHANNEL, _positionAsString());
++ ca_proplist_sets(proplist, CA_PROP_CANBERRA_ENABLE, "1");
++
++ ca_proplist_sets(proplist, CA_PROP_EVENT_ID, sound_name);
++ if (ca_context_play_full(m_Canberra, 0, proplist, NULL, NULL) < 0) {
++ // Try a different sound name.
++ ca_proplist_sets(proplist, CA_PROP_EVENT_ID, "audio-test-signal");
++ if (ca_context_play_full(m_Canberra, 0, proplist, NULL, NULL) < 0) {
++ // Finaly try this... if this doesn't work, then stuff it.
++ ca_proplist_sets(proplist, CA_PROP_EVENT_ID, "bell-window-system");
++ }
++ }
++
++ ca_context_change_device(m_Canberra, NULL);
++ ca_proplist_destroy(proplist);
++}
++
++const char* TestSpeakerWidget::_positionAsString()
++{
++ switch (m_Pos)
++ {
++ case PA_CHANNEL_POSITION_FRONT_LEFT:
++ return "front-left";
++
++ case PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER:
++ return "front-left-of-center";
++
++ case PA_CHANNEL_POSITION_FRONT_CENTER:
++ return "front-center";
++
++ case PA_CHANNEL_POSITION_MONO:
++ return "mono";
++
++ case PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER:
++ return "front-right-of-center";
++
++ case PA_CHANNEL_POSITION_FRONT_RIGHT:
++ return "front-right";
++
++ case PA_CHANNEL_POSITION_SIDE_LEFT:
++ return "side-left";
++
++ case PA_CHANNEL_POSITION_SIDE_RIGHT:
++ return "side-right";
++
++ case PA_CHANNEL_POSITION_REAR_LEFT:
++ return "rear-left";
++
++ case PA_CHANNEL_POSITION_REAR_CENTER:
++ return "rear-center";
++
++ case PA_CHANNEL_POSITION_REAR_RIGHT:
++ return "rear-right";
++
++ case PA_CHANNEL_POSITION_LFE:
++ return "lfe";
++
++ default:
++ break;
++ }
++ return "invalid";
++}
++
++QString TestSpeakerWidget::_positionName()
++{
++ switch (m_Pos)
++ {
++ case PA_CHANNEL_POSITION_FRONT_LEFT:
++ return i18n("Front Left");
++
++ case PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER:
++ return i18n("Front Left of Center");
++
++ case PA_CHANNEL_POSITION_FRONT_CENTER:
++ return i18n("Front Center");
++
++ case PA_CHANNEL_POSITION_MONO:
++ return i18n("Mono");
++
++ case PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER:
++ return i18n("Front Right of Center");
++
++ case PA_CHANNEL_POSITION_FRONT_RIGHT:
++ return i18n("Front Right");
++
++ case PA_CHANNEL_POSITION_SIDE_LEFT:
++ return i18n("Side Left");
++
++ case PA_CHANNEL_POSITION_SIDE_RIGHT:
++ return i18n("Side Right");
++
++ case PA_CHANNEL_POSITION_REAR_LEFT:
++ return i18n("Rear Left");
++
++ case PA_CHANNEL_POSITION_REAR_CENTER:
++ return i18n("Rear Center");
++
++ case PA_CHANNEL_POSITION_REAR_RIGHT:
++ return i18n("Rear Right");
++
++ case PA_CHANNEL_POSITION_LFE:
++ return i18n("Subwoofer");
++
++ default:
++ break;
++ }
++ return i18n("Unknown Channel");
++}
++
++const char* TestSpeakerWidget::_positionSoundName()
++{
++ switch (m_Pos)
++ {
++ case PA_CHANNEL_POSITION_FRONT_LEFT:
++ return "audio-channel-front-left";
++
++ case PA_CHANNEL_POSITION_FRONT_RIGHT:
++ return "audio-channel-front-right";
++
++ case PA_CHANNEL_POSITION_FRONT_CENTER:
++ return "audio-channel-front-center";
++
++ case PA_CHANNEL_POSITION_REAR_LEFT:
++ return "audio-channel-rear-left";
++
++ case PA_CHANNEL_POSITION_REAR_RIGHT:
++ return "audio-channel-rear-right";
++
++ case PA_CHANNEL_POSITION_REAR_CENTER:
++ return "audio-channel-rear-center";
++
++ case PA_CHANNEL_POSITION_LFE:
++ return "audio-channel-lfe";
++
++ case PA_CHANNEL_POSITION_SIDE_LEFT:
++ return "audio-channel-side-left";
++
++ case PA_CHANNEL_POSITION_SIDE_RIGHT:
++ return "audio-channel-side-right";
++ default:
++ break;
++ }
++ return NULL;
++}
++
++
++#include "testspeakerwidget.moc"
++// vim: sw=4 sts=4 et tw=100
+
+Property changes on: runtime/phonon/kcm/testspeakerwidget.cpp
+___________________________________________________________________
+Added: svn:mime-type
+ + text/plain
+Added: svn:eol-style
+ + native
+
+Index: runtime/phonon/kcm/testspeakerwidget.h
+===================================================================
+--- runtime/phonon/kcm/testspeakerwidget.h (revision 0)
++++ runtime/phonon/kcm/testspeakerwidget.h (revision 1154776)
+@@ -0,0 +1,50 @@
++/* This file is part of the KDE project
++ Copyright (C) 2010 Colin Guthrie <cguthrie at mandriva.org>
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License version 2
++ as published by the Free Software Foundation.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the Free Software
++ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
++ 02110-1301, USA.
++
++*/
++
++#ifndef PHONON_TESTSPEAKERWIDGET_H
++#define PHONON_TESTSPEAKERWIDGET_H
++
++#include <kpushbutton.h>
++
++#include <canberra.h>
++#include <pulse/pulseaudio.h>
++
++
++class SpeakerSetup;
++
++class TestSpeakerWidget: public KPushButton
++{
++ Q_OBJECT
++ public:
++ TestSpeakerWidget(const pa_channel_position_t pos, ca_context *canberra, SpeakerSetup* ss);
++
++ private slots:
++ void clicked();
++
++ private:
++ QString _positionName();
++ const char* _positionAsString();
++ const char* _positionSoundName();
++
++ SpeakerSetup* m_Ss;
++ pa_channel_position_t m_Pos;
++ ca_context* m_Canberra;
++};
++
++#endif // PHONON_TESTSPEAKERWIDGET_H
+
+Property changes on: runtime/phonon/kcm/testspeakerwidget.h
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+
+Index: runtime/phonon/kcm/speakersetup.ui
+===================================================================
+--- runtime/phonon/kcm/speakersetup.ui (revision 0)
++++ runtime/phonon/kcm/speakersetup.ui (revision 1154776)
+@@ -0,0 +1,142 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<ui version="4.0">
++ <author>Matthias Kretz <kretz at kde.org</author>
++ <class>SpeakerSetup</class>
++ <widget class="QWidget" name="SpeakerSetup">
++ <property name="geometry">
++ <rect>
++ <x>0</x>
++ <y>0</y>
++ <width>537</width>
++ <height>465</height>
++ </rect>
++ </property>
++ <layout class="QVBoxLayout" name="verticalLayout">
++ <item>
++ <widget class="QGroupBox" name="hardwareGroupBox">
++ <property name="title">
++ <string>Hardware</string>
++ </property>
++ <layout class="QGridLayout" name="_3">
++ <item row="3" column="1">
++ <widget class="QComboBox" name="profileBox">
++ <property name="sizePolicy">
++ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
++ <horstretch>0</horstretch>
++ <verstretch>0</verstretch>
++ </sizepolicy>
++ </property>
++ </widget>
++ </item>
++ <item row="2" column="1">
++ <widget class="KComboBox" name="cardBox">
++ <property name="sizePolicy">
++ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
++ <horstretch>0</horstretch>
++ <verstretch>0</verstretch>
++ </sizepolicy>
++ </property>
++ </widget>
++ </item>
++ <item row="3" column="0">
++ <widget class="QLabel" name="profileLabel">
++ <property name="text">
++ <string>Profile</string>
++ </property>
++ <property name="buddy">
++ <cstring>profileBox</cstring>
++ </property>
++ </widget>
++ </item>
++ <item row="2" column="0">
++ <widget class="QLabel" name="cardLabel">
++ <property name="text">
++ <string>Sound Card</string>
++ </property>
++ <property name="buddy">
++ <cstring>cardBox</cstring>
++ </property>
++ </widget>
++ </item>
++ </layout>
++ </widget>
++ </item>
++ <item>
++ <widget class="QGroupBox" name="outputGroupBox">
++ <property name="title">
++ <string>Output</string>
++ </property>
++ <layout class="QGridLayout" name="_2">
++ <item row="0" column="1">
++ <widget class="KComboBox" name="sinkBox">
++ <property name="sizePolicy">
++ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
++ <horstretch>0</horstretch>
++ <verstretch>0</verstretch>
++ </sizepolicy>
++ </property>
++ </widget>
++ </item>
++ <item row="1" column="0">
++ <widget class="QLabel" name="portLabel">
++ <property name="text">
++ <string>Connector</string>
++ </property>
++ <property name="buddy">
++ <cstring>portBox</cstring>
++ </property>
++ </widget>
++ </item>
++ <item row="1" column="1">
++ <widget class="QComboBox" name="portBox">
++ <property name="sizePolicy">
++ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
++ <horstretch>0</horstretch>
++ <verstretch>0</verstretch>
++ </sizepolicy>
++ </property>
++ </widget>
++ </item>
++ <item row="0" column="0">
++ <widget class="QLabel" name="sinkLabel">
++ <property name="text">
++ <string>Sound Output</string>
++ </property>
++ <property name="buddy">
++ <cstring>sinkBox</cstring>
++ </property>
++ </widget>
++ </item>
++ </layout>
++ </widget>
++ </item>
++ <item>
++ <widget class="QGroupBox" name="groupBox">
++ <property name="sizePolicy">
++ <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
++ <horstretch>0</horstretch>
++ <verstretch>0</verstretch>
++ </sizepolicy>
++ </property>
++ <property name="title">
++ <string>Speaker Placement and Testing</string>
++ </property>
++ <layout class="QVBoxLayout" name="_4">
++ <item>
++ <layout class="QGridLayout" name="placementGrid"/>
++ </item>
++ </layout>
++ </widget>
++ </item>
++ </layout>
++ </widget>
++ <customwidgets>
++ <customwidget>
++ <class>KComboBox</class>
++ <extends>QComboBox</extends>
++ <header>kcombobox.h</header>
++ </customwidget>
++ </customwidgets>
++ <resources/>
++ <connections/>
++</ui>
+Index: runtime/phonon/kcm/speakersetup.cpp
+===================================================================
+--- runtime/phonon/kcm/speakersetup.cpp (revision 0)
++++ runtime/phonon/kcm/speakersetup.cpp (revision 1154776)
+@@ -0,0 +1,664 @@
++/* This file is part of the KDE project
++ Copyright (C) 2010 Colin Guthrie <cguthrie at mandriva.org>
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License version 2
++ as published by the Free Software Foundation.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the Free Software
++ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
++ 02110-1301, USA.
++
++*/
++
++#include "speakersetup.h"
++#include "testspeakerwidget.h"
++#include <kgenericfactory.h>
++#include <kconfiggroup.h>
++#include <kaboutdata.h>
++#include <kicon.h>
++
++#include <glib.h>
++#include <pulse/xmalloc.h>
++#include <pulse/glib-mainloop.h>
++#include <QtCore/QAbstractEventDispatcher>
++#include <QtCore/QFileInfo>
++#include <QtCore/QDir>
++#include <QtDBus/QDBusConnection>
++#include <QtDBus/QDBusInterface>
++
++#define SS_DEFAULT_ICON "audio-card"
++
++
++static pa_glib_mainloop *s_mainloop = NULL;
++static pa_context *s_context = NULL;
++
++typedef struct {
++ uint32_t index;
++ QString name;
++ QString icon;
++ QMap<uint32_t,QPair<QString,QString> > profiles;
++ QString activeProfile;
++} cardInfo;
++
++QMap<uint32_t,cardInfo> s_Cards;
++
++typedef struct {
++ uint32_t index;
++ uint32_t cardIndex;
++ QString name;
++ QString icon;
++ pa_channel_map channelMap;
++ QMap<uint32_t,QPair<QString,QString> > ports;
++ QString activePort;
++} sinkInfo;
++
++QMap<uint32_t,sinkInfo> s_Sinks;
++
++static int debugLevel() {
++ static int level = -1;
++ if (level < 1) {
++ level = 0;
++ QString pulseenv = qgetenv("PHONON_PULSEAUDIO_DEBUG");
++ int l = pulseenv.toInt();
++ if (l > 0)
++ level = (l > 2 ? 2 : l);
++ }
++ return level;
++}
++
++static void logMessage(const QString &message, int priority = 2, QObject *obj=0);
++static void logMessage(const QString &message, int priority, QObject *obj)
++{
++ if (debugLevel() > 0) {
++ QString output;
++ if (obj) {
++ // Strip away namespace from className
++ QString className(obj->metaObject()->className());
++ int nameLength = className.length() - className.lastIndexOf(':') - 1;
++ className = className.right(nameLength);
++ output.sprintf("%s %s (%s %p)", message.toLatin1().constData(),
++ obj->objectName().toLatin1().constData(),
++ className.toLatin1().constData(), obj);
++ }
++ else {
++ output = message;
++ }
++ if (priority <= debugLevel()) {
++ qDebug() << QString("PulseSupport(%1): %2").arg(priority).arg(output);
++ }
++ }
++}
++
++
++static void card_cb(pa_context *c, const pa_card_info *i, int eol, void *userdata) {
++ Q_ASSERT(c);
++ Q_ASSERT(userdata);
++
++ SpeakerSetup* ss = static_cast<SpeakerSetup*>(userdata);
++
++ if (eol < 0) {
++ if (pa_context_errno(c) == PA_ERR_NOENTITY)
++ return;
++
++ logMessage(QString("Card callback failure"));
++ return;
++ }
++
++ if (eol > 0) {
++ ss->updateFromPulse();
++ return;
++ }
++
++ Q_ASSERT(i);
++ ss->updateCard(i);
++}
++
++static void sink_cb(pa_context *c, const pa_sink_info *i, int eol, void *userdata) {
++ Q_ASSERT(c);
++ Q_ASSERT(userdata);
++
++ SpeakerSetup* ss = static_cast<SpeakerSetup*>(userdata);
++
++ if (eol < 0) {
++ if (pa_context_errno(c) == PA_ERR_NOENTITY)
++ return;
++
++ logMessage(QString("Sink callback failure"));
++ return;
++ }
++
++ if (eol > 0) {
++ ss->updateIndependantDevices();
++ ss->updateFromPulse();
++ return;
++ }
++
++ Q_ASSERT(i);
++ ss->updateSink(i);
++}
++
++static void subscribe_cb(pa_context *c, pa_subscription_event_type_t t, uint32_t index, void *userdata) {
++ Q_ASSERT(c);
++ Q_ASSERT(userdata);
++
++ SpeakerSetup* ss = static_cast<SpeakerSetup*>(userdata);
++
++ switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) {
++ case PA_SUBSCRIPTION_EVENT_CARD:
++ if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {
++ ss->removeCard(index);
++ } else {
++ pa_operation *o;
++ if (!(o = pa_context_get_card_info_by_index(c, index, card_cb, ss))) {
++ logMessage(QString("pa_context_get_card_info_by_index() failed"));
++ return;
++ }
++ pa_operation_unref(o);
++ }
++ break;
++
++ case PA_SUBSCRIPTION_EVENT_SINK:
++ if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {
++ ss->removeSink(index);
++ } else {
++ pa_operation *o;
++ if (!(o = pa_context_get_sink_info_by_index(c, index, sink_cb, ss))) {
++ logMessage(QString("pa_context_get_sink_info_by_index() failed"));
++ return;
++ }
++ pa_operation_unref(o);
++ }
++ break;
++ }
++}
++
++
++static const char* statename(pa_context_state_t state)
++{
++ switch (state)
++ {
++ case PA_CONTEXT_UNCONNECTED: return "Unconnected";
++ case PA_CONTEXT_CONNECTING: return "Connecting";
++ case PA_CONTEXT_AUTHORIZING: return "Authorizing";
++ case PA_CONTEXT_SETTING_NAME: return "Setting Name";
++ case PA_CONTEXT_READY: return "Ready";
++ case PA_CONTEXT_FAILED: return "Failed";
++ case PA_CONTEXT_TERMINATED: return "Terminated";
++ }
++
++ static QString unknown;
++ unknown = QString("Unknown state: %0").arg(state);
++ return unknown.toAscii().constData();
++}
++
++static void context_state_callback(pa_context *c, void *userdata)
++{
++ Q_ASSERT(c);
++ Q_ASSERT(userdata);
++
++ SpeakerSetup* ss = static_cast<SpeakerSetup*>(userdata);
++
++ logMessage(QString("context_state_callback %1").arg(statename(pa_context_get_state(c))));
++ pa_context_state_t state = pa_context_get_state(c);
++ if (state == PA_CONTEXT_READY) {
++ // Attempt to load things up
++ pa_operation *o;
++
++ pa_context_set_subscribe_callback(c, subscribe_cb, ss);
++
++ if (!(o = pa_context_subscribe(c, (pa_subscription_mask_t)
++ (PA_SUBSCRIPTION_MASK_CARD|
++ PA_SUBSCRIPTION_MASK_SINK), NULL, NULL))) {
++ logMessage(QString("pa_context_subscribe() failed"));
++ return;
++ }
++ pa_operation_unref(o);
++
++ if (!(o = pa_context_get_card_info_list(c, card_cb, ss))) {
++ logMessage(QString("pa_context_get_card_info_list() failed"));
++ return;
++ }
++ pa_operation_unref(o);
++
++ if (!(o = pa_context_get_sink_info_list(c, sink_cb, ss))) {
++ logMessage(QString("pa_context_get_sink_info_list() failed"));
++ return;
++ }
++ pa_operation_unref(o);
++
++ ss->load();
++
++ } else if (!PA_CONTEXT_IS_GOOD(state)) {
++ /// @todo Deal with reconnection...
++ //logMessage(QString("Connection to PulseAudio lost: %1").arg(pa_strerror(pa_context_errno(c))));
++
++ // If this is our probe phase, exit our context immediately
++ if (s_context != c)
++ pa_context_disconnect(c);
++ else {
++ pa_context_unref(s_context);
++ s_context = NULL;
++ //QTimer::singleShot(50, PulseSupport::getInstance(), SLOT(connectToDaemon()));
++ }
++ }
++}
++
++
++SpeakerSetup::SpeakerSetup(QWidget *parent)
++ : QWidget(parent)
++ , m_OutstandingRequests(2)
++ , m_Canberra(NULL)
++{
++ setupUi(this);
++
++ cardLabel->setEnabled(false);
++ cardBox->setEnabled(false);
++ profileLabel->setVisible(false);
++ profileBox->setVisible(false);
++
++ sinkLabel->setEnabled(false);
++ sinkBox->setEnabled(false);
++ portLabel->setVisible(false);
++ portBox->setVisible(false);
++
++ for (int i=0; i<5; ++i)
++ placementGrid->setColumnStretch(i, 1);
++ for (int i=0; i<3; ++i)
++ placementGrid->setRowStretch(i, 1);
++
++ m_Icon = new QLabel(this);
++ const QFileInfo fi(QDir(QDir::homePath()), ".face.icon");
++ if (fi.exists())
++ m_Icon->setPixmap(QPixmap(fi.absoluteFilePath()).scaled(KIconLoader::SizeHuge, KIconLoader::SizeHuge, Qt::KeepAspectRatio));
++ else
++ m_Icon->setPixmap(KIcon("system-users").pixmap(KIconLoader::SizeHuge, KIconLoader::SizeHuge));
++ placementGrid->addWidget(m_Icon, 1, 2, Qt::AlignCenter);
++
++ update();
++ connect(cardBox, SIGNAL(currentIndexChanged(int)), SLOT(cardChanged()));
++ connect(profileBox, SIGNAL(currentIndexChanged(int)), SLOT(profileChanged()));
++ connect(sinkBox, SIGNAL(currentIndexChanged(int)), SLOT(sinkChanged()));
++ connect(portBox, SIGNAL(currentIndexChanged(int)), SLOT(portChanged()));
++
++ // We require a glib event loop
++ if (QLatin1String(QAbstractEventDispatcher::instance()->metaObject()->className())
++ != "QGuiEventDispatcherGlib") {
++ logMessage("Disabling PulseAudio integration for lack of GLib event loop.");
++ return;
++ }
++
++ s_mainloop = pa_glib_mainloop_new(NULL);
++ Q_ASSERT(s_mainloop);
++
++ pa_mainloop_api *api = pa_glib_mainloop_get_api(s_mainloop);
++
++ s_context = pa_context_new(api, "kspeakersetup");
++ int rv;
++ rv = pa_context_connect(s_context, NULL, PA_CONTEXT_NOFAIL, 0);
++ Q_ASSERT(rv >= 0);
++
++ pa_context_set_state_callback(s_context, &context_state_callback, this);
++
++ rv = ca_context_create(&m_Canberra);
++ Q_ASSERT(rv >= 0);
++}
++
++SpeakerSetup::~SpeakerSetup()
++{
++ ca_context_destroy(m_Canberra);
++ pa_context_unref(s_context);
++ s_context = NULL;
++ pa_glib_mainloop_free(s_mainloop);
++ s_mainloop = NULL;
++}
++
++void SpeakerSetup::load()
++{
++}
++
++void SpeakerSetup::save()
++{
++}
++
++void SpeakerSetup::defaults()
++{
++}
++
++void SpeakerSetup::updateCard(const pa_card_info* i)
++{
++ cardInfo info;
++ info.index = i->index;
++
++ const char* description = pa_proplist_gets(i->proplist, PA_PROP_DEVICE_DESCRIPTION);
++ info.name = description ? QString::fromUtf8(description) : i->name;
++
++ const char* icon = pa_proplist_gets(i->proplist, PA_PROP_DEVICE_ICON_NAME);
++ info.icon = icon ? icon : SS_DEFAULT_ICON;
++
++ for (uint32_t j = 0; j < i->n_profiles; ++j)
++ info.profiles[i->profiles[j].priority] = QPair<QString,QString>(i->profiles[j].name, QString::fromUtf8(i->profiles[j].description));
++ if (i->active_profile)
++ info.activeProfile = i->active_profile->name;
++
++
++ bool bs = cardBox->blockSignals(true);
++ if (s_Cards.contains(i->index)) {
++ int idx = cardBox->findData(i->index);
++ if (idx >= 0) {
++ cardBox->setItemIcon(idx, KIcon(info.icon));
++ cardBox->setItemText(idx, info.name);
++ }
++ }
++ else
++ cardBox->addItem(KIcon(info.icon), info.name, i->index);
++ cardBox->blockSignals(bs);
++
++ s_Cards[i->index] = info;
++
++ cardChanged();
++
++ logMessage(QString("Got info about card %1").arg(info.name));
++}
++
++void SpeakerSetup::removeCard(uint32_t index)
++{
++ s_Cards.remove(index);
++ updateFromPulse();
++ int idx = cardBox->findData(index);
++ if (idx >= 0)
++ cardBox->removeItem(idx);
++}
++
++void SpeakerSetup::updateSink(const pa_sink_info* i)
++{
++ sinkInfo info;
++ info.index = i->index;
++ info.cardIndex = i->card;
++ info.name = QString::fromUtf8(i->description);
++
++ const char* icon = pa_proplist_gets(i->proplist, PA_PROP_DEVICE_ICON_NAME);
++ info.icon = icon ? icon : SS_DEFAULT_ICON;
++
++ info.channelMap = i->channel_map;
++
++ for (uint32_t j = 0; j < i->n_ports; ++j)
++ info.ports[i->ports[j]->priority] = QPair<QString,QString>(i->ports[j]->name, QString::fromUtf8(i->ports[j]->description));
++ if (i->active_port)
++ info.activePort = i->active_port->name;
++
++ s_Sinks[i->index] = info;
++
++ // Need to update the currently displayed port if this sink is the currently displayed one.
++ if (info.ports.size()) {
++ int idx = sinkBox->currentIndex();
++ if (idx >= 0) {
++ uint32_t sink_index = sinkBox->itemData(idx).toUInt();
++ if (sink_index == i->index) {
++ bool bs = portBox->blockSignals(true);
++ portBox->setCurrentIndex(portBox->findData(info.activePort));
++ portBox->blockSignals(bs);
++ }
++ }
++ }
++
++ logMessage(QString("Got info about sink %1").arg(info.name));
++}
++
++void SpeakerSetup::removeSink(uint32_t index)
++{
++ s_Sinks.remove(index);
++ updateIndependantDevices();
++ updateFromPulse();
++ int idx = sinkBox->findData(index);
++ if (idx >= 0)
++ sinkBox->removeItem(idx);
++}
++
++void SpeakerSetup::updateFromPulse()
++{
++ if (m_OutstandingRequests > 0) {
++ if (0 == --m_OutstandingRequests) {
++ // Work out which seclector to pick by default (we want to choose a real Card if possible)
++ if (s_Cards.size() != cardBox->count())
++ cardBox->setCurrentIndex(1);
++ emit ready();
++ }
++ }
++
++ if (!m_OutstandingRequests) {
++ if (!s_Cards.size() && !s_Sinks.size()) {
++ cardLabel->setEnabled(false);
++ cardBox->setEnabled(false);
++ profileLabel->setVisible(false);
++ profileBox->setVisible(false);
++
++ sinkLabel->setEnabled(false);
++ sinkBox->setEnabled(false);
++ portLabel->setVisible(false);
++ portBox->setVisible(false);
++ }
++ if (s_Cards.size() && !cardBox->isEnabled()) {
++ cardLabel->setEnabled(true);
++ cardBox->setEnabled(true);
++ cardChanged();
++ }
++ if (s_Sinks.size() && !sinkBox->isEnabled()) {
++ sinkLabel->setEnabled(true);
++ sinkBox->setEnabled(true);
++ sinkChanged();
++ }
++ }
++}
++
++void SpeakerSetup::cardChanged()
++{
++ int idx = cardBox->currentIndex();
++ if (idx < 0) {
++ profileLabel->setVisible(false);
++ profileBox->setVisible(false);
++ return;
++ }
++
++ uint32_t card_index = cardBox->itemData(idx).toUInt();
++ Q_ASSERT(PA_INVALID_INDEX == card_index || s_Cards.contains(card_index));
++ bool show_profiles = (PA_INVALID_INDEX != card_index && s_Cards[card_index].profiles.size());
++ if (show_profiles) {
++ cardInfo &card_info = s_Cards[card_index];
++ bool bs = profileBox->blockSignals(true);
++ profileBox->clear();
++ for (QMap<uint32_t, QPair<QString,QString> >::iterator it = card_info.profiles.begin(); it != card_info.profiles.end(); ++it)
++ profileBox->insertItem(0, it.value().second, it.value().first);
++ profileBox->setCurrentIndex(profileBox->findData(card_info.activeProfile));
++ profileBox->blockSignals(bs);
++ }
++ profileLabel->setVisible(show_profiles);
++ profileBox->setVisible(show_profiles);
++
++
++ bool bs = sinkBox->blockSignals(true);
++ sinkBox->clear();
++ for (QMap<uint32_t,sinkInfo>::iterator it = s_Sinks.begin(); it != s_Sinks.end(); ++it) {
++ if (it->cardIndex == card_index)
++ sinkBox->addItem(KIcon(it->icon), it->name, it->index);
++ }
++ sinkBox->blockSignals(bs);
++
++ outputGroupBox->setEnabled(!!sinkBox->count());
++
++ sinkChanged();
++
++ logMessage(QString("Doing update %1").arg(cardBox->currentIndex()));
++
++ emit changed();
++}
++
++void SpeakerSetup::profileChanged()
++{
++ uint32_t card_index = cardBox->itemData(cardBox->currentIndex()).toUInt();
++ Q_ASSERT(PA_INVALID_INDEX != card_index);
++
++ QString profile = profileBox->itemData(profileBox->currentIndex()).toString();
++ logMessage(QString("Changing profile to %1").arg(profile));
++
++ cardInfo &card_info = s_Cards[card_index];
++ Q_ASSERT(card_info.profiles.size());
++
++ pa_operation *o;
++ if (!(o = pa_context_set_card_profile_by_index(s_context, card_index, profile.toAscii().constData(), NULL, NULL)))
++ logMessage(QString("pa_context_set_card_profile_by_name() failed"));
++ else
++ pa_operation_unref(o);
++
++ emit changed();
++}
++
++void SpeakerSetup::updateIndependantDevices()
++{
++ // Should we display the "Independant Devices" drop down?
++ // Count all the sinks without cards
++ bool showID = false;
++ for (QMap<uint32_t,sinkInfo>::iterator it = s_Sinks.begin(); it != s_Sinks.end(); ++it) {
++ if (PA_INVALID_INDEX == it->cardIndex) {
++ showID = true;
++ break;
++ }
++ }
++
++ bool haveID = (PA_INVALID_INDEX == cardBox->itemData(0).toUInt());
++
++ logMessage(QString("Want ID: %1; Have ID: %2").arg(showID?"Yes":"No").arg(haveID?"Yes":"No"));
++
++ bool bs = cardBox->blockSignals(true);
++ if (haveID && !showID)
++ cardBox->removeItem(0);
++ else if (!haveID && showID)
++ cardBox->insertItem(0, KIcon(SS_DEFAULT_ICON), "Independent Devices", PA_INVALID_INDEX);
++ cardBox->blockSignals(bs);
++}
++
++void SpeakerSetup::sinkChanged()
++{
++ int idx = sinkBox->currentIndex();
++ if (idx < 0) {
++ portLabel->setVisible(false);
++ portBox->setVisible(false);
++ _updatePlacementTester();
++ return;
++ }
++ uint32_t sink_index = sinkBox->itemData(idx).toUInt();
++ Q_ASSERT(s_Sinks.contains(sink_index));
++ sinkInfo &sink_info = s_Sinks[sink_index];
++ logMessage(QString("Updating ports for sink '%1' (%2 ports available)").arg(sink_info.name).arg(sink_info.ports.size()));
++
++ bool show_ports = !!sink_info.ports.size();
++ if (show_ports) {
++ bool bs = portBox->blockSignals(true);
++ portBox->clear();
++ for (QMap<uint32_t, QPair<QString,QString> >::iterator it = sink_info.ports.begin(); it != sink_info.ports.end(); ++it)
++ portBox->insertItem(0, it.value().second, it.value().first);
++ portBox->setCurrentIndex(portBox->findData(sink_info.activePort));
++ portBox->blockSignals(bs);
++ }
++ portLabel->setVisible(show_ports);
++ portBox->setVisible(show_ports);
++
++ if (sinkBox->currentIndex() >= 0)
++ _updatePlacementTester();
++
++ emit changed();
++}
++
++void SpeakerSetup::portChanged()
++{
++ uint32_t sink_index = sinkBox->itemData(sinkBox->currentIndex()).toUInt();
++ Q_ASSERT(PA_INVALID_INDEX != sink_index);
++
++ QString port = portBox->itemData(portBox->currentIndex()).toString();
++ logMessage(QString("Changing port to %1").arg(port));
++
++ sinkInfo &sink_info = s_Sinks[sink_index];
++ Q_ASSERT(sink_info.ports.size());
++
++ pa_operation *o;
++ if (!(o = pa_context_set_sink_port_by_index(s_context, sink_index, port.toAscii().constData(), NULL, NULL)))
++ logMessage(QString("pa_context_set_sink_port_by_index() failed"));
++ else
++ pa_operation_unref(o);
++
++ emit changed();
++}
++
++void SpeakerSetup::_updatePlacementTester()
++{
++ static const int position_table[] = {
++ /* Position, X, Y */
++ PA_CHANNEL_POSITION_FRONT_LEFT, 0, 0,
++ PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER, 1, 0,
++ PA_CHANNEL_POSITION_FRONT_CENTER, 2, 0,
++ PA_CHANNEL_POSITION_MONO, 2, 0,
++ PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER, 3, 0,
++ PA_CHANNEL_POSITION_FRONT_RIGHT, 4, 0,
++ PA_CHANNEL_POSITION_SIDE_LEFT, 0, 1,
++ PA_CHANNEL_POSITION_SIDE_RIGHT, 4, 1,
++ PA_CHANNEL_POSITION_REAR_LEFT, 0, 2,
++ PA_CHANNEL_POSITION_REAR_CENTER, 2, 2,
++ PA_CHANNEL_POSITION_REAR_RIGHT, 4, 2,
++ PA_CHANNEL_POSITION_LFE, 3, 2
++ };
++
++ QLayoutItem* w;
++ while ((w = placementGrid->takeAt(0))) {
++ if (w->widget() != m_Icon) {
++ if (w->widget())
++ delete w->widget();
++ delete w;
++ }
++ }
++ placementGrid->addWidget(m_Icon, 1, 2, Qt::AlignCenter);
++ int idx = sinkBox->currentIndex();
++ if (idx < 0)
++ return;
++
++ uint32_t sink_index = sinkBox->itemData(idx).toUInt();
++ Q_ASSERT(s_Sinks.contains(sink_index));
++ sinkInfo& sink_info = s_Sinks[sink_index];
++
++ for (int i = 0; i < 36; i += 3) {
++ pa_channel_position_t pos = (pa_channel_position_t)position_table[i];
++ // Check to see if we have this item in our current channel map.
++ bool have = false;
++ for (uint32_t j = 0; j < sink_info.channelMap.channels; ++j) {
++ if (sink_info.channelMap.map[j] == pos) {
++ have = true;
++ break;
++ }
++ }
++ if (!have) {
++ continue;
++ }
++
++ KPushButton* btn = new TestSpeakerWidget(pos, m_Canberra, this);//KPushButton(KIcon("audio-card"), (name ? name : "Unknown Channel"), this);
++ placementGrid->addWidget(btn, position_table[i+2], position_table[i+1], Qt::AlignCenter);
++ }
++
++}
++
++uint32_t SpeakerSetup::getCurrentSinkIndex()
++{
++ int idx = sinkBox->currentIndex();
++ if (idx < 0)
++ return PA_INVALID_INDEX;
++
++ return sinkBox->itemData(idx).toUInt();
++}
++
++
++#include "speakersetup.moc"
++// vim: sw=4 sts=4 et tw=100
+
+Property changes on: runtime/phonon/kcm/speakersetup.cpp
+___________________________________________________________________
+Added: svn:mime-type
+ + text/plain
+Added: svn:eol-style
+ + native
+
+Index: runtime/phonon/kcm/speakersetup.h
+===================================================================
+--- runtime/phonon/kcm/speakersetup.h (revision 0)
++++ runtime/phonon/kcm/speakersetup.h (revision 1154776)
+@@ -0,0 +1,70 @@
++/* This file is part of the KDE project
++ Copyright (C) 2010 Colin Guthrie <cguthrie at mandriva.org>
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License version 2
++ as published by the Free Software Foundation.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the Free Software
++ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
++ 02110-1301, USA.
++
++*/
++
++#ifndef PHONON_SPEAKERSETUP_H
++#define PHONON_SPEAKERSETUP_H
++
++#include <canberra.h>
++#include <pulse/pulseaudio.h>
++
++#include "ui_speakersetup.h"
++#define KDE3_SUPPORT
++#include <kcmodule.h>
++#undef KDE3_SUPPORT
++#include <kconfig.h>
++
++//class QLabel;
++
++class SpeakerSetup : public QWidget, private Ui::SpeakerSetup
++{
++ Q_OBJECT
++ public:
++ SpeakerSetup(QWidget *parent = 0);
++ ~SpeakerSetup();
++
++ void load();
++ void save();
++ void defaults();
++ uint32_t getCurrentSinkIndex();
++ void updateCard(const pa_card_info*);
++ void removeCard(uint32_t idx);
++ void updateSink(const pa_sink_info*);
++ void removeSink(uint32_t idx);
++ void updateFromPulse();
++ void updateIndependantDevices();
++
++ public Q_SLOTS:
++ void cardChanged();
++ void profileChanged();
++ void sinkChanged();
++ void portChanged();
++
++ Q_SIGNALS:
++ void changed();
++ void ready();
++
++ private:
++ void _updatePlacementTester();
++
++ QLabel* m_Icon;
++ int m_OutstandingRequests;
++ ca_context* m_Canberra;
++};
++
++#endif // PHONON_SPEAKERSETUP_H
+
+Property changes on: runtime/phonon/kcm/speakersetup.h
+___________________________________________________________________
+Added: svn:eol-style
+ + native
+
+Index: runtime/phonon/kcm/main.cpp
+===================================================================
+--- runtime/phonon/kcm/main.cpp (revision 1154775)
++++ runtime/phonon/kcm/main.cpp (revision 1154776)
+@@ -1,5 +1,6 @@
+ /* This file is part of the KDE project
+ Copyright (C) 2006-2007 Matthias Kretz <kretz at kde.org>
++ Copyright (C) 2010 Colin Guthrie <cguthrie at mandriva.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+@@ -28,6 +29,10 @@
+ #include "devicepreference.h"
+ #include "backendselection.h"
+
++#ifdef HAVE_PULSEAUDIO
++# include "speakersetup.h"
++#endif
++
+ K_PLUGIN_FACTORY(PhononKcmFactory, registerPlugin<PhononKcm>();)
+ K_EXPORT_PLUGIN(PhononKcmFactory("kcm_phonon"))
+
+@@ -39,23 +44,33 @@
+ KDE_VERSION_STRING, KLocalizedString(), KAboutData::License_GPL,
+ ki18n("Copyright 2006 Matthias Kretz"));
+ about->addAuthor(ki18n("Matthias Kretz"), KLocalizedString(), "kretz at kde.org");
++ about->addAuthor(ki18n("Colin Guthrie"), KLocalizedString(), "cguthrie at mandriva.org");
+ setAboutData(about);
+
+ setLayout(new QHBoxLayout);
+ layout()->setMargin(0);
+ layout()->setSpacing(0);
+
+- KTabWidget *tabs = new KTabWidget(this);
+- layout()->addWidget(tabs);
++ m_tabs = new KTabWidget(this);
++ layout()->addWidget(m_tabs);
+
+ m_devicePreferenceWidget = new DevicePreference(this);
+- tabs->addTab(m_devicePreferenceWidget, i18n("Device Preference"));
++ m_tabs->addTab(m_devicePreferenceWidget, i18n("Device Preference"));
+ m_backendSelection = new BackendSelection(this);
+- tabs->addTab(m_backendSelection, i18n("Backend"));
++ m_tabs->addTab(m_backendSelection, i18n("Backend"));
++
+ load();
+ connect(m_backendSelection, SIGNAL(changed()), SLOT(changed()));
+ connect(m_devicePreferenceWidget, SIGNAL(changed()), SLOT(changed()));
++
+ setButtons( KCModule::Default|KCModule::Apply|KCModule::Help );
++
++#ifdef HAVE_PULSEAUDIO
++ m_speakerSetup = new SpeakerSetup(this);
++ m_speakerSetup->setVisible(false);
++ connect(m_speakerSetup, SIGNAL(ready()), SLOT(speakerSetupReady()));
++ connect(m_speakerSetup, SIGNAL(changed()), SLOT(changed()));
++#endif
+ }
+
+ void PhononKcm::load()
+@@ -76,5 +91,13 @@
+ m_backendSelection->defaults();
+ }
+
++#ifdef HAVE_PULSEAUDIO
++void PhononKcm::speakerSetupReady()
++{
++ m_tabs->insertTab(1, m_speakerSetup, i18n("Speaker Setup"));
++ emit changed();
++}
++#endif
++
+ #include "main.moc"
+ // vim: ts=4
+Index: runtime/phonon/kcm/main.h
+===================================================================
+--- runtime/phonon/kcm/main.h (revision 1154775)
++++ runtime/phonon/kcm/main.h (revision 1154776)
+@@ -25,6 +25,11 @@
+ class DevicePreference;
+ class BackendSelection;
+
++#ifdef HAVE_PULSEAUDIO
++class SpeakerSetup;
++#endif
++class KTabWidget;
++
+ class PhononKcm : public KCModule
+ {
+ Q_OBJECT
+@@ -35,9 +40,18 @@
+ void save();
+ void defaults();
+
++#ifdef HAVE_PULSEAUDIO
++ private Q_SLOTS:
++ void speakerSetupReady();
++#endif
++
+ private:
++ KTabWidget* m_tabs;
+ DevicePreference *m_devicePreferenceWidget;
+ BackendSelection *m_backendSelection;
++#ifdef HAVE_PULSEAUDIO
++ SpeakerSetup* m_speakerSetup;
++#endif
+ };
+
+ #endif // MAIN_H
+Index: runtime/phonon/kcm/CMakeLists.txt
+===================================================================
+--- runtime/phonon/kcm/CMakeLists.txt (revision 1154775)
++++ runtime/phonon/kcm/CMakeLists.txt (revision 1154776)
+@@ -1,3 +1,11 @@
++set(PULSEAUDIO_MINIMUM_VERSION "0.9.16")
++macro_optional_find_package(PulseAudio)
++macro_log_feature(PULSEAUDIO_FOUND "PulseAudio" "PulseAudio Audio Server" "http://www.pulseaudio.org/" FALSE "0.9.16" "libpulse is needed for speaker setup GUI")
++find_package(GLIB2)
++
++pkg_check_modules(CANBERRA libcanberra)
++macro_log_feature(CANBERRA_FOUND "libcanberra" "libcanberra audio library" "http://0pointer.de/lennart/projects/libcanberra/" FALSE "" "libcanberra is needed for speaker setup GUI")
++
+ add_subdirectory(xine)
+
+ set(kcmphonon_SRCS main.cpp devicepreference.cpp backendselection.cpp)
+@@ -2,6 +10,17 @@
+ kde4_add_ui_files(kcmphonon_SRCS devicepreference.ui backendselection.ui)
++set(kcmphonon_LIBS ${KDE4_PHONON_LIBS} ${KDE4_KCMUTILS_LIBS} ${KDE4_KIO_LIBS})
+
++if(GLIB2_FOUND AND PULSEAUDIO_FOUND AND CANBERRA_FOUND)
++ add_definitions(-DHAVE_PULSEAUDIO)
++
++ set(kcmphonon_SRCS ${kcmphonon_SRCS} speakersetup.cpp testspeakerwidget.cpp)
++ kde4_add_ui_files(kcmphonon_SRCS speakersetup.ui)
++
++ include_directories(${GLIB2_INCLUDE_DIR} ${PULSEAUDIO_INCLUDE_DIR} ${CANBERRA_INCLUDE_DIRS})
++
++ set(kcmphonon_LIBS ${kcmphonon_LIBS} ${GLIB2_LIBRARIES} ${PULSEAUDIO_LIBRARY} ${PULSEAUDIO_MAINLOOP_LIBRARY} ${CANBERRA_LIBRARIES})
++endif(GLIB2_FOUND AND PULSEAUDIO_FOUND AND CANBERRA_FOUND)
++
+ kde4_add_plugin(kcm_phonon ${kcmphonon_SRCS})
+-target_link_libraries(kcm_phonon ${KDE4_PHONON_LIBS} ${KDE4_KCMUTILS_LIBS}
+- ${KDE4_KIO_LIBS})
++target_link_libraries(kcm_phonon ${kcmphonon_LIBS})
+
diff --git a/kdebase-runtime.spec b/kdebase-runtime.spec
index 6caafab..f8130ca 100644
--- a/kdebase-runtime.spec
+++ b/kdebase-runtime.spec
@@ -6,7 +6,7 @@
Name: kdebase-runtime
Summary: KDE Runtime
Version: 4.5.2
-Release: 2%{?dist}
+Release: 3%{?dist}
# http://techbase.kde.org/Policies/Licensing_Policy
License: LGPLv2+
@@ -23,6 +23,11 @@ Patch5: kdebase-runtime-4.3.1-manpath.patch
# add OnlyShowIn=KDE to Desktop/Home.desktop (like trash.desktop)
Patch6: kdebase-runtime-4.3.3-home_onlyshowin_kde.patch
+## upstream patches
+# pulseaudio speaker setup backport, courtesy of coling/mandriva
+# http://svn.mandriva.com/cgi-bin/viewvc.cgi/packages/cooker/kdebase4-runtime/current/SOURCES/kdebase-runtime-4.5-speakersetup.patch
+Patch100: kdebase-runtime-4.5-speakersetup.patch
+
Provides: kdebase4-runtime = %{version}-%{release}
Obsoletes: kdebase4-runtime < %{version}-%{release}
@@ -52,11 +57,13 @@ BuildRequires: kde-filesystem
BuildRequires: alsa-lib-devel
BuildRequires: attica-devel
BuildRequires: bzip2-devel
+BuildRequires: chrpath
BuildRequires: clucene-core-devel
BuildRequires: exiv2-devel
BuildRequires: hal-devel
BuildRequires: kdelibs4-devel >= %{version}
BuildRequires: kdepimlibs-devel >= %{version}
+BuildRequires: libcanberra-devel
BuildRequires: libsmbclient-devel
BuildRequires: libssh-devel >= 0.4.2
BuildRequires: libXScrnSaver-devel
@@ -110,6 +117,8 @@ BuildArch: noarch
%patch3 -p1 -b .iconthemes-inherit
#patch5 -p1 -b .manpath
%patch6 -p1 -b .home_onlyshowin_kde
+%patch100 -p1 -b .speakersetup
+
%build
mkdir -p %{_target_platform}
@@ -147,6 +156,10 @@ install -p -D -m755 drkonqi/doc/examples/installdbgsymbols_fedora.sh \
# FIXME: -devel type files, omit for now
rm -vf %{buildroot}%{_kde4_libdir}/lib{kwalletbackend,molletnetwork}.so
+# rpaths
+# use chrpath hammer for now, find better patching solutions later -- Rex
+chrpath --delete %{buildroot}%{_libdir}/kde4/plugins/phonon_platform/kde.so
+
%clean
rm -rf %{buildroot}
@@ -236,6 +249,10 @@ fi
%changelog
+* Fri Oct 15 2010 Rex Dieter <rdieter at fedoraproject.org> - 4.5.2-3
+- pa speakersetup backport (courtesy of coling/mandriva)
+- hammer rpath from phonon_platform/kde.so
+
* Fri Oct 15 2010 Rex Dieter <rdieter at fedoraproject.org> - 4.5.2-2
- use kde4's copy of khelpcenter.desktop
More information about the scm-commits
mailing list