source: abuse/tags/pd/imlib/port/aix_orig/gen_drv.c @ 161

Last change on this file since 161 was 49, checked in by Sam Hocevar, 15 years ago
  • Imported original public domain release, for future reference.
  • Property svn:keywords set to Id
File size: 7.5 KB
Line 
1
2#define NUM_CHANNELS 8
3#define STDOUT_FD driver_out_fd
4#define STDIN_FD  driver_in_fd
5
6
7
8#define DOUT_NAME  "/tmp/sfxdrv.signal"
9#define DIN_NAME "/tmp/sfxdrv.command"
10
11
12enum { SFXCMD_QUIT,
13       SFXCMD_REGISTER,
14       SFXCMD_UNREGISTER,
15       SFXCMD_PLAY
16     };
17
18typedef struct sfx_handle_s sfx_handle;
19
20struct sfx_handle_s
21{
22  int          shm_id;
23  void         *shm_data_pointer;
24  sfx_handle   *next; 
25  long         size;
26  int          use_count;
27};
28
29int driver_out_fd,driver_in_fd;
30sfx_handle *sfx_list=NULL;
31
32
33
34#define TOTAL_SIGS 29
35
36int sigs[TOTAL_SIGS]={SIGHUP,SIGINT,SIGQUIT,SIGILL,SIGTRAP,
37                      SIGABRT,SIGIOT,SIGBUS,SIGFPE,SIGKILL,
38                      SIGUSR1,SIGSEGV,SIGUSR2,SIGPIPE,SIGALRM,
39                      SIGTERM,SIGCHLD,SIGCONT,SIGSTOP,
40                      SIGTSTP,SIGTTIN,SIGTTOU,SIGIO,
41                      SIGURG,SIGXCPU,SIGXFSZ,SIGVTALRM,SIGPROF,
42                      SIGWINCH};
43 
44struct channel
45{
46  unsigned char *data;         // next data to be qued
47  long left;                   // how much is left to play? 
48  unsigned char volume;        // indexed into volume table
49  unsigned long add_time;      // time at which the channel started playing
50  sfx_handle *snd;             // pointer to actual sound, so delete can stop us if need be
51} channels[NUM_CHANNELS];
52
53#define uchar unsigned char
54short buf[BUF_SIZE];   // mixing buffer
55
56// add a new sound effect into the channel list, if no free channel
57// oldest gets replaced with new sound
58void play(sfx_handle *snd, unsigned char volume)
59{
60  int i,free_channel=-1;
61  unsigned long oldest_channel=0,
62                oldest_channel_time=10000,
63                newest_channel_time=0;
64
65  for (i=0;i<NUM_CHANNELS;i++)
66  {
67    if (channels[i].data)
68    {
69      int my_time=channels[i].add_time;
70      if (my_time<oldest_channel_time)
71      {
72        oldest_channel=i;
73        oldest_channel_time=my_time;
74      }
75      if (my_time>newest_channel_time)
76        newest_channel_time=my_time;
77    } else free_channel=i;
78  }
79 
80  if (free_channel==-1)
81    free_channel=oldest_channel;
82
83  channels[free_channel].snd=snd;
84  channels[free_channel].add_time=newest_channel_time+1;
85  channels[free_channel].data=(uchar *)snd->shm_data_pointer;
86  channels[free_channel].left=snd->size;
87  channels[free_channel].volume=volume*32/128;
88//  fprintf(stderr, "vol=%d\n", channels[free_channel].volume);
89}
90
91
92int output_sounds()  // return 0 if no sounds to ouput
93{
94  unsigned char *s;
95  int i,j;
96  unsigned char *data;
97 
98  int run_size;
99  memset(buf,0,sizeof buf);
100  for (j=0;j<NUM_CHANNELS;j++)
101  {
102    data = channels[j].data;
103    if (data)
104    {
105      if (channels[j].left<=BUF_SIZE)    // handle imminent channel death
106          {
107        run_size=channels[j].left;
108                channels[j].data = NULL;
109          }
110      else
111          {
112                run_size=BUF_SIZE;
113                channels[j].data += BUF_SIZE;
114          }
115          channels[j].left -= BUF_SIZE;
116     
117      // add the chanels together into an int
118          // reserve the clip and scale to proper 16-bit for the output step
119      for (i=0;i<run_size;i++)
120                buf[i] += ((short)data[i] - 128) * channels[j].volume;
121
122    }
123  }
124
125  output_samples(buf);
126
127  return 1;    // always say we have something, we will do blanks if nothing else
128
129}
130
131
132
133#ifdef __sgi
134void clean_up(...)
135#else
136void clean_up(int why)      // on exit unattach all shared memory links
137#endif
138
139  sfx_handle *last;
140  while (sfx_list)
141  {
142    shmdt((char *)sfx_list->shm_data_pointer);
143    if (shmctl(sfx_list->shm_id,IPC_RMID,NULL)!=0)
144      printf("shmctl failed, why?\n");
145    last=sfx_list;
146    sfx_list=sfx_list->next;
147    free(last);
148  }
149  sound_uninit();
150  unlink(DIN_NAME);
151  unlink(DOUT_NAME);
152}
153
154void die()
155{ clean_up(0);
156  exit(0);
157}
158
159
160static int sound_fd_ready_to_read(int fd)
161{
162  struct timeval tv={0,0};
163  fd_set kbd_set,ex_set;
164  FD_ZERO(&kbd_set);
165  FD_SET(fd,&kbd_set);
166  memcpy((void *)&ex_set,(void *)&kbd_set,sizeof(ex_set));
167  select(FD_SETSIZE,&kbd_set,NULL,&ex_set,&tv);                // check for exception
168  if (FD_ISSET(fd,&ex_set))
169    die();
170  return (FD_ISSET(fd,&kbd_set));
171}
172
173
174void sound_watch()
175{
176
177  sfx_handle *sfx;
178
179  while (1)
180  {
181    while (sound_fd_ready_to_read(STDIN_FD))
182    {
183      uchar cmd;
184                        int rc;
185      if ((rc=read(STDIN_FD,&cmd,1))!=1)
186      { die(); }
187                  fprintf(stderr,"recv'd %d bytes\n", rc);
188      switch (cmd)
189      {
190        case SFXCMD_REGISTER :
191        {
192          int shm_id;
193          long size;
194          uchar return_code;
195          if (read(STDIN_FD,&shm_id,sizeof(shm_id))!=sizeof(shm_id))
196          { fprintf(stderr,"sndrv er1\n"); die(); }
197          if (read(STDIN_FD,&size,sizeof(size))!=sizeof(size))
198          { fprintf(stderr,"sndrv er2\n"); die(); }
199
200          sfx=malloc(sizeof(sfx_handle));
201          sfx->shm_id=shm_id;
202          sfx->shm_data_pointer=shmat(shm_id,NULL,0);
203          if (!sfx->shm_data_pointer)
204          { fprintf(stderr,"Sound driver : unable to attach shared memory segment\n"); die(); }
205          sfx->size=size;
206          sfx->use_count=0;
207          sfx->next=sfx_list;
208          sfx_list=sfx;
209               
210                fprintf(stderr,"registered %d %d\n", shm_id, size);
211
212          cmd=1;
213          if (write(STDOUT_FD,&cmd,sizeof(cmd))!=sizeof(cmd))
214          { fprintf(stderr,"sndrv er3\n"); die(); }
215
216        } break;
217        case SFXCMD_UNREGISTER :
218        {
219          int shm_id,i;
220          sfx_handle *f,*find=NULL,*last_find=NULL;
221          if (read(STDIN_FD,&shm_id,sizeof(shm_id))!=sizeof(shm_id))
222          { die(); }
223          for (f=sfx_list;f && !find;f=f->next)   // see if we can find the shm id in list
224          {
225            if (f->shm_id==shm_id)
226              find=f;
227            last_find=find;         // svae last link so we can remove from the list
228          }
229         
230          if (find)
231          {
232            // see if there are any sound channels playing this sound, if so stop them because
233            // memory is fixing to be deleted
234            for (i=0;i<NUM_CHANNELS;i++)
235            {
236              if (channels[i].snd==find)
237                channels[i].data=NULL;
238            }
239            // now free the memory
240            shmdt((char *)find->shm_data_pointer);          // detach and remove shm
241            if (last_find)
242              last_find->next=find->next;           // unlink from sound list
243            else
244              sfx_list=sfx_list->next;
245          } else { fprintf(stderr,"Attempt to remove unknown sound effect\n"); die(); }
246        } break;
247
248        case SFXCMD_PLAY :
249        {
250          int shm_id,i,volume;
251          sfx_handle *f;
252          if (read(STDIN_FD,&shm_id,sizeof(shm_id))!=sizeof(shm_id))
253            die();
254          if (read(STDIN_FD,&volume,sizeof(volume))!=sizeof(volume))
255            die();
256          for (f=sfx_list;f && f->shm_id!=shm_id;f=f->next);
257          if (f)
258            play(f,volume);
259          else fprintf(stderr,"sound driver : bad id to play\n");
260//              fprintf(stderr, "play %d %d \n", shm_id, volume);
261        } break;
262        default :     // die on unknown or DIE command
263        { die(); }
264      }
265    }
266    output_sounds();
267  }
268}
269
270
271main()
272{
273
274        int i;
275        uchar success;
276/*
277        int chd;
278  chd=fork();
279  if (chd)
280  {
281    printf("%d\n",chd);         // tell parent the sound driver's process number
282    return 0;
283  }
284*/
285        printf("%d\n",getpid());         // tell parent the sound driver's process number
286        fclose(stdout);
287
288  success=sound_init();    // initailize sound and send status to who ever ran us.
289  if (!success)
290  {
291    printf("-1");
292    return 0;
293  }
294
295  unlink(DIN_NAME);
296  unlink(DOUT_NAME);
297
298//  int old_mask=umask(S_IRWXU | S_IRWXG | S_IRWXO);
299  if (mkfifo(DIN_NAME,S_IRWXU | S_IRWXG | S_IRWXO))
300  { perror("Sound driver : unable to make fifo in /tmp");
301    return 0;
302  }
303  chmod(DIN_NAME,S_IRWXU | S_IRWXG | S_IRWXO);
304
305  if (mkfifo(DOUT_NAME,S_IRWXU | S_IRWXG | S_IRWXO))
306  { perror("Sound driver : unable to make fifo in /tmp");
307    return 0;
308  }
309
310  chmod(DOUT_NAME,S_IRWXU | S_IRWXG | S_IRWXO);
311  //umask(old_mask);
312
313  driver_out_fd=open(DOUT_NAME,O_RDWR);
314  if (driver_out_fd<0)
315  { perror(DOUT_NAME);
316    exit(1);
317  }
318
319  driver_in_fd=open(DIN_NAME,O_RDWR);
320  if (driver_in_fd<0)
321  { perror(DIN_NAME);
322    exit(1);
323  }
324
325  for (i=0;i<TOTAL_SIGS;i++)
326    signal(sigs[i],clean_up);
327
328  sound_watch();
329
330  return 0;
331}
332
333
334
Note: See TracBrowser for help on using the repository browser.