summaryrefslogtreecommitdiff
path: root/src/model/pulsemodel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/model/pulsemodel.cpp')
-rw-r--r--src/model/pulsemodel.cpp55
1 files changed, 50 insertions, 5 deletions
diff --git a/src/model/pulsemodel.cpp b/src/model/pulsemodel.cpp
index 640b918..49a17c2 100644
--- a/src/model/pulsemodel.cpp
+++ b/src/model/pulsemodel.cpp
@@ -2,11 +2,13 @@
#include "pulsedevice.h"
#include <tqapplication.h>
+#include <tqtimer.h>
// Custom events posted from the PA thread to the main thread.
static const int PA_EVENT = TQEvent::User + 1;
static const int PA_SERVER_EVENT = TQEvent::User + 3;
static const int PA_CARD_EVENT = TQEvent::User + 4;
+static const int PA_DIED_EVENT = TQEvent::User + 5;
struct PAServerEvent : public TQCustomEvent {
TQString defaultSinkName;
@@ -183,18 +185,27 @@ bool PulseModel::open()
void PulseModel::close()
{
- // Detach monitor streams on all devices before tearing down the mainloop.
TQPtrList<PulseDevice> *allLists[4] = { &m_sinks, &m_sources, &m_sinkInputs, &m_sourceOutputs };
+
+ bool alreadyDead = false;
+ if ( m_context ) {
+ pa_context_state_t state = pa_context_get_state( m_context );
+ alreadyDead = ( state == PA_CONTEXT_FAILED ||
+ state == PA_CONTEXT_TERMINATED );
+ }
+
for ( int i = 0; i < 4; i++ )
for ( TQPtrListIterator<PulseDevice> it(*allLists[i]); *it; ++it )
- (*it)->detach();
+ (*it)->detach( alreadyDead );
if ( m_context ) {
- pa_threaded_mainloop_lock( m_mainloop );
- pa_context_disconnect( m_context );
+ if ( !alreadyDead ) {
+ pa_threaded_mainloop_lock( m_mainloop );
+ pa_context_disconnect( m_context );
+ pa_threaded_mainloop_unlock( m_mainloop );
+ }
pa_context_unref( m_context );
m_context = 0;
- pa_threaded_mainloop_unlock( m_mainloop );
}
if ( m_mainloop ) {
pa_threaded_mainloop_stop( m_mainloop );
@@ -247,6 +258,7 @@ void PulseModel::contextStateCb( pa_context *c, void *userdata )
break;
case PA_CONTEXT_FAILED:
case PA_CONTEXT_TERMINATED:
+ TQApplication::postEvent( self, new TQCustomEvent(PA_DIED_EVENT) );
break;
default:
break;
@@ -437,8 +449,41 @@ void PulseModel::cardInfoCb( pa_context *, const pa_card_info *info, int eol, vo
// ---- main thread event handler ----------------------------------------------
+void PulseModel::reconnect()
+{
+ open();
+}
+
void PulseModel::customEvent( TQCustomEvent *e )
{
+ if ( e->type() == PA_DIED_EVENT ) {
+ if ( !m_mainloop ) return; // already handling a previous die event
+ // Notify UI that all devices are gone, then tear down and retry.
+ TQPtrList<PulseDevice> *allLists[4] = { &m_sinks, &m_sources, &m_sinkInputs, &m_sourceOutputs };
+ for ( int i = 0; i < 4; i++ ) {
+ TQPtrListIterator<PulseDevice> it( *allLists[i] );
+ while ( *it ) {
+ PulseDevice *dev = *it;
+ ++it;
+ emit deviceRemoved( dev );
+ }
+ }
+ // Zero out default-device pointers in connected UI before devices are deleted.
+ emit defaultOutputChanged( 0 );
+ emit defaultInputChanged( 0 );
+ // Sever all remaining signal connections on every device so that
+ // close() can delete them safely regardless of cross-device wiring.
+ for ( int i = 0; i < 4; i++ )
+ for ( TQPtrListIterator<PulseDevice> it( *allLists[i] ); *it; ++it )
+ disconnect( *it, 0, 0, 0 );
+ m_sinksByName.clear();
+ m_sourcesByName.clear();
+ m_sourceOutputToSource.clear();
+ m_cards.clear();
+ close();
+ TQTimer::singleShot( 2000, this, TQ_SLOT(reconnect()) );
+ return;
+ }
if ( e->type() == PA_CARD_EVENT ) {
PACardEvent *ev = static_cast<PACardEvent *>(e);
if ( ev->removed ) {