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