source: abuse/tags/pd/imlib/port/aix/gen_drv.c @ 604

Last change on this file since 604 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: 6.3 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          handle;
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;
31static int sfx_shm_id;
32static void *sfx_shm_addr;
33
34
35#define TOTAL_SIGS 29
36
37int sigs[TOTAL_SIGS]={SIGHUP,SIGINT,SIGQUIT,SIGILL,SIGTRAP,
38                      SIGABRT,SIGIOT,SIGBUS,SIGFPE,SIGKILL,
39                      SIGUSR1,SIGSEGV,SIGUSR2,SIGPIPE,SIGALRM,
40                      SIGTERM,SIGCHLD,SIGCONT,SIGSTOP,
41                      SIGTSTP,SIGTTIN,SIGTTOU,SIGIO,
42                      SIGURG,SIGXCPU,SIGXFSZ,SIGVTALRM,SIGPROF,
43                      SIGWINCH};
44 
45struct channel
46{
47  unsigned char *data;         // next data to be qued
48  long left;                   // how much is left to play? 
49  unsigned char volume;        // indexed into volume table
50  unsigned long add_time;      // time at which the channel started playing
51  sfx_handle *snd;             // pointer to actual sound, so delete can stop us if need be
52} channels[NUM_CHANNELS];
53
54#define uchar unsigned char
55short buf[BUF_SIZE];   // mixing buffer
56
57// add a new sound effect into the channel list, if no free channel
58// oldest gets replaced with new sound
59void play(sfx_handle *snd, unsigned char volume)
60{
61  int i,free_channel=-1;
62  unsigned long oldest_channel=0,
63                oldest_channel_time=10000,
64                newest_channel_time=0;
65
66  for (i=0;i<NUM_CHANNELS;i++)
67  {
68    if (channels[i].data)
69    {
70      int my_time=channels[i].add_time;
71      if (my_time<oldest_channel_time)
72      {
73        oldest_channel=i;
74        oldest_channel_time=my_time;
75      }
76      if (my_time>newest_channel_time)
77        newest_channel_time=my_time;
78    } else free_channel=i;
79  }
80 
81  if (free_channel==-1)
82    free_channel=oldest_channel;
83
84  channels[free_channel].snd=snd;
85  channels[free_channel].add_time=newest_channel_time+1;
86  channels[free_channel].data=(uchar *)snd->shm_data_pointer;
87  channels[free_channel].left=snd->size;
88  channels[free_channel].volume=volume*32/128;
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    last=sfx_list;
143    sfx_list=sfx_list->next;
144    free(last);
145  }
146  sound_uninit();
147  unlink(DIN_NAME);
148  unlink(DOUT_NAME);
149        shmdt(sfx_shm_addr);
150}
151
152void die()
153{ clean_up(0);
154  exit(0);
155}
156
157
158static int sound_fd_ready_to_read(int fd)
159{
160  struct timeval tv={0,0};
161  fd_set kbd_set,ex_set;
162  FD_ZERO(&kbd_set);
163  FD_SET(fd,&kbd_set);
164  memcpy((void *)&ex_set,(void *)&kbd_set,sizeof(ex_set));
165  select(FD_SETSIZE,&kbd_set,NULL,&ex_set,&tv);                // check for exception
166  if (FD_ISSET(fd,&ex_set))
167    die();
168  return (FD_ISSET(fd,&kbd_set));
169}
170
171
172void sound_watch()
173{
174
175  sfx_handle *sfx;
176
177  while (1)
178  {
179    while (sound_fd_ready_to_read(STDIN_FD))
180    {
181      uchar cmd;
182                        int rc;
183      if ((rc=read(STDIN_FD,&cmd,1))!=1)
184      { die(); }
185      switch (cmd)
186      {
187        case SFXCMD_REGISTER :
188        {
189          int handle;
190          long size;
191          uchar return_code;
192          if (read(STDIN_FD,&handle,sizeof(handle))!=sizeof(handle))
193          { fprintf(stderr,"sndrv er1\n"); die(); }
194          if (read(STDIN_FD,&size,sizeof(size))!=sizeof(size))
195          { fprintf(stderr,"sndrv er2\n"); die(); }
196
197          sfx=malloc(sizeof(sfx_handle));
198          sfx->handle=handle;
199          sfx->shm_data_pointer=sfx_shm_addr + handle;
200          sfx->size=size;
201          sfx->use_count=0;
202          sfx->next=sfx_list;
203          sfx_list=sfx;
204
205          cmd=1;
206          if (write(STDOUT_FD,&cmd,sizeof(cmd))!=sizeof(cmd))
207          { fprintf(stderr,"sndrv er3\n"); die(); }
208
209        } break;
210        case SFXCMD_PLAY :
211        {
212          int handle,i,volume;
213          sfx_handle *f;
214          if (read(STDIN_FD,&handle,sizeof(handle))!=sizeof(handle))
215            die();
216          if (read(STDIN_FD,&volume,sizeof(volume))!=sizeof(volume))
217            die();
218          for (f=sfx_list;f && f->handle!=handle;f=f->next);
219          if (f)
220            play(f,volume);
221          else fprintf(stderr,"sound driver : bad id to play\n");
222        } break;
223        default :     // die on unknown or DIE command
224        { die(); }
225      }
226    }
227    output_sounds();
228  }
229}
230
231
232main()
233{
234
235        int i;
236        uchar success;
237/*
238        int chd;
239  chd=fork();
240  if (chd)
241  {
242    printf("%d\n",chd);         // tell parent the sound driver's process number
243    return 0;
244  }
245*/
246        printf("%d\n",getpid());         // tell parent the sound driver's process number
247        fclose(stdout);
248
249  success=sound_init();    // initailize sound and send status to who ever ran us.
250  if (!success)
251  {
252    printf("-1");
253    return 0;
254  }
255
256  unlink(DIN_NAME);
257  unlink(DOUT_NAME);
258
259//  int old_mask=umask(S_IRWXU | S_IRWXG | S_IRWXO);
260  if (mkfifo(DIN_NAME,S_IRWXU | S_IRWXG | S_IRWXO))
261  { perror("Sound driver : unable to make fifo in /tmp");
262    return 0;
263  }
264  chmod(DIN_NAME,S_IRWXU | S_IRWXG | S_IRWXO);
265
266  if (mkfifo(DOUT_NAME,S_IRWXU | S_IRWXG | S_IRWXO))
267  { perror("Sound driver : unable to make fifo in /tmp");
268    return 0;
269  }
270
271  chmod(DOUT_NAME,S_IRWXU | S_IRWXG | S_IRWXO);
272  //umask(old_mask);
273
274  driver_out_fd=open(DOUT_NAME,O_RDWR);
275  if (driver_out_fd<0)
276  { perror(DOUT_NAME);
277    exit(1);
278  }
279
280  driver_in_fd=open(DIN_NAME,O_RDWR);
281  if (driver_in_fd<0)
282  { perror(DIN_NAME);
283    exit(1);
284  }
285
286        if (read(STDIN_FD, &sfx_shm_id, sizeof(sfx_shm_id))!=sizeof(sfx_shm_id))
287                die();
288        sfx_shm_addr = shmat(sfx_shm_id, NULL, 0);
289        write(STDOUT_FD, (void*)&main, 1);
290
291  for (i=0;i<TOTAL_SIGS;i++)
292    signal(sigs[i],clean_up);
293
294  sound_watch();
295
296  return 0;
297}
298
299
300
Note: See TracBrowser for help on using the repository browser.