1 module speech.audio.portaudio;
2 
3 import speech.audio.exception : AudioException;
4 import deimos.portaudio;
5 
6 shared static this()
7 {
8 	paEnforce(Pa_Initialize());
9 }
10 
11 shared static ~this()
12 {
13 	paEnforce(Pa_Terminate());
14 }
15 
16 class PortaudioException : AudioException
17 {
18 	immutable PaError code;
19 
20 	this(PaError err, string file = __FILE__, uint line = __LINE__, Exception next = null)
21 	{
22 		import std.string : fromStringz;
23 		this.code = err;
24 		super(fromStringz(Pa_GetErrorText(err)).idup, file, line, next);
25 	}
26 }
27 
28 void paEnforce(PaError err, string file = __FILE__, uint line = __LINE__)
29 {
30 	import std.string : fromStringz;
31 	if(err != paNoError)
32 		throw new PortaudioException(err, file, line);
33 }
34 
35 struct Device
36 {
37 	package(speech):
38 	PaDeviceIndex index;
39 	const(PaDeviceInfo)* info;
40 
41 	this(PaDeviceIndex index)
42 	{
43 		this.index = index;
44 		this.info = Pa_GetDeviceInfo(index);
45 	}
46 
47 	public:
48 	string name() @property
49 	{
50 		import std.string : fromStringz;
51 		return fromStringz(info.name).idup;
52 	}
53 
54 	int maxInputChannels() @property
55 	{
56 		return info.maxInputChannels;
57 	}
58 
59 	int maxOutputChannels() @property
60 	{
61 		return info.maxOutputChannels;
62 	}
63 }
64 
65 auto outputDevices()
66 {
67 	import std.algorithm.iteration : filter, map;
68 	import std.range : iota;
69 	return iota(0, Pa_GetDeviceCount()).map!(devIndex => Device(devIndex)).filter!(dev => dev.maxOutputChannels > 0);
70 }
71 
72 Device defaultOutputDevice()
73 {
74 	return Device(Pa_GetDefaultOutputDevice());
75 }
76