Crossfire Client, Trunk  R21611
main.c
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2013 Mark Wedel and the Crossfire Development Team
5  * Copyright (c) 1992 Frank Tore Johansen
6  *
7  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
8  * welcome to redistribute it under certain conditions. For details, please
9  * see COPYING and LICENSE.
10  *
11  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
12  */
13 
18 #include "client.h"
19 
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 
24 #include <SDL.h>
25 
26 #include "common.h"
27 #include "version.h"
28 
29 static bool debug = false;
30 
32 static void print_version() {
33  printf("Crossfire Sound Server %s\n", FULL_VERSION);
34 }
35 
37 static void print_quickhelp() {
38  fprintf(stderr, "Type 'cfsndserv -h' for usage.\n");
39 }
40 
42 static void print_usage() {
43  printf(
44  "Usage: cfsndserv [options]\n"
45  "\n"
46  "Options:\n"
47  " -h display this help message\n"
48  " -v display version information\n"
49  );
50 }
51 
79 static int parse_input(char *data, int len) {
80  char* dptr; /* Pointer used when parsing data */
81  char* sound = NULL; /* Points to a sound or music name */
82  char* source = NULL;
83  int soundlen;
84  int spacelen;
85  int type = 0;
86  int dir = 0;
87  int vol = 0;
88  int x = 0;
89  int y = 0;
90  int i = 0;
91 
92  dptr = strtok(data, "\"");
93  /*
94  * Is data a blank line (ending with LF) or is it a quoted, empty string?
95  */
96  if (dptr == NULL) {
97  fprintf(stderr, "Sound/music command does not contain any data.\n");
98  return -1;
99  }
100  /*
101  * If the first character is not a quote character, a sound command is
102  * expected.
103  */
104  if (data[0] != '\"') {
105  /*
106  * There are 5 numeric values expected and required. Technically, if
107  * cfsndserv was new, and the client old, 4 might be present, but the
108  * player does not attempt to support old clients.
109  */
110  i = sscanf(dptr, "%d %d %d %d %d", &x, &y, &dir, &vol, &type);
111 
112  if ((i != 5)
113  || (dir < 0)
114  || (dir > 8)
115  || (vol < 0)
116  || (vol > 100)
117  || (type < 1)) {
118  /*
119  * There is not much point in trying to work with data that does
120  * not fit some basic rules known at the time of development.
121  */
122  fprintf(stderr, "Unrecognized sound command data format.\n");
123  return -1;
124  }
125  }
126  /*
127  * Below this point, when type == 0, a music command is expected, and when
128  * type != 0, a sound command is required.
129  */
130  if (type) {
131  /*
132  * dptr points to the numerics already read, so advance to the string
133  * following the first quote delimiter. A sound source name is
134  * expected.
135  */
136  dptr = strtok(NULL, "\"");
137  if (dptr == NULL) {
138  fprintf(stderr, "Sound command is missing sound/source names.\n");
139  return -1;
140  }
141  source = dptr;
142 
143  /*
144  * Verify there is whitespace between source and sound names.
145  */
146  dptr = strtok(NULL, "\"");
147  if (dptr == NULL) {
148  fprintf(stderr, "Sound command is missing the sound name.\n");
149  return -1;
150  }
151  spacelen = strlen(dptr);
152  for (i = 0; i < spacelen; i++) {
153  if (dptr[i] != ' ' && dptr[i] != '\t') {
154  fprintf(stderr, "Invalid characters after source name.\n");
155  return -1;
156  }
157  }
158  /*
159  * Advance the data pointer to the following sound name.
160  */
161  dptr = strtok(NULL, "\"");
162  if (dptr == NULL) {
163  fprintf(stderr, "Sound command is missing the sound name.\n");
164  return -1;
165  }
166  }
167  /*
168  * Record the sound or music name here (type determines which it is).
169  */
170  sound = dptr;
171  soundlen = strlen(dptr);
172  /*
173  * If there was a trailing quote after the sound or music name, there will
174  * be a null there now, and sound[soundlen] should point to the character
175  * just before another null at data[len-1] (that terminates the command).
176  */
177  i = sound - data + soundlen + 1 + 1;
178  if (i - 1 == len) {
179  fprintf(stderr, "Sound or music name does not end with a quote.\n");
180  return -1;
181  }
182  if (i > len) {
183  fprintf(stderr,
184  "Invalid data after sound/music name (a quoted string needed)\n");
185  return -1;
186  }
187 
188  if (type) {
189  /* Play sound effect. */
190  if (debug) {
191  fprintf(stderr,
192  "Playing sound "
193  "%d,%d dir=%d vol=%d type=%d source=\"%s\" sound=\"%s\"\n",
194  x, y, dir, vol, type, source, sound);
195  }
196  cf_play_sound(x, y, dir, vol, type, sound, source);
197  } else {
198  /* Play music. */
199  if (debug) {
200  fprintf(stderr, "Playing music \"%s\"\n", sound);
201  }
202  cf_play_music(sound);
203  }
204 
205  return 0;
206 }
207 
208 int main(int argc, char *argv[]) {
209  int flag;
210  while ((flag = getopt(argc, argv, "hv")) != -1) {
211  switch (flag) {
212  case 'h':
213  print_usage();
214  exit(EXIT_SUCCESS);
215  break;
216  case 'v':
217  print_version();
218  exit(EXIT_SUCCESS);
219  break;
220  case '?':
221  print_quickhelp();
222  exit(EXIT_FAILURE);
223  break;
224  }
225  }
226 
227  if (g_getenv("CF_SOUND_DEBUG") != NULL) {
228  debug = true;
229  }
230 
231  if (cf_snd_init() != 0) {
232  exit(EXIT_FAILURE);
233  }
234 
235  char inbuf[1024];
236  while (fgets(inbuf, sizeof(inbuf), stdin) != NULL) {
237  parse_input(inbuf, strlen(inbuf));
238  }
239  cf_snd_exit();
240 }
static void print_quickhelp()
Definition: main.c:37
static int parse_input(char *data, int len)
Definition: main.c:79
void cf_play_sound(gint8 x, gint8 y, guint8 dir, guint8 vol, guint8 type, char const sound[static 1], char const source[static 1])
Definition: cfsndserv.c:131
void cf_snd_exit()
Definition: cfsndserv.c:194
int main(int argc, char *argv[])
Definition: main.c:459
static bool debug
Definition: main.c:29
int cf_snd_init()
Definition: cfsndserv.c:80
void cf_play_music(const char *music_name)
Definition: cfsndserv.c:168
static void print_version()
Definition: main.c:32
static void print_usage()
Definition: main.c:42
#define FULL_VERSION
Definition: version.h:1