examples

Toy examples in single C files.
git clone git://henryandlizzy.uk/examples
Log | Files | Refs

pulse-async-client.cpp (3025B)


      1 #include <pulse/pulseaudio.h>
      2 #include <unistd.h>
      3 
      4 #include <iostream>
      5 #include <vector>
      6 #include <span>
      7 #include <memory>
      8 #include <fstream>
      9 
     10 bool ready = false;
     11 
     12 std::vector<short> sample;
     13 std::vector<short>::const_iterator pos;
     14 
     15 void play_sample(std::span<short> buf)
     16 {
     17 	for (auto& s : buf)
     18 	{
     19 		if (pos != sample.cend())
     20 			s = *pos++;
     21 		else
     22 			s = 0;
     23 	}
     24 }
     25 
     26 void wavegen(std::span<short> buf)
     27 {
     28 	static unsigned i;
     29 	for (auto& s : buf)
     30 	{
     31 		unsigned x;
     32 
     33 		if (i > 100)
     34 			x = 100 - i;
     35 		else
     36 			x = i;
     37 
     38 		x *= 2 * SHRT_MAX / 100;
     39 		s = x - SHRT_MAX;
     40 
     41 		if (++i > 200)
     42 			i = 0;
     43 	}
     44 }
     45 
     46 void pulse_state_cb(pa_context* c, void*)
     47 {
     48 	std::cout << "pulse state = " << pa_context_get_state(c) << '\n';
     49 	if (pa_context_get_state(c) == PA_CONTEXT_READY)
     50 		ready = true;
     51 }
     52 
     53 void write_cb(pa_stream* s, size_t, void*)
     54 {
     55 	void* buf;
     56 	size_t len = -1;
     57 	pa_stream_begin_write(s, &buf, &len);
     58 
     59 	auto v = (short*)buf;
     60 	play_sample({v, len/2});
     61 	pa_stream_write(s, buf, len, nullptr, 0, PA_SEEK_RELATIVE);
     62 }
     63 
     64 void underflow_cb(pa_stream*, void*)
     65 {
     66 	std::cout << __func__ << '\n';
     67 }
     68 
     69 struct mainloop
     70 {
     71 	mainloop(void)
     72 	:	h(pa_mainloop_new(), &pa_mainloop_free)
     73 	{
     74 		assert(h);
     75 	}
     76 
     77 	pa_mainloop_api* get_api(void)
     78 	{
     79 		return pa_mainloop_get_api(h.get());
     80 	}
     81 
     82 	operator pa_mainloop*(void)
     83 	{
     84 		return h.get();
     85 	}
     86 
     87 private:
     88 	std::unique_ptr<pa_mainloop, void(*)(pa_mainloop*)> h;
     89 };
     90 
     91 struct context
     92 {
     93 	context(pa_mainloop_api* api, char const* name)
     94 	:	h(pa_context_new_with_proplist(api, name, nullptr), pa_context_unref)
     95 	{
     96 		assert(h);
     97 	}
     98 
     99 	operator pa_context*(void)
    100 	{
    101 		return h.get();
    102 	}
    103 
    104 private:
    105 	std::unique_ptr<pa_context, void(*)(pa_context*)> h;
    106 };
    107 
    108 int main(void)
    109 {
    110 	{
    111 		std::ifstream file{"res/pluck.mono44100s16le", std::ios::binary | std::ios::ate};
    112 		assert(file);
    113 		auto size = file.tellg();
    114 		sample.resize(size/2);
    115 		file.seekg(0);
    116 		assert(file.read((char*)sample.data(), size));
    117 		pos = sample.cbegin();
    118 	}
    119 
    120 	mainloop mainloop{};
    121 	auto api = mainloop.get_api();
    122 
    123 	context ctx{api, "pulse-test"};
    124 	assert(ctx);
    125 
    126 	pa_context_set_state_callback(ctx, pulse_state_cb, nullptr);
    127 	if (pa_context_connect(ctx, nullptr, PA_CONTEXT_NOAUTOSPAWN, nullptr))
    128 		perror("pa_context_connect");
    129 
    130 	while(not ready)
    131 		pa_mainloop_iterate(mainloop, 0, nullptr);
    132 
    133 	pa_sample_spec ss =
    134 	{
    135 		.format = PA_SAMPLE_S16LE,
    136 		.rate = 44100,
    137 		.channels = 1,
    138 	};
    139 	auto playstream = pa_stream_new(ctx, "playback", &ss, nullptr);
    140 	assert(playstream);
    141 
    142 	pa_stream_set_write_callback(playstream, write_cb, nullptr);
    143 	pa_stream_set_underflow_callback(playstream, underflow_cb, nullptr);
    144 
    145 	pa_buffer_attr bufattr =
    146 	{
    147 		.maxlength = (uint32_t)-1,
    148 		.tlength = (uint32_t)-1,
    149 		.prebuf = (uint32_t)-1,
    150 		.minreq = (uint32_t)-1,
    151 		.fragsize = (uint32_t)-1,
    152 	};
    153 	auto r = pa_stream_connect_playback(playstream, nullptr, &bufattr, PA_STREAM_NOFLAGS /*PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_ADJUST_LATENCY | PA_STREAM_AUTO_TIMING_UPDATE*/, nullptr, nullptr);
    154 	assert(not r);
    155 
    156 	pa_mainloop_run(mainloop, nullptr);
    157 
    158 	pa_context_disconnect(ctx);
    159 
    160 	return 0;
    161 }