diff --git a/src/mumble/ALSAAudio.cpp b/src/mumble/ALSAAudio.cpp index b68af5a96..0f9f6f3a0 100644 --- a/src/mumble/ALSAAudio.cpp +++ b/src/mumble/ALSAAudio.cpp @@ -45,7 +45,15 @@ class ALSAEnumerator { QHash qhOutput; ALSAEnumerator(); }; -static ALSAEnumerator cards; + +static ALSAEnumerator *cards = NULL; + +class ALSAAudioInit : public DeferInit { + void initialize() { cards = new ALSAEnumerator(); }; + void destroy() { delete cards; cards = NULL; }; +}; + +static ALSAAudioInit aai; class ALSAAudioInputRegistrar : public AudioInputRegistrar { public: @@ -77,7 +85,7 @@ AudioInput *ALSAAudioInputRegistrar::create() { const QList ALSAAudioInputRegistrar::getDeviceChoices() { QList qlReturn; - QStringList qlInputDevs = cards.qhInput.keys(); + QStringList qlInputDevs = cards->qhInput.keys(); qSort(qlInputDevs); if (qlInputDevs.contains(g.s.qsALSAInput)) { @@ -86,7 +94,7 @@ const QList ALSAAudioInputRegistrar::getDeviceChoices() { } foreach(const QString &dev, qlInputDevs) { - QString t=QString::fromLatin1("[%1] %2").arg(dev).arg(cards.qhInput[dev]); + QString t=QString::fromLatin1("[%1] %2").arg(dev).arg(cards->qhInput[dev]); qlReturn << audioDevice(t, dev); } @@ -108,7 +116,7 @@ AudioOutput *ALSAAudioOutputRegistrar::create() { const QList ALSAAudioOutputRegistrar::getDeviceChoices() { QList qlReturn; - QStringList qlOutputDevs = cards.qhOutput.keys(); + QStringList qlOutputDevs = cards->qhOutput.keys(); qSort(qlOutputDevs); if (qlOutputDevs.contains(g.s.qsALSAOutput)) { @@ -117,7 +125,7 @@ const QList ALSAAudioOutputRegistrar::getDeviceChoices() { } foreach(const QString &dev, qlOutputDevs) { - QString t=QString::fromLatin1("[%1] %2").arg(dev).arg(cards.qhInput[dev]); + QString t=QString::fromLatin1("[%1] %2").arg(dev).arg(cards->qhInput[dev]); qlReturn << audioDevice(t, dev); } @@ -196,16 +204,16 @@ ALSAEnumerator::ALSAEnumerator() { ALSAConfig::ALSAConfig(Settings &st) : ConfigWidget(st) { setupUi(this); - QList qlOutputDevs = cards.qhOutput.keys(); + QList qlOutputDevs = cards->qhOutput.keys(); qSort(qlOutputDevs); - QList qlInputDevs = cards.qhInput.keys(); + QList qlInputDevs = cards->qhInput.keys(); qSort(qlInputDevs); bool found; found = false; foreach(QString dev, qlInputDevs) { - QString t=QString::fromLatin1("[%1] %2").arg(dev).arg(cards.qhInput[dev]); + QString t=QString::fromLatin1("[%1] %2").arg(dev).arg(cards->qhInput[dev]); qcbInputDevice->addItem(t, dev); if (dev == g.s.qsALSAInput) { found = true; @@ -219,7 +227,7 @@ ALSAConfig::ALSAConfig(Settings &st) : ConfigWidget(st) { found = false; foreach(QString dev, qlOutputDevs) { - QString t=QString::fromLatin1("[%1] %2").arg(dev).arg(cards.qhOutput[dev]); + QString t=QString::fromLatin1("[%1] %2").arg(dev).arg(cards->qhOutput[dev]); qcbOutputDevice->addItem(t, dev); if (dev == g.s.qsALSAOutput) { found = true; diff --git a/src/mumble/Global.cpp b/src/mumble/Global.cpp index 691249419..1d7b3b4b8 100644 --- a/src/mumble/Global.cpp +++ b/src/mumble/Global.cpp @@ -44,3 +44,31 @@ Global::Global() { bPushToMute = false; bCenterPosition = false; } + +QMultiMap *DeferInit::qmDeferers = NULL; + +void DeferInit::add(int priority) { + if (qmDeferers == NULL) { + qmDeferers = new QMultiMap(); + } + qmDeferers->insert(priority, this); +} + +DeferInit::~DeferInit() { +} + +void DeferInit::run_initializers() { + if (! qmDeferers) + return; + foreach(DeferInit *d, *qmDeferers) { + d->initialize(); + } +} + +void DeferInit::run_destroyers() { + if (! qmDeferers) + return; + foreach(DeferInit *d, *qmDeferers) { + d->destroy(); + } +} diff --git a/src/mumble/Global.h b/src/mumble/Global.h index aa4b1e5ba..7b415258a 100644 --- a/src/mumble/Global.h +++ b/src/mumble/Global.h @@ -84,6 +84,25 @@ struct Global { Global(); }; +// Class to handle ordered initialization of globals. +// This allows the same link-time magic as used everywhere else +// for globals that need an init before the GUI starts, but +// after we reach main(). + +class DeferInit { + protected: + static QMultiMap *qmDeferers; + void add(int priority); + public: + DeferInit(int priority) { add(priority); }; + DeferInit() { add(0); }; + virtual ~DeferInit(); + virtual void initialize() { }; + virtual void destroy() { }; + static void run_initializers(); + static void run_destroyers(); +}; + // -Wshadow is bugged. If an inline function of a class uses a variable or // parameter named 'g', that will generate a warning even if the class header // is included long before this definition. diff --git a/src/mumble/OSS.cpp b/src/mumble/OSS.cpp index 267ded2ee..013359416 100644 --- a/src/mumble/OSS.cpp +++ b/src/mumble/OSS.cpp @@ -50,7 +50,14 @@ class OSSEnumerator { OSSEnumerator(); }; -static OSSEnumerator cards; +static OSSEnumerator *cards = NULL; + +class OSSInit : public DeferInit { + void initialize() { cards = new OSSEnumerator(); }; + void destroy() { delete cards; cards = NULL; }; +}; + +static OSSInit ossi; class OSSInputRegistrar : public AudioInputRegistrar { public: @@ -82,7 +89,7 @@ AudioInput *OSSInputRegistrar::create() { const QList OSSInputRegistrar::getDeviceChoices() { QList qlReturn; - QStringList qlInputDevs = cards.qhInput.keys(); + QStringList qlInputDevs = cards->qhInput.keys(); qSort(qlInputDevs); if (qlInputDevs.contains(g.s.qsOSSInput)) { @@ -91,7 +98,7 @@ const QList OSSInputRegistrar::getDeviceChoices() { } foreach(const QString &dev, qlInputDevs) { - qlReturn << audioDevice(cards.qhInput.value(dev), dev); + qlReturn << audioDevice(cards->qhInput.value(dev), dev); } return qlReturn; @@ -111,7 +118,7 @@ AudioOutput *OSSOutputRegistrar::create() { const QList OSSOutputRegistrar::getDeviceChoices() { QList qlReturn; - QStringList qlOutputDevs = cards.qhOutput.keys(); + QStringList qlOutputDevs = cards->qhOutput.keys(); qSort(qlOutputDevs); if (qlOutputDevs.contains(g.s.qsOSSOutput)) { @@ -120,7 +127,7 @@ const QList OSSOutputRegistrar::getDeviceChoices() { } foreach(const QString &dev, qlOutputDevs) { - qlReturn << audioDevice(cards.qhOutput.value(dev), dev); + qlReturn << audioDevice(cards->qhOutput.value(dev), dev); } return qlReturn; @@ -185,16 +192,16 @@ OSSEnumerator::OSSEnumerator() { OSSConfig::OSSConfig(Settings &st) : ConfigWidget(st) { setupUi(this); - QList qlOutputDevs = cards.qhOutput.keys(); + QList qlOutputDevs = cards->qhOutput.keys(); qSort(qlOutputDevs); - QList qlInputDevs = cards.qhInput.keys(); + QList qlInputDevs = cards->qhInput.keys(); qSort(qlInputDevs); bool found; found = false; foreach(QString dev, qlInputDevs) { - qcbInputDevice->addItem(cards.qhInput.value(dev), dev); + qcbInputDevice->addItem(cards->qhInput.value(dev), dev); if (dev == g.s.qsOSSInput) { found = true; qcbInputDevice->setCurrentIndex(qcbInputDevice->count() - 1); @@ -203,7 +210,7 @@ OSSConfig::OSSConfig(Settings &st) : ConfigWidget(st) { found = false; foreach(QString dev, qlOutputDevs) { - qcbOutputDevice->addItem(cards.qhOutput.value(dev), dev); + qcbOutputDevice->addItem(cards->qhOutput.value(dev), dev); if (dev == g.s.qsOSSOutput) { found = true; qcbOutputDevice->setCurrentIndex(qcbOutputDevice->count() - 1); @@ -267,10 +274,10 @@ OSSInput::~OSSInput() { void OSSInput::run() { bRunning = true; - QByteArray device = cards.qhDevices.value(g.s.qsOSSInput).toLatin1(); + QByteArray device = cards->qhDevices.value(g.s.qsOSSInput).toLatin1(); if (device.isEmpty()) { qWarning("OSSInput: Stored device not found, falling back to default"); - device = cards.qhDevices.value(QString()).toLatin1(); + device = cards->qhDevices.value(QString()).toLatin1(); } int fd = open(device.constData(), O_RDONLY, 0); @@ -331,10 +338,10 @@ OSSOutput::~OSSOutput() { void OSSOutput::run() { bRunning = true; - QByteArray device = cards.qhDevices.value(g.s.qsOSSOutput).toLatin1(); + QByteArray device = cards->qhDevices.value(g.s.qsOSSOutput).toLatin1(); if (device.isEmpty()) { qWarning("OSSOutput: Stored device not found, falling back to default"); - device = cards.qhDevices.value(QString()).toLatin1(); + device = cards->qhDevices.value(QString()).toLatin1(); } int fd = open(device.constData(), O_WRONLY, 0); diff --git a/src/mumble/PulseAudio.cpp b/src/mumble/PulseAudio.cpp index ce743a925..2a74f36a3 100644 --- a/src/mumble/PulseAudio.cpp +++ b/src/mumble/PulseAudio.cpp @@ -38,7 +38,7 @@ #include #include -static PulseAudioSystem pasys; +static PulseAudioSystem *pasys = NULL; static const pa_sample_spec ss = { PA_SAMPLE_S16LE, SAMPLE_RATE, 1 }; @@ -67,6 +67,14 @@ class PulseAudioOutputRegistrar : public AudioOutputRegistrar { static PulseAudioInputRegistrar airPulseAudio; static PulseAudioOutputRegistrar aorPulseAudio; +class PulseAudioInit : public DeferInit { + public: + void initialize() { pasys = new PulseAudioSystem(); }; + void destroy() { delete pasys; pasys = NULL; }; +}; + +static PulseAudioInit pulseinit; + PulseAudioSystem::PulseAudioSystem() { pasInput = pasOutput = pasSpeaker = NULL; iDelayCache = 0; @@ -90,7 +98,6 @@ PulseAudioSystem::PulseAudioSystem() { jbJitter = jitter_buffer_init(); int margin = 320; jitter_buffer_ctl(jbJitter, JITTER_BUFFER_SET_MARGIN, &margin); - start(QThread::TimeCriticalPriority); } @@ -472,7 +479,7 @@ AudioInput *PulseAudioInputRegistrar::create() { const QList PulseAudioInputRegistrar::getDeviceChoices() { QList qlReturn; - QStringList qlInputDevs = pasys.qhInput.keys(); + QStringList qlInputDevs = pasys->qhInput.keys(); qSort(qlInputDevs); if (qlInputDevs.contains(g.s.qsPulseAudioInput)) { @@ -481,7 +488,7 @@ const QList PulseAudioInputRegistrar::getDeviceChoices() { } foreach(const QString &dev, qlInputDevs) { - qlReturn << audioDevice(pasys.qhInput.value(dev), dev); + qlReturn << audioDevice(pasys->qhInput.value(dev), dev); } return qlReturn; @@ -501,7 +508,7 @@ AudioOutput *PulseAudioOutputRegistrar::create() { const QList PulseAudioOutputRegistrar::getDeviceChoices() { QList qlReturn; - QStringList qlOutputDevs = pasys.qhOutput.keys(); + QStringList qlOutputDevs = pasys->qhOutput.keys(); qSort(qlOutputDevs); if (qlOutputDevs.contains(g.s.qsPulseAudioOutput)) { @@ -510,7 +517,7 @@ const QList PulseAudioOutputRegistrar::getDeviceChoices() { } foreach(const QString &dev, qlOutputDevs) { - qlReturn << audioDevice(pasys.qhOutput.value(dev), dev); + qlReturn << audioDevice(pasys->qhOutput.value(dev), dev); } return qlReturn; @@ -529,17 +536,17 @@ static ConfigRegistrar registrar(22, PulseAudioConfigDialogNew); PulseAudioConfig::PulseAudioConfig(Settings &st) : ConfigWidget(st) { setupUi(this); - QStringList qlOutputDevs = pasys.qhOutput.keys(); + QStringList qlOutputDevs = pasys->qhOutput.keys(); qSort(qlOutputDevs); - QStringList qlInputDevs = pasys.qhInput.keys(); + QStringList qlInputDevs = pasys->qhInput.keys(); qSort(qlInputDevs); foreach(QString dev, qlInputDevs) { - qcbInputDevice->addItem(pasys.qhInput.value(dev), dev); + qcbInputDevice->addItem(pasys->qhInput.value(dev), dev); } foreach(QString dev, qlOutputDevs) { - qcbOutputDevice->addItem(pasys.qhOutput.value(dev), dev); + qcbOutputDevice->addItem(pasys->qhOutput.value(dev), dev); } } @@ -588,20 +595,24 @@ void PulseAudioConfig::on_qsOutputDelay_valueChanged(int v) { PulseAudioInput::PulseAudioInput() { bRunning = true; bHasSpeaker = g.s.bPulseAudioEcho; - pasys.wakeup(); + if (pasys) + pasys->wakeup(); }; PulseAudioInput::~PulseAudioInput() { bRunning = false; - pasys.wakeup(); + if (pasys) + pasys->wakeup(); } PulseAudioOutput::PulseAudioOutput() { bRunning = true; - pasys.wakeup(); + if (pasys) + pasys->wakeup(); } PulseAudioOutput::~PulseAudioOutput() { bRunning = false; - pasys.wakeup(); + if (pasys) + pasys->wakeup(); } diff --git a/src/mumble/main.cpp b/src/mumble/main.cpp index 643408ed1..6afaec5b1 100644 --- a/src/mumble/main.cpp +++ b/src/mumble/main.cpp @@ -96,6 +96,8 @@ int main(int argc, char **argv) { // Load preferences g.s.load(); + DeferInit::run_initializers(); + if (! g.s.qsStyle.isEmpty()) { a.setStyle(g.s.qsStyle); } @@ -210,6 +212,8 @@ int main(int argc, char **argv) { delete g.o; delete g.qs; + + DeferInit::run_destroyers(); return res; }