1 //**************************************************************************
2 //**
3 //**	##   ##    ##    ##   ##   ####     ####   ###     ###
4 //**	##   ##  ##  ##  ##   ##  ##  ##   ##  ##  ####   ####
5 //**	 ## ##  ##    ##  ## ##  ##    ## ##    ## ## ## ## ##
6 //**	 ## ##  ########  ## ##  ##    ## ##    ## ##  ###  ##
7 //**	  ###   ##    ##   ###    ##  ##   ##  ##  ##       ##
8 //**	   #    ##    ##    #      ####     ####   ##       ##
9 //**
10 //**	$Id: snd_streamplayer.cpp 3866 2008-11-17 18:58:49Z dj_jl $
11 //**
12 //**	Copyright (C) 1999-2006 Jānis Legzdiņš
13 //**
14 //**	This program is free software; you can redistribute it and/or
15 //**  modify it under the terms of the GNU General Public License
16 //**  as published by the Free Software Foundation; either version 2
17 //**  of the License, or (at your option) any later version.
18 //**
19 //**	This program is distributed in the hope that it will be useful,
20 //**  but WITHOUT ANY WARRANTY; without even the implied warranty of
21 //**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 //**  GNU General Public License for more details.
23 //**
24 //**************************************************************************
25 
26 // HEADER FILES ------------------------------------------------------------
27 
28 #include "gamedefs.h"
29 #include "snd_local.h"
30 
31 // MACROS ------------------------------------------------------------------
32 
33 // TYPES -------------------------------------------------------------------
34 
35 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
36 
37 // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
38 
39 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
40 
41 // EXTERNAL DATA DECLARATIONS ----------------------------------------------
42 
43 // PUBLIC DATA DEFINITIONS -------------------------------------------------
44 
45 // PRIVATE DATA DEFINITIONS ------------------------------------------------
46 
47 // CODE --------------------------------------------------------------------
48 
49 //==========================================================================
50 //
51 //	VStreamMusicPlayer::Init
52 //
53 //==========================================================================
54 
Init()55 void VStreamMusicPlayer::Init()
56 {
57 }
58 
59 //==========================================================================
60 //
61 //	VStreamMusicPlayer::Shutdown
62 //
63 //==========================================================================
64 
Shutdown()65 void VStreamMusicPlayer::Shutdown()
66 {
67 	guard(VStreamMusicPlayer::Shutdown);
68 	Stop();
69 	unguard;
70 }
71 
72 //==========================================================================
73 //
74 //	VStreamMusicPlayer::Tick
75 //
76 //==========================================================================
77 
Tick(float)78 void VStreamMusicPlayer::Tick(float)
79 {
80 	guard(VStreamMusicPlayer::Tick);
81 	if (!StrmOpened)
82 		return;
83 	if (Stopping && FinishTime + 1.0 < Sys_Time())
84 	{
85 		//	Finish playback.
86 		Stop();
87 		return;
88 	}
89 	if (Paused)
90 	{
91 		//	Pause playback.
92 		return;
93 	}
94 	for (int Len = SoundDevice->GetStreamAvailable(); Len;
95 		Len = SoundDevice->GetStreamAvailable())
96 	{
97 		short* Data = SoundDevice->GetStreamBuffer();
98 		int StartPos = 0;
99 		while (!Stopping && StartPos < Len)
100 		{
101 			int SamplesDecoded = Codec->Decode(Data + StartPos * 2, Len - StartPos);
102 			StartPos += SamplesDecoded;
103 			if (Codec->Finished())
104 			{
105 				//	Stream ended.
106 				if (CurrLoop)
107 				{
108 					//	Restart stream.
109 					Codec->Restart();
110 				}
111 				else
112 				{
113 					//	We'll wait for 1 second to finish playing.
114 					Stopping = true;
115 					FinishTime = Sys_Time();
116 				}
117 			}
118 			else if (StartPos < Len)
119 			{
120 				//	Should never happen.
121 				GCon->Log("Stream decoded less but is not finished");
122 				Stopping = true;
123 				FinishTime = Sys_Time();
124 			}
125 		}
126 		if (Stopping)
127 		{
128 			memset(Data + StartPos * 2, 0, (Len - StartPos) * 4);
129 		}
130 		SoundDevice->SetStreamData(Data, Len);
131 	}
132 	unguard;
133 }
134 
135 //==========================================================================
136 //
137 //	VStreamMusicPlayer::Play
138 //
139 //==========================================================================
140 
Play(VAudioCodec * InCodec,const char * InName,bool InLoop)141 void VStreamMusicPlayer::Play(VAudioCodec* InCodec, const char* InName,
142 	bool InLoop)
143 {
144 	guard(VStreamMusicPlayer::Play);
145 	StrmOpened = SoundDevice->OpenStream(InCodec->SampleRate,
146 		InCodec->SampleBits, InCodec->NumChannels);
147 	if (!StrmOpened)
148 		return;
149 	Codec = InCodec;
150 	CurrSong = InName;
151 	CurrLoop = InLoop;
152 	Stopping = false;
153 	if (Paused)
154 	{
155 		Resume();
156 	}
157 	unguard;
158 }
159 
160 //==========================================================================
161 //
162 //	VStreamMusicPlayer::Pause
163 //
164 //==========================================================================
165 
Pause()166 void VStreamMusicPlayer::Pause()
167 {
168 	guard(VStreamMusicPlayer::Pause);
169 	if (!StrmOpened)
170 		return;
171 	SoundDevice->PauseStream();
172 	Paused = true;
173 	unguard;
174 }
175 
176 //==========================================================================
177 //
178 //	VStreamMusicPlayer::Resume
179 //
180 //==========================================================================
181 
Resume()182 void VStreamMusicPlayer::Resume()
183 {
184 	guard(VStreamMusicPlayer::Resume);
185 	if (!StrmOpened)
186 		return;
187 	SoundDevice->ResumeStream();
188 	Paused = false;
189 	unguard;
190 }
191 
192 //==========================================================================
193 //
194 //	VStreamMusicPlayer::Stop
195 //
196 //==========================================================================
197 
Stop()198 void VStreamMusicPlayer::Stop()
199 {
200 	guard(VStreamMusicPlayer::Stop);
201 	if (!StrmOpened)
202 		return;
203 	delete Codec;
204 	Codec = NULL;
205 	SoundDevice->CloseStream();
206 	StrmOpened = false;
207 	unguard;
208 }
209 
210 //==========================================================================
211 //
212 //	VStreamMusicPlayer::IsPlaying
213 //
214 //==========================================================================
215 
IsPlaying()216 bool VStreamMusicPlayer::IsPlaying()
217 {
218 	guard(VStreamMusicPlayer::IsPlaying);
219 	if (!StrmOpened)
220 		return false;
221 	return true;
222 	unguard;
223 }
224