about summary refs log tree commit diff
path: root/nixpkgs/pkgs/applications/networking/mumble
diff options
context:
space:
mode:
authorAlyssa Ross <hi@alyssa.is>2019-01-07 02:18:36 +0000
committerAlyssa Ross <hi@alyssa.is>2019-01-07 02:18:47 +0000
commit36f56d99fa0a0765c9f1de4a5f17a9b05830c3f2 (patch)
treeb3faaf573407b32aa645237a4d16b82778a39a92 /nixpkgs/pkgs/applications/networking/mumble
parent4e31070265257dc67d120c27e0f75c2344fdfa9a (diff)
parentabf060725d7614bd3b9f96764262dfbc2f9c2199 (diff)
downloadnixlib-36f56d99fa0a0765c9f1de4a5f17a9b05830c3f2.tar
nixlib-36f56d99fa0a0765c9f1de4a5f17a9b05830c3f2.tar.gz
nixlib-36f56d99fa0a0765c9f1de4a5f17a9b05830c3f2.tar.bz2
nixlib-36f56d99fa0a0765c9f1de4a5f17a9b05830c3f2.tar.lz
nixlib-36f56d99fa0a0765c9f1de4a5f17a9b05830c3f2.tar.xz
nixlib-36f56d99fa0a0765c9f1de4a5f17a9b05830c3f2.tar.zst
nixlib-36f56d99fa0a0765c9f1de4a5f17a9b05830c3f2.zip
Add 'nixpkgs/' from commit 'abf060725d7614bd3b9f96764262dfbc2f9c2199'
git-subtree-dir: nixpkgs
git-subtree-mainline: 4e31070265257dc67d120c27e0f75c2344fdfa9a
git-subtree-split: abf060725d7614bd3b9f96764262dfbc2f9c2199
Diffstat (limited to 'nixpkgs/pkgs/applications/networking/mumble')
-rw-r--r--nixpkgs/pkgs/applications/networking/mumble/default.nix158
-rw-r--r--nixpkgs/pkgs/applications/networking/mumble/mumble-jack-support.patch457
-rw-r--r--nixpkgs/pkgs/applications/networking/mumble/overlay.nix28
3 files changed, 643 insertions, 0 deletions
diff --git a/nixpkgs/pkgs/applications/networking/mumble/default.nix b/nixpkgs/pkgs/applications/networking/mumble/default.nix
new file mode 100644
index 000000000000..d0a690496e27
--- /dev/null
+++ b/nixpkgs/pkgs/applications/networking/mumble/default.nix
@@ -0,0 +1,158 @@
+{ stdenv, fetchurl, fetchFromGitHub, fetchpatch, pkgconfig
+, qt4, qmake4Hook, qt5, avahi, boost, libopus, libsndfile, protobuf, speex, libcap
+, alsaLib, python
+, jackSupport ? false, libjack2 ? null
+, speechdSupport ? false, speechd ? null
+, pulseSupport ? false, libpulseaudio ? null
+, iceSupport ? false, zeroc_ice ? null
+}:
+
+assert jackSupport -> libjack2 != null;
+assert speechdSupport -> speechd != null;
+assert pulseSupport -> libpulseaudio != null;
+assert iceSupport -> zeroc_ice != null;
+
+with stdenv.lib;
+let
+  generic = overrides: source: stdenv.mkDerivation (source // overrides // {
+    name = "${overrides.type}-${source.version}";
+
+    patches = (source.patches or []) ++ optional jackSupport ./mumble-jack-support.patch;
+
+    nativeBuildInputs = [ pkgconfig python ]
+      ++ { qt4 = [ qmake4Hook ]; qt5 = [ qt5.qmake ]; }."qt${toString source.qtVersion}"
+      ++ (overrides.nativeBuildInputs or [ ]);
+    buildInputs = [ boost protobuf avahi ]
+      ++ { qt4 = [ qt4 ]; qt5 = [ qt5.qtbase ]; }."qt${toString source.qtVersion}"
+      ++ (overrides.buildInputs or [ ]);
+
+    qmakeFlags = [
+      "CONFIG+=c++11"
+      "CONFIG+=shared"
+      "CONFIG+=no-g15"
+      "CONFIG+=packaged"
+      "CONFIG+=no-update"
+      "CONFIG+=no-embed-qt-translations"
+      "CONFIG+=bundled-celt"
+      "CONFIG+=no-bundled-opus"
+      "CONFIG+=no-bundled-speex"
+    ] ++ optional (!speechdSupport) "CONFIG+=no-speechd"
+      ++ optional jackSupport "CONFIG+=no-oss CONFIG+=no-alsa CONFIG+=jackaudio"
+      ++ optional (!iceSupport) "CONFIG+=no-ice"
+      ++ (overrides.configureFlags or [ ]);
+
+    preConfigure = ''
+       qmakeFlags="$qmakeFlags DEFINES+=PLUGIN_PATH=$out/lib"
+       patchShebangs scripts
+    '';
+
+    makeFlags = [ "release" ];
+
+    installPhase = ''
+      mkdir -p $out/{lib,bin}
+      find release -type f -not -name \*.\* -exec cp {} $out/bin \;
+      find release -type f -name \*.\* -exec cp {} $out/lib \;
+
+      mkdir -p $out/share/man/man1
+      cp man/mum* $out/share/man/man1
+    '' + (overrides.installPhase or "");
+
+    enableParallelBuilding = true;
+
+    meta = {
+      description = "Low-latency, high quality voice chat software";
+      homepage = https://mumble.info;
+      license = licenses.bsd3;
+      maintainers = with maintainers; [ jgeerds wkennington ];
+      platforms = platforms.linux;
+    };
+  });
+
+  client = source: generic {
+    type = "mumble";
+
+    nativeBuildInputs = optionals (source.qtVersion == 5) [ qt5.qttools ];
+    buildInputs = [ libopus libsndfile speex ]
+      ++ optional (source.qtVersion == 5) qt5.qtsvg
+      ++ optional stdenv.isLinux alsaLib
+      ++ optional jackSupport libjack2
+      ++ optional speechdSupport speechd
+      ++ optional pulseSupport libpulseaudio;
+
+    configureFlags = [
+      "CONFIG+=no-server"
+    ];
+
+    NIX_CFLAGS_COMPILE = optional speechdSupport "-I${speechd}/include/speech-dispatcher";
+
+    installPhase = ''
+      mkdir -p $out/share/applications
+      cp scripts/mumble.desktop $out/share/applications
+
+      mkdir -p $out/share/icons{,/hicolor/scalable/apps}
+      cp icons/mumble.svg $out/share/icons
+      ln -s $out/share/icons/mumble.svg $out/share/icons/hicolor/scalable/apps
+    '';
+  } source;
+
+  server = generic {
+    type = "murmur";
+
+    postPatch = optional iceSupport ''
+      grep -Rl '/usr/share/Ice' . | xargs sed -i 's,/usr/share/Ice/,${zeroc_ice}/,g'
+    '';
+
+    configureFlags = [
+      "CONFIG+=no-client"
+    ];
+
+    buildInputs = [ libcap ] ++ optional iceSupport zeroc_ice;
+  };
+
+  stableSource = rec {
+    version = "1.2.19";
+    qtVersion = 4;
+
+    src = fetchurl {
+      url = "https://github.com/mumble-voip/mumble/releases/download/${version}/mumble-${version}.tar.gz";
+      sha256 = "1s60vaici3v034jzzi20x23hsj6mkjlc0glipjq4hffrg9qgnizh";
+    };
+
+    patches = [
+      # Fix compile error against boost 1.66 (#33655):
+      (fetchpatch {
+        url = "https://github.com/mumble-voip/mumble/commit/"
+            + "ea861fe86743c8402bbad77d8d1dd9de8dce447e.patch";
+        sha256 = "1r50dc8dcl6jmbj4abhnay9div7y56kpmajzqd7ql0pm853agwbh";
+      })
+      # Fixes hang on reconfiguring audio (often including startup)
+      # https://github.com/mumble-voip/mumble/pull/3418
+      (fetchpatch {
+        url = "https://github.com/mumble-voip/mumble/commit/"
+            + "fbbdf2e8ab7d93ed6f7680268ad0689b7eaa71ad.patch";
+        sha256 = "1yhj62mlwm6q42i4aclbia645ha97d3j4ycxhgafr46dbjs0gani";
+      })
+    ];
+  };
+
+  gitSource = rec {
+    version = "2018-07-01";
+    qtVersion = 5;
+
+    # Needs submodules
+    src = fetchFromGitHub {
+      owner = "mumble-voip";
+      repo = "mumble";
+      rev = "c19ac8c0b0f934d2ff206858d7cb66352d6eb418";
+      sha256 = "1mzp1bgn49ycs16d6r8icqq35wq25198fs084vyq6j5f78ni7pvz";
+      fetchSubmodules = true;
+    };
+  };
+in {
+  mumble     = client stableSource;
+  mumble_git = client gitSource;
+  murmur     = server stableSource;
+  murmur_git = (server gitSource).overrideAttrs (old: {
+    meta = old.meta // { broken = iceSupport; };
+  });
+}
diff --git a/nixpkgs/pkgs/applications/networking/mumble/mumble-jack-support.patch b/nixpkgs/pkgs/applications/networking/mumble/mumble-jack-support.patch
new file mode 100644
index 000000000000..7c18a33193df
--- /dev/null
+++ b/nixpkgs/pkgs/applications/networking/mumble/mumble-jack-support.patch
@@ -0,0 +1,457 @@
+The patch was created by Filipe Coelho (falkTX) of the KXStudio
+project. http://kxstudio.sourceforge.net
+
+diff -U 3 -H -d -r -N -- mumble-1.2.2.orig/src/mumble/JackAudio.cpp mumble-1.2.2/src/mumble/JackAudio.cpp
+--- mumble-1.2.2.orig/src/mumble/JackAudio.cpp	1970-01-01 01:00:00.000000000 +0100
++++ mumble-1.2.2/src/mumble/JackAudio.cpp	2011-01-26 06:02:00.000000000 +0000
+@@ -0,0 +1,314 @@
++/* Copyright (C) 2011, Benjamin Jemlich <pcgod@users.sourceforge.net>
++   Copyright (C) 2011, Filipe Coelho <falktx@gmail.com>
++
++   All rights reserved.
++
++   Redistribution and use in source and binary forms, with or without
++   modification, are permitted provided that the following conditions
++   are met:
++
++   - Redistributions of source code must retain the above copyright notice,
++     this list of conditions and the following disclaimer.
++   - Redistributions in binary form must reproduce the above copyright notice,
++     this list of conditions and the following disclaimer in the documentation
++     and/or other materials provided with the distribution.
++   - Neither the name of the Mumble Developers nor the names of its
++     contributors may be used to endorse or promote products derived from this
++     software without specific prior written permission.
++
++   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
++   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
++   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
++   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
++   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
++   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
++   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
++   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++*/
++
++#include "JackAudio.h"
++#include "User.h"
++#include "Global.h"
++#include "MainWindow.h"
++#include "Timer.h"
++
++#include <cstring>
++
++static JackAudioSystem *jasys = NULL;
++
++class JackAudioInputRegistrar : public AudioInputRegistrar {
++        public:
++                JackAudioInputRegistrar();
++                virtual AudioInput *create();
++                virtual const QList<audioDevice> getDeviceChoices();
++                virtual void setDeviceChoice(const QVariant &, Settings &);
++                virtual bool canEcho(const QString &) const;
++};
++
++class JackAudioOutputRegistrar : public AudioOutputRegistrar {
++        public:
++                JackAudioOutputRegistrar();
++                virtual AudioOutput *create();
++                virtual const QList<audioDevice> getDeviceChoices();
++                virtual void setDeviceChoice(const QVariant &, Settings &);
++};
++
++class JackAudioInit : public DeferInit {
++        public:
++                JackAudioInputRegistrar *airJackAudio;
++                JackAudioOutputRegistrar *aorJackAudio;
++                void initialize() {
++                        jasys = new JackAudioSystem();
++                        jasys->init_jack();
++                        jasys->qmWait.lock();
++                        jasys->qwcWait.wait(&jasys->qmWait, 1000);
++                        jasys->qmWait.unlock();
++                        if (jasys->bJackIsGood) {
++                                airJackAudio = new JackAudioInputRegistrar();
++                                aorJackAudio = new JackAudioOutputRegistrar();
++                        } else {
++                                airJackAudio = NULL;
++                                aorJackAudio = NULL;
++                                delete jasys;
++                                jasys = NULL;
++                        }
++                };
++                void destroy() {
++                        if (airJackAudio)
++                                delete airJackAudio;
++                        if (aorJackAudio)
++                                delete aorJackAudio;
++                        if (jasys) {
++                                jasys->close_jack();
++                                delete jasys;
++                                jasys = NULL;
++                        }
++                };
++};
++
++static JackAudioInit jackinit; //unused
++
++JackAudioSystem::JackAudioSystem() {
++        bJackIsGood = false;
++        iSampleRate = 0;
++}
++
++JackAudioSystem::~JackAudioSystem() {
++}
++
++void JackAudioSystem::init_jack()
++{
++        client = jack_client_open("mumble", JackNullOption, 0);
++
++        if (client) {
++                in_port = jack_port_register(client, "input", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
++                out_port = jack_port_register(client, "output", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
++                jack_set_process_callback(client, process_callback, this);
++                jack_set_sample_rate_callback(client, srate_callback, this);
++                jack_on_shutdown(client, shutdown_callback, this);
++
++                iSampleRate = jack_get_sample_rate(client);
++
++                if (jack_activate(client) || in_port == NULL || out_port == NULL) {
++                    client = NULL;
++                    return;
++                }
++
++                int port_flags;
++                unsigned i = -1;
++                const char** ports = jack_get_ports(client, 0, 0, JackPortIsPhysical);
++
++                if (ports) {
++                    while (ports[++i])
++                    {
++                        jack_port_t* port = jack_port_by_name(client, ports[i]);
++                        port_flags = jack_port_flags(port);
++
++                        if (port_flags & (JackPortIsPhysical|JackPortIsOutput) && strstr(jack_port_type(port), "audio")) {
++                            jack_connect(client, ports[i], jack_port_name(in_port));
++                        }
++                        if (port_flags & (JackPortIsPhysical|JackPortIsInput) && strstr(jack_port_type(port), "audio")) {
++                            jack_connect(client, jack_port_name(out_port), ports[i]);
++                        }
++                    }
++                }
++
++                jack_free(ports);
++
++                // If we made it this far, then everything is okay
++                qhInput.insert(QString(), tr("Hardware Ports"));
++                qhOutput.insert(QString(), tr("Hardware Ports"));
++                bJackIsGood = true;
++
++            } else {
++                bJackIsGood = false;
++                client = NULL;
++            }
++}
++
++void JackAudioSystem::close_jack()
++{
++        if (client) {
++                jack_deactivate(client);
++                jack_client_close(client);
++                client = NULL;
++        }
++}
++
++int JackAudioSystem::process_callback(jack_nframes_t nframes, void *arg)
++{
++        JackAudioSystem *jas = (JackAudioSystem*)arg;
++
++        if (jas && jas->bJackIsGood) {
++                AudioInputPtr ai = g.ai;
++                AudioOutputPtr ao = g.ao;
++                JackAudioInput *jai = (JackAudioInput*)(ai.get());
++                JackAudioOutput *jao = (JackAudioOutput*)(ao.get());
++
++                if (jai && jai->bRunning && jai->iMicChannels > 0 && !jai->isFinished()) {
++                        void* input = jack_port_get_buffer(jas->in_port, nframes);
++                        if ((float*)input != 0)
++                            jai->addMic(input, nframes);
++                }
++
++                if (jao && jao->bRunning && jao->iChannels > 0 && !jao->isFinished()) {
++                        jack_default_audio_sample_t* output = (jack_default_audio_sample_t*)jack_port_get_buffer(jas->out_port, nframes);
++                        memset(output, 0, sizeof(jack_default_audio_sample_t)*nframes); //TEST
++                        jao->mix(output, nframes);
++                }
++        }
++
++        return 0;
++}
++
++int JackAudioSystem::srate_callback(jack_nframes_t frames, void *arg)
++{
++        JackAudioSystem *jas = (JackAudioSystem*)arg;
++        jas->iSampleRate = frames;
++        return 0;
++}
++
++void JackAudioSystem::shutdown_callback(void *arg)
++{
++        JackAudioSystem *jas = (JackAudioSystem*)arg;
++        jas->bJackIsGood = false;
++}
++
++JackAudioInputRegistrar::JackAudioInputRegistrar() : AudioInputRegistrar(QLatin1String("JACK"), 10) {
++}
++
++AudioInput *JackAudioInputRegistrar::create() {
++        return new JackAudioInput();
++}
++
++const QList<audioDevice> JackAudioInputRegistrar::getDeviceChoices() {
++        QList<audioDevice> qlReturn;
++
++        QStringList qlInputDevs = jasys->qhInput.keys();
++        qSort(qlInputDevs);
++
++        foreach(const QString &dev, qlInputDevs) {
++                qlReturn << audioDevice(jasys->qhInput.value(dev), dev);
++        }
++
++        return qlReturn;
++}
++
++void JackAudioInputRegistrar::setDeviceChoice(const QVariant &choice, Settings &s) {
++        Q_UNUSED(choice);
++        Q_UNUSED(s);
++}
++
++bool JackAudioInputRegistrar::canEcho(const QString &osys) const {
++        Q_UNUSED(osys);
++        return false;
++}
++
++JackAudioOutputRegistrar::JackAudioOutputRegistrar() : AudioOutputRegistrar(QLatin1String("JACK"), 10) {
++}
++
++AudioOutput *JackAudioOutputRegistrar::create() {
++        return new JackAudioOutput();
++}
++
++const QList<audioDevice> JackAudioOutputRegistrar::getDeviceChoices() {
++        QList<audioDevice> qlReturn;
++
++        QStringList qlOutputDevs = jasys->qhOutput.keys();
++        qSort(qlOutputDevs);
++
++        foreach(const QString &dev, qlOutputDevs) {
++                qlReturn << audioDevice(jasys->qhOutput.value(dev), dev);
++        }
++
++        return qlReturn;
++}
++
++void JackAudioOutputRegistrar::setDeviceChoice(const QVariant &choice, Settings &s) {
++        Q_UNUSED(choice);
++        Q_UNUSED(s);
++}
++
++JackAudioInput::JackAudioInput() {
++        bRunning = true;
++        iMicChannels = 0;
++};
++
++JackAudioInput::~JackAudioInput() {
++        bRunning = false;
++        iMicChannels = 0;
++        qmMutex.lock();
++        qwcWait.wakeAll();
++        qmMutex.unlock();
++        wait();
++}
++
++void JackAudioInput::run() {
++        if (jasys && jasys->bJackIsGood) {
++            iMicFreq = jasys->iSampleRate;
++            iMicChannels = 1;
++            eMicFormat = SampleFloat;
++            initializeMixer();
++        }
++
++        qmMutex.lock();
++        while (bRunning)
++                qwcWait.wait(&qmMutex);
++        qmMutex.unlock();
++}
++
++JackAudioOutput::JackAudioOutput() {
++        bRunning = true;
++        iChannels = 0;
++}
++
++JackAudioOutput::~JackAudioOutput() {
++        bRunning = false;
++        iChannels = 0;
++        qmMutex.lock();
++        qwcWait.wakeAll();
++        qmMutex.unlock();
++        wait();
++}
++
++void JackAudioOutput::run() {
++        if (jasys && jasys->bJackIsGood) {
++            unsigned int chanmasks[32];
++
++            chanmasks[0] = SPEAKER_FRONT_LEFT;
++            chanmasks[1] = SPEAKER_FRONT_RIGHT;
++
++            eSampleFormat = SampleFloat;
++            iMixerFreq = jasys->iSampleRate;
++            iChannels = 1;
++            initializeMixer(chanmasks);
++        }
++
++        qmMutex.lock();
++        while (bRunning)
++                qwcWait.wait(&qmMutex);
++        qmMutex.unlock();
++}
+diff -U 3 -H -d -r -N -- mumble-1.2.2.orig/src/mumble/JackAudio.h mumble-1.2.2/src/mumble/JackAudio.h
+--- mumble-1.2.2.orig/src/mumble/JackAudio.h	1970-01-01 01:00:00.000000000 +0100
++++ mumble-1.2.2/src/mumble/JackAudio.h	2011-01-26 06:03:58.000000000 +0000
+@@ -0,0 +1,97 @@
++/* Copyright (C) 2011, Benjamin Jemlich <pcgod@users.sourceforge.net>
++   Copyright (C) 2011, Filipe Coelho <falktx@gmail.com>
++
++   All rights reserved.
++
++   Redistribution and use in source and binary forms, with or without
++   modification, are permitted provided that the following conditions
++   are met:
++
++   - Redistributions of source code must retain the above copyright notice,
++     this list of conditions and the following disclaimer.
++   - Redistributions in binary form must reproduce the above copyright notice,
++     this list of conditions and the following disclaimer in the documentation
++     and/or other materials provided with the distribution.
++   - Neither the name of the Mumble Developers nor the names of its
++     contributors may be used to endorse or promote products derived from this
++     software without specific prior written permission.
++
++   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
++   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
++   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
++   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
++   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
++   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
++   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
++   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++*/
++
++#ifndef _JACKAUDIO_H
++#define _JACKAUDIO_H
++
++#include "AudioInput.h"
++#include "AudioOutput.h"
++#include <jack/jack.h>
++
++class JackAudioOutput;
++class JackAudioInput;
++
++class JackAudioSystem : public QObject {
++        private:
++                Q_OBJECT
++                Q_DISABLE_COPY(JackAudioSystem)
++        protected:
++                jack_client_t* client;
++                jack_port_t* in_port;
++                jack_port_t* out_port;
++
++                static int process_callback(jack_nframes_t nframes, void *arg);
++                static int srate_callback(jack_nframes_t frames, void *arg);
++                static void shutdown_callback(void *arg);
++        public:
++                QHash<QString, QString> qhInput;
++                QHash<QString, QString> qhOutput;
++                bool bJackIsGood;
++                int iSampleRate;
++                QMutex qmWait;
++                QWaitCondition qwcWait;
++
++                void init_jack();
++                void close_jack();
++
++                JackAudioSystem();
++                ~JackAudioSystem();
++};
++
++class JackAudioInput : public AudioInput {
++                friend class JackAudioSystem;
++        private:
++                Q_OBJECT
++                Q_DISABLE_COPY(JackAudioInput)
++        protected:
++                QMutex qmMutex;
++                QWaitCondition qwcWait;
++        public:
++                JackAudioInput();
++                ~JackAudioInput();
++                void run();
++};
++
++class JackAudioOutput : public AudioOutput {
++                friend class JackAudioSystem;
++        private:
++                Q_OBJECT
++                Q_DISABLE_COPY(JackAudioOutput)
++        protected:
++                QMutex qmMutex;
++                QWaitCondition qwcWait;
++        public:
++                JackAudioOutput();
++                ~JackAudioOutput();
++                void run();
++};
++
++#endif
+diff -U 3 -H -d -r -N -- mumble-1.2.2.orig/src/mumble/mumble.pro mumble-1.2.2/src/mumble/mumble.pro
+--- mumble-1.2.2.orig/src/mumble/mumble.pro	2010-02-09 16:34:51.000000000 +0000
++++ mumble-1.2.2/src/mumble/mumble.pro	2011-01-26 01:45:55.000000000 +0000
+@@ -93,11 +93,17 @@
+ unix {
+   HAVE_PULSEAUDIO=$$system(pkg-config --modversion --silence-errors libpulse)
+   HAVE_PORTAUDIO=$$system(pkg-config --modversion --silence-errors portaudio-2.0)
++  HAVE_JACKAUDIO=$$system(pkg-config --modversion --silence-errors jack)
+ 
+   !isEmpty(HAVE_PORTAUDIO):!CONFIG(no-portaudio) {
+     CONFIG *= portaudio
+   }
+ 
++  !isEmpty(HAVE_JACKAUDIO):!CONFIG(no-jackaudio) {
++    CONFIG -= portaudio
++    CONFIG *= jackaudio
++  }
++
+   !isEmpty(HAVE_PULSEAUDIO):!CONFIG(no-pulseaudio) {
+     CONFIG -= portaudio
+     CONFIG *= pulseaudio
+@@ -110,6 +116,13 @@
+     QMAKE_CXXFLAGS_DEBUG *= -I../../speex/include -I../../speexbuild
+   }
+ 
++  jackaudio {
++        DEFINES *= USE_JACKAUDIO
++        PKGCONFIG *= jack
++        HEADERS *= JackAudio.h
++        SOURCES *= JackAudio.cpp
++  }
++
+   CONFIG *= link_pkgconfig
+ 
+   PKGCONFIG *= openssl sndfile
diff --git a/nixpkgs/pkgs/applications/networking/mumble/overlay.nix b/nixpkgs/pkgs/applications/networking/mumble/overlay.nix
new file mode 100644
index 000000000000..185672a21f8c
--- /dev/null
+++ b/nixpkgs/pkgs/applications/networking/mumble/overlay.nix
@@ -0,0 +1,28 @@
+{ stdenv, lib, which, file, mumble, mumble_i686
+}:
+
+let
+  binPath = lib.makeBinPath [ which file ];
+in stdenv.mkDerivation {
+  name = "mumble-overlay-${mumble.version}";
+
+  inherit (mumble) src;
+
+  phases = [ "unpackPhase" "installPhase" "fixupPhase" ];
+
+  installPhase = ''
+    mkdir -p $out/lib
+    ln -s ${mumble}/lib/libmumble.so.1.* $out/lib/libmumble.so.1
+    ${lib.optionalString (mumble_i686 != null) ''
+      mkdir -p $out/lib32
+      ln -s ${mumble_i686}/lib/libmumble.so.1.* $out/lib32/libmumble.so.1
+    ''}
+    install -Dm755 scripts/mumble-overlay $out/bin/mumble-overlay
+    sed -i "s,/usr/lib,$out/lib,g" $out/bin/mumble-overlay
+    sed -i '2iPATH="${binPath}:$PATH"' $out/bin/mumble-overlay
+  '';
+
+  meta = {
+    platforms = stdenv.lib.platforms.linux;
+  };
+}