summaryrefslogtreecommitdiff
path: root/src/model/pulsemodel.h
blob: d0e93b495b1784a34077be33930d936459a0bb3d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#pragma once

#include <tqobject.h>
#include <tqptrlist.h>
#include <tqmap.h>
#include <tqvaluelist.h>

#include <pulse/pulseaudio.h>

#include "audiodevice.h"

class PulseDevice;

// ---- shared port struct -----------------------------------------------------

struct PulseDevicePort {
    TQString name;
    TQString description;
};

// ---- card data structures ---------------------------------------------------

struct PulseCardProfile {
    TQString name;
    TQString description;
    bool    available;
};

struct PulseCardPort {
    TQString  name;
    TQString  description;
    int      available;         // pa_port_available_t: 0=unknown, 1=no, 2=yes
    int      direction;         // PA_DIRECTION_INPUT=1, PA_DIRECTION_OUTPUT=2
    uint32_t type;              // pa_device_port_type_t
    TQString  availabilityGroup;
};

struct PulseCardInfo {
    uint32_t index;
    TQString  name;
    TQString  description;
    TQString  activeProfile;
    TQString  vendor;       // device.vendor.name
    TQString  product;      // device.product.name
    TQString  formFactor;   // device.form_factor
    TQString  busType;      // device.bus (pci/usb/etc)
    TQValueList<PulseCardProfile> profiles;
    TQValueList<PulseCardPort>    ports;
};

// ---- model ------------------------------------------------------------------

class PulseModel : public TQObject
{
    TQ_OBJECT

public:
    explicit PulseModel( TQObject *parent = 0 );
    ~PulseModel();

    bool open();
    void close();

    TQPtrList<AudioDevice> devices( AudioDevice::Category cat ) const;
    AudioDevice *defaultOutput() const;
    AudioDevice *defaultInput()  const;

    void setDefaultOutput( AudioDevice *dev );
    void setDefaultInput( AudioDevice *dev );
    void moveSinkInputToSink( AudioDevice *playbackDev, AudioDevice *outputDev );

    TQValueList<PulseCardInfo> cards() const { return m_cards; }
    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 );

signals:
    void deviceAdded( AudioDevice *dev );
    void deviceRemoved( AudioDevice *dev );
    void defaultOutputChanged( AudioDevice *dev );
    void defaultInputChanged( AudioDevice *dev );
    void ready();

    void cardAdded( uint32_t index );
    void cardRemoved( uint32_t index );
    void cardUpdated( uint32_t index );

    void sinkUpdated( uint32_t paIndex );
    void sourceUpdated( uint32_t paIndex );

private slots:
    void reconnect();

private:
    static void contextStateCb( pa_context *c, void *userdata );
    static void serverInfoCb( pa_context *c, const pa_server_info *info, void *userdata );
    static void sinkInfoCb( pa_context *c, const pa_sink_info *info, int eol, void *userdata );
    static void sourceInfoCb( pa_context *c, const pa_source_info *info, int eol, void *userdata );
    static void sinkInputInfoCb( pa_context *c, const pa_sink_input_info *info, int eol, void *userdata );
    static void sourceOutputInfoCb( pa_context *c, const pa_source_output_info *info, int eol, void *userdata );
    static void cardInfoCb( pa_context *c, const pa_card_info *info, int eol, void *userdata );
    static void subscribeCb( pa_context *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata );

    void enumerateAll();
    void addOrUpdateSink( const pa_sink_info *info );
    void addOrUpdateSource( const pa_source_info *info );
    void addOrUpdateSinkInput( const pa_sink_input_info *info );
    void addOrUpdateSourceOutput( const pa_source_output_info *info );
    void removeDevice( AudioDevice::Category cat, uint32_t paIndex );

    pa_threaded_mainloop *m_mainloop;
    pa_context           *m_context;

    TQPtrList<PulseDevice> m_sinks;
    TQPtrList<PulseDevice> m_sources;
    TQPtrList<PulseDevice> m_sinkInputs;
    TQPtrList<PulseDevice> m_sourceOutputs;

    TQMap<TQString, PulseDevice*> m_sinksByName;
    TQMap<TQString, PulseDevice*> m_sourcesByName;
    TQString                      m_defaultSinkName;
    TQString                      m_defaultSourceName;
    TQMap<uint32_t, uint32_t>     m_sourceOutputToSource; // soIdx → sourceIdx

    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 );
};