pulselayer.h 7.96 KB
Newer Older
1
/*
2
 *  Copyright (C) 2004, 2005, 2006, 2008, 2009, 2010, 2011 Savoir-Faire Linux Inc.
3
 *  Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>
4
 *  Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com>
5
6
7
8
9
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
Julien Bonjean's avatar
Julien Bonjean committed
10
 *
11
12
13
14
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
Julien Bonjean's avatar
Julien Bonjean committed
15
 *
16
17
18
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
20
21
22
23
24
25
26
27
28
29
 *
 *  Additional permission under GNU GPL version 3 section 7:
 *
 *  If you modify this program, or any covered work, by linking or
 *  combining it with the OpenSSL project's OpenSSL library (or a
 *  modified version of that library), containing parts covered by the
 *  terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
 *  grants you additional permission to convey the resulting work.
 *  Corresponding Source for a non-source form of such a combination
 *  shall include the source code for the parts of OpenSSL used as well
 *  as that of the covered work.
30
31
32
33
34
 */

#ifndef _PULSE_LAYER_H
#define _PULSE_LAYER_H

35
#include "audio/audiolayer.h"
36
#include <pulse/pulseaudio.h>
37
#include <pulse/stream.h>
38

39
40
#include <list>
#include <string>
41

42
43
44
#define PLAYBACK_STREAM_NAME	    "SFLphone playback"
#define CAPTURE_STREAM_NAME	    "SFLphone capture"
#define RINGTONE_STREAM_NAME        "SFLphone ringtone"
45

46
47
class RingBuffer;
class ManagerImpl;
48
49
50
class AudioStream;
class DcBlocker;
class SamplerateConverter;
51

52
53
typedef std::list<std::string> DeviceList;

Julien Bonjean's avatar
Julien Bonjean committed
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
class PulseLayer : public AudioLayer
{
    public:
        PulseLayer (ManagerImpl* manager);
        ~PulseLayer (void);
        /**
         * Check if no devices are opened, otherwise close them.
         * Then open the specified devices by calling the private functions open_device
         * @param indexIn	The number of the card chosen for capture
         * @param indexOut	The number of the card chosen for playback
         * @param sampleRate  The sample rate
         * @param frameSize	  The frame size
         * @param stream	  To indicate which kind of stream you want to open
         *			  SFL_PCM_CAPTURE
         *			  SFL_PCM_PLAYBACK
         *			  SFL_PCM_BOTH
         * @param plugin	  The alsa plugin ( dmix , default , front , surround , ...)
         */
Tristan Matthews's avatar
Tristan Matthews committed
72
        void openDevice (int indexIn, int indexOut, int indexRing, int sampleRate, int frameSize , int stream, const std::string &plugin) ;
Julien Bonjean's avatar
Julien Bonjean committed
73
74

        DeviceList* getSinkList (void) {
75
            return &sinkList_;
Julien Bonjean's avatar
Julien Bonjean committed
76
77
78
        }

        DeviceList* getSourceList (void) {
79
            return &sourceList_;
Julien Bonjean's avatar
Julien Bonjean committed
80
81
82
83
84
85
        }

        void updateSinkList (void);

        void updateSourceList (void);

86
        bool inSinkList (const std::string &deviceName) const;
Julien Bonjean's avatar
Julien Bonjean committed
87

88
        bool inSourceList (const std::string &deviceName) const;
Julien Bonjean's avatar
Julien Bonjean committed
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

        void startStream (void);

        void stopStream (void);

        static void context_state_callback (pa_context* c, void* user_data);

        /**
         * Reduce volume of every audio applications connected to the same sink
         */
        void reducePulseAppsVolume (void);

        /**
         * Restore the volume of every audio applications connected to the same sink to PA_VOLUME_NORM
         */
        void restorePulseAppsVolume (void);

        /**
         * Set the volume of a sink.
         * @param index The index of the stream
         * @param channels	The stream's number of channels
         * @param volume The new volume (between 0 and 100)
         */
        void setSinkVolume (int index, int channels, int volume);
        void setSourceVolume (int index, int channels, int volume);

        void setPlaybackVolume (int volume);
        void setCaptureVolume (int volume);

        /**
         * Accessor
         * @return AudioStream* The pointer on the playback AudioStream object
         */
122
123
        AudioStream* getPlaybackStream() const {
            return playback_;
Julien Bonjean's avatar
Julien Bonjean committed
124
125
126
127
128
129
        }

        /**
         * Accessor
         * @return AudioStream* The pointer on the record AudioStream object
         */
130
131
        AudioStream* getRecordStream() const {
            return record_;
Julien Bonjean's avatar
Julien Bonjean committed
132
133
134
135
136
137
        }

