Vegastrike 0.5.1 rc1  1.0
Original sources for Vegastrike Evolved
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
soundserver.mac.cpp
Go to the documentation of this file.
1 int GetMaxVolume();
2 void changehome( bool to, bool linuxhome = true );
3 #ifdef __APPLE__
4 #include "lin_time.h"
5 #include <sys/types.h>
6 #include <pwd.h>
7 #include <unistd.h>
8 #include <sys/wait.h>
9 #include <vector>
10 #include <string>
11 
12 #include "inet.h"
13 
14 extern "C" {
15 #include "../fmod.h"
16 }
17 using std::string;
18 using std::vector;
19 void music_finished();
20 bool AllDone = false;
21 void Cleanup( int sockets_to_be_cleaned )
22 {
23  FSOUND_Close();
24  INET_cleanup();
25  if (sockets_to_be_cleaned != -1)
26  INET_close( sockets_to_be_cleaned );
27 }
28 signed char endcallback( FSOUND_STREAM *stream, void *buf, int len, int param )
29 {
30  if (!buf)
31  AllDone = true;
32  return 0;
33 }
34 struct Music
35 {
36  FSOUND_STREAM *m;
37  int channel;
38  Music()
39  {
40  m = NULL;
41  channel = 0;
42  }
43  void Stop()
44  {
45  if (m) FSOUND_Stream_Stop( m );
46  }
47  void Free()
48  {
49  if (m) FSOUND_Stream_Close( m );
50  m = NULL;
51  }
52  bool SimpleLoad( const char *file )
53  {
54  m = FSOUND_Stream_OpenFile( file, FSOUND_NORMAL|FSOUND_MPEGACCURATE, 0 );
55  return m != NULL;
56  }
57  bool Load( const char *file );
58  void Play( float fadeout )
59  {
60  if (!m) return;
61  assert( AllDone == false );
62  FSOUND_Stream_SetEndCallback( m, endcallback, 0 );
63  FSOUND_Stream_SetSynchCallback( m, endcallback, 0 );
64  channel = FSOUND_Stream_Play( FSOUND_FREE, m );
65  SetVolume( 0 );
66  if (fadeout*10 > 1)
67  for (unsigned int i = 0; i < fadeout*10; i++) {
68  SetVolume( i/( (float) fadeout*10 ) );
69  micro_sleep( 100000 );
70  }
71  SetVolume( 1 );
72  }
73  void FadeOut( float fadeout )
74  {
75  if (!m) return;
76  if (fadeout*10 > 1)
77  for (unsigned int i = 0; i < fadeout*10; i++) {
78  SetVolume( 1-( i/( (float) fadeout*10 ) ) );
79  micro_sleep( 100000 );
80  }
81  SetVolume( 0 );
82  }
83 
84  void SetVolume( float vol )
85  {
86  if (m)
87  F_API FSOUND_SetVolume( this->channel, (int) ( vol*GetMaxVolume() ) );
88  }
89 };
90 #endif
91 int fadeout = 0, fadein = 0;
92 float volume = 0, soft_volume = 0;
93 int bits = 0, done = 0;
94 
95 int sende = 1;
96 std::string curmus;
97 bool watch_for_sende( pid_t p )
98 {
99  int status;
100  if ( waitpid( p, &status, WNOHANG ) ) {
101  ++sende;
102  if (sende > 0)
103  music_finished();
104  return true;
105  }
106  return false;
107 }
108 
109 std::string my_getstring( int socket )
110 {
111  std::string str;
112  int arg;
113  do {
114  arg = INET_fgetc( socket );
115  if ( (arg != '\r') && (arg != '\n') && (arg != '\0') )
116  str += (char) arg;
117  } while ( (arg != '\n') && (arg != '\0') );
118  return str;
119 }
120 
121 void ForkedProcess( const char *file, float fade, int fd )
122 {
123  printf( "initing device drivers\n" );
124  if ( !FSOUND_Init( 44100, 64, FSOUND_INIT_GLOBALFOCUS ) ) {
125  printf( "SOUND Error %d\n", FSOUND_GetError() );
126  exit( 1 );
127  }
128  Music mus;
129  mus.Load( file );
130  if (mus.m) {
131  mus.Play( fade );
132 
133  printf( "f0rked playing %s\n", file );
134  while ( !INET_BytesToRead( fd ) )
135  if (AllDone) {
136  printf( "song done\n" );
137  mus.Free();
138  return;
139  }
140  mus.Stop();
141  mus.Free();
142  }
143 }
144 int ForkThenPlay( const char *file, float fade, int mysocket )
145 {
146  printf( "playing %s", file );
147  int filedes[2] = {-1, -1};
148  //socketpair(AF_UNIX,SOCK_STREAM,0,filedes);
149  pipe( filedes );
150  pid_t fark = fork();
151  if (fark) {
152  close( mysocket );
153  printf( "f0rking subprocess\n" );
154  ForkedProcess( file, fade, filedes[0] );
155  Cleanup( filedes[0] );
156  exit( 0 ); //Dun!
157  return -1;
158  }
159  printf( "forking main loop\n" );
160  curmus = file;
161  return filedes[1];
162 }
163 int mysocket = -1;
165 {
166  printf( "send e ratio %d\n", (int) sende );
167  if (sende) {
168  char data = 'e';
169  INET_Write( mysocket, sizeof (char), &data );
170  printf( "\ne\n[SONG DONE]\n" );
171  curmus = "";
172  }
173 }
174 void FinishOlde( int open_file )
175 {
176  if (open_file != -1) {
177  if (INET_Write( open_file, 1, "k" ) > 0)
178  sende--; //kill
179  INET_close( open_file );
180  open_file = -1;
181  }
182 }
183 
184 int main( int argc, char **argv )
185 {
186  int open_file = -1;
187 
188  INET_startup();
189  GetMaxVolume();
190  //load the song
191  for (int i = 0; i < 10 && mysocket == -1; i++) {
192  int port = 4364;
193  if (argc > 1)
194  port = atoi( argv[1] );
195  mysocket = INET_AcceptFrom( port, "localhost" );
196  }
197  if (mysocket == -1)
198  return 1;
199  printf( "\n[CONNECTED]\n" );
200  char ministr[2] = {'\0', '\0'};
201  while (!done) {
202  char arg;
203  string str;
204  if ( INET_BytesToRead( mysocket ) ) {
205  arg = INET_fgetc( mysocket );
206  printf( "%c", arg );
207  switch (arg)
208  {
209  case 'p':
210  case 'P':
211  arg = INET_fgetc( mysocket );
212  str = my_getstring( mysocket );
213  printf( "%s", str.c_str() );
214  if (str != curmus) {
215  FinishOlde( open_file );
216  open_file = ForkThenPlay( str.c_str(), fadeout, mysocket );
217  curmus = str;
218  } else {
219  printf( "\n[%s WITH %d FADEIN AND %d FADEOUT IS ALREADY PLAYING]\n", str.c_str(), fadein, fadeout );
220  }
221  break;
222  case 'i':
223  case 'I':
224  arg = INET_fgetc( mysocket );
225  str = my_getstring( mysocket );
226  printf( "%s", str.c_str() );
227  fadein = atoi( str.c_str() );
228  printf( "\n[SETTING FADEIN TO %d]\n", fadein );
229  break;
230  case 'o':
231  case 'O':
232  arg = INET_fgetc( mysocket );
233  str = my_getstring( mysocket );
234  printf( "%s", str.c_str() );
235  fadeout = atoi( str.c_str() );
236  printf( "\n[SETTING FADEOUT TO %d]\n", fadeout );
237  break;
238  case 'v':
239  case 'V':
240  {
241  int vtype = INET_fgetc( mysocket );
242  str = my_getstring( mysocket );
243  printf( "%s", str.c_str() );
244  switch (vtype)
245  {
246  case 'h':
247  case 'H':
248  volume = (float) atof( str.c_str() );
249  break;
250  case 's':
251  case 'S':
252  soft_volume = (float) atof( str.c_str() );
253  str = my_getstring( mysocket );
254  printf( "%s", str.c_str() );
255  break;
256  }
257  printf( "\n[SETTING VOLUME TO %f]\n", volume*soft_volume );
258  //music.SetVolume(volume);
259  break;
260  }
261  case 's':
262  case 'S':
263  printf( "\n[STOPPING ALL MUSIC]\n" );
264  curmus = "";
265  FinishOlde();
266  break;
267  case 'h':
268  case 'H':
269  //Softvolume not yet supported - ignore it
270  INET_fgetc( mysocket );
271  INET_fgetc( mysocket );
272  break;
273  case 't':
274  case 'T':
275  case '\0':
276  INET_close( mysocket );
277  done = true;
278  printf( "\n[TERMINATING MUSIC SERVER]\n" );
279  break;
280  }
281  }
282  }
283  Cleanup( open_file );
284 
285  return 0;
286 }
287 
288 bool Music::Load( const char *file )
289 {
290  if ( !SimpleLoad( file ) ) {
291  changehome( true, false );
292  SimpleLoad( file );
293  changehome( false );
294  if (m == NULL) {
295  changehome( true, true );
296  SimpleLoad( file );
297  changehome( false );
298  if (m == NULL)
299  return false;
300  }
301  }
302  return true;
303 }
304 
305 void changehome( bool to, bool linuxhome )
306 {
307  static std::vector< std::string >paths;
308  if (to) {
309  char mycurpath[8192];
310  getcwd( mycurpath, 8191 );
311  mycurpath[8191] = '\0';
312  paths.push_back( std::string( mycurpath ) );
313 #ifndef _WIN32
314  if (linuxhome) {
315  struct passwd *pwent;
316  pwent = getpwuid( getuid() );
317  chdir( pwent->pw_dir );
318  }
319 #endif
320  chdir( ".vegastrike" );
321  } else if ( !paths.empty() ) {
322  chdir( paths.back().c_str() );
323  paths.pop_back();
324  }
325 }
326 
328 {
329 #ifdef __APPLE__
330  static int maxVol = FSOUND_GetSFXMasterVolume();
331  return maxVol;
332 
333 #else
334  return 0;
335 #endif
336 }
337