Crossfire Client, Branches  R11627
sound.c
Go to the documentation of this file.
1 const char * const rcsid_gtk_sound_c =
2  "$Id: sound.c 9719 2008-08-04 18:57:47Z ryo_saeba $";
3 
4 /*
5  CrossFire, A Multiplayer game for X-windows
6 
7  Copyright (C) 2001 Mark Wedel & Crossfire Development Team
8  Copyright (C) 1992 Frank Tore Johansen
9 
10  This program is free software; you can redistribute it and/or modify
11  it under the terms of the GNU General Public License as published by
12  the Free Software Foundation; either version 2 of the License, or
13  (at your option) any later version.
14 
15  This program is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  GNU General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with this program; if not, write to the Free Software
22  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 
24  The author can be reached via e-mail to crossfire-devel@real-time.com
25 */
26 
27 
35 #include <config.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <ctype.h>
39 #include <signal.h>
40 #include <errno.h>
41 #include <client-types.h>
42 #include "client.h"
43 
44 
45 /* Got a pipe signal. As of now, only thing we are piped to is the
46  * sound client.
47  */
48 static void signal_pipe(int i) {
49  /* do nothing, but perhaps do something more in the future */
50 }
51 
52 static FILE *sound_pipe = NULL;
54 /* init_sounds open the audio device, and reads any configuration files
55  * that need to be. It returns 0 on success. On failure, the calling
56  * function will likely disable sound support/requests from the server.
57  */
58 
59 #ifndef WIN32
60 int init_sounds(void)
61 {
62  char sound_path[MAX_BUF];
63 
64  /* Easy trick - global nosound is set in the arg processing - if set,
65  * just return -1 - this way, the calling function only needs to check
66  * the value of init_sounds, and not worry about checking nosound.
67  */
68  if (!want_config[CONFIG_SOUND]) return -1;
69 
70  if (sound_server[0] == '\0') {
71  LOG(LOG_ERROR,"init_sounds:", "sound-server variable not set to anything");
72  return -1;
73  }
74  /* if an absolute path is given, we use it unadorned. Otherwise, we
75  * use the path in the BINDIR.
76  */
77  if (sound_server[0] == '/')
78  strcpy(sound_path, sound_server);
79  else
80  sprintf(sound_path, "%s/%s", BINDIR, sound_server);
81 
82  if (access(sound_path, X_OK)<0) {
83  fprintf(stderr,"Unable to access %s sound server process\n", sound_path);
84  return -1;
85  }
86 
87  sound_process=raiseChild(sound_path,CHILD_STDIN|CHILD_STDOUT|CHILD_STDERR);
89 
90  if (fcntl(sound_process->tube[0], F_SETFL, O_NONBLOCK)<0) {
91  /* setting non blocking isn't 100% critical, but a good thing if
92  * we can do it
93  */
94  perror("init_sounds: Warning - unable to set non blocking on sound pipe\n");
95  }
96  sound_pipe=fdopen(sound_process->tube[0],"w");
97  signal(SIGPIPE, signal_pipe);/*perhaps throwing this out :\*/
98  return 0;
99 }
100 #endif
101 
102 
103 /* Plays sound 'soundnum'. soundtype is 0 for normal sounds, 1 for
104  * spell_sounds. This might get extended in the future. x,y are offset
105  * (assumed from player) to play sound. This information is used to
106  * determine value and left vs right speaker balance.
107  *
108  * This procedure seems to be very slow - much slower than I would
109  * expect. Might need to run this is a thread or fork off.
110  */
111 
112 static void play_sound(int soundnum, int soundtype, int x, int y)
113 {
114 #ifndef WIN32
115 
116  if (!use_config[CONFIG_SOUND]) return;
117  if ( (fprintf(sound_pipe,"%4x %4x %4x %4x\n",soundnum,soundtype,x,y)<=0) ||
118  (fflush(sound_pipe)!=0) ){
119  LOG(LOG_ERROR,"gtk::play_sound","couldn't write to sound pipe: %d",errno);
121  fclose(sound_pipe);
122  sound_process=NULL;
123  return;
124  }
125 #endif
126 }
127 
128 
129 #ifndef WIN32
130 void SoundCmd(unsigned char *data, int len)
131 {
132  int x, y, num, type;
133 
134  if (len!=5) {
135  LOG(LOG_WARNING,"gtk::SoundCmd","Got invalid length on sound command: %d", len);
136  return;
137  }
138  x = data[0];
139  y = data[1];
140  num = GetShort_String(data+2);
141  type = data[4];
142 
143 #if 0
144  fprintf(stderr,"Playing sound %d (type %d), offset %d, %x\n",
145  num, type, x ,y);
146 #endif
147  play_sound(num, type, x, y);
148 }
149 #endif
150 
151 void Sound2Cmd(unsigned char *data, int len)
152 {
153  uint8 x, y, dir, volume, type, len_action;
154  char* action = NULL;
155  uint8 len_name;
156  char* name = NULL;
157  /* sound2 <x><y><dir><volume><type><len of action>action<len of name>name */
158  /* b b b b b b str b str*/
159  if (len<8) {
160  LOG(LOG_WARNING,"gtk::Sound2Cmd","Got too short length on sound2 command: %d\n", len);
161  return;
162  }
163  x = data[0];
164  y = data[1];
165  dir = data[2];
166  volume = data[3];
167  type = data[4];
168  len_action = data[5];
169  /* Prevent invald index. */
170  if (len_action >= (len-8)) {
171  LOG(LOG_WARNING, "gtk::Sound2Cmd", "Bad length of \"len of action\" in sound2 command: %d\n", len);
172  return;
173  }
174  if (len_action != 0) {
175  action = (char*)data+6;
176  data[6+len_action]='\0';
177  }
178  /* Lets make it readable, compiler will optimize the addition order anyway*/
179  len_name = data[6+len_action+1];
180  if (len_name >= (len-8-len_action)) {
181  LOG(LOG_WARNING, "gtk::Sound2Cmd", "Bad length of \"len of name\" in sound2 command: %d\n", len);
182  return;
183  }
184  if (len_name != 0) {
185  name = (char*)data+6+len_action+1;
186  data[6+len_action+1+len_name]='\0';
187  }
188  LOG(LOG_WARNING, "gtk::Sound2Cmd", "Playing sound2 x=%hhd y=%hhd dir=%hhd volume=%hhd type=%hhd\n",
189  x, y, dir, volume, type);
190  LOG(LOG_WARNING, "gtk::Sound2Cmd", " len_action=%hhd action=%s\n", len_action, action);
191  LOG(LOG_WARNING, "gtk::Sound2Cmd", " len_name=%hhd name=%s\n", len_name, name);
192  LOG(LOG_WARNING, "gtk::Sound2Cmd", "Please impement sound2!");
193  /* TODO: Play sound here. Can't implement/test as server never actually
194  * sends this yet it seems. As this code is mostly duplicated between the
195  * different clients, make sure to update the other ones too.
196  */
197 }
198 
199 void MusicCmd(const char *data, int len) {
200  if (!strncmp(data, "NONE", len)) {
201  /* TODO stop music */
202  } else {
203  LOG(LOG_WARNING, "gtk::MusicCmd", "music command: %s (Implement me!)\n", data);
204  /* TODO: Play music. Can't impmement/test as server doesn't send this
205  * version of the command yet it seems.
206  */
207  }
208 }
static ChildProcess * sound_process
Definition: sound.c:53
static FILE * sound_pipe
Definition: sound.c:52
short GetShort_String(const unsigned char *data)
Definition: newsocket.c:162
void Sound2Cmd(unsigned char *data, int len)
Definition: sound.c:151
void logChildPipe(ChildProcess *child, LogLevel level, int flag)
Definition: misc.c:290
sint16 want_config[CONFIG_NUMS]
Definition: init.c:50
static void play_sound(int soundnum, int soundtype, int x, int y)
Definition: sound.c:112
void LOG(LogLevel level, const char *origin, const char *format,...)
Definition: misc.c:178
#define CHILD_STDOUT
Definition: client.h:406
sint16 use_config[CONFIG_NUMS]
Definition: init.c:50
const char *const rcsid_gtk_sound_c
Definition: sound.c:1
#define CHILD_STDERR
Definition: client.h:407
char * name
Definition: image.c:61
int init_sounds(void)
Definition: sound.c:60
#define CHILD_STDIN
Definition: client.h:405
static void signal_pipe(int i)
Definition: sound.c:48
ChildProcess * raiseChild(char *name, int flag)
Definition: misc.c:297
#define MAX_BUF
Definition: client-types.h:128
int tube[3]
Definition: client.h:414
char * sound_server
Definition: client.c:62
void MusicCmd(const char *data, int len)
Definition: sound.c:199
unsigned char uint8
Definition: client-types.h:81
#define CONFIG_SOUND
Definition: client.h:164
void SoundCmd(unsigned char *data, int len)
Definition: sound.c:130