summaryrefslogtreecommitdiff
path: root/src/model
diff options
context:
space:
mode:
Diffstat (limited to 'src/model')
-rw-r--r--src/model/pulsemodel.cpp114
-rw-r--r--src/model/pulsemodel.h28
2 files changed, 139 insertions, 3 deletions
diff --git a/src/model/pulsemodel.cpp b/src/model/pulsemodel.cpp
index 49a17c2..31df0ca 100644
--- a/src/model/pulsemodel.cpp
+++ b/src/model/pulsemodel.cpp
@@ -31,6 +31,9 @@ struct PAEvent : public TQCustomEvent {
TQString iconName;
TQString paName; // raw PA name (sinks/sources only, for default tracking)
uint32_t parentIndex; // for Playback: parent sink PA index
+ uint32_t cardIdx; // for Output/Input: owning card PA index
+ TQString activePortName;
+ TQValueList<PulseDevicePort> devPorts;
PAEvent( Kind k, AudioDevice::Category c, uint32_t idx,
const TQString &n = TQString(), int vol = 0, bool m = false,
@@ -39,7 +42,8 @@ struct PAEvent : public TQCustomEvent {
const TQString &pname = TQString() )
: TQCustomEvent(PA_EVENT), kind(k), cat(c), paIndex(idx),
name(n), volume(vol), muted(m), channels(ch), pan(p),
- monitorName(mon), iconName(icon), paName(pname), parentIndex(parent) {}
+ monitorName(mon), iconName(icon), paName(pname), parentIndex(parent),
+ cardIdx(PA_INVALID_INDEX) {}
};
struct PACardEvent : public TQCustomEvent {
@@ -297,6 +301,15 @@ void PulseModel::sinkInfoCb( pa_context *, const pa_sink_info *info, int eol, vo
TQString::fromUtf8( pa_proplist_gets( info->proplist, PA_PROP_DEVICE_ICON_NAME ) ? : "" ),
PA_INVALID_INDEX,
TQString::fromUtf8( info->name ) );
+ ev->cardIdx = info->card;
+ ev->activePortName = info->active_port
+ ? TQString::fromUtf8( info->active_port->name ) : TQString();
+ for ( uint32_t i = 0; i < info->n_ports; ++i ) {
+ PulseDevicePort p;
+ p.name = TQString::fromUtf8( info->ports[i]->name );
+ p.description = TQString::fromUtf8( info->ports[i]->description );
+ ev->devPorts.append( p );
+ }
TQApplication::postEvent( self, ev );
}
@@ -306,7 +319,7 @@ void PulseModel::sourceInfoCb( pa_context *, const pa_source_info *info, int eol
// Skip monitor sources — they're PA internals, not real inputs.
if ( info->monitor_of_sink != PA_INVALID_INDEX ) return;
PulseModel *self = static_cast<PulseModel *>(userdata);
- TQApplication::postEvent( self, new PAEvent(
+ PAEvent *ev = new PAEvent(
PAEvent::DeviceAdded, AudioDevice::Input, info->index,
TQString::fromUtf8( info->description ),
paVolumeToPercent( info->volume ), info->mute != 0,
@@ -314,7 +327,17 @@ void PulseModel::sourceInfoCb( pa_context *, const pa_source_info *info, int eol
TQString::fromUtf8( info->name ),
TQString::fromUtf8( pa_proplist_gets( info->proplist, PA_PROP_DEVICE_ICON_NAME ) ? : "" ),
PA_INVALID_INDEX,
- TQString::fromUtf8( info->name ) ) );
+ TQString::fromUtf8( info->name ) );
+ ev->cardIdx = info->card;
+ ev->activePortName = info->active_port
+ ? TQString::fromUtf8( info->active_port->name ) : TQString();
+ for ( uint32_t i = 0; i < info->n_ports; ++i ) {
+ PulseDevicePort p;
+ p.name = TQString::fromUtf8( info->ports[i]->name );
+ p.description = TQString::fromUtf8( info->ports[i]->description );
+ ev->devPorts.append( p );
+ }
+ TQApplication::postEvent( self, ev );
}
void PulseModel::sinkInputInfoCb( pa_context *, const pa_sink_input_info *info, int eol, void *userdata )
@@ -585,6 +608,16 @@ void PulseModel::customEvent( TQCustomEvent *e )
for ( it = m_sourcesByName.begin(); it != m_sourcesByName.end(); ++it ) {
if ( it.data() == dev ) { m_sourcesByName.remove(it); break; }
}
+ // Clean up port tracking maps.
+ if ( ev->cat == AudioDevice::Output ) {
+ m_sinkCard.remove( ev->paIndex );
+ m_sinkActivePort.remove( ev->paIndex );
+ m_sinkPorts.remove( ev->paIndex );
+ } else if ( ev->cat == AudioDevice::Input ) {
+ m_sourceCard.remove( ev->paIndex );
+ m_sourceActivePort.remove( ev->paIndex );
+ m_sourcePorts.remove( ev->paIndex );
+ }
// If a recording stream ended, decrement its parent source's count.
if ( ev->cat == AudioDevice::Recording ) {
TQMap<uint32_t,uint32_t>::Iterator si = m_sourceOutputToSource.find( ev->paIndex );
@@ -610,6 +643,25 @@ void PulseModel::customEvent( TQCustomEvent *e )
if ( sink ) monitorName = sink->monitorName();
}
+ // Store / update port data for sinks and sources.
+ if ( ev->cat == AudioDevice::Output ) {
+ m_sinkCard[ev->paIndex] = ev->cardIdx;
+ m_sinkPorts[ev->paIndex] = ev->devPorts;
+ TQString oldPort = m_sinkActivePort.contains(ev->paIndex)
+ ? m_sinkActivePort[ev->paIndex] : TQString();
+ m_sinkActivePort[ev->paIndex] = ev->activePortName;
+ if ( ev->activePortName != oldPort )
+ emit sinkUpdated( ev->paIndex );
+ } else if ( ev->cat == AudioDevice::Input ) {
+ m_sourceCard[ev->paIndex] = ev->cardIdx;
+ m_sourcePorts[ev->paIndex] = ev->devPorts;
+ TQString oldPort = m_sourceActivePort.contains(ev->paIndex)
+ ? m_sourceActivePort[ev->paIndex] : TQString();
+ m_sourceActivePort[ev->paIndex] = ev->activePortName;
+ if ( ev->activePortName != oldPort )
+ emit sourceUpdated( ev->paIndex );
+ }
+
PulseDevice *dev = findDevice( *list, ev->paIndex );
if ( dev ) {
dev->update( ev->name, ev->volume, ev->muted, ev->channels, ev->pan, monitorName, ev->iconName );
@@ -734,4 +786,60 @@ void PulseModel::setCardProfile( uint32_t cardIndex, const TQString &profileName
pa_threaded_mainloop_unlock( m_mainloop );
}
+TQValueList<PulseModel::DevicePortInfo> PulseModel::sinksForCard( uint32_t cardIndex ) const
+{
+ TQValueList<DevicePortInfo> result;
+ for ( TQPtrListIterator<PulseDevice> it(m_sinks); *it; ++it ) {
+ uint32_t idx = (*it)->paIndex();
+ if ( !m_sinkCard.contains(idx) || m_sinkCard[idx] != cardIndex )
+ continue;
+ DevicePortInfo info;
+ info.paIndex = idx;
+ info.description = (*it)->name();
+ info.activePort = m_sinkActivePort.contains(idx) ? m_sinkActivePort[idx] : TQString();
+ info.ports = m_sinkPorts.contains(idx) ? m_sinkPorts[idx]
+ : TQValueList<PulseDevicePort>();
+ result.append( info );
+ }
+ return result;
+}
+
+TQValueList<PulseModel::DevicePortInfo> PulseModel::sourcesForCard( uint32_t cardIndex ) const
+{
+ TQValueList<DevicePortInfo> result;
+ for ( TQPtrListIterator<PulseDevice> it(m_sources); *it; ++it ) {
+ uint32_t idx = (*it)->paIndex();
+ if ( !m_sourceCard.contains(idx) || m_sourceCard[idx] != cardIndex )
+ continue;
+ DevicePortInfo info;
+ info.paIndex = idx;
+ info.description = (*it)->name();
+ info.activePort = m_sourceActivePort.contains(idx) ? m_sourceActivePort[idx] : TQString();
+ info.ports = m_sourcePorts.contains(idx) ? m_sourcePorts[idx]
+ : TQValueList<PulseDevicePort>();
+ result.append( info );
+ }
+ return result;
+}
+
+void PulseModel::setSinkPort( uint32_t sinkPaIndex, const TQString &portName )
+{
+ if ( !m_context || !m_mainloop || portName.isEmpty() ) return;
+ pa_threaded_mainloop_lock( m_mainloop );
+ pa_operation *op = pa_context_set_sink_port_by_index(
+ m_context, sinkPaIndex, portName.utf8().data(), 0, 0 );
+ if ( op ) pa_operation_unref( op );
+ pa_threaded_mainloop_unlock( m_mainloop );
+}
+
+void PulseModel::setSourcePort( uint32_t sourcePaIndex, const TQString &portName )
+{
+ if ( !m_context || !m_mainloop || portName.isEmpty() ) return;
+ pa_threaded_mainloop_lock( m_mainloop );
+ pa_operation *op = pa_context_set_source_port_by_index(
+ m_context, sourcePaIndex, portName.utf8().data(), 0, 0 );
+ if ( op ) pa_operation_unref( op );
+ pa_threaded_mainloop_unlock( m_mainloop );
+}
+
#include "pulsemodel.moc"
diff --git a/src/model/pulsemodel.h b/src/model/pulsemodel.h
index c1d4561..d0e93b4 100644
--- a/src/model/pulsemodel.h
+++ b/src/model/pulsemodel.h
@@ -11,6 +11,13 @@
class PulseDevice;
+// ---- shared port struct -----------------------------------------------------
+
+struct PulseDevicePort {
+ TQString name;
+ TQString description;
+};
+
// ---- card data structures ---------------------------------------------------
struct PulseCardProfile {
@@ -66,6 +73,17 @@ public:
const PulseCardInfo *card( uint32_t index ) const;
void setCardProfile( uint32_t cardIndex, const TQString &profileName );
+ struct DevicePortInfo {
+ uint32_t paIndex;
+ TQString description;
+ TQString activePort;
+ TQValueList<PulseDevicePort> ports;
+ };
+ TQValueList<DevicePortInfo> sinksForCard( uint32_t cardIndex ) const;
+ TQValueList<DevicePortInfo> sourcesForCard( uint32_t cardIndex ) const;
+ void setSinkPort( uint32_t sinkPaIndex, const TQString &portName );
+ void setSourcePort( uint32_t sourcePaIndex, const TQString &portName );
+
protected:
void customEvent( TQCustomEvent *e );
@@ -80,6 +98,9 @@ signals:
void cardRemoved( uint32_t index );
void cardUpdated( uint32_t index );
+ void sinkUpdated( uint32_t paIndex );
+ void sourceUpdated( uint32_t paIndex );
+
private slots:
void reconnect();
@@ -116,6 +137,13 @@ private:
TQValueList<PulseCardInfo> m_cards;
+ TQMap<uint32_t, uint32_t> m_sinkCard;
+ TQMap<uint32_t, TQString> m_sinkActivePort;
+ TQMap<uint32_t, TQValueList<PulseDevicePort>> m_sinkPorts;
+ TQMap<uint32_t, uint32_t> m_sourceCard;
+ TQMap<uint32_t, TQString> m_sourceActivePort;
+ TQMap<uint32_t, TQValueList<PulseDevicePort>> m_sourcePorts;
+
PulseDevice *findDevice( TQPtrList<PulseDevice> &list, uint32_t paIndex );
PulseCardInfo *findCard( uint32_t index );
};