added the class pulse_audio_sink
@@ -0,0 +1,107 @@ | ||
1 | +// pulse_audio.cpp: PulseAudio device | |
2 | + | |
3 | +// Copyright Takeshi Mouri 2008. | |
4 | +// Distributed under the Boost Software License, Version 1.0. | |
5 | +// (See accompanying file LICENSE_1_0.txt or copy at | |
6 | +// http://www.boost.org/LICENSE_1_0.txt) | |
7 | + | |
8 | +// See http://hamigaki.sourceforge.jp/libs/audio for library home page. | |
9 | + | |
10 | +#define HAMIGAKI_AUDIO_SOURCE | |
11 | +#include <hamigaki/audio/pulse_audio.hpp> | |
12 | +#include <boost/iostreams/detail/ios.hpp> | |
13 | +#include <pulse/simple.h> | |
14 | + | |
15 | +namespace | |
16 | +{ | |
17 | + | |
18 | +pa_sample_format_t type_to_format(hamigaki::audio::sample_format_type type) | |
19 | +{ | |
20 | + if (type == hamigaki::audio::uint8) | |
21 | + return PA_SAMPLE_U8; | |
22 | + else if (type == hamigaki::audio::int_le16) | |
23 | + return PA_SAMPLE_S16LE; | |
24 | + else if (type == hamigaki::audio::int_be16) | |
25 | + return PA_SAMPLE_S16BE; | |
26 | + else if (type == hamigaki::audio::float_le32) | |
27 | + return PA_SAMPLE_FLOAT32LE; | |
28 | + else if (type == hamigaki::audio::float_be32) | |
29 | + return PA_SAMPLE_FLOAT32BE; | |
30 | + else | |
31 | + throw BOOST_IOSTREAMS_FAILURE("unsupported PCM format"); | |
32 | +} | |
33 | + | |
34 | +} // namespace | |
35 | + | |
36 | +namespace hamigaki { namespace audio { | |
37 | + | |
38 | +class pulse_audio_sink::impl | |
39 | +{ | |
40 | +public: | |
41 | + impl(const char* app, const char* name, const pcm_format& fmt) | |
42 | + { | |
43 | + pa_sample_spec ss = {}; | |
44 | + ss.format = type_to_format(fmt.type); | |
45 | + ss.rate = fmt.rate; | |
46 | + ss.channels = fmt.channels; | |
47 | + | |
48 | + int error; | |
49 | + handle_ = ::pa_simple_new( | |
50 | + 0, app, PA_STREAM_PLAYBACK, 0, name, &ss, 0, 0, &error); | |
51 | + if (handle_ == 0) | |
52 | + throw BOOST_IOSTREAMS_FAILURE("pa_simple_new() failed"); | |
53 | + } | |
54 | + | |
55 | + ~impl() | |
56 | + { | |
57 | + ::pa_simple_free(handle_); | |
58 | + } | |
59 | + | |
60 | + std::streamsize write(const char* s, std::streamsize n) | |
61 | + { | |
62 | + int error; | |
63 | + if (::pa_simple_write(handle_, s, n, &error) < 0) | |
64 | + throw BOOST_IOSTREAMS_FAILURE("pa_simple_write() failed"); | |
65 | + | |
66 | + return n; | |
67 | + } | |
68 | + | |
69 | + pcm_format format() const | |
70 | + { | |
71 | + return fmt_; | |
72 | + } | |
73 | + | |
74 | + void close() | |
75 | + { | |
76 | + int error; | |
77 | + if (::pa_simple_drain(handle_, &error) < 0) | |
78 | + throw BOOST_IOSTREAMS_FAILURE("pa_simple_write() failed"); | |
79 | + } | |
80 | + | |
81 | +private: | |
82 | + pa_simple* handle_; | |
83 | + pcm_format fmt_; | |
84 | +}; | |
85 | + | |
86 | +pulse_audio_sink::pulse_audio_sink( | |
87 | + const char* app, const char* name, const pcm_format& fmt) | |
88 | + : pimpl_(new impl(app, name, fmt)) | |
89 | +{ | |
90 | +} | |
91 | + | |
92 | +std::streamsize pulse_audio_sink::write(const char* s, std::streamsize n) | |
93 | +{ | |
94 | + return pimpl_->write(s, n); | |
95 | +} | |
96 | + | |
97 | +pcm_format pulse_audio_sink::format() const | |
98 | +{ | |
99 | + return pimpl_->format(); | |
100 | +} | |
101 | + | |
102 | +void pulse_audio_sink::close() | |
103 | +{ | |
104 | + pimpl_->close(); | |
105 | +} | |
106 | + | |
107 | +} } // End namespaces audio, hamigaki. |
@@ -0,0 +1,67 @@ | ||
1 | +// pulse_audio.hpp: PulseAudio device | |
2 | + | |
3 | +// Copyright Takeshi Mouri 2008. | |
4 | +// Distributed under the Boost Software License, Version 1.0. | |
5 | +// (See accompanying file LICENSE_1_0.txt or copy at | |
6 | +// http://www.boost.org/LICENSE_1_0.txt) | |
7 | + | |
8 | +// See http://hamigaki.sourceforge.jp/libs/audio for library home page. | |
9 | + | |
10 | +#ifndef HAMIGAKI_AUDIO_PULSE_AUDIO_HPP | |
11 | +#define HAMIGAKI_AUDIO_PULSE_AUDIO_HPP | |
12 | + | |
13 | +#include <hamigaki/audio/detail/config.hpp> | |
14 | +#include <hamigaki/audio/detail/auto_link/hamigaki_audio.hpp> | |
15 | +#include <hamigaki/audio/pcm_format.hpp> | |
16 | +#include <boost/iostreams/categories.hpp> | |
17 | +#include <boost/shared_ptr.hpp> | |
18 | + | |
19 | +#ifdef BOOST_HAS_ABI_HEADERS | |
20 | + #include BOOST_ABI_PREFIX | |
21 | +#endif | |
22 | + | |
23 | +#ifdef BOOST_MSVC | |
24 | + #pragma warning(push) | |
25 | + #pragma warning(disable : 4251) | |
26 | +#endif | |
27 | + | |
28 | +namespace hamigaki { namespace audio { | |
29 | + | |
30 | +class HAMIGAKI_AUDIO_DECL pulse_audio_sink | |
31 | +{ | |
32 | +public: | |
33 | + typedef char char_type; | |
34 | + | |
35 | + struct category | |
36 | + : boost::iostreams::sink_tag | |
37 | + , boost::iostreams::closable_tag | |
38 | + , boost::iostreams::optimally_buffered_tag | |
39 | + , pcm_format_tag | |
40 | + {}; | |
41 | + | |
42 | + pulse_audio_sink(const char* app, const char* name, const pcm_format& fmt); | |
43 | + std::streamsize write(const char* s, std::streamsize n); | |
44 | + pcm_format format() const; | |
45 | + void close(); | |
46 | + | |
47 | + std::streamsize optimal_buffer_size() const | |
48 | + { | |
49 | + return this->format().optimal_buffer_size(); | |
50 | + } | |
51 | + | |
52 | +private: | |
53 | + class impl; | |
54 | + boost::shared_ptr<impl> pimpl_; | |
55 | +}; | |
56 | + | |
57 | +} } // End namespaces audio, hamigaki. | |
58 | + | |
59 | +#ifdef BOOST_MSVC | |
60 | + #pragma warning(pop) | |
61 | +#endif | |
62 | + | |
63 | +#ifdef BOOST_HAS_ABI_HEADERS | |
64 | + #include BOOST_ABI_SUFFIX | |
65 | +#endif | |
66 | + | |
67 | +#endif // HAMIGAKI_AUDIO_PULSE_AUDIO_HPP |