pulselayer.h 6.14 KB
Newer Older
1
/*
2
 *  Copyright (C) 2004-2013 Savoir-Faire Linux Inc.
3
 *  Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>
4
 *  Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com>
Tristan Matthews's avatar
Tristan Matthews committed
5
 *  Author: Андрей Лухнов <aol.nnov@gmail.com>
6
 *  Author: Adrien Beraud <adrien.beraud@gmail.com>
7 8 9 10 11
 *
 *  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
12
 *
13 14 15 16
 *  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
17
 *
18 19
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
20
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
21 22 23 24 25 26 27 28 29 30 31
 *
 *  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.
32 33
 */

34 35
#ifndef PULSE_LAYER_H_
#define PULSE_LAYER_H_
36

37 38
#include <list>
#include <string>
39 40 41 42
#include <pulse/pulseaudio.h>
#include <pulse/stream.h>
#include "audio/audiolayer.h"
#include "noncopyable.h"
43
#include "logger.h"
44

45
class AudioPreference;
46
class AudioStream;
47

48 49 50
/**
 * Convenience structure to hold PulseAudio device propreties such as supported channel number etc.
 */
Adrien Béraud's avatar
Adrien Béraud committed
51
typedef struct PaDeviceInfos {
Tristan Matthews's avatar
Tristan Matthews committed
52
        uint32_t index;
53 54 55
        std::string name;
        pa_sample_spec sample_spec;
        pa_channel_map channel_map;
56

57
        PaDeviceInfos(unsigned idx, const char* ep_name, const pa_sample_spec &samp_spec, const pa_channel_map &chan_map)
58 59
            : index(idx), name(ep_name), sample_spec(samp_spec), channel_map(chan_map) {}
        virtual ~PaDeviceInfos() {}
60

61 62 63 64 65 66 67 68 69 70 71 72
        /**
         * Unary function to search for a device by name in a list using std functions.
         */
        class nameComparator {
            public:
                explicit nameComparator(const std::string &ref) : baseline(ref) {}
                bool operator()(const PaDeviceInfos &arg) {
                    return arg.name == baseline;
                }
            private:
                const std::string &baseline;
        };
73 74
} PaDeviceInfos;

75
class PulseLayer : public AudioLayer {
Julien Bonjean's avatar
Julien Bonjean committed
76
    public:
77
        PulseLayer(AudioPreference &pref);
78
        ~PulseLayer();
Julien Bonjean's avatar
Julien Bonjean committed
79

80 81 82
        /**
         * Write data from the ring buffer to the harware and read data from the hardware
         */
83 84 85
        void readFromMic();
        void writeToSpeaker();
        void ringtoneToSpeaker();
86 87


88
        void updateSinkList();
Julien Bonjean's avatar
Julien Bonjean committed
89

90
        void updateSourceList();
Julien Bonjean's avatar
Julien Bonjean committed
91

Adrien Béraud's avatar
Adrien Béraud committed
92
        bool inSinkList(const std::string &deviceName);
Julien Bonjean's avatar
Julien Bonjean committed
93

Adrien Béraud's avatar
Adrien Béraud committed
94
        bool inSourceList(const std::string &deviceName);
Julien Bonjean's avatar
Julien Bonjean committed
95

96 97
        virtual std::vector<std::string> getCaptureDeviceList() const;
        virtual std::vector<std::string> getPlaybackDeviceList() const;
98
        int getAudioDeviceIndex(const std::string& name) const;
Adrien Béraud's avatar
Adrien Béraud committed
99

100
        std::string getAudioDeviceName(int index, PCMType type) const;
Julien Bonjean's avatar
Julien Bonjean committed
101

102 103 104
        virtual void startStream();

        virtual void stopStream();
Julien Bonjean's avatar
Julien Bonjean committed
105

106
    private:
107
        static void context_state_callback(pa_context* c, void* user_data);
108 109 110 111 112 113 114 115 116
        static void context_changed_callback(pa_context* c,
                                             pa_subscription_event_type_t t,
                                             uint32_t idx , void* userdata);
        static void source_input_info_callback(pa_context *c,
                                               const pa_source_info *i,
                                               int eol, void *userdata);
        static void sink_input_info_callback(pa_context *c,
                                             const pa_sink_info *i,
                                             int eol, void *userdata);
Julien Bonjean's avatar
Julien Bonjean committed
117

118 119
        virtual void updatePreference(AudioPreference &pref, int index, PCMType type);

120 121 122 123
        virtual int getIndexCapture() const;
        virtual int getIndexPlayback() const;
        virtual int getIndexRingtone() const;

124
        NON_COPYABLE(PulseLayer);
Julien Bonjean's avatar
Julien Bonjean committed
125 126 127 128 129

        /**
         * Create the audio streams into the given context
         * @param c	The pulseaudio context
         */
130
        void createStreams(pa_context* c);
Julien Bonjean's avatar
Julien Bonjean committed
131 132 133 134

        /**
         * Close the connection with the local pulseaudio server
         */
135
        void disconnectAudioStream();
Julien Bonjean's avatar
Julien Bonjean committed
136 137 138 139

        /**
         * A stream object to handle the pulseaudio playback stream
         */
140
        AudioStream* playback_;
Julien Bonjean's avatar
Julien Bonjean committed
141 142 143 144

        /**
         * A stream object to handle the pulseaudio capture stream
         */
145
        AudioStream* record_;
Julien Bonjean's avatar
Julien Bonjean committed
146 147 148 149

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

152
        /**
153
         * Contains the list of playback devices
154
         */
155
        std::vector<PaDeviceInfos> sinkList_;
156 157

        /**
158
         * Contains the list of capture devices
159
         */
160
        std::vector<PaDeviceInfos> sourceList_;
Adrien Béraud's avatar
Adrien Béraud committed
161 162

        /**
163
         * Returns a pointer to the PaEndpointInfos with the given name in sourceList_, or nullptr if not found.
Adrien Béraud's avatar
Adrien Béraud committed
164
         */
165
        const PaDeviceInfos* getDeviceInfos(const std::vector<PaDeviceInfos>&, const std::string& name) const;
166 167 168 169

        /*
         * Buffers used to avoid doing malloc/free in the audio thread
         */
Adrien Béraud's avatar
Adrien Béraud committed
170
        AudioBuffer mic_buffer_;
Julien Bonjean's avatar
Julien Bonjean committed
171

172 173 174
        /** PulseAudio context and asynchronous loop */
        pa_context* context_;
        pa_threaded_mainloop* mainloop_;
175 176 177
        bool enumeratingSinks_;
        bool enumeratingSources_;
        AudioPreference &preference_;
178

Julien Bonjean's avatar
Julien Bonjean committed
179
        friend class AudioLayerTest;
180 181
};

182
#endif // PULSE_LAYER_H_
183