        /**
         * Accessor
         * @return AudioStream* The pointer on the ringtone AudioStream object
         */
138
139
        AudioStream* getRingtoneStream() const {
            return ringtone_;
Julien Bonjean's avatar
Julien Bonjean committed
140
141
        }

142
143
        int getSpkrVolume (void) const {
            return spkrVolume_;
Julien Bonjean's avatar
Julien Bonjean committed
144
145
        }
        void setSpkrVolume (int value) {
146
            spkrVolume_ = value;
Julien Bonjean's avatar
Julien Bonjean committed
147
148
        }

149
150
        int getMicVolume (void) const {
            return micVolume_;
Julien Bonjean's avatar
Julien Bonjean committed
151
152
        }
        void setMicVolume (int value) {
153
            micVolume_ = value;
Julien Bonjean's avatar
Julien Bonjean committed
154
155
        }

Alexandre Savard's avatar
Alexandre Savard committed
156
157
158
        /**
         * Handle used to write voice data to speaker
         */
Julien Bonjean's avatar
Julien Bonjean committed
159
160
        void processPlaybackData (void);

Alexandre Savard's avatar
Alexandre Savard committed
161
162
163
        /**
         * Handle used to write voice data to microphone
         */
Julien Bonjean's avatar
Julien Bonjean committed
164
165
        void processCaptureData (void);

Alexandre Savard's avatar
Alexandre Savard committed
166
167
168
        /**
         * Handle used to write audio data to speaker
         */
Julien Bonjean's avatar
Julien Bonjean committed
169
170
        void processRingtoneData (void);

Alexandre Savard's avatar
Alexandre Savard committed
171
172
173
        /**
         * Process speaker and microphone audio data
         */
Julien Bonjean's avatar
Julien Bonjean committed
174
175
176
177
178
179
        void processData (void);

        /**
         * Get the noise suppressor state
         * @return true if noise suppressor activated
         */
180
        bool getNoiseSuppressState (void) const {
Julien Bonjean's avatar
Julien Bonjean committed
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
            return AudioLayer::_noisesuppressstate;
        }

        /**
         * Set the noise suppressor state
         * @param state true if noise suppressor active, false elsewhere
         */
        void setNoiseSuppressState (bool state);

    private:
        // Copy Constructor
        PulseLayer (const PulseLayer& rh);

        // Assignment Operator
        PulseLayer& operator= (const PulseLayer& rh);


        /**
         * Drop the pending frames and close the capture device
         */
        void closeCaptureStream (void);

        /**
         * Write data from the ring buffer to the harware and read data from the hardware
         */
        void readFromMic (void);
        void writeToSpeaker (void);
        void ringtoneToSpeaker (void);

        /**
         * Create the audio streams into the given context
         * @param c	The pulseaudio context
         */
214
        void createStreams (pa_context* c);
Julien Bonjean's avatar
Julien Bonjean committed
215
216
217
218
219
220
221
222
223
224
225
226
227
228

        /**
         * Drop the pending frames and close the playback device
         */
        void closePlaybackStream (void);

        /**
         * Establishes the connection with the local pulseaudio server
         */
        void connectPulseAudioServer (void);

        /**
         * Close the connection with the local pulseaudio server
         */
229
        void disconnectAudioStream (void);
Julien Bonjean's avatar
Julien Bonjean committed
230
231
232
233
234
235

        /**
         * Get some information about the pulseaudio server
         */
        void serverinfo (void);

236
237
238
239
240
        void openLayer (void);

        void closeLayer (void);


Julien Bonjean's avatar
Julien Bonjean committed
241
        /** PulseAudio context and asynchronous loop */
242
243
        pa_context* context_;
        pa_threaded_mainloop* mainloop_;
Julien Bonjean's avatar
Julien Bonjean committed
244
245
246
247

        /**
         * A stream object to handle the pulseaudio playback stream
         */
248
        AudioStream* playback_;
Julien Bonjean's avatar
Julien Bonjean committed
249
250
251
252

        /**
         * A stream object to handle the pulseaudio capture stream
         */
253
        AudioStream* record_;
Julien Bonjean's avatar
Julien Bonjean committed
254
255
256
257

        /**
         * A special stream object to handle specific playback stream for ringtone
         */
258
        AudioStream* ringtone_;
Julien Bonjean's avatar
Julien Bonjean committed
259
260

        /** Sample rate converter object */
261
        SamplerateConverter * converter_;
Julien Bonjean's avatar
Julien Bonjean committed
262

263
264
        int spkrVolume_;
        int micVolume_;
Julien Bonjean's avatar
Julien Bonjean committed
265

266
267
        DeviceList sinkList_;
        DeviceList sourceList_;
Julien Bonjean's avatar
Julien Bonjean committed
268
269
270

    public:
        friend class AudioLayerTest;
271
272
273
274
};

#endif // _PULSE_LAYER_H_