1 module arsd.audio;
2 
3 import sdl.SDL;
4 import sdl.SDL_mixer;
5 
6 import std.string;
7 
8 import arsd.engine;
9 
10 bool audioIsLoaded; // potential hack material
11 
12 class Sound {
13   public:
14 	this(char[] filename){
15 		if(!audioIsLoaded)
16 			return;
17 		sfx = Mix_LoadWAV(std..string.toStringz(filename));
18 		if(sfx is null)
19 			throw new Exception(immutableString("Sound load " ~ filename));
20 	}
21 
22 	/*
23 	this(Wav wav){
24 		auto w = wav.toMemory;
25 		SDL_RWops* a = SDL_RWFromMem(w, w.length)
26 		if(a is null) throw new Exception("sdl rw ops");
27 		scope(exit) SDL_FreeRW(a);
28 		sfx = Mix_LoadWAV_RW(a, 0);
29 		if(sfx is null) throw new Exception("loadwav rw");
30 	}
31 	*/
32 
33 	~this(){
34 		if(sfx !is null)
35 			Mix_FreeChunk(sfx);
36 	}
37 
38   private:
39 	Mix_Chunk* sfx;
40 }
41 
42 class Music {
43   public:
44 	this(char[] filename){
45 		if(!audioIsLoaded)
46 			return;
47 		mus = Mix_LoadMUS(std..string.toStringz(filename));
48 		if(mus is null)
49 			throw new Exception(immutableString("Music load " ~ filename));
50 	}
51 
52 	~this(){
53 		if(mus !is null)
54 			Mix_FreeMusic(mus);
55 	}
56   private:
57 	Mix_Music* mus;
58 }
59 
60 class Audio{
61   public:
62 	this(bool act = true){
63 		if(audioIsLoaded)
64 			throw new Exception("Cannot load audio twice");
65 
66 		if(!act){
67 			audioIsLoaded = false;
68 			active = false;
69 			return;
70 		}
71 		if(Mix_OpenAudio(22050, AUDIO_S16SYS, 2, 4096/2 /* the /2 is new */) != 0){
72 			active = false; //throw new Error;
73 			error = true;
74 			audioIsLoaded = false;
75 		} else {
76 			active = true;
77 			error = false;
78 			audioIsLoaded = true;
79 		}
80 
81 		sfxChannel = 1;
82 
83 		careAboutErrors = false;
84 	}
85 
86 	void activate(){
87 		if(!audioIsLoaded) return;
88 		if(!error)
89 			active = true;
90 	}
91 
92 	void deactivate(){
93 		if(!audioIsLoaded) return;
94 		active = false;
95 	}
96 
97 	void toggleActivation(){
98 		if(!audioIsLoaded) return;
99 		if(error)
100 			return;
101 		active = !active;
102 	}
103 
104 	~this(){
105 		if(audioIsLoaded){
106 			Mix_HaltMusic();
107 			Mix_HaltChannel(-1);
108 			Mix_CloseAudio();
109 		}
110 	}
111 
112 	void playEffect(Sound snd, bool loop = false){
113 		if(!active || snd is null)
114 			return;
115 
116 		//if(Mix_Playing(sfxChannel))
117 		//	return;
118 
119 		sfxChannel = Mix_PlayChannel(-1, snd.sfx, loop == true ? -1 : 0);
120 
121 	}
122 	void stopEffect(){
123 		if(!active)
124 			return;
125 
126 		Mix_HaltChannel(sfxChannel);
127 	}
128 
129 	void playMusic(Music mus, bool loop = true){
130 		if(!active || mus is null)
131 			return;
132 
133 		if(Mix_PlayMusic(mus.mus, loop == true ? -1 : 0) == -1)
134 			throw new Exception("play music");
135 		//	musicIsPlaying = false;
136 		else
137 			musicIsPlaying = true;
138 	}
139 
140 	void pauseMusic(){
141 		if(!active)
142 			return;
143 
144 		if(musicIsPlaying){
145 			Mix_PauseMusic();
146 			musicIsPaused = true;
147 		}
148 	}
149 
150 	void unpauseMusic(){
151 		if(!active)
152 			return;
153 
154 		if(musicIsPaused){
155 			Mix_ResumeMusic();
156 			musicIsPaused = false;
157 		}
158 	}
159 
160 	void stopMusic(){
161 		if(!active)
162 			return;
163 
164 		Mix_HaltMusic();
165 	}
166 
167 
168 	void stopAll(){
169 		if(!active)
170 			return;
171 
172 		Mix_HaltMusic();
173 		Mix_HaltChannel(-1);
174 	}
175 
176   private:
177   	int sfxChannel;
178 	bool active;
179 	bool error;
180 
181 	bool musicIsPaused;
182 	bool musicIsPlaying;
183 
184 	bool careAboutErrors;
185 }
186 
187 	int Mix_PlayChannel(int channel, Mix_Chunk* chunk, int loops) {
188 		return Mix_PlayChannelTimed(channel,chunk,loops,-1);
189 	}
190 	Mix_Chunk * Mix_LoadWAV(in char *file) {
191 		return Mix_LoadWAV_RW(SDL_RWFromFile(file, "rb"), 1);
192 	}