/* * Copyright (C) 1994 Mark Boyns (boyns@sdsu.edu) and * Mark Scott (mscott@mcd.mot.com) * * FvwmAudio version 1.1 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* ChangeLog * Fixed FvwmAudio to reflect the changes made to the module protocol. * Szijarto Szabolcs provided FvwmSound code that used $HOSTDISPLAY for the rplay host. The code has been added to FvwmAudio. * Fixed bugs reported by beta testers, thanks! * Builtin rplay support has been added to FvwmAudio. This support is enabled when FvwmAudio is compiled with HAVE_RPLAY defined and when FvwmAudioPlayCmd is set to builtin-rplay. I guess it's safe to say that FvwmSound is now obsolete. -- Mark Boyns 5/7/94 * FvwmAudio is based heavily on an Fvwm module "FvwmSound" by Mark Boyns and the real credit for this really goes to him for the concept. I just stripped out the "rplay" library dependencies to allow generic audio play command support. */ /* * This module is based on FvwmModuleDebugger which has the following * copyright: * * This module, and the entire ModuleDebugger program, and the concept for * interfacing this module to the Window Manager, are all original work * by Robert Nation * * Copyright 1994, Robert Nation. No guarantees or warantees or anything * are provided or implied in any way whatsoever. Use this program at your * own risk. Permission to use this program for any purpose is given, * as long as the copyright is kept intact. */ /* * fvwm includes: */ #include #include #include #include #include #include #include #include #include #include "../../configure.h" #include "../../fvwm/module.h" #include "../../version.h" #include "../../libs/fvwmlib.h" /* * rplay includes: */ #ifdef HAVE_RPLAY #include #endif #define BUILTIN_STARTUP MAX_MESSAGES #define BUILTIN_SHUTDOWN MAX_MESSAGES+1 #define BUILTIN_UNKNOWN MAX_MESSAGES+2 #define MAX_BUILTIN 3 #define BUFSIZE 512 /* globals */ char *MyName; int fd_width; int fd[2]; char audio_play_cmd_line[BUFSIZE], audio_play_dir[BUFSIZE]; time_t audio_delay = 0; /* seconds */ #ifdef HAVE_RPLAY int rplay_fd = -1; #endif /* prototypes */ void Loop(int *); void process_message(unsigned long,unsigned long *); void DeadPipe(int); void config(char *); void done(int); int audio_play(short); /* define the message table */ char *messages[MAX_MESSAGES+MAX_BUILTIN] = { "toggle_paging", "new_page", "new_desk", "add_window", "raise_window", "lower_window", "configure_window", "focus_change", "destroy_window", "iconify", "deiconify", "window_name", "icon_name", "res_class", "res_name", "end_windowlist", "icon_location", "map", /* add builtins here */ "startup", "shutdown", "unknown", }; /* define the sound table */ char *sound_table[MAX_MESSAGES+MAX_BUILTIN]; #ifdef HAVE_RPLAY /* define the rplay table */ RPLAY *rplay_table[MAX_MESSAGES+MAX_BUILTIN]; #endif int main(int argc, char **argv) { char *temp, *s; if ((argc != 6)&&(argc != 7)) { fprintf(stderr,"%s Version %s should only be executed by fvwm!\n", MyName, VERSION); exit(1); } /* Save our program name - for error messages */ temp = argv[0]; s=strrchr(argv[0], '/'); if (s != NULL) temp = s + 1; MyName = safemalloc(strlen(temp)+2); strcpy(MyName,"*"); strcat(MyName, temp); /* Dead pipe == Fvwm died */ signal (SIGPIPE, DeadPipe); fd[0] = atoi(argv[1]); fd[1] = atoi(argv[2]); audio_play_dir[0] = '\0'; audio_play_cmd_line[0] = '\0'; /* * Read the sound configuration. */ config(argv[3]); /* * Play the startup sound. */ audio_play(BUILTIN_STARTUP); SendText(fd,"Nop",0); Loop(fd); return 0; } /*********************************************************************** * * Procedure: * config - read the sound configuration file. * ***********************************************************************/ void config(char *config_file) { FILE *fp; char buf[BUFSIZE]; char *message; char *sound; char *p; int i, found; #ifdef HAVE_RPLAY char host[128]; int volume = RPLAY_DEFAULT_VOLUME; int priority = RPLAY_DEFAULT_PRIORITY; #endif fp = fopen(config_file, "r"); if (fp == NULL) { done(1); } /* * Intialize all the sounds. */ for (i = 0; i < MAX_MESSAGES+MAX_BUILTIN; i++) { sound_table[i] = NULL; #ifdef HAVE_RPLAY rplay_table[i] = NULL; #endif } #ifdef HAVE_RPLAY strcpy(host, rplay_default_host()); #endif while (fgets(buf, sizeof(buf), fp)) { buf[strlen(buf)-1] = '\0'; if (buf[0] != '*') { continue; } /* * Search for *FvwmAudio. */ if (mystrncasecmp(buf, MyName, strlen(MyName)) == 0) { p = strtok(buf, " \t"); if (mystrcasecmp(p, "*FvwmAudioPlayCmd") == 0) { p = strtok(NULL, "\n"); /* allow parameters */ if (p && *p) { strcpy(audio_play_cmd_line, p); } } else if (mystrcasecmp(p, "*FvwmAudioDir") == 0) { p = strtok(NULL, " \t"); if (p && *p) { strcpy(audio_play_dir, p); } } else if (mystrcasecmp(p, "*FvwmAudioDelay") == 0) { p = strtok(NULL, " \t"); if (p && *p) { audio_delay = atoi(p); } } #ifdef HAVE_RPLAY /* * Check for rplay configuration options. */ else if (mystrcasecmp(p, "*FvwmAudioRplayHost") == 0) { p = strtok(NULL, " \t"); if (p && *p) { /* * Check for environment variables like $HOSTDISPLAY. */ if (*p == '$') { char *c1, *c2; c2 = host; for (c1 = (char *)getenv(p+1); *c1 && (*c1 != ':'); c1++) { *c2++ = *c1; } *c2 = '\0'; } else { strcpy(host, p); } } } else if (mystrcasecmp(p, "*FvwmAudioRplayVolume") == 0) { p = strtok(NULL, " \t"); if (p && *p) { volume = atoi(p); } } else if (mystrcasecmp(p, "*FvwmAudioRplayPriority") == 0) { p = strtok(NULL, " \t"); if (p && *p) { priority = atoi(p); } } #endif /* * *FvwmAudio */ else { message = strtok(NULL, " \t"); sound = strtok(NULL, " \t"); if (!message || !*message || !sound || !*sound) { continue; } found = 0; for (i = 0; !found && i < MAX_MESSAGES+MAX_BUILTIN; i++) { if (mystrcasecmp(message, messages[i]) == 0) { #ifdef HAVE_RPLAY rplay_table[i] = rplay_create(RPLAY_PLAY); rplay_set(rplay_table[i], RPLAY_APPEND, RPLAY_SOUND, sound, RPLAY_PRIORITY, priority, RPLAY_VOLUME, volume, NULL); #endif sound_table[i]=safemalloc(strlen(sound)+1); strcpy(sound_table[i],sound); found++; } } } } } fclose(fp); #ifdef HAVE_RPLAY /* * Builtin rplay support is enabled when FvwmAudioPlayCmd == builtin-rplay. */ if (mystrcasecmp(audio_play_cmd_line, "builtin-rplay") == 0) { rplay_fd = rplay_open(host); if (rplay_fd < 0) { rplay_perror("rplay_open"); done(1); } } #endif } /*********************************************************************** * * Procedure: * Loop - wait for data to process * ***********************************************************************/ void Loop(int *fd) { unsigned long header[3], *body; char *cbody; int body_length,count,count2=0, total; time_t now, last_time = 0; unsigned long code; while (1) { if ((count = read(fd[1],header,3*sizeof(unsigned long))) > 0) { /* * Ignore messages that occur during the delay * period. */ now = time(0); if (now < (last_time + audio_delay)) { continue; } last_time = now; if(header[0] == START_FLAG) { body_length = header[2]-3; body = (unsigned long *) safemalloc(body_length * sizeof(unsigned long)); cbody = (char *)body; total = 0; while(total < body_length*sizeof(unsigned long)) { if((count2=read(fd[1],&cbody[total], body_length*sizeof(unsigned long)-total)) >0) total += count2; else if(count2 < 0) DeadPipe(0); } /* * code will equal the number of shifts in the * base-2 header[1] number. Could use log here * but this should be fast enough. */ code = -1; while (header[1]) { code++; header[1] >>= 1; } /* * Play the sound. */ if (code >= 0 && code < MAX_MESSAGES) { audio_play(code); } else { audio_play(BUILTIN_UNKNOWN); } free(body); } } if(count <= 0) DeadPipe(1); } } /*********************************************************************** * * Procedure: * SIGPIPE handler - SIGPIPE means fvwm is dying * ***********************************************************************/ void DeadPipe(int nonsense) { done(0); } /*********************************************************************** * * Procedure: * done - common exit point for FvwmAudio. * ***********************************************************************/ void done(int n) { audio_play(BUILTIN_SHUTDOWN); exit(n); } /*********************************************************************** * * Procedure: * * audio_play - actually plays sound from lookup table * **********************************************************************/ int audio_play(short sound) { static char buf[BUFSIZE]; #ifdef HAVE_RPLAY if (rplay_fd != -1) { if (rplay_table[sound]) { if (rplay(rplay_fd, rplay_table[sound]) < 0) { rplay_perror("rplay"); } } return 0; } #endif if (sound_table[sound]) { memset(buf,NULL,BUFSIZE); /* * Don't use audio_play_dir if it's NULL or if the sound file * is an absolute pathname. */ if (audio_play_dir[0] == '\0' || sound_table[sound][0] == '/') { sprintf(buf,"%s %s", audio_play_cmd_line, sound_table[sound]); } else { sprintf(buf,"%s %s/%s", audio_play_cmd_line, audio_play_dir, sound_table[sound]); } return system(buf); } return 1; }