1 /*
2  *  zlib License
3  *  
4  *  (C) 2016 jython234
5  *  
6  *  This software is provided 'as-is', without any express or implied
7  *  warranty.  In no event will the authors be held liable for any damages
8  *  arising from the use of this software.
9  *  
10  *  Permission is granted to anyone to use this software for any purpose,
11  *  including commercial applications, and to alter it and redistribute it
12  *  freely, subject to the following restrictions:
13  *  
14  *  1. The origin of this software must not be misrepresented; you must not
15  *     claim that you wrote the original software. If you use this software
16  *     in a product, an acknowledgment in the product documentation would be
17  *     appreciated but is not required.
18  *  2. Altered source versions must be plainly marked as such, and must not be
19  *     misrepresented as being the original software.
20  *  3. This notice may not be removed or altered from any source distribution.
21 */
22 module blocksound.backend.types;
23 
24 import blocksound.core;
25 
26 debug(blocksound_verbose) {
27     package void notifyLoadLib(string lib) @safe {
28         import std.stdio : writeln;
29         writeln("[BlockSound]: Loaded ", lib);
30     }
31 }
32 
33 version(blocksound_ALBackend) {
34     /// Name of the backend used for blocksound.
35     immutable string BACKEND = "OpenAL";
36 } else {
37     /// Name of the backend used for blocksound.
38     immutable string BACKEND = "None";
39 }
40 
41 /// Used by AudioManager to create a source.
42 Source backend_createSource(Vec3 loc) @system {
43     version(blocksound_ALBackend) {
44         import blocksound.backend.openal : ALSource;
45 
46         Source source = new ALSource();
47         source.location = loc;
48         return source;
49     } else {
50         throw new Exception("No backend avaliable! (Try compiling with version \"blocksound_ALBackend\" enabled)");
51     }
52 }
53 
54 /// Used by AudioManager to create a streaming source.
55 StreamingSource backend_createStreamingSource(Vec3 loc) @system {
56     version(blocksound_ALBackend) {
57         import blocksound.backend.openal : ALStreamingSource;
58 
59         StreamingSource source = new ALStreamingSource();
60         source.location = loc;
61         return source;
62     } else {
63         throw new Exception("No backend avaliable! (Try compiling with version \"blocksound_ALBackend\" enabled)");
64     }
65 }
66 
67 /// Base class for the audio backend.
68 abstract class AudioBackend {
69     
70     abstract void setListenerLocation(in Vec3 loc) @trusted;
71 
72     abstract void setListenerGain(in float gain) @trusted;
73 
74     abstract void cleanup() @trusted;
75 }
76 
77 /// Represents a source that emits audio.
78 abstract class Source {
79     protected Vec3 _location;
80     protected Sound sound;
81 
82     /// The location of the source.
83     @property Vec3 location() @safe nothrow { return _location; }
84     /// The location of the source.
85     @property void location(Vec3 loc) @safe nothrow {
86         _location = loc;
87     }
88 
89     /++
90         Create a new source. The backend class will automatically be
91         determined.
92 
93         Returns: A new Source instance.
94     +/
95     deprecated("Use AudioManager.createSource()") 
96     static Source newSource(Vec3 location) @system {
97         version(blocksound_ALBackend) {
98             import blocksound.backend.openal : ALSource;
99 
100             Source source = new ALSource();
101             source.location = location;
102             return source;
103         } else {
104             throw new Exception("No backend avaliable! (Try compiling with version \"blocksound_ALBackend\" enabled)");
105         }
106     }
107     
108     /++
109         Set the Sound that this Source plays.
110 
111         Params:
112                 sound =     The Sound that the Source plays.
113     +/
114     final void setSound(Sound sound) @trusted {
115         this.sound = sound;
116         _setSound(sound);
117     }
118 
119     protected abstract void _setSound(Sound sound) @trusted;
120 
121     /++
122         Set if the Source should loop the Sound.
123 
124         Params:
125                 loop =  If the Source should loop it's Sound.
126     +/
127     abstract void setLooping(in bool loop) @trusted;
128 
129     /// Plays the Sound that belongs to this Source.
130     abstract void play() @trusted;
131 
132     /// Pause the Sound that is playing.
133     abstract void pause() @trusted;
134 
135     /// Stops playing the Sound.
136     abstract void stop() @trusted;
137 
138     /++
139         Returns: If the Source has stopped playing it's Sound.
140     +/
141     abstract bool hasFinishedPlaying() @trusted;
142 
143     /// Cleans up the resources used by the Source.
144     final void cleanup() @trusted {
145         sound.cleanup();
146         _cleanup();
147     }
148 
149     abstract protected void _cleanup();
150 }
151 
152 /// Represents a source that emits audio, uses streaming
153 abstract class StreamingSource : Source {
154 
155 }
156 
157 /++
158     Represents a sound, loaded in memory. For
159     larger sounds, consider using streaming instead.
160 
161     TODO: STREAMING
162 +/
163 interface Sound {
164     /// Frees resources used by the sound.
165     void cleanup() @trusted;
166 }
167 
168 /++
169     Represents a sound which is loaded in chunks
170     while playing, to save memory. Use for long/large
171     sounds. 
172 +/
173 interface StreamedSound : Sound {
174     
175 }