Crossfire Client, Branch  R11627
sound.c
Go to the documentation of this file.
00001 const char *rcsid_x11_sound_c =
00002     "$Id: sound.c 9215 2008-06-02 18:31:04Z anmaster $";
00003 /*
00004     Crossfire client, a client program for the crossfire program.
00005 
00006     Copyright (C) 2001 Mark Wedel & Crossfire Development Team
00007 
00008     This program is free software; you can redistribute it and/or modify
00009     it under the terms of the GNU General Public License as published by
00010     the Free Software Foundation; either version 2 of the License, or
00011     (at your option) any later version.
00012 
00013     This program is distributed in the hope that it will be useful,
00014     but WITHOUT ANY WARRANTY; without even the implied warranty of
00015     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016     GNU General Public License for more details.
00017 
00018     You should have received a copy of the GNU General Public License
00019     along with this program; if not, write to the Free Software
00020     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00021 
00022     The author can be reached via e-mail to crossfire-devel@real-time.com
00023 */
00024 
00031 #include <config.h>
00032 #include <stdio.h>
00033 #include <stdlib.h>
00034 #include <ctype.h>
00035 #include <signal.h>
00036 #include <client-types.h>
00037 #include "client.h"
00038 
00039 
00040 int nosound=0;
00041 
00042 /* Got a pipe signal.  As of now, only thing we are piped to is the
00043  * sound client.
00044  */
00045 void signal_pipe(int i) {
00046     /* do nothing, but perhaps do something more in the future */
00047 }
00048 
00049 FILE *sound_pipe;
00050 ChildProcess* sound_process;
00051 
00052 
00053 /* init_sounds open the audio device, and reads any configuration files
00054  * that need to be.  It returns 0 on success.  On failure, the calling
00055  * function will likely disable sound support/requests from the server.
00056  */
00057 
00058 int init_sounds(void)
00059 {
00060     /* Easy trick - global nosound is set in the arg processing - if set,
00061      * just return -1 - this way, the calling function only needs to check
00062      * the value of init_sounds, and not worry about checking nosound.
00063      */
00064     if (!want_config[CONFIG_SOUND]) return -1;
00065 
00066     /*if (sound_process) //kill*/
00067 
00068     sound_process=raiseChild(BINDIR "/cfsndserv",CHILD_STDIN|CHILD_STDOUT|CHILD_STDERR);
00069     logChildPipe(sound_process, LOG_INFO, CHILD_STDOUT|CHILD_STDERR);
00070     sound_pipe=fdopen(sound_process->tube[0],"w");
00071     signal(SIGPIPE, signal_pipe);/*perhaps throwing this out :\*/
00072     return 0;
00073 }
00074 
00075 
00076 
00077 /* Plays sound 'soundnum'.  soundtype is 0 for normal sounds, 1 for
00078  * spell_sounds.  This might get extended in the future.  x,y are offset
00079  * (assumed from player) to play sound.  This information is used to
00080  * determine value and left vs right speaker balance.
00081  *
00082  * This procedure seems to be very slow - much slower than I would
00083  * expect. Might need to run this is a thread or fork off.
00084  */
00085 
00086 static void play_sound(int soundnum, int soundtype, int x, int y)
00087 {
00088     if (nosound) return;
00089 
00090     if (fprintf(sound_pipe,"%4x %4x %4x %4x\n",soundnum,soundtype,x,y)<=0) {
00091         nosound=1;
00092         fclose(sound_pipe);
00093         return;
00094     }
00095     if (fflush(sound_pipe)!=0) {
00096         nosound=1;
00097         fclose(sound_pipe);
00098         return;
00099    }
00100 }
00101 
00102 
00103 void SoundCmd(unsigned char *data,  int len)
00104 {
00105     int x, y, num, type;
00106 
00107     if (len!=5) {
00108         fprintf(stderr,"Got invalid length on sound command: %d\n", len);
00109         return;
00110     }
00111     x = data[0];
00112     y = data[1];
00113     num = GetShort_String(data+2);
00114     type = data[4];
00115 
00116 #if 0
00117     fprintf(stderr,"Playing sound %d (type %d), offset %d, %x\n",
00118             num, type, x ,y);
00119 #endif
00120     play_sound(num, type, x, y);
00121 }
00122 
00123 void Sound2Cmd(unsigned char *data, int len)
00124 {
00125     uint8 x, y, dir, volume, type, len_action;
00126     char* action = NULL;
00127     uint8 len_name;
00128     char* name = NULL;
00129     /* sound2 <x><y><dir><volume><type><len of action>action<len of name>name */
00130     /*         b  b  b    b       b     b             str    b           str*/
00131     if (len<8) {
00132         fprintf(stderr, "Got too short length on sound2 command: %d\n", len);
00133         return;
00134     }
00135     x = data[0];
00136     y = data[1];
00137     dir = data[2];
00138     volume = data[3];
00139     type = data[4];
00140     len_action = data[5];
00141     /* Prevent invald index. */
00142     if (len_action >= (len-8)) {
00143         fprintf(stderr, "Bad length of \"len of action\" in sound2 command: %d\n", len);
00144         return;
00145     }
00146     if (len_action != 0) {
00147         action = (char*)data+6;
00148         data[6+len_action]='\0';
00149     }
00150     /* Lets make it readable, compiler will optimize the addition order anyway*/
00151     len_name = data[6+len_action+1];
00152     if (len_name >= (len-8-len_action)) {
00153         fprintf(stderr, "Bad length of \"len of name\" in sound2 command: %d\n", len);
00154         return;
00155     }
00156     if (len_name != 0) {
00157         name = (char*)data+6+len_action+1;
00158         data[6+len_action+1+len_name]='\0';
00159     }
00160 
00161     fprintf(stderr, "Playing sound2 x=%hhd y=%hhd dir=%hhd volume=%hhd type=%hhd\n",
00162             x, y, dir, volume, type);
00163     fprintf(stderr, "               len_action=%hhd action=%s\n", len_action, action);
00164     fprintf(stderr, "               len_name=%hhd name=%s\n", len_name, name);
00165     fprintf(stderr, "Please impement sound2!");
00166     /* TODO: Play sound here. Can't implement/test as server never actually
00167      * sends this yet it seems. As this code is mostly duplicated between the
00168      * different clients, make sure to update the other ones too.
00169      */
00170 }
00171 
00172 
00173 void MusicCmd(const char *data, int len) {
00174     if (!strncmp(data, "NONE", len)) {
00175         /* TODO stop music */
00176     } else {
00177         fprintf(stderr, "gtk::MusicCmd", "music command: %s (Implement me!)\n", data);
00178         /* TODO: Play music. Can't impmement/test as server doesn't send this
00179          * version of the command yet it seems.
00180          */
00181     }
00182 }