1 // Copyright (c) <2012> <Leif Asbrink>
2 //
3 // Permission is hereby granted, free of charge, to any person
4 // obtaining a copy of this software and associated documentation
5 // files (the "Software"), to deal in the Software without restriction,
6 // including without limitation the rights to use, copy, modify,
7 // merge, publish, distribute, sublicense, and/or sell copies of
8 // the Software, and to permit persons to whom the Software is
9 // furnished to do so, subject to the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be
12 // included in all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
16 // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
18 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19 // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
21 // OR OTHER DEALINGS IN THE SOFTWARE.
22 
23 
24 #include <unistd.h>
25 #include <fcntl.h>
26 #include <string.h>
27 #include <pthread.h>
28 #include <semaphore.h>
29 #include "globdef.h"
30 #include "uidef.h"
31 #include "sigdef.h"
32 #include "fft1def.h"
33 #include "fft2def.h"
34 #include "fft3def.h"
35 #include "conf.h"
36 #include "lconf.h"
37 #include "screendef.h"
38 #include "sdrdef.h"
39 #include "vernr.h"
40 #include "rusage.h"
41 #include "thrdef.h"
42 #include "hwaredef.h"
43 #include "ldef.h"
44 #include "txdef.h"
45 #include "options.h"
46 #include "keyboard_def.h"
47 #include "padef.h"
48 
49 
50 
51 
52 #define ABOVE_MAX_SPEED 768000
53 #define MAX_COLUMN 80
54 
55 #define DEVFLAG_R 1
56 #define DEVFLAG_W 2
57 #define DEVFLAG_RW 4
58 #if HAVE_OSS == 1
59 char dev_name[sizeof(SND_DEV)+2];
60 #endif
61 int devmodes[3]={O_RDONLY,O_WRONLY,O_RDWR};
62 char *devmode_txt[3]={"RDONLY","WRONLY","RDWR"};
63 #define DEVMODE_RDONLY 0
64 #define DEVMODE_WRONLY 1
65 #define DEVMODE_RDWR 2
66 
67 double round(double x);
68 void thread_test_rxad(void);
69 void thread_test_rxda(void);
70 void thread_test_txda(void);
71 
72 int soundcard_test_block_count[MAX_IOTEST];
73 int soundcard_test_cmd_flag[MAX_IOTEST];
74 pthread_t thread_identifier_soundcard_test[MAX_IOTEST];
75 ROUTINE thread_iotest[MAX_IOTEST]={thread_test_rxad,     //0
76                                    thread_test_rxda,     //1
77                                    thread_test_txda};    //2
78 
79 int dev_flag[MAX_DEVNAMES];
80 int dev_rd_channels[MAX_DEVNAMES];
81 int dev_max_rd_speed[MAX_DEVNAMES];
82 int dev_min_rd_speed[MAX_DEVNAMES];
83 int dev_rd_bytes[MAX_DEVNAMES];
84 int dev_wr_channels[MAX_DEVNAMES];
85 int dev_max_wr_speed[MAX_DEVNAMES];
86 int dev_min_wr_speed[MAX_DEVNAMES];
87 int dev_wr_bytes[MAX_DEVNAMES];
88 char blanks[60];
89 
90 char *wish_anyway="Do you wish to try to use it anyway (Y/N)?";
91 char *rx_logfile_name="soundboard_rx_init.log";
92 char *intrate_string=" interrupt rate: ";
93 int low_speeds[MAX_LOWSPEED]={1,5000,6000,8000,11025,16000,
94                               22050,24000,48000,96000};
95 
96 int zrw; // untested return value for OSS
97 void fix_prio(int no);
98 
99 
100 #if (ALSA_PRESENT == 1)
101 // alsa definitions start
102 
103 #include <alsa/asoundlib.h>
104 #define MAX_ALSADEV 24
105 snd_pcm_t *rx_ad_handle, *rx_da_handle;
106 snd_pcm_t *tx_ad_handle, *tx_da_handle;
107 
108 int  alsa_dev_seq_nmbr;
109 char alsa_dev_soundcard_name [256];
110 char alsa_dev_name [64];
111 char alsa_dev_hw_pcm_name[MAX_ALSADEV];
112 char alsa_dev_plughw_pcm_name[MAX_ALSADEV];
113 
114 unsigned int alsa_dev_min_rate[MAX_ALSADEV];
115 unsigned int alsa_dev_max_rate[MAX_ALSADEV];
116 int  alsa_dev_min_channels;
117 int  alsa_dev_max_channels;
118 int  alsa_dev_min_bytes;
119 int  alsa_dev_max_bytes;
120 
121 
122 
edit_soundcard_name(char * s)123 void edit_soundcard_name(char *s)
124 {
125 int i,j,k,l;
126 // We are called with a string with a high number of blanks in the text.
127 // minimise the blanks and limit total text string length to max 51
128 i=(int)strlen(s);
129 j=0;
130 again:;
131 while(s[j] != ' ')j++;
132 if (j >= i) goto finish;
133 k=j;
134 while(s[k] == ' ')k++;
135 if (k >= i) goto finish;
136 l=k;
137 while(s[l] != ' ' && l < i)
138   {
139   j=j+1;
140   s[j]=s[l];
141   if (j != l)s[l]=' ';
142   l++;
143   }
144 if (l<i) goto again;
145 finish:;
146 j++;
147 if(j>51)j=51;
148 s[j]='\0';
149 }
150 
alsa_get_dev_names(int n)151 int alsa_get_dev_names(int n)
152 {
153 //This routine returns  alsa_dev_hw_pcm_name
154 //               	alsa_dev_plughw_pcm_name
155 //			alsa_dev_soundcard_name
156 //			alsa_dev_name
157 //                      alsa_dev_seq_nmbr
158 //for a valid sequence number n on input.
159 //This routine is not "thread safe"
160 //n  must be positive and less than  MAX_ALSADEV
161 
162 //Returncode is negative if n invalid,
163 //                       if alsa errors
164 //                       if no device found for input sequence number.
165 snd_ctl_t *handle;
166 snd_ctl_card_info_t *info;
167 snd_pcm_info_t *pcminfo;
168 
169 int err, idx, dev, dev_seq_nmbr;
170 char str[128];
171 int retcode;
172 
173 alsa_dev_seq_nmbr=0;
174 sprintf(alsa_dev_hw_pcm_name ," ");
175 sprintf(alsa_dev_plughw_pcm_name," ");
176 sprintf(alsa_dev_soundcard_name," ");
177 sprintf(alsa_dev_name," ");
178 idx=-1;
179 dev_seq_nmbr=0;
180 retcode=-10;
181 if(n < 0 || n >= MAX_ALSADEV)
182   {
183   retcode=-6;
184   goto exit_3;
185   }
186 snd_ctl_card_info_malloc(&info);
187 snd_pcm_info_malloc(&pcminfo);
188 while (1)  // loop trough all cards
189   {
190   err=snd_card_next(&idx);
191   if(err < 0)
192     {
193     SNDLOG"alsa_get_dev_names:snd_card_next error: %s\n", snd_strerror(err));
194     retcode=-5;
195     goto exit_2;
196     }
197   if(idx < 0)  // no more cards available
198     {
199     SNDLOG"alsa_get_dev_pcm_name:end of available card/devices reached\n");
200     retcode=-1;
201     goto exit_2;
202     }
203   sprintf(str, "hw:CARD=%i", idx);
204   SNDLOG"Testing %s\n",str);
205   err=snd_ctl_open( &handle, str, 0);
206   if(err < 0)
207     {
208     SNDLOG"alsa_get_dev_names:snd_ctl_open error: %s\n", snd_strerror(err));
209     retcode=-4;
210     goto exit_2;
211     }
212   err=snd_ctl_card_info(handle, info);
213   if(err < 0)
214     {
215     SNDLOG"alsa_get_dev_names:HW info error: %s\n", snd_strerror(err));
216     retcode=-3;
217     goto exit_1;
218     }
219   dev=-1;
220   while (1)  // loop trough all devices for this card
221     {
222     err=snd_ctl_pcm_next_device(handle, &dev);
223     if(err < 0)
224       {
225       SNDLOG"alsa_get_dev_names:PCM next device error: %s\n", snd_strerror(err));
226       retcode=-2;
227       goto exit_1;
228       }
229     if(dev < 0)      // no more devices available for this card, get next card
230         {
231         snd_ctl_close(handle);
232         break;
233         }
234 // check first if device has  valid  pcminfo,
235 //if not, go to next device without incrementing dev seq nmbr
236       snd_pcm_info_set_device(pcminfo, (unsigned int)dev);
237       snd_pcm_info_set_subdevice(pcminfo, 0);
238       snd_pcm_info_set_stream(pcminfo, SND_PCM_STREAM_CAPTURE);
239       if((err=snd_ctl_pcm_info(handle, pcminfo))<0)
240 	{
241         snd_pcm_info_set_stream(pcminfo, SND_PCM_STREAM_PLAYBACK);
242         if((err=snd_ctl_pcm_info(handle, pcminfo))<0) goto next_device;
243 	}
244 //if valid, check if match with n
245     if(dev_seq_nmbr == n)
246       {
247 // if match with n, get all device name-info and exit loop
248       alsa_dev_seq_nmbr=dev_seq_nmbr;
249       sprintf(alsa_dev_hw_pcm_name ,"hw:%i,%i", idx,dev);
250       sprintf(alsa_dev_plughw_pcm_name,"plughw:%i,%i", idx,dev);
251       snd_pcm_info_set_device(pcminfo, (unsigned int)dev);
252       snd_pcm_info_set_subdevice(pcminfo, 0);
253       snd_pcm_info_set_stream(pcminfo, SND_PCM_STREAM_CAPTURE);
254       err=snd_ctl_pcm_info(handle, pcminfo);
255       if(err==0)
256         {
257         sprintf(alsa_dev_name," %s, %s",snd_ctl_card_info_get_name(info),snd_pcm_info_get_id(pcminfo));
258         }
259       else
260         {
261         snd_pcm_info_set_stream(pcminfo, SND_PCM_STREAM_PLAYBACK);
262         err=snd_ctl_pcm_info(handle, pcminfo);
263         if(err==0)
264           {
265           sprintf(alsa_dev_name," %s, %s",snd_ctl_card_info_get_name(info),snd_pcm_info_get_id(pcminfo));
266           }
267         else
268           {
269           SNDLOG"alsa_get_dev_names:snd_ctl_pcm_info error: %s\n", snd_strerror(err));
270           retcode=-7;
271           goto exit_1;
272           }
273         }
274       sprintf(alsa_dev_soundcard_name," %s",snd_ctl_card_info_get_longname(info));
275       edit_soundcard_name(alsa_dev_soundcard_name);
276       SNDLOG"device found: alsa_dev_plughw_pcm_name=%s \n", alsa_dev_plughw_pcm_name);
277       retcode=0;
278       goto exit_1;
279       }
280 // if no match with n, increment  seq nbr of valid devices
281     dev_seq_nmbr= dev_seq_nmbr+1;
282 //get next device
283     next_device:;
284     }  // end while loop through devices
285   }    // end while loop through cards
286 exit_1:;
287 snd_ctl_close(handle);
288 exit_2:;
289 snd_ctl_card_info_free(info);
290 snd_pcm_info_free (pcminfo);
291 exit_3:;
292 SNDLOG"(alsa_get_dev_pcm_name: n=%i, retcode =%d) \n\n",n,retcode);
293 return retcode;
294 }
295 
296 
alsar_get_dev_pcm_names(int n,void * al_dev_plughw_pcm_name,void * al_dev_hw_pcm_name)297 int  alsar_get_dev_pcm_names (int n,
298                               void *al_dev_plughw_pcm_name,
299                               void *al_dev_hw_pcm_name  )
300 {
301 //Threadsafe version of alsa_get_dev_names
302 //with limited functionality:
303 //This  routine returns only dev_plughw_pcm_name and dev_hw_pcm_name
304 //for a valid sequence number n on input.
305 //n  must be positive and less than  MAX_ALSADEV
306 //Returncode is negative if n invalid,
307 //                       if alsa errors
308 //                       if no device found for input sequence number.
309 snd_ctl_t *handle;
310 snd_ctl_card_info_t *info;
311 snd_pcm_info_t *pcminfo;
312 int err, idx, dev, dev_seq_nmbr;
313 char str[128];
314 int retcode ;
315 retcode=-10;
316 alsa_dev_seq_nmbr=0;
317 sprintf((char *)(al_dev_plughw_pcm_name)," ");
318 sprintf((char *)(al_dev_hw_pcm_name)," ");
319 if(n < 0 || n >= MAX_ALSADEV)
320   {
321   retcode=-6;
322   goto exit_3;
323   }
324 idx=-1;
325 dev_seq_nmbr=0;
326 snd_ctl_card_info_malloc(&info);
327 snd_pcm_info_malloc(&pcminfo);
328 while (1)      // loop through cards
329   {
330   err=snd_card_next(&idx);
331   if(err < 0)
332     {
333     SNDLOG"alsar_get_dev_pcm_name:snd_card_next error: %s\n", snd_strerror(err));
334     retcode=-5;
335     goto exit_2;
336     }
337   if(idx < 0)  // no more cards available
338     {
339     SNDLOG"alsar_get_dev_pcm_name:end of available card/devices reached\n");
340     retcode=-1;
341     goto exit_2;
342     }
343   sprintf(str, "hw:CARD=%i", idx);
344   SNDLOG"Testing %s\n",str);
345   err=snd_ctl_open( &handle, str, 0);
346   if(err < 0)
347     {
348     SNDLOG"alsar_get_dev_pcm_name:snd_ctl_open error: %s\n", snd_strerror(err));
349     retcode=-4;
350     goto exit_2;
351     }
352   err=snd_ctl_card_info(handle, info);
353   if(err < 0)
354     {
355     SNDLOG"alsar_get_dev_pcm_name:HW info error: %s\n", snd_strerror(err));
356     retcode=-3;
357     goto exit_1;
358     }
359   dev=-1;
360   while (1) // loop through all devices for this card
361     {
362     err=snd_ctl_pcm_next_device(handle, &dev);
363     if(err < 0)
364       {
365       SNDLOG"alsar_get_dev_pcm_name:PCM next device error: %s\n", snd_strerror(err));
366       retcode=-2;
367       goto exit_1;
368       }
369     if(dev < 0)   // no more devices available for this card
370       {
371       snd_ctl_close(handle);
372       break;
373       }
374 // check first if device has  valid  pcminfo,
375 //if not, go to next device without incrementing dev seq nmbr
376     snd_pcm_info_set_device(pcminfo, (unsigned int)dev);
377     snd_pcm_info_set_subdevice(pcminfo, 0);
378     snd_pcm_info_set_stream(pcminfo, SND_PCM_STREAM_CAPTURE);
379     err=snd_ctl_pcm_info(handle, pcminfo);
380     if(err<0)
381       {
382       snd_pcm_info_set_stream(pcminfo, SND_PCM_STREAM_PLAYBACK);
383       err=snd_ctl_pcm_info(handle, pcminfo);
384       if(err<0) goto next_device;
385       }
386 
387 //if valid, check if match with n
388     if(dev_seq_nmbr == n)
389       {
390 // if match with n, get  limited device name-info and exit loop
391       alsa_dev_seq_nmbr=dev_seq_nmbr;
392       sprintf((char*)(al_dev_hw_pcm_name) ,"hw:%i,%i", idx,dev);
393       sprintf((char *)(al_dev_plughw_pcm_name),"plughw:%i,%i", idx,dev);
394       SNDLOG"device found: dev_plughw_pcm_name=%s\n",((char *)(al_dev_plughw_pcm_name)));
395       retcode=0;
396       goto exit_1;
397       }
398 // if no match with n, increment  seq nmbr of valid devices
399     dev_seq_nmbr= dev_seq_nmbr+1;
400 // get next_device
401     next_device:;
402     }  // end while loop through devices
403   }    // end while loop through cards
404 exit_1:;
405 snd_ctl_close(handle);
406 exit_2:;
407 snd_ctl_card_info_free(info);
408 snd_pcm_info_free (pcminfo);
409 exit_3:;
410 SNDLOG"(alsar_get_dev_pcm_name: n=%i, retcode =%d) \n\n",n,retcode);
411 return retcode;
412 }
413 
414 
415 
alsa_get_dev_native_capabilities(int n,int mode)416 int  alsa_get_dev_native_capabilities(int n,int mode)
417 {
418 // This single threaded routine returns the native hw capabilities of a given
419 // soundcard/device n, in either capture or playback mode (mode input parameter).
420 // This is done by opening the device with a pcm_name=hw:n,0  and
421 // querying hw_params
422 // Returncode is negative if
423 //                         device does not exist
424 //                         alsa error
425 
426 snd_pcm_t *wk_handle;
427 snd_pcm_hw_params_t *hw_params;
428 unsigned int val;
429 int err, dir;
430 
431 dir=0;
432 alsa_dev_min_rate[n]=0;
433 alsa_dev_max_rate[n]=0;
434 alsa_dev_min_channels=0;
435 alsa_dev_max_channels=0;
436 alsa_dev_min_bytes=0;
437 alsa_dev_max_bytes=0;
438 
439 if((err=alsa_get_dev_names (n)) < 0 ) {
440 SNDLOG"alsa_get_dev_native_capabilities: alsa_get_dev_id failed\n" );
441 return -1;
442 }
443 if((err=snd_pcm_open(&wk_handle, alsa_dev_hw_pcm_name, mode, 0)) < 0) {
444 SNDLOG"alsa_get_dev_native_capabilities: open failed,%s\n",alsa_dev_hw_pcm_name );
445 return -2;
446 }
447 if((err=snd_pcm_hw_params_malloc(&hw_params)) < 0) {
448 SNDLOG"alsa_get_dev_native_capabilities: snd_pcm_hw_params_malloc failed\n" );
449 snd_pcm_close(wk_handle);
450 return -3;
451 }
452 if((err=snd_pcm_hw_params_any(wk_handle, hw_params)) < 0) {
453 SNDLOG"alsa_get_dev_native_capabilities: snd_pcm_hw_params_any failed\n" );
454 snd_pcm_hw_params_free (hw_params);
455 snd_pcm_close(wk_handle);
456 return -4;
457 }
458 // get sampling rate
459 if((err= snd_pcm_hw_params_get_rate_max (hw_params, &val, &dir)) < 0){
460 SNDLOG"alsa_get_dev_native_capabilities: snd_pcm_hw_params_get_rate_max failed\n" );
461 snd_pcm_hw_params_free (hw_params);
462 snd_pcm_close(wk_handle);
463 return -5;
464 }
465 alsa_dev_max_rate[n]=(int)val;
466 
467 if((err= snd_pcm_hw_params_get_rate_min (hw_params, &val, &dir)) < 0) {
468 SNDLOG"alsa_get_dev_native_capabilities: snd_pcm_hw_params_get_rate_min failed\n" );
469 snd_pcm_hw_params_free (hw_params);
470 snd_pcm_close(wk_handle);
471 return -6;
472 }
473 alsa_dev_min_rate[n]=(int)val;
474 
475 // get # channels
476 if((err= snd_pcm_hw_params_get_channels_max(hw_params, &val)) < 0) {
477 SNDLOG"alsa_get_dev_native_capabilities: snd_pcm_hw_params_get_channels_max failed\n" );
478 snd_pcm_hw_params_free (hw_params);
479 snd_pcm_close(wk_handle);
480 return -7;
481 }
482 alsa_dev_max_channels=(int)val;
483 
484 if((err= snd_pcm_hw_params_get_channels_min(hw_params, &val)) < 0){
485 SNDLOG"alsa_get_dev_native_capabilities: snd_pcm_hw_params_get_channels_min failed\n" );
486 snd_pcm_hw_params_free (hw_params);
487 snd_pcm_close(wk_handle);
488 return -8;
489 }
490 alsa_dev_min_channels=(int)val;
491 
492 // get  min # of bytes
493 if((err=snd_pcm_hw_params_test_format (wk_handle, hw_params,SND_PCM_FORMAT_U8)) == 0)
494   {
495   alsa_dev_min_bytes=1;
496   }
497 else
498   {
499   if((err=snd_pcm_hw_params_test_format (wk_handle, hw_params,SND_PCM_FORMAT_S16_LE)) == 0)
500     {
501     alsa_dev_min_bytes=2;
502     }
503   else
504     {
505     if((err=snd_pcm_hw_params_test_format (wk_handle, hw_params,SND_PCM_FORMAT_S32_LE)) == 0)
506       {
507       alsa_dev_min_bytes=4;
508       }
509     else {
510          SNDLOG"alsa_get_dev_native_capabilities: snd_pcm_hw_params_test_format failed\n" );
511          //probably an alsa error, assume 2 bytes
512          alsa_dev_min_bytes=2;
513          }
514     }
515   }
516 // get  max # of bytes
517 if((err=snd_pcm_hw_params_test_format (wk_handle, hw_params,SND_PCM_FORMAT_S32_LE)) == 0)
518   {
519   alsa_dev_max_bytes=4;
520   }
521 else
522   {
523   if((err=snd_pcm_hw_params_test_format (wk_handle, hw_params,SND_PCM_FORMAT_S16_LE)) == 0)
524     {
525     alsa_dev_max_bytes=2;
526     }
527   else
528     {
529     if((err=snd_pcm_hw_params_test_format (wk_handle, hw_params,SND_PCM_FORMAT_U8)) == 0)
530       {
531       alsa_dev_max_bytes=1;
532       }
533     else{
534         SNDLOG"alsa_get_dev_native_capabilities: snd_pcm_hw_params_test_format failed\n" );
535         //probably an alsa error, assume 2 bytes
536         alsa_dev_max_bytes=2;
537         }
538     }
539   }
540 snd_pcm_hw_params_free (hw_params);
541 snd_pcm_close(wk_handle);
542 return 0;
543 }
544 
alsar_get_dev_native_capabilities(int n,int mode,int * al_dev_min_rate,int * al_dev_max_rate,int * al_dev_min_channels,int * al_dev_max_channels,int * al_dev_min_bytes,int * al_dev_max_bytes)545 int  alsar_get_dev_native_capabilities(int n,
546                                  int mode,
547                                  int *al_dev_min_rate,
548                                  int *al_dev_max_rate,
549 				 int *al_dev_min_channels,
550 				 int *al_dev_max_channels,
551                                  int *al_dev_min_bytes,
552                                  int *al_dev_max_bytes
553 					)
554 {
555 // threadsafe version of alsa_get_dev_native_capabilities
556 // This routine returns the native hw capabilities of a given
557 // soundcard/device n, in capture or playback mode (mode input parameter).
558 // This is done by opening the device with a pcm_name=hw:n,0  and
559 // querying hw_params
560 // Returncode is negative if
561 //                         device does not exist
562 //                         alsa error
563 
564 snd_pcm_t *wk_handle;
565 snd_pcm_hw_params_t *hw_params;
566 unsigned int val;
567 int err, dir;
568 char dev_plughw_pcm_name[MAX_ALSADEV];
569 char dev_hw_pcm_name[MAX_ALSADEV];
570 
571 dir=0;
572 
573 *al_dev_min_rate=0;
574 *al_dev_max_rate=0;
575 *al_dev_min_channels=0;
576 *al_dev_max_channels=0;
577 *al_dev_min_bytes=0;
578 *al_dev_max_bytes=0;
579 
580 //check if valid device
581 if (( alsar_get_dev_pcm_names(n,dev_plughw_pcm_name,dev_hw_pcm_name))< 0 )
582 {
583 SNDLOG"alsar_get_dev_native_capabilities: alsar_get_dev_plughw_pcm_name failed\n" );
584 return -1;
585 }
586 if((err=snd_pcm_open(&wk_handle, dev_hw_pcm_name, mode, 0)) < 0) {
587 SNDLOG"alsar_get_dev_native_capabilities: open failed,%s\n",dev_hw_pcm_name );
588 return -2;
589 }
590 if((err=snd_pcm_hw_params_malloc (&hw_params)) < 0) {
591 SNDLOG"alsar_get_dev_native_capabilities: snd_pcm_hw_params_malloc failed\n" );
592 snd_pcm_close(wk_handle);
593 return -3;
594 }
595 if((err=snd_pcm_hw_params_any(wk_handle, hw_params)) < 0) {
596 SNDLOG"alsar_get_dev_native_capabilities: snd_pcm_hw_params_any failed\n" );
597 snd_pcm_hw_params_free (hw_params);
598 snd_pcm_close(wk_handle);
599 return -4;
600 }
601 // get max sampling rate
602 if((err= snd_pcm_hw_params_get_rate_max (hw_params, &val, &dir)) < 0){
603 SNDLOG"alsar_get_dev_native_capabilities: snd_pcm_hw_params_get_rate_max failed\n" );
604 snd_pcm_hw_params_free (hw_params);
605 snd_pcm_close(wk_handle);
606 return -5;
607 }
608 *al_dev_max_rate=(int)val;
609 
610 // get min sampling rate
611 if((err= snd_pcm_hw_params_get_rate_min (hw_params, &val, &dir)) < 0) {
612 SNDLOG"alsar_get_dev_native_capabilities: snd_pcm_hw_params_get_rate_min failed\n" );
613 snd_pcm_hw_params_free (hw_params);
614 snd_pcm_close(wk_handle);
615 return -6;
616 }
617 *al_dev_min_rate=(int)val;
618 
619 // get max # channels
620 if((err= snd_pcm_hw_params_get_channels_max(hw_params, &val)) < 0) {
621 SNDLOG"alsar_get_dev_native_capabilities: snd_pcm_hw_params_get_channels_max failed\n" );
622 snd_pcm_hw_params_free (hw_params);
623 snd_pcm_close(wk_handle);
624 return -4;
625 }
626 *al_dev_max_channels=(int)val;
627 
628 // get min # channels
629 if((err= snd_pcm_hw_params_get_channels_min(hw_params, &val)) < 0){
630 SNDLOG"alsar_get_dev_native_capabilities: snd_pcm_hw_params_get_channels_min failed\n" );
631 snd_pcm_hw_params_free (hw_params);
632 snd_pcm_close(wk_handle);
633 return -8;
634 }
635 *al_dev_min_channels=(int)val;
636 
637 // get  min # of bytes
638 if((err=snd_pcm_hw_params_test_format (wk_handle, hw_params,SND_PCM_FORMAT_U8)) == 0)
639   {
640   *al_dev_min_bytes=1;
641   }
642 else
643   {
644   if((err=snd_pcm_hw_params_test_format (wk_handle, hw_params,SND_PCM_FORMAT_S16_LE)) == 0)
645     {
646     *al_dev_min_bytes=2;
647     }
648   else
649     {
650     if((err=snd_pcm_hw_params_test_format (wk_handle, hw_params,SND_PCM_FORMAT_S32_LE)) == 0)
651       {
652       *al_dev_min_bytes=4;
653       }
654     else {
655          SNDLOG"alsar_get_dev_native_capabilities: snd_pcm_hw_params_test_format failed\n" );
656          //probably an alsa error, assume 2 bytes
657          *al_dev_min_bytes=2;
658          }
659     }
660   }
661 // get  max # of bytes
662 if((err=snd_pcm_hw_params_test_format (wk_handle, hw_params,SND_PCM_FORMAT_S32_LE)) == 0)
663   {
664   *al_dev_max_bytes=4;
665   }
666 else
667   {
668   if((err=snd_pcm_hw_params_test_format (wk_handle, hw_params,SND_PCM_FORMAT_S16_LE)) == 0)
669     {
670     *al_dev_max_bytes=2;
671     }
672   else
673     {
674     if((err=snd_pcm_hw_params_test_format (wk_handle, hw_params,SND_PCM_FORMAT_U8)) == 0)
675       {
676       *al_dev_max_bytes=1;
677       }
678     else{
679         SNDLOG"alsar_get_dev_native_capabilities: snd_pcm_hw_params_test_format failed\n" );
680         //probably an alsa error, assume 2 bytes
681         *al_dev_max_bytes=2;
682         }
683     }
684   }
685 snd_pcm_hw_params_free (hw_params);
686 snd_pcm_close(wk_handle);
687 return 0;
688 }
689 
alsa_get_native_samplerate(int n,int mode,int * line,unsigned int * returned_sampling_rate)690 int alsa_get_native_samplerate (int n,
691                                 int mode,
692                                 int *line,
693                                 unsigned int *returned_sampling_rate)
694 {
695 (void) line;
696 (void) returned_sampling_rate;
697 int err,i,k,id;
698 unsigned int val;
699 char s[80];
700 char dev_hw_pcm_name[MAX_ALSADEV];
701 char dev_plughw_pcm_name[MAX_ALSADEV];
702 unsigned int  native_sampling_rate[MAX_ALSADEV];
703 snd_pcm_t *wk_handle;
704 snd_pcm_hw_params_t *hw_params;
705 // 0 terminated  list
706 static unsigned int standardSampleRates[] = {8000, 9600,
707         11025, 12000, 16000, 22050, 24000, 32000,
708         44100, 48000, 50000,88200, 96000, 119466, 192000,
709         224000, 448000, 0};
710 unsigned int sample_rates[32];
711 unsigned int smin, smax;
712 err=alsar_get_dev_pcm_names(n,dev_plughw_pcm_name,dev_hw_pcm_name);
713 if (err!=0) return -1;
714 err=snd_pcm_hw_params_malloc (&hw_params);
715 if (err!=0) return -2;
716 err=snd_pcm_open(&wk_handle, dev_hw_pcm_name, mode, 0);
717 if (err!=0)
718   {
719   snd_pcm_hw_params_free (hw_params);
720   return -3;
721   }
722 clear_screen();
723 line[0]=2;
724 sprintf(s,"This is a native  ALSA device.");
725 lir_text(1,line[0], s);
726 line[0]+=1;
727 sprintf(s,"Select sampling rate by line number from list:");
728 lir_text(1,line[0], s);
729 line[0]+=2;
730 i=0;
731 smin=alsa_dev_min_rate[n];
732 smax=alsa_dev_max_rate[n];
733 if(smin == smax)
734   {
735   smin=0;
736   }
737 while(standardSampleRates[i] != 0 )
738   {
739   if(smax == standardSampleRates[i])smax=0;
740   if(smin == standardSampleRates[i])smin=0;
741   sample_rates[i]=standardSampleRates[i];
742   i++;
743   }
744 if(smin != 0)
745   {
746   sample_rates[i]=smin;
747   i++;
748   }
749 if(smax > 0)
750   {
751   sample_rates[i]=smax;
752   i++;
753   }
754 sample_rates[i]=0;
755 i=0;
756 k=0;
757 while(sample_rates[i] != 0 )
758    {
759    val=(unsigned int)sample_rates[i];
760    err=snd_pcm_hw_params_any(wk_handle, hw_params);
761    if (err!=0)
762      {
763      snd_pcm_close(wk_handle);
764      snd_pcm_hw_params_free (hw_params);
765      return -4;
766      }
767    err=snd_pcm_hw_params_set_rate(wk_handle,hw_params,val, 0);
768    if(err == 0)
769      {
770      sprintf(s,"%2d -> %6d ",k,val);
771      lir_text(1,line[0],s);
772      native_sampling_rate[k]= val;
773      line[0]++;
774      k++;
775      }
776     i++;
777    }
778 line[0]++;
779 sprintf(s,"Enter line number >");
780 lir_text(1,line[0],s);
781 id=lir_get_integer(21,line[0],2, 0, k-1);
782 *returned_sampling_rate=native_sampling_rate[id];
783 snd_pcm_close(wk_handle);
784 snd_pcm_hw_params_free (hw_params);
785 return 0;
786 }
787 
select_alsadev(int open_mode,int * line)788 int select_alsadev(int open_mode, int *line)
789 {
790 //display available devices for a specific mode  and return sequence number of selected device
791 char s[200];
792 int i, err;
793 line[0]++;
794 sprintf(s,"device soundcard-device-name                                device      sample-rate  channels  bytes");
795 SNDLOG"%s\n",s);
796 lir_text(0,line[0],s);
797 line[0]++;
798 sprintf(s,"seq-no              (soundcard-name)                       pcm-name      min / max   min/max  min/max");
799 SNDLOG"%s\n",s);
800 lir_text(0,line[0],s);
801 line[0]++;
802 sprintf(s,"------ --------------------------------------------------  ----------   -----------  -------  ------- " );
803 SNDLOG"%s\n",s);
804 lir_text(0,line[0],s);
805 line[0]++;
806 for(i=0; i<MAX_ALSADEV; i++)
807   {
808   err=alsa_get_dev_names(i);
809   if(err == -1) goto end_alsa_get_dev_names;
810   if(err == 0)
811     {
812     err=alsa_get_dev_native_capabilities(i, open_mode);
813     if(err == 0)
814       {
815       line[0]++;
816       sprintf(s,"%i", alsa_dev_seq_nmbr);
817       lir_text(2,line[0],s);
818       sprintf(s,"%s", alsa_dev_name);
819       lir_text(6,line[0],s);
820       sprintf(s,"(%s)", alsa_dev_soundcard_name);
821       lir_text(20,line[0]+1,s);
822       sprintf(s,"%s", alsa_dev_plughw_pcm_name);
823       lir_text(59,line[0],s);
824       sprintf(s,"%i/%i", alsa_dev_min_rate[i], alsa_dev_max_rate[i]);
825       lir_text(72,line[0],s);
826       sprintf(s,"%i/%i ", alsa_dev_min_channels, alsa_dev_max_channels);
827       lir_text(86,line[0],s);
828       sprintf(s,"%i/%i ", alsa_dev_min_bytes, alsa_dev_max_bytes);
829       lir_text(96,line[0],s);
830       sprintf(s,"     %i   %s (%s)  %s   %i/%i   %i/%i   %i/%i ",
831              alsa_dev_seq_nmbr, alsa_dev_name, alsa_dev_soundcard_name,
832                          alsa_dev_plughw_pcm_name, alsa_dev_min_rate[i],
833                            alsa_dev_max_rate[i],alsa_dev_min_channels,
834                             alsa_dev_max_channels, alsa_dev_min_bytes,
835                                                    alsa_dev_max_bytes );
836       line[0]+=2;
837       SNDLOG"%s\n",s);
838       }
839     }
840   }
841 end_alsa_get_dev_names:;
842 again:;
843 sprintf(s,"Enter selected device-seq-nmbr >" );
844 SNDLOG"%s\n",s);
845 line[0]=line[0]+2;
846 lir_text(0,line[0],s);
847 i=lir_get_integer(33, line[0], 2, 0,MAX_ALSADEV-1);
848 if(kill_all_flag)return -1;
849 sprintf(s,"User selected  %i",i);
850 SNDLOG"%s\n",s);
851 err=alsa_get_dev_names (i);
852 if(err < 0)
853   {
854   lir_text(37,line[0],"invalid device-seq-nmbr, try again");
855   sprintf(s,"invalid device-seq-nmbr, try again");
856   SNDLOG"%s\n",s);
857   goto again;
858   }
859 err=alsa_get_dev_native_capabilities(i,open_mode);
860 if(err != 0)
861   {
862   lir_text(37,line[0],"incompatible capabilities, try again");
863   sprintf(s,"incompatible capabilities, try again");
864   SNDLOG"%s\n",s);
865   goto again;
866   }
867 lir_text(37,line[0],blanks);
868 line[0]++;
869 return i;
870 }
871 
chk_open_alsa(int no,int bytes,int speed,int channels,int mode)872 int chk_open_alsa(int no, int bytes, int speed, int channels, int mode)
873 {
874 int err;
875 char dev_plughw_pcm_name[MAX_ALSADEV];
876 char dev_hw_pcm_name[MAX_ALSADEV];
877 
878 int al_dev_min_rate;
879 int al_dev_max_rate;
880 int al_dev_min_channels;
881 int al_dev_max_channels;
882 int al_dev_min_bytes;
883 int al_dev_max_bytes;
884 //check if device exists
885 err= alsar_get_dev_pcm_names(no,dev_plughw_pcm_name,dev_hw_pcm_name);
886 if( err < 0 )return -1;
887 //check capabilities of device
888 err=alsar_get_dev_native_capabilities( no,
889                                  mode,
890                                  &al_dev_min_rate,
891                                  &al_dev_max_rate,
892 				 &al_dev_min_channels,
893 				 &al_dev_max_channels,
894                                  &al_dev_min_bytes,
895                                  &al_dev_max_bytes);
896 if( err != 0 )return -2;
897 if( speed < al_dev_min_rate )return -4;
898 if( speed > al_dev_max_rate )return -5;
899 if( channels > al_dev_max_channels )return -7;
900 if( bytes < al_dev_min_bytes )return -8;
901 if( bytes > al_dev_max_bytes )return -9;
902 return 0;
903 }
904 
alsa_errors(int err)905 void alsa_errors(int err)
906 {
907 char s[80];
908 switch (err)
909   {
910   case EIO:
911   lirerr(1169);
912   return;
913 
914   default:
915   sprintf(s,"ALSA error code: %d",err);
916   clear_screen();
917   lir_text(0,0,s);
918   lir_text(0,2,press_any_key);
919   await_keyboard();
920   lirerr(1127);
921   return;
922   }
923 }
924 
925 
926 
alsaread(snd_pcm_t * handle,char * buf,snd_pcm_uframes_t frames)927 int alsaread(snd_pcm_t *handle, char *buf, snd_pcm_uframes_t frames)
928 {
929 int k, err;
930 xx:;
931 err=snd_pcm_readi(handle, buf, frames);
932 if(kill_all_flag)return FALSE;
933 k=0;
934 if((unsigned int)err != frames)
935   {
936   if(err == -EPIPE)   // EPIPE, try recovery
937     {
938     k++;
939     err= snd_pcm_recover(handle, err, 0);
940     if(err < 0)
941       {
942       lirerr(1108); // recovery failed
943       return FALSE;
944       }
945     lir_sleep(3000);
946     if(k < 5)goto xx;
947     return FALSE;
948     }
949   else
950     {
951     if(err < 0)
952       {
953       alsa_errors(-err);
954       return FALSE;
955       }
956     else
957       {
958 // We had a short read. Wait for the device to recover.
959 // Then read remaining bytes.
960       k=err;
961       err=0;
962       while(err == 0)
963         {
964 // Split the wait in 100 ms intervals and check whether ESC has
965 // been pressed. In case the CPU is really busy we could be
966 // waiting here for a very long time.
967         err=snd_pcm_wait(handle, 100);
968         lir_sched_yield();
969         if(kill_all_flag)return FALSE;
970         }
971       if(err > 0)
972         {
973 read_more:;
974         err=snd_pcm_readi(handle, &buf[k], frames-(long unsigned int)k);
975         }
976       if((unsigned int)err != frames-(long unsigned int)k)
977         {
978         if(err == -EPIPE)   // EPIPE, try recovery
979           {
980           err= snd_pcm_recover(handle, err, 0);
981           if(err < 0)lirerr(1108); // recovery failed
982           return FALSE;
983           }
984         else
985           {
986           if(err < 0)
987             {
988             alsa_errors(-err);
989             return FALSE;
990             }
991           else
992             {
993             k+=err;
994             goto read_more;
995             }
996           }
997         }
998       }
999     }
1000   }
1001 return TRUE;
1002 }
1003 
1004 #endif
1005 
lir_tx_adread(char * buf)1006 void lir_tx_adread(char *buf)
1007 {
1008 #if (ALSA_PRESENT == 1)
1009 int err;
1010 char s[40];
1011 #endif
1012 int nread;
1013 #if (ALSA_PRESENT == 1)
1014 if( (ui.use_alsa&NATIVE_ALSA_USED)!=0)
1015   {
1016   err=alsaread(tx_ad_handle, buf, (snd_pcm_uframes_t) snd[TXAD].block_frames);
1017   if(err == FALSE)
1018     {
1019     no_of_tx_overrun_errors++;
1020     sprintf(s,"TX%s%d",overrun_error_msg,no_of_tx_overrun_errors);
1021     wg_error(s,WGERR_TXIN);
1022     }
1023   }
1024 else
1025 #endif
1026   {
1027   nread=read(tx_audio_in, buf, (size_t)snd[TXAD].block_bytes);
1028   if(nread != snd[TXAD].block_bytes)lirerr(1283);
1029   }
1030 }
1031 
thread_rx_adinput(void)1032 void thread_rx_adinput(void)
1033 {
1034 #if RUSAGE_OLD == TRUE
1035 int local_workload_counter;
1036 #endif
1037 double read_start_time,total_reads;
1038 short int *rxin_isho2;
1039 int *rxin_int1, *rxin_int2;
1040 int rxin_local_workload_reset;
1041 #if (ALSA_PRESENT == 1)
1042 int err;
1043 char s[40];
1044 #endif
1045 int i;
1046 int timing_loop_counter,timing_loop_counter_max,initial_skip_flag;
1047 #if OSNUM == OSNUM_LINUX
1048 fix_prio(THREAD_RX_ADINPUT);
1049 clear_thread_times(THREAD_RX_ADINPUT);
1050 #endif
1051 #if RUSAGE_OLD == TRUE
1052 local_workload_counter=workload_counter;
1053 #endif
1054 // Open the hware_command thread in case we are using the WSE units.
1055 if( allow_wse_parport != 0)
1056   {
1057   linrad_thread_create(THREAD_HWARE_COMMAND);
1058   }
1059 if(screen_loop_counter_max==0)screen_loop_counter_max=1;
1060 
1061 if(thread_command_flag[THREAD_SCREEN] != THRFLAG_NOT_ACTIVE)
1062  {
1063   while(thread_status_flag[THREAD_SCREEN]!=THRFLAG_ACTIVE &&
1064         thread_status_flag[THREAD_SCREEN]!=THRFLAG_IDLE &&
1065         thread_status_flag[THREAD_SCREEN]!=THRFLAG_SEM_WAIT)
1066     {
1067     if(thread_command_flag[THREAD_RX_ADINPUT] ==
1068                                            THRFLAG_KILL)goto rx_adin_init_error;
1069     lir_sleep(10000);
1070     }
1071   }
1072 sys_func(THRFLAG_OPEN_RX_SNDIN);
1073 if(kill_all_flag) goto rx_adin_init_error;
1074 if(lir_rxin_status != LIR_OK)goto rx_adin_init_error;
1075 update_extio_rx_freq();
1076 update_extio_rx_gain();
1077 #include "timing_setup.c"
1078 thread_status_flag[THREAD_RX_ADINPUT]=THRFLAG_ACTIVE;
1079 while(!kill_all_flag &&
1080            thread_command_flag[THREAD_RX_ADINPUT] == THRFLAG_ACTIVE)
1081   {
1082 #include "input_speed.c"
1083 #if RUSAGE_OLD == TRUE
1084   if(local_workload_counter != workload_counter)
1085     {
1086     local_workload_counter=workload_counter;
1087     make_thread_times(THREAD_RX_ADINPUT);
1088     }
1089 #endif
1090   if ( (ui.use_alsa&PORTAUDIO_RX_IN) != 0)
1091     {
1092     rxin_isho=(short int*)(&timf1_char[timf1p_pa]);
1093     pa_rx_input();
1094     }
1095   else
1096     {
1097     rxin_isho=(short int*)(&timf1_char[timf1p_pa]);
1098     if(ui.rx_addev_no < 256)
1099       {
1100 #if (ALSA_PRESENT == 1)
1101       if( (ui.use_alsa&NATIVE_ALSA_USED)!=0)
1102         {
1103         err=alsaread(rx_ad_handle,
1104                   (char*)rxin_isho, (snd_pcm_uframes_t)snd[RXAD].block_frames);
1105   if(kill_all_flag) goto rxadin_error_exit;
1106         if(err == FALSE)
1107           {
1108           no_of_rx_overrun_errors++;
1109           sprintf(s,"RX%s%d",overrun_error_msg,no_of_rx_overrun_errors);
1110           wg_error(s,WGERR_RXIN);
1111           }
1112         }
1113       else
1114 #endif
1115         {
1116         zrw=read(rx_audio_in, rxin_isho, (size_t)snd[RXAD].block_bytes);
1117         }
1118       }
1119     else
1120       {
1121       rxin_isho2=(short int*)(&timf1_char[timf1p_pa]);
1122       zrw=read(rx_audio_in, rxin_isho, (size_t)(snd[RXAD].block_bytes>>1));
1123       zrw=read(rx_audio_in2, rxin_isho2, (size_t)(snd[RXAD].block_bytes>>1));
1124       if( (ui.rx_input_mode&DWORD_INPUT) == 0)
1125         {
1126         for(i=snd[RXAD].block_frames-1; i>=0; i--)
1127           {
1128           rxin_isho[4*i  ]=rxin_isho[2*i  ];
1129           rxin_isho[4*i+1]=rxin_isho[2*i+1];
1130           rxin_isho[4*i+2]=rxin_isho2[2*i  ];
1131           rxin_isho[4*i+3]=rxin_isho2[2*i+1];
1132           }
1133         }
1134       else
1135         {
1136         rxin_int1=(int*)rxin_isho;
1137         rxin_int2=(int*)rxin_isho2;
1138         for(i=snd[RXAD].block_frames-1; i>=0; i--)
1139           {
1140           rxin_int1[4*i  ]=rxin_int1[2*i  ];
1141           rxin_int1[4*i+1]=rxin_int1[2*i+1];
1142           rxin_int1[4*i+2]=rxin_int2[2*i  ];
1143           rxin_int1[4*i+3]=rxin_int2[2*i+1];
1144           }
1145         }
1146       }
1147     }
1148   finish_rx_read();
1149   if(kill_all_flag) goto rxadin_error_exit;
1150   }
1151 rxadin_error_exit:;
1152 /*   Maybe needed with OSS in RDWR mode ????
1153 while( rx_audio_out == rx_audio_in ||
1154        tx_audio_out == rx_audio_in)
1155   {
1156   lir_sleep(10000);
1157   }
1158 */
1159 close_rx_sndin();
1160 rx_adin_init_error:;
1161 if( allow_wse_parport != 0)
1162   {
1163   linrad_thread_stop_and_join(THREAD_HWARE_COMMAND);
1164   }
1165 thread_status_flag[THREAD_RX_ADINPUT]=THRFLAG_RETURNED;
1166 while(thread_command_flag[THREAD_RX_ADINPUT] != THRFLAG_NOT_ACTIVE)
1167   {
1168   lir_sleep(1000);
1169   }
1170 }
1171 
thread_test_rxda(void)1172 void thread_test_rxda(void)
1173 {
1174 int i;
1175 genparm[DA_OUTPUT_SPEED]=ui.rx_min_da_speed;
1176 if(genparm[DA_OUTPUT_SPEED] < 8000)genparm[DA_OUTPUT_SPEED]=8000;
1177 rx_daout_bytes=ui.rx_max_da_bytes;
1178 rx_daout_channels=ui.rx_max_da_channels;
1179 snd[RXDA].framesize=rx_daout_bytes*rx_daout_channels;
1180 snd[RXDA].block_frames=(int)((float)genparm[DA_OUTPUT_SPEED]*.025F);
1181 make_power_of_two(&snd[RXDA].block_frames);
1182 snd[RXDA].block_bytes=snd[RXDA].block_frames*snd[RXDA].framesize;
1183 min_delay_time=0.025F;
1184 daout=malloc((size_t)(8*snd[RXDA].block_bytes));
1185 daout_pa=0;
1186 daout_px=0;
1187 for(i=0; i<4*snd[RXDA].block_bytes; i++)
1188   {
1189   daout[daout_pa]=0;
1190   daout_pa++;
1191   }
1192 daout_bufmask=8*snd[RXDA].block_bytes-1;
1193 daout_pa*=2;
1194 open_rx_sndout();
1195 if(kill_all_flag)return;
1196 while(!kill_all_flag &&
1197       soundcard_test_cmd_flag[RXDA] == THRFLAG_ACTIVE)
1198   {
1199 // Write data to the output device.
1200   lir_rx_dawrite();
1201   soundcard_test_block_count[RXDA]++;
1202   }
1203 close_rx_sndout();
1204 free(daout);
1205 }
1206 
thread_test_txda(void)1207 void thread_test_txda(void)
1208 {
1209 char *buf;
1210 int i;
1211 snd[TXDA].framesize=ui.tx_da_bytes*ui.tx_da_channels;
1212 snd[TXDA].block_bytes=(1000+ui.tx_da_speed)*snd[TXDA].framesize/1000;
1213 make_power_of_two((int*)&snd[TXDA].block_bytes);
1214 open_tx_sndout();
1215 if(kill_all_flag)return;
1216 buf=malloc((size_t)snd[TXDA].block_bytes);
1217 if(buf == NULL)
1218   {
1219   lirerr(1245231);
1220   return;
1221   }
1222 for(i=0; i<snd[TXDA].block_bytes; i++)
1223   {
1224   buf[i]=0;
1225   }
1226 while(!kill_all_flag &&
1227       soundcard_test_cmd_flag[TXDA] == THRFLAG_ACTIVE)
1228   {
1229 // Write data to the output device.
1230   lir_tx_dawrite(buf);
1231   soundcard_test_block_count[TXDA]++;
1232   }
1233 close_tx_sndout();
1234 free(buf);
1235 }
1236 
thread_test_rxad(void)1237 void thread_test_rxad(void)
1238 {
1239 char *buf;
1240 #if (ALSA_PRESENT == 1)
1241 int err;
1242 #endif
1243 snd[RXAD].block_frames=ui.rx_ad_speed/50;
1244 make_power_of_two((int*)(&snd[RXAD].block_frames));
1245 snd[RXAD].interrupt_rate=(float)(ui.rx_ad_speed)/(float)snd[RXAD].block_frames;
1246 snd[RXAD].framesize=2*ui.rx_ad_channels;
1247 if( (ui.rx_input_mode&DWORD_INPUT) != 0) snd[RXAD].framesize*=2;
1248 snd[RXAD].block_bytes=snd[RXAD].framesize*snd[RXAD].block_frames;
1249 timf1_bytes=8*snd[RXAD].block_bytes;
1250 timf1_bytemask=timf1_bytes-1;
1251 timf1_char=malloc((size_t)timf1_bytes);
1252 if(timf1_char==NULL)
1253   {
1254   lirerr(23658);
1255   return;
1256   }
1257 timf1p_sdr=0;
1258 timf1p_pa=0;
1259 open_rx_sndin(FALSE);
1260 if(kill_all_flag)
1261   {
1262   free(timf1_char);
1263   return;
1264   }
1265 buf=malloc((size_t)snd[RXAD].block_bytes);
1266 if(buf == NULL)
1267   {
1268   lirerr(1233231);
1269   free(timf1_char);
1270   return;
1271   }
1272 while(!kill_all_flag && soundcard_test_cmd_flag[RXAD] == THRFLAG_ACTIVE)
1273   {
1274   if ( (ui.use_alsa&PORTAUDIO_RX_IN) != 0)
1275     {
1276     timf1p_pa=(timf1p_pa+snd[RXAD].block_bytes)&timf1_bytemask;
1277     pa_rx_input();
1278     }
1279   else
1280     {
1281     if(ui.rx_addev_no < 256)
1282       {
1283 #if (ALSA_PRESENT == 1)
1284       if( (ui.use_alsa&NATIVE_ALSA_USED)!=0)
1285         {
1286         err=alsaread(rx_ad_handle, buf,
1287                                   (snd_pcm_uframes_t)snd[RXAD].block_frames);
1288         if(err != TRUE)
1289           {
1290           lir_text(0,screen_last_line-1,"ERROR");
1291           }
1292         }
1293       else
1294 #endif
1295         {
1296         zrw=read(rx_audio_in, buf, (size_t)snd[RXAD].block_bytes);
1297         }
1298       }
1299     else
1300       {
1301       zrw=read(rx_audio_in, buf, (size_t)(snd[RXAD].block_bytes>>1));
1302       zrw=read(rx_audio_in2, buf, (size_t)(snd[RXAD].block_bytes>>1));
1303       }
1304     }
1305   soundcard_test_block_count[RXAD]++;
1306   }
1307 //*********************ööööööööööööö*********************
1308 //this may be needed in RDWR mode with OSS.
1309 //while( !kill_all_flag &&
1310 //       (rx_audio_out == rx_audio_in ||
1311 //        tx_audio_out == rx_audio_in))lir_sleep(10000);
1312 
1313 close_rx_sndin();
1314 free(timf1_char);
1315 free(buf);
1316 }
1317 
lir_tx_output_samples(void)1318 int lir_tx_output_samples(void)
1319 {
1320 #if (ALSA_PRESENT == 1)
1321 int err;
1322 char s[40];
1323 snd_pcm_sframes_t frame_avail;
1324 if( (ui.use_alsa&NATIVE_ALSA_USED)!=0)
1325   {
1326 //Try to synchronize stream position with hardware
1327   err=snd_pcm_hwsync(tx_da_handle);
1328   if(err != 0)
1329     {
1330     if(err == -EPIPE)       // underrun, try to recover
1331       {
1332       no_of_tx_underrun_errors++;
1333       sprintf(s,"TX%s%d",underrun_error_msg,no_of_tx_underrun_errors);
1334       wg_error(s,WGERR_TXOUT);
1335       snd_pcm_prepare(tx_da_handle);
1336       err=snd_pcm_hwsync(tx_da_handle);
1337       if(err < 0)
1338         {
1339 //      lirerr(872315);  // accept error, we have to live with less accurate data in frame_avail
1340         }
1341       }
1342     else
1343       {
1344 //    lirerr(872316);  // accept error, we have to live with less accurate data in frame_avail
1345       }
1346     }
1347   frame_avail= snd_pcm_avail_update(tx_da_handle);
1348   if(frame_avail < 0)
1349           {
1350 //          lirerr(872317);
1351           return 0;
1352           }
1353   return (int)(snd[TXDA].tot_frames-frame_avail);
1354   }
1355 else
1356 #endif
1357   {
1358 #if HAVE_OSS == 1
1359   if(ioctl(tx_audio_out,SNDCTL_DSP_GETOSPACE, &tx_da_info) == -1)
1360                                                           lirerr(872313);
1361 return snd[TXDA].tot_frames-tx_da_info.bytes/snd[TXDA].framesize;
1362 #endif
1363   }
1364 return 0;
1365 }
1366 
lir_tx_input_samples(void)1367 int lir_tx_input_samples(void)
1368 {
1369 #if (ALSA_PRESENT == 1)
1370 int err;
1371 char s[40];
1372 snd_pcm_sframes_t frame_avail;
1373 if( (ui.use_alsa&NATIVE_ALSA_USED)!=0)
1374   {
1375 //Synchronize stream position with hardware
1376   err=snd_pcm_hwsync(tx_ad_handle);
1377     {
1378     if(err == -EPIPE)       // underrun, try to recover
1379       {
1380       no_of_tx_overrun_errors++;
1381       sprintf(s,"TX%s%d",overrun_error_msg,no_of_tx_overrun_errors);
1382       wg_error(s,WGERR_TXIN);
1383       snd_pcm_prepare(tx_ad_handle);
1384       err=snd_pcm_hwsync(tx_ad_handle);
1385       if(err < 0)
1386         {
1387 //        lirerr(872318);   // recovery failed, we have to live with less accurate data in frame_avail
1388         }
1389       }
1390     else
1391       {
1392 //      lirerr(872319);     // snd_pcm_hwsync failed with unknown error, we have to live with less accurate data in frame_avail
1393       }
1394     }
1395 frame_avail= snd_pcm_avail_update(tx_ad_handle);
1396 if(frame_avail < 0)
1397           {
1398 //          lirerr(872314); //accept a lesser optimal solution
1399           return 0;
1400           }
1401 
1402 return (int)frame_avail;
1403 
1404   }
1405 else
1406 #endif
1407   {
1408 #if HAVE_OSS == 1
1409   if(ioctl(tx_audio_in,SNDCTL_DSP_GETISPACE, &tx_ad_info) == -1)lirerr(872314);
1410   return tx_ad_info.bytes/snd[TXAD].framesize;
1411 #endif
1412   }
1413 return 0;
1414 }
1415 
lir_empty_da_device_buffer(void)1416 void lir_empty_da_device_buffer(void)
1417 {
1418 if( (ui.use_alsa&PORTAUDIO_RX_OUT) != 0)
1419   {
1420   return;
1421   }
1422 if(rx_audio_out == -1)return;
1423 if(rx_audio_in == rx_audio_out &&
1424                    rx_input_thread == THREAD_RX_ADINPUT)return;
1425 if(tx_audio_in == rx_audio_out)return;
1426 #if (ALSA_PRESENT == 1)
1427 if( (ui.use_alsa&NATIVE_ALSA_USED)!=0)
1428   {
1429   snd_pcm_drop(rx_da_handle);
1430   snd_pcm_prepare(rx_da_handle);
1431   }
1432 else
1433 #endif
1434   {
1435 #if HAVE_OSS== 1
1436   if(ioctl(rx_audio_out,SNDCTL_DSP_GETOSPACE, &rx_da_info) == -1)
1437     {
1438     lirerr(1077);
1439     return;
1440     }
1441   if(rx_da_info.fragstotal - rx_da_info.fragments <= 4)
1442     {
1443     zrw=write(rx_audio_out,&daout[daout_px],(size_t)snd[RXDA].block_bytes);
1444     }
1445   if(ioctl(rx_audio_out,SNDCTL_DSP_RESET,0)==-1)
1446     {
1447     lirerr(1205);
1448     return;
1449     }
1450 #endif
1451   }
1452 }
1453 
lir_tx_dawrite(char * buf)1454 void lir_tx_dawrite(char *buf)
1455 {
1456 #if (ALSA_PRESENT == 1)
1457 int err;
1458 char s[40];
1459 if( (ui.use_alsa&NATIVE_ALSA_USED)!=0)
1460   {
1461   err=snd_pcm_writei(tx_da_handle, buf,
1462                                  (snd_pcm_uframes_t)snd[TXDA].block_frames);
1463   if(err != snd[TXDA].block_frames)
1464       {
1465       if(err == -EPIPE)             // underrun try to recover
1466         {
1467         no_of_tx_underrun_errors++;
1468         sprintf(s,"TX%s%d",underrun_error_msg,no_of_tx_underrun_errors);
1469         wg_error(s,WGERR_TXOUT);
1470         err= snd_pcm_recover(tx_da_handle, err, 0);
1471         if(err < 0)
1472           {
1473           lirerr(1140);              // recovery failed
1474           }
1475          }
1476       else
1477         {
1478         if(err > 0 && err < (long) (snd[TXDA].block_frames ) )
1479          {
1480          lirerr(1328);                // short write
1481          }
1482         else
1483          {
1484          lirerr(1329);                // catch all other errors
1485          }
1486         }
1487        }
1488   }
1489 else
1490 #endif
1491   {
1492 #if HAVE_OSS == 1
1493   zrw=write(tx_audio_out,buf,(size_t)snd[TXDA].block_bytes);
1494 #else
1495   zrw=buf[0];
1496 #endif
1497   }
1498 }
1499 
lir_rx_dawrite(void)1500 void lir_rx_dawrite(void)
1501 {
1502 #if (ALSA_PRESENT == 1)
1503 int err;
1504 char s[40];
1505 int i, retry;
1506 #endif
1507 #if (HAVE_OSS == 1 || ALSA_PRESENT == 1)
1508 int wrbytes;
1509 #endif
1510 int bytes_written, bytes_to_write;
1511 int cnt;
1512 if( (ui.use_alsa&PORTAUDIO_RX_OUT) != 0)
1513   {
1514 // We assume Portaudio is always OK.
1515   lir_sched_yield();
1516   return;
1517   }
1518 bytes_written=0;
1519 bytes_to_write=snd[RXDA].block_bytes;
1520 cnt=0;
1521 while(bytes_to_write > 0)
1522   {
1523 #if (ALSA_PRESENT == 1)
1524   if(daout_px+bytes_to_write > daout_bufmask)
1525     {
1526     wrbytes=daout_bufmask+1-daout_px;
1527     }
1528   else
1529     {
1530     wrbytes=bytes_to_write;
1531     }
1532   if( (ui.use_alsa&NATIVE_ALSA_USED)!=0)
1533     {
1534     i=wrbytes/snd[RXDA].framesize;
1535     err=snd_pcm_writei(rx_da_handle, &daout[daout_px],(snd_pcm_uframes_t)i);
1536     if(err == i)
1537       {
1538       bytes_written=wrbytes;
1539       }
1540     else
1541       {
1542       if(err < 0)
1543         {
1544         retry=0;
1545         if(err == -EPIPE)            // underrun, try to recover
1546           {
1547           if(count_rx_underrun_flag)
1548             {
1549             no_of_rx_underrun_errors++;
1550             sprintf(s,"RX%s%d",underrun_error_msg,no_of_rx_underrun_errors);
1551             wg_error(s,WGERR_RXOUT);
1552             }
1553 recover:;
1554           err= snd_pcm_recover(rx_da_handle, err, 0);
1555           }
1556         if(err == -EBUSY)
1557           {
1558           retry++;
1559           if(retry < 15)
1560             {
1561             lir_sleep(1000);
1562             goto recover;
1563             }
1564           }
1565         if(err == -EBADFD)
1566           {
1567           close_rx_sndout();
1568           open_rx_sndout();
1569           if(kill_all_flag) return;
1570           }
1571         }
1572       else
1573         {
1574         if(err > 0 && err < (long) (snd[RXDA].block_frames ) )
1575           {
1576           bytes_written=err*snd[RXDA].framesize;
1577           }
1578         else
1579           {
1580           lirerr(1332);              // catch all other errors
1581           }
1582         }
1583       }
1584     }
1585   else
1586 #endif
1587     {
1588 #if HAVE_OSS == 1
1589     if(daout_px+bytes_to_write > daout_bufmask)
1590       {
1591       wrbytes=daout_bufmask+1-daout_px;
1592       }
1593     else
1594       {
1595       wrbytes=bytes_to_write;
1596       }
1597     bytes_written=write(rx_audio_out,&daout[daout_px],(size_t)wrbytes);
1598     if(bytes_written < 0)
1599       {
1600       lir_sched_yield();
1601       if(ioctl(rx_audio_out,SNDCTL_DSP_RESET,0)==-1)
1602         {
1603         lirerr(1205001);
1604         return;
1605         }
1606       close_rx_sndout();
1607       lir_sched_yield();
1608       open_rx_sndout();
1609       lir_sched_yield();
1610       bytes_written=write(rx_audio_out,&daout[daout_px], (size_t)wrbytes);
1611       if(bytes_written < 0)
1612         {
1613         lirerr(1205002);
1614         return;
1615         }
1616       }
1617 #endif
1618     }
1619   daout_px=(daout_px+bytes_written)&daout_bufmask;
1620   bytes_to_write-=bytes_written;
1621   cnt++;
1622   if(cnt>10)
1623     {
1624     lirerr(1331);
1625     }
1626   }
1627 }
1628 
sndlog_sync(void)1629 void sndlog_sync(void)
1630 {
1631 fflush(sndlog);
1632 //sync();
1633 }
1634 
1635 #if HAVE_OSS == 1
make_devname(int nn,char * ss)1636 void make_devname(int nn, char* ss)
1637 {
1638 char s[80];
1639 int n;
1640 n=nn&255;
1641 // This routine is greatly simplified July 2006 thanks to Diane Bruce, VA3DB.
1642 sprintf(s,"%s",SND_DEV);
1643 if(s[0] == 'u')
1644   {
1645   lirerr(1200);
1646   return;
1647   }
1648 if(n>MAX_DEVNAMES)
1649   {
1650   lirerr(1255);
1651   return;
1652   }
1653 if(n+2 == MAX_DEVNAMES)
1654   {
1655   sprintf(ss, "%s", SND_DEV);
1656   }
1657 else
1658   {
1659   sprintf(ss, "%s%d", SND_DEV, n);
1660   }
1661 }
1662 #endif
1663 
close_rx_sndin(void)1664 void close_rx_sndin(void)
1665 {
1666 #if (ALSA_PRESENT == 1)
1667 int err;
1668 #endif
1669 if(ui.use_extio != 0 && ui.extio_type != 4)return;
1670 if( (ui.use_alsa&PORTAUDIO_RX_IN) != 0)
1671   {
1672   close_portaudio_rxad();
1673   return;
1674   }
1675 if(rx_audio_in != -1)
1676   {
1677   if(rx_audio_out == rx_audio_in)
1678     {
1679     close_rx_sndout();
1680     }
1681 #if (ALSA_PRESENT == 1)
1682   if( (ui.use_alsa&NATIVE_ALSA_USED)!=0)
1683     {
1684     err=snd_pcm_close(rx_ad_handle);
1685     if(err < 0)
1686       {
1687       lirerr(1005);
1688       return;
1689       }
1690      }
1691   else
1692 #endif
1693     {
1694     if(close(rx_audio_in) == -1)
1695       {
1696       lirerr(1005);
1697       return;
1698       }
1699     }
1700   if(ui.rx_addev_no > 255)
1701     {
1702     if(close(rx_audio_in2) == -1)lirerr(1173);
1703     }
1704   }
1705 rx_audio_in=-1;
1706 }
1707 
open_tx_sndin(void)1708 void open_tx_sndin(void)
1709 {
1710 #if (ALSA_PRESENT == 1)
1711 float t1;
1712 int i, j;
1713 unsigned int val;
1714 static snd_pcm_format_t format;
1715 snd_pcm_hw_params_t *hw_ad_params;
1716 int err, resample;
1717 #endif
1718 #if HAVE_OSS == 1
1719 char ss[sizeof(SND_DEV)+2];
1720 int frag;
1721 float t2;
1722 int m, k;
1723 #endif
1724 snd[TXAD].block_frames=snd[TXAD].block_bytes/snd[TXAD].framesize;
1725 if(snd[TXAD].block_frames<8)snd[TXAD].block_frames=8;
1726 snd[TXAD].interrupt_rate=(float)(ui.tx_ad_speed)/(float)snd[TXAD].block_frames;
1727 while(snd[TXAD].interrupt_rate > ui.max_dma_rate)
1728   {
1729   snd[TXAD].interrupt_rate/=2;
1730   snd[TXAD].block_bytes*=2;
1731   snd[TXAD].block_frames*=2;
1732   }
1733 while(snd[TXAD].interrupt_rate < ui.min_dma_rate && snd[TXAD].block_frames>8)
1734   {
1735   snd[TXAD].interrupt_rate*=2;
1736   snd[TXAD].block_bytes/=2;
1737   snd[TXAD].block_frames/=2;
1738   }
1739 DEB"\nTXin%sDesired %f",intrate_string,snd[TXAD].interrupt_rate);
1740 if(ui.tx_addev_no == ui.rx_dadev_no && ui.rx_damode == O_RDWR)
1741   {
1742   while(rx_audio_out == -1)
1743     {
1744     lir_sleep(10000);
1745     }
1746   tx_audio_in=rx_audio_out;
1747   return;
1748   }
1749 #if (ALSA_PRESENT == 1)
1750 if( (ui.use_alsa&NATIVE_ALSA_USED)!=0)
1751   {
1752  char tx_input_plughw_pcm_name  [MAX_ALSADEV];
1753  char tx_input_hw_pcm_name  [MAX_ALSADEV];
1754   err=chk_open_alsa(ui.tx_addev_no,
1755                     ui.tx_ad_bytes,
1756                     ui.tx_ad_speed,
1757                     ui.tx_ad_channels,
1758                     SND_PCM_STREAM_CAPTURE);
1759     if(err != 0)
1760       {
1761       lirerr(1153);  //chk_open tx_input failed
1762       return;
1763       }
1764 //get plughw_pcm_name corresponding with ui definition
1765   alsar_get_dev_pcm_names(ui.tx_addev_no,tx_input_plughw_pcm_name,tx_input_hw_pcm_name);
1766   err=snd_pcm_open(&tx_ad_handle, tx_input_plughw_pcm_name,
1767                                                      SND_PCM_STREAM_CAPTURE,0);
1768   if(err < 0)
1769     {
1770     lirerr(1333);    // open tx_input failed
1771     return;
1772     }
1773 // use tx_audio_in as switch for compatibility reasons with the existing OSS logic */
1774 // do not think this is used any more (May 2010)
1775   tx_audio_in=1;
1776 //alsa housekeeping
1777   err=snd_pcm_hw_params_malloc(&hw_ad_params);
1778   if(err < 0)
1779     {
1780     lirerr(1272);
1781     return;
1782     }
1783   err=snd_pcm_hw_params_any(tx_ad_handle, hw_ad_params);
1784   if(err < 0)
1785     {
1786     lirerr(1282);
1787     return;
1788     }
1789 // Interleaved mode
1790   err=snd_pcm_hw_params_set_access(tx_ad_handle, hw_ad_params,
1791                                              SND_PCM_ACCESS_RW_INTERLEAVED);
1792   if(err< 0)
1793     {
1794     lirerr(1294);
1795     return;
1796     }
1797 // Set sample format
1798   if(ui.tx_ad_bytes == 2)
1799     {
1800     format=SND_PCM_FORMAT_S16_LE;
1801     }
1802   else
1803     {
1804     format=SND_PCM_FORMAT_S32_LE;
1805     }
1806   err=snd_pcm_hw_params_set_format(tx_ad_handle, hw_ad_params,format);
1807   if(err < 0)
1808     {
1809     lirerr(1295);
1810     return;
1811     }
1812 // Set number of ad_channels
1813   err=snd_pcm_hw_params_set_channels(tx_ad_handle,
1814                        hw_ad_params, (unsigned int)ui.tx_ad_channels);
1815   if(err < 0)
1816     {
1817     lirerr(1296);
1818     return;
1819     }
1820 // Set sample rate
1821 // first set hardware resample
1822   resample=1;
1823   err=snd_pcm_hw_params_set_rate_resample(tx_ad_handle,
1824                    hw_ad_params, (unsigned int)resample);
1825   if(err < 0)
1826     {
1827     lirerr(1298);
1828     return;
1829     }
1830 // now set sample rate
1831   val=(unsigned int)ui.tx_ad_speed;
1832   err=snd_pcm_hw_params_set_rate_near(tx_ad_handle,hw_ad_params, &val, 0);
1833   if(err < 0)
1834     {
1835     lirerr(1299);
1836     return;
1837     }
1838   t1=(float)(val)/(float)ui.tx_ad_speed;
1839   if(t1 > 1.05 || t1 < 0.95)
1840     {
1841     lirerr(1012);
1842     return;
1843     }
1844   ui.tx_ad_speed=(int)val;
1845 // Set period size:
1846 // We want the period_size to match txad.block_fragments
1847   i=snd[TXAD].block_frames;
1848   j=0;
1849 periodset:;
1850   err=snd_pcm_hw_params_set_period_size(tx_ad_handle,hw_ad_params,
1851                           (snd_pcm_uframes_t)snd[TXAD].block_frames, 0);
1852   if(err < 0)
1853     {
1854     if(j==0)
1855       {
1856       snd[TXAD].block_frames/=2;
1857       if(snd[TXAD].block_frames > 32)goto periodset;
1858       j=1;
1859       snd[TXAD].block_frames=i;
1860       }
1861     snd[TXAD].block_frames*=2;
1862     if(snd[TXAD].block_frames < 8192)goto periodset;
1863     lirerr(1318);
1864     return;
1865     }
1866 //  Write all the parameters to the driver
1867   err=snd_pcm_hw_params(tx_ad_handle, hw_ad_params);
1868   if(err < 0)
1869     {
1870     lirerr(1301);
1871     return;
1872     }
1873 // free the memory for the hardware parameter structure
1874   snd_pcm_hw_params_free(hw_ad_params);
1875   i=snd[TXAD].block_frames;
1876   make_power_of_two(&i);
1877   if(i != (int)snd[TXAD].block_frames)
1878     {
1879     lirerr(1149);
1880     return;
1881     }
1882   snd[TXAD].interrupt_rate=
1883                      (float)(ui.tx_ad_speed)/(float)snd[TXAD].block_frames;
1884   DEB"\nTXin%sActual %f",intrate_string,snd[TXAD].interrupt_rate);
1885   }
1886 else
1887 #endif
1888   {
1889 #if HAVE_OSS == 1
1890   make_devname(ui.tx_addev_no, ss);
1891   if(kill_all_flag)return;
1892   tx_audio_in=open( ss ,O_RDONLY|O_EXCL, 0);
1893   if(tx_audio_in == -1)
1894     {
1895     lirerr(1260);
1896     return;
1897     }
1898 // We want the fragment size to match snd[TXAD].block_bytes.
1899   frag=0;
1900   m=snd[TXAD].block_bytes;
1901   while(m>1)
1902     {
1903     m>>=1;
1904     frag++;
1905     }
1906   if(frag < 5)frag=5;
1907   frag=frag|0x7fff0000;
1908   if(ioctl(tx_audio_in, SNDCTL_DSP_SETFRAGMENT, &frag) == -1)
1909     {
1910     lirerr(1262);
1911     return;
1912     }
1913   m=AFMT_S16_LE;
1914 #ifdef AFMT_S32_LE
1915   if(ui.tx_ad_bytes==4)m=AFMT_S32_LE;
1916 #else
1917   ui.tx_ad_bytes=2;
1918 #endif
1919   k=m;
1920   if(ioctl(tx_audio_in, SNDCTL_DSP_SETFMT, &m) == -1)
1921     {
1922     lirerr(231013);
1923     return;
1924     }
1925   if(m!=k)
1926     {
1927     lirerr(231014);
1928     return;
1929     }
1930 // Set number of channels
1931   k=ui.tx_ad_channels;
1932   m=k;
1933   if(ioctl(tx_audio_in, SNDCTL_DSP_CHANNELS, &m) == -1)
1934     {
1935     lirerr(231009);
1936     return;
1937     }
1938   if(m != k)
1939     {
1940     lirerr(231010);
1941     return;
1942     }
1943   m=ui.tx_ad_speed;
1944   if(ioctl(tx_audio_in, SNDCTL_DSP_SPEED, &m)==-1)
1945     {
1946     lirerr(231011);
1947     return;
1948     }
1949   t2=(float)(m)/(float)ui.tx_ad_speed;
1950   if(t2 > 1.05 || t2 < 0.95)
1951     {
1952     lirerr(231012);
1953     return;
1954     }
1955   ui.tx_ad_speed=m;
1956 // This has to be the last ioctl call before read or write!!
1957   t2=(float)(ui.tx_ad_channels*ui.tx_ad_bytes*
1958                                ui.tx_ad_speed)/(float)snd[TXAD].block_bytes;
1959   DEB"\nTXin interrupt_rate: Desired  %f",t2);
1960   ioctl(tx_audio_in, SNDCTL_DSP_GETBLKSIZE,&m);
1961   t2=(float)(ui.tx_ad_channels*ui.tx_ad_bytes*ui.tx_ad_speed)/(float)m;
1962   DEB"  actual %f\n",t2);
1963 #endif
1964   }
1965 }
1966 
close_tx_sndin(void)1967 void close_tx_sndin(void)
1968 {
1969 #if (ALSA_PRESENT == 1)
1970 int err;
1971 #endif
1972 if(tx_audio_in == -1)return;
1973 if(ui.tx_addev_no == ui.rx_dadev_no && ui.rx_damode == O_RDWR)
1974   {
1975   tx_audio_in=-1;
1976   return;
1977   }
1978 #if (ALSA_PRESENT == 1)
1979 if( (ui.use_alsa&NATIVE_ALSA_USED)!=0)
1980   {
1981   err=snd_pcm_close(tx_ad_handle);
1982   if(err < 0)
1983     {
1984     lirerr(1005);
1985     return;
1986     }
1987    }
1988 else
1989 #endif
1990   {
1991 #if HAVE_OSS == 1
1992   if(close(tx_audio_in)==-1)lirerr(231037);
1993   tx_audio_in=-1;
1994 #endif
1995   }
1996 }
1997 
open_tx_sndout(void)1998 void open_tx_sndout(void)
1999 {
2000 #if (ALSA_PRESENT == 1)
2001 unsigned int val;
2002 static snd_pcm_format_t format;
2003 snd_pcm_hw_params_t *hw_da_params;
2004 int ii, dir, err, resample;
2005 int i;
2006 float t1;
2007 #endif
2008 #if HAVE_OSS == 1
2009 int frag;
2010 char ss[sizeof(SND_DEV)+2];
2011 int m, k;
2012 float t2;
2013 #endif
2014 snd[TXDA].block_frames=snd[TXDA].block_bytes/snd[TXDA].framesize;
2015 if(snd[TXDA].block_frames<8)
2016   {
2017   snd[TXDA].block_frames=8;
2018   snd[TXDA].block_bytes=snd[TXDA].block_frames*snd[TXDA].framesize;
2019   }
2020 snd[TXDA].interrupt_rate=(float)(ui.tx_da_speed)/(float)snd[TXDA].block_frames;
2021 while(snd[TXDA].interrupt_rate > ui.max_dma_rate)
2022   {
2023   snd[TXDA].interrupt_rate/=2;
2024   snd[TXDA].block_bytes*=2;
2025   snd[TXDA].block_frames*=2;
2026   }
2027 while(snd[TXDA].interrupt_rate < ui.min_dma_rate && snd[TXDA].block_frames>8)
2028   {
2029   snd[TXDA].interrupt_rate*=2;
2030   snd[TXDA].block_bytes/=2;
2031   snd[TXDA].block_frames/=2;
2032   }
2033 
2034 DEB"\nTXout%sDesired %f",intrate_string,snd[TXDA].interrupt_rate);
2035 #if (ALSA_PRESENT == 1)
2036 if( (ui.use_alsa&NATIVE_ALSA_USED)!=0)
2037   {
2038   char tx_out_plughw_pcm_name[MAX_ALSADEV];
2039   char tx_out_hw_pcm_name[MAX_ALSADEV];
2040 
2041   err=chk_open_alsa(ui.tx_dadev_no,
2042                     ui.tx_da_bytes,
2043                     ui.tx_da_speed,
2044                     ui.tx_da_channels,
2045                     SND_PCM_STREAM_PLAYBACK);
2046     if(err != 0)
2047       {
2048       lirerr(1151);
2049       return;
2050       }
2051 //get plughw_pcm_name corresponding with ui definition
2052   alsar_get_dev_pcm_names(ui.tx_dadev_no,tx_out_plughw_pcm_name,tx_out_hw_pcm_name);
2053   if((err=snd_pcm_open(&tx_da_handle, tx_out_plughw_pcm_name,
2054                                          SND_PCM_STREAM_PLAYBACK, 0)) < 0)
2055     {
2056     lirerr(1304);
2057     return;
2058     }
2059 // use tx_audio_out as switch for compatibility reasons with the existing OSS logic
2060 // do not think this is used any more (May 2010)
2061   tx_audio_out=1;
2062 //*********************************************************************
2063 //******************** SET PLAYBACK PARAMETERS THE ALSA WAY ******
2064 //*********************************************************************
2065   err=snd_pcm_hw_params_malloc (&hw_da_params);
2066   if(err < 0)
2067     {
2068     lirerr(1305);
2069     return;
2070     }
2071   err=snd_pcm_hw_params_any(tx_da_handle, hw_da_params);
2072   if(err < 0)
2073     {
2074     lirerr(1306);
2075     return;
2076     }
2077 // Interleaved mode
2078   err=snd_pcm_hw_params_set_access(tx_da_handle, hw_da_params,
2079                                          SND_PCM_ACCESS_RW_INTERLEAVED);
2080   if(err < 0)
2081     {
2082     lirerr(1307);
2083     return;
2084     }
2085 // Set sample format
2086   if(ui.tx_da_bytes == 2)
2087     {
2088     format=SND_PCM_FORMAT_S16_LE;
2089     }
2090   else
2091     {
2092     format=SND_PCM_FORMAT_S32_LE;
2093     }
2094   err=snd_pcm_hw_params_set_format(tx_da_handle, hw_da_params,format);
2095   if(err < 0)
2096     {
2097     lirerr(1308);
2098     return;
2099     }
2100 // Set number of da_channels
2101   err=snd_pcm_hw_params_set_channels(tx_da_handle,
2102                               hw_da_params, (unsigned int)ui.tx_da_channels);
2103   if(err <0)
2104     {
2105     lirerr(1309);
2106     return;
2107     }
2108 // Set sample rate
2109 // first enable  hardware resample
2110   resample=1;
2111   err=snd_pcm_hw_params_set_rate_resample(tx_da_handle,
2112                                          hw_da_params, (unsigned int)resample);
2113   if(err < 0)
2114     {
2115     lirerr(1310);
2116     return;
2117     }
2118 // now set sample rate
2119   val=(unsigned int)ui.tx_da_speed;
2120   if((err =snd_pcm_hw_params_set_rate_near(
2121                                    tx_da_handle,hw_da_params, &val, 0)<0))
2122     {
2123     lirerr(1311);
2124     return;
2125     }
2126   t1=(float)(val)/(float)ui.tx_da_speed;
2127   if(t1 > 1.05 || t1 < 0.95)
2128     {
2129     lirerr(1023);
2130     return;
2131     }
2132   ui.tx_da_speed=(int)val;
2133   dir=0;
2134 // obtained value is <,=,> target-value, according value of  dir (-1,0,1)
2135   err=snd_pcm_hw_params_set_period_size_near(tx_da_handle, hw_da_params,
2136                    (snd_pcm_uframes_t*)((void*)&snd[TXDA].block_frames), &dir);
2137   if(err < 0)
2138     {
2139     lirerr(1312);
2140     return;
2141     }
2142 // check obtained  period size
2143   err=snd_pcm_hw_params_get_period_size(hw_da_params,
2144                   (snd_pcm_uframes_t*)((void*)&snd[TXDA].block_frames), &dir);
2145   if(err < 0)
2146     {
2147     DEB"\nopen_tx_sndout:Unable to get period size for playback: %s\n",
2148                                                        snd_strerror(err));
2149     lirerr(12953);
2150     return;
2151     }
2152   ii=snd[TXDA].block_frames;
2153   make_power_of_two(&ii);
2154   i=ii;
2155   if(i != snd[TXDA].block_frames)
2156     {
2157     lirerr(1148);
2158     return;
2159     }
2160   snd[TXDA].block_bytes=snd[TXDA].block_frames*snd[TXDA].framesize;
2161   snd[TXDA].interrupt_rate=(float)(ui.tx_da_speed)/(float)snd[TXDA].block_frames;
2162 // set the hw parameters
2163   err=snd_pcm_hw_params(tx_da_handle, hw_da_params);
2164   if(err < 0)
2165     {
2166     lirerr(1313);
2167     return;
2168     }
2169 // free the memory for the hardware parameter struct
2170   snd_pcm_hw_params_free (hw_da_params);
2171   snd[TXDA].block_frames= snd[TXDA].block_bytes/snd[TXDA].framesize;
2172 // get buffersize
2173   err=snd_pcm_get_params ( tx_da_handle,
2174                  (snd_pcm_uframes_t*)((void*)&snd[TXDA].tot_frames),
2175                  (snd_pcm_uframes_t*)((void*)&snd[TXDA].block_frames) );
2176   if(err < 0)
2177       {
2178       lirerr(1313);
2179       return;
2180       }
2181   snd[TXDA].tot_bytes=snd[TXDA].tot_frames*snd[TXDA].framesize;
2182   goto ok_exit;
2183   }
2184 else
2185 #endif
2186   {
2187 #if HAVE_OSS == 1
2188   if(ui.rx_addev_no == ui.tx_dadev_no && ui.rx_admode == O_RDWR )
2189     {
2190     m=0;
2191     while(rx_audio_in == -1)
2192       {
2193       m++;
2194       lir_sleep(30000);
2195       if(m>100)
2196         {
2197         lirerr(32963);
2198         }
2199       }
2200     snd[TXDA]=snd[RXAD];
2201     tx_audio_out=rx_audio_in;
2202     }
2203   else
2204     {
2205     make_devname(ui.tx_dadev_no, ss);
2206     if(kill_all_flag)return;
2207     tx_audio_out=open( ss, O_WRONLY|O_NONBLOCK|O_EXCL, 0);
2208     if(tx_audio_out == -1)
2209       {
2210       lirerr(1079);
2211       return;
2212       }
2213     frag=0;
2214     m=snd[TXDA].block_bytes;
2215     while(m>1)
2216       {
2217       m>>=1;
2218       frag++;
2219       }
2220     if(frag < 5)frag=5;
2221     frag=frag|0x7fff0000;
2222     if(ioctl(tx_audio_out, SNDCTL_DSP_SETFRAGMENT, &frag) == -1)
2223       {
2224       lirerr(991262);
2225       return;
2226       }
2227     m=AFMT_S16_LE;
2228 #ifdef AFMT_S32_LE
2229     if(ui.tx_da_bytes==4)m=AFMT_S32_LE;
2230 #else
2231     ui.tx_da_bytes=2;
2232 #endif
2233     k=m;
2234     if(ioctl(tx_audio_out, SNDCTL_DSP_SETFMT, &m) == -1)
2235       {
2236       lirerr(231013);
2237       return;
2238       }
2239     if(m!=k)
2240       {
2241       lirerr(231014);
2242       return;
2243       }
2244 // Set number of channels
2245     k=ui.tx_da_channels;
2246     m=k;
2247     if(ioctl(tx_audio_out, SNDCTL_DSP_CHANNELS, &m) == -1)
2248       {
2249       lirerr(231009);
2250       return;
2251       }
2252     if(m != k)
2253       {
2254       lirerr(231010);
2255       return;
2256       }
2257     m=ui.tx_da_speed;
2258     if(ioctl(tx_audio_out, SNDCTL_DSP_SPEED, &m)==-1)
2259       {
2260       lirerr(231011);
2261       return;
2262       }
2263     t2=(float)(m)/(float)ui.tx_da_speed;
2264     if(t2 > 1.05 || t2 < 0.95)
2265       {
2266       lirerr(231112);
2267       return;
2268       }
2269     ui.tx_da_speed=m;
2270     }
2271   if(ioctl(tx_audio_out,SNDCTL_DSP_GETOSPACE, &tx_da_info) == -1)
2272                                                           lirerr(872313);
2273   snd[TXDA].tot_bytes=tx_da_info.fragstotal*tx_da_info.fragsize;
2274   snd[TXDA].tot_frames=snd[TXDA].tot_bytes/snd[TXDA].framesize;
2275   snd[TXDA].block_bytes=tx_da_info.fragsize;
2276   snd[TXDA].block_frames=snd[TXDA].block_bytes/snd[TXDA].framesize;
2277   snd[TXDA].interrupt_rate=(float)(ui.tx_da_speed)/(float)snd[TXDA].block_frames;
2278 #endif
2279   }
2280 #if (ALSA_PRESENT == 1)
2281 ok_exit:;
2282 #endif
2283 DEB"\nTXout%sActual %f",intrate_string,snd[TXDA].interrupt_rate);
2284 }
2285 
close_tx_sndout(void)2286 void close_tx_sndout(void)
2287 {
2288 #if (ALSA_PRESENT == 1)
2289 int err;
2290 #endif
2291 if(tx_audio_out == -1)return;
2292 if(ui.tx_dadev_no == ui.rx_addev_no && ui.rx_admode == O_RDWR)
2293   {
2294   tx_audio_out=-1;
2295   return;
2296   }
2297 #if (ALSA_PRESENT == 1)
2298 if( (ui.use_alsa&NATIVE_ALSA_USED)!=0)
2299   {
2300   snd_pcm_drop(tx_da_handle);
2301   err= snd_pcm_close(tx_da_handle);
2302   if(err < 0)lirerr(1006);
2303   }
2304 else
2305 #endif
2306   {
2307 #if HAVE_OSS == 1
2308   if(ioctl(tx_audio_out,SNDCTL_DSP_RESET,0)==-1)
2309     {
2310     lirerr(1288);
2311     }
2312   if(close(tx_audio_out)==-1)lirerr(1287);
2313   tx_audio_out=-1;
2314 #endif
2315   }
2316 }
2317 
close_rx_sndout(void)2318 void close_rx_sndout(void)
2319 {
2320 #if (ALSA_PRESENT == 1)
2321 int err;
2322 #endif
2323 if(rx_audio_out == -1)
2324   {
2325   return;
2326   }
2327 if( (ui.use_alsa&PORTAUDIO_RX_OUT) != 0)
2328   {
2329   close_portaudio_rxda();
2330   goto freebuf;
2331   }
2332 #if (ALSA_PRESENT == 1)
2333 if( (ui.use_alsa&NATIVE_ALSA_USED)!=0)
2334   {
2335   snd_pcm_drop(rx_da_handle);
2336   err= snd_pcm_close(rx_da_handle);
2337   if(err < 0)lirerr(1006);
2338   }
2339 else
2340 #endif
2341   {
2342 #if HAVE_OSS == 1
2343   if(rx_audio_out != rx_audio_in)
2344     {
2345     if(ioctl(rx_audio_out,SNDCTL_DSP_RESET,0)==-1)
2346       {
2347       lirerr(1026);
2348       }
2349     if(close(rx_audio_out)==-1)lirerr(1006);
2350     }
2351 #endif
2352   }
2353 freebuf:;
2354 rx_audio_out=-1;
2355 }
2356 
open_rx_sndin(int report_errors)2357 int open_rx_sndin(int report_errors)
2358 {
2359 #if HAVE_OSS == 1
2360 char ss[sizeof(SND_DEV)+2];
2361 audio_buf_info ad_info;
2362 int i, j, frag;
2363 float t2;
2364 #endif
2365 #if (ALSA_PRESENT == 1)
2366 int ir;
2367 snd_pcm_format_t format;
2368 snd_pcm_hw_params_t *hw_ad_params;
2369 int k, err, resample;
2370 unsigned int val;
2371 float t1;
2372 ir=report_errors;
2373 #endif
2374 lir_rxin_status=report_errors;
2375 lir_rxin_status=LIR_OK;
2376 if(ui.use_extio != 0 && ui.extio_type != 4)return 0;
2377 if( (rx_audio_in) != -1)
2378   {
2379   if(ui.rx_admode == O_RDWR)return 0;
2380   lirerr(1000);
2381   return 0;
2382   }
2383 if( (ui.use_alsa&PORTAUDIO_RX_IN) != 0)
2384   {
2385   open_portaudio_rxad();
2386   return 0;
2387   }
2388 #if (ALSA_PRESENT == 1)
2389 if( (ui.use_alsa&NATIVE_ALSA_USED)!=0)
2390   {
2391   char rx_sndin_plughw_pcm_name  [MAX_ALSADEV];
2392   char rx_sndin_hw_pcm_name  [MAX_ALSADEV];
2393   ir=2;
2394   if( (ui.rx_input_mode&DWORD_INPUT) != 0)ir=4;
2395   err=chk_open_alsa(ui.rx_addev_no,
2396                     ir,
2397                     ui.rx_ad_speed,
2398                     ui.rx_ad_channels,
2399                     SND_PCM_STREAM_CAPTURE);
2400   if(err != 0)
2401     {
2402     lirerr(1152);  // chkopen rx_sndin failed
2403     return 0;
2404     }
2405 //get plughw_pcm_name corresponding with ui definition
2406   alsar_get_dev_pcm_names(ui.rx_addev_no,rx_sndin_plughw_pcm_name,rx_sndin_hw_pcm_name );
2407   err=snd_pcm_open(&rx_ad_handle, rx_sndin_plughw_pcm_name,
2408                                                  SND_PCM_STREAM_CAPTURE, 0);
2409   if(err < 0)
2410     {
2411     lirerr(1271);  // open rx_sndin failed
2412     return 0;
2413     }
2414 // use rx_audio_in as switch for compatibility reasons with the existing OSS logic */
2415   rx_audio_in=2;
2416 //alsa housekeeping
2417   err=snd_pcm_hw_params_malloc(&hw_ad_params);
2418   if(err < 0)
2419     {
2420     lirerr(1272);
2421     return 0;
2422     }
2423   err=snd_pcm_hw_params_any(rx_ad_handle, hw_ad_params);
2424   if(err < 0)
2425     {
2426     lirerr(1282);
2427     return 0;
2428     }
2429 // Interleaved mode
2430   err=snd_pcm_hw_params_set_access(rx_ad_handle, hw_ad_params,
2431                                               SND_PCM_ACCESS_RW_INTERLEAVED);
2432   if(err < 0)
2433     {
2434     lirerr(1294);
2435     return 0;
2436     }
2437 // Set sample format
2438   format=SND_PCM_FORMAT_S16_LE;
2439   if( (ui.rx_input_mode&DWORD_INPUT) != 0) format=SND_PCM_FORMAT_S32_LE;
2440   err=snd_pcm_hw_params_set_format (rx_ad_handle, hw_ad_params,format);
2441   if(err < 0)
2442     {
2443     lirerr(1295);
2444     return 0;
2445     }
2446 // Set number of ad_channels
2447   err=snd_pcm_hw_params_set_channels(rx_ad_handle, hw_ad_params,
2448                                           (unsigned int)ui.rx_ad_channels);
2449   if(err < 0)
2450     {
2451     lirerr(1296);
2452     return 0;
2453     }
2454 // Set sample rate
2455 // first disable  hardware resample
2456   resample=0;
2457   err=snd_pcm_hw_params_set_rate_resample(rx_ad_handle,
2458                                           hw_ad_params,
2459                                           (unsigned int)resample);
2460   if(err < 0)
2461     {
2462     lirerr(1298);
2463     return 0;
2464     }
2465 // now set sample rate
2466   val=(unsigned int)ui.rx_ad_speed;
2467   err=snd_pcm_hw_params_set_rate_near(rx_ad_handle,hw_ad_params, &val, 0);
2468   if(err<0)
2469     {
2470     lirerr(1299);
2471     return 0;
2472     }
2473   t1=(float)(val)/(float)ui.rx_ad_speed;
2474   if(t1 > 1.05 || t1 < 0.95)
2475     {
2476     lirerr(1012);
2477     return 0;
2478     }
2479   ui.rx_ad_speed=(int)val;
2480 // Set period size:
2481 // We want the period_size to match snd[RXAD].block_frames
2482   val=(unsigned int)snd[RXAD].block_frames;
2483   k=1;
2484 periodset:;
2485   err=snd_pcm_hw_params_set_period_size(rx_ad_handle,hw_ad_params, val, 0);
2486   if(err<0)
2487     {
2488     if(k==1)
2489       {
2490       val/=2;
2491       if(val > 32)goto periodset;
2492       }
2493     k*=2;
2494     val=(unsigned int)(k*snd[RXAD].block_frames);
2495     if(k<=64)goto periodset;
2496     lirerr(1300);
2497     return 0;
2498     }
2499 //  Write all the parameters to the driver
2500   if((err=snd_pcm_hw_params(rx_ad_handle, hw_ad_params))< 0)
2501     {
2502     lirerr(1301);
2503     return 0;
2504     }
2505 // free the memory for the hardware parameter structure
2506   snd_pcm_hw_params_free (hw_ad_params);
2507 
2508   snd[RXAD].block_frames=snd[RXAD].block_bytes/snd[RXAD].framesize;
2509   return 0;
2510   }
2511 else
2512 #endif
2513   {
2514 #if HAVE_OSS == 1
2515   make_devname(ui.rx_addev_no, ss);
2516   if(kill_all_flag)return 0;
2517   rx_audio_in=open(ss ,ui.rx_admode|O_EXCL , 0);
2518   if(rx_audio_in == -1)
2519     {
2520     lirerr(1007);
2521     return 0;
2522     }
2523   if(ui.rx_addev_no > 255)
2524     {
2525     i=ui.rx_addev_no/255-1;
2526     make_devname(i, ss);
2527     if(kill_all_flag)return 0;
2528     rx_audio_in2=open( ss ,ui.rx_admode|O_EXCL , 0);
2529     if(rx_audio_in2 == -1)
2530       {
2531       lirerr(1174);
2532       return 0;
2533       }
2534     }
2535 // We want the fragment size to match snd[RXAD].block_bytes.
2536   frag=0;
2537   i=snd[RXAD].block_bytes>>1;
2538   while(i>0)
2539     {
2540     i>>=1;
2541     frag++;
2542     }
2543   if(frag < 4)frag=4;
2544   if(ui.rx_addev_no > 255)
2545     {
2546     frag--;
2547     if(frag < 4)frag=4;
2548     frag=frag|0x7fff0000;
2549     if(ioctl(rx_audio_in2, SNDCTL_DSP_SETFRAGMENT, &frag) == -1)
2550       {
2551       lirerr(1175);
2552       return 0;
2553       }
2554     }
2555   frag=frag|0x7fff0000;
2556   if(ioctl(rx_audio_in, SNDCTL_DSP_SETFRAGMENT, &frag) == -1)
2557     {
2558     lirerr(1008);
2559     return 0;
2560     }
2561   i=AFMT_S16_LE;
2562 #ifdef AFMT_S32_LE
2563   if( (ui.rx_input_mode&DWORD_INPUT) != 0)i=AFMT_S32_LE;
2564 #else
2565   if( (ui.rx_input_mode&DWORD_INPUT) != 0)
2566     {
2567     lirerr(1246);
2568     return 0;
2569     }
2570 #endif
2571   j=i;
2572   if(ioctl(rx_audio_in, SNDCTL_DSP_SETFMT, &i) == -1)
2573     {
2574     lirerr(1013);
2575     return 0;
2576     }
2577   if(i!=j)
2578     {
2579     lirerr(1014);
2580     return 0;
2581     }
2582   if(ui.rx_addev_no > 255)
2583     {
2584     j=i;
2585     if(ioctl(rx_audio_in2, SNDCTL_DSP_SETFMT, &i) == -1)
2586       {
2587       lirerr(1176);
2588       return 0;
2589       }
2590     if(i!=j)
2591       {
2592       lirerr(1177);
2593       return 0;
2594       }
2595     }
2596 // Set number of ad_channels
2597   j=ui.rx_ad_channels;
2598   if(ui.rx_addev_no > 255)j=2;
2599   i=j;
2600   if(ioctl(rx_audio_in, SNDCTL_DSP_CHANNELS, &i) == -1)
2601     {
2602     lirerr(1009);
2603     return 0;
2604     }
2605   if(i != j)
2606     {
2607     lirerr(1010);
2608     return 0;
2609     }
2610   if(ui.rx_addev_no > 255)
2611     {
2612     i=j;
2613     if(ioctl(rx_audio_in2, SNDCTL_DSP_CHANNELS, &i) == -1)
2614       {
2615       lirerr(1178);
2616       return 0;
2617       }
2618     if(i != j)
2619       {
2620       lirerr(1179);
2621       return 0;
2622       }
2623     }
2624   i=ui.rx_ad_speed;
2625   if(ioctl(rx_audio_in, SNDCTL_DSP_SPEED, &i)==-1)
2626     {
2627     lirerr(1011);
2628     return 0;
2629     }
2630   t2=(float)(i)/(float)ui.rx_ad_speed;
2631   if(t2 > 1.05 || t2 < 0.95)
2632     {
2633     lirerr(1012);
2634     return 0;
2635     }
2636   ui.rx_ad_speed=i;
2637   if(ui.rx_addev_no > 255)
2638     {
2639     if(ioctl(rx_audio_in2, SNDCTL_DSP_SPEED, &i)==-1)
2640       {
2641       lirerr(1180);
2642       return 0;
2643       }
2644     if(i != ui.rx_ad_speed)
2645       {
2646       lirerr(1181);
2647       return 0;
2648       }
2649 // Now that both devices are configured to be equal, synchronize them.
2650     i=0;
2651     if(ioctl(rx_audio_in,SNDCTL_DSP_SETTRIGGER,&i)==-1)
2652       {
2653       lirerr(1183);
2654       return 0;
2655       }
2656     i=0;
2657     if(ioctl(rx_audio_in2,SNDCTL_DSP_SETTRIGGER,&i)==-1)
2658       {
2659       lirerr(1184);
2660       return 0;
2661       }
2662     i=PCM_ENABLE_INPUT;
2663     if(ioctl(rx_audio_in,SNDCTL_DSP_SETTRIGGER,&i)==-1)
2664       {
2665       lirerr(1183);
2666       return 0;
2667       }
2668     i=PCM_ENABLE_INPUT;
2669     if(ioctl(rx_audio_in2,SNDCTL_DSP_SETTRIGGER,&i)==-1)
2670       {
2671       lirerr(1184);
2672       return 0;
2673       }
2674     }
2675   if(ioctl(rx_audio_in, SNDCTL_DSP_GETISPACE, &ad_info) == -1)
2676     {
2677     lirerr(1109);
2678     return 0;
2679     }
2680   overrun_limit=ad_info.fragstotal-1;
2681   if(ui.rx_addev_no > 255)
2682     {
2683     if(ioctl(rx_audio_in2, SNDCTL_DSP_GETISPACE, &ad_info) == -1)
2684       {
2685       lirerr(1109);
2686       return 0;
2687       }
2688     if(overrun_limit != ad_info.fragstotal-1)
2689       {
2690       lirerr(1109);
2691       }
2692     }
2693 // This has to be the last ioctl call before read or write!!
2694   ioctl(rx_audio_in,SNDCTL_DSP_GETBLKSIZE,&i);
2695   snd[RXAD].block_frames=snd[RXAD].block_bytes/snd[RXAD].framesize;
2696 #endif
2697   }
2698 return 0;
2699 }
2700 
open_rx_sndout(void)2701 void open_rx_sndout(void)
2702 {
2703 #if (ALSA_PRESENT == 1)
2704 snd_pcm_hw_params_t *hw_da_params;
2705 static snd_pcm_format_t format;
2706 int err, resample, dir;
2707 unsigned int val;
2708 #endif
2709 float t1;
2710 #if HAVE_OSS == 1
2711 char cc;
2712 int frag;
2713 char ss[sizeof(SND_DEV)+2];
2714 char* tmpbuf;
2715 int j;
2716 #endif
2717 int i;
2718 lir_rxout_status=LIR_OK;
2719 snd[RXDA].framesize=rx_daout_channels*rx_daout_bytes;
2720 t1=min_delay_time;
2721 i=4;
2722 if(diskread_flag >= 2)i=1;
2723 if(t1 < fft3_blocktime/(float)i)
2724   {
2725   t1=fft3_blocktime/(float)i;
2726   }
2727 if(t1 > 1)t1=1;
2728 snd[RXDA].block_frames=(int)(0.75F*t1*(float)genparm[DA_OUTPUT_SPEED]);
2729 make_power_of_two(&snd[RXDA].block_frames);
2730 // make the minimum block 8 frames
2731 if(snd[RXDA].block_frames < 8)snd[RXDA].block_frames=8;
2732 make_power_of_two(&snd[RXDA].block_frames);
2733 snd[RXDA].interrupt_rate=(float)(genparm[DA_OUTPUT_SPEED])/
2734                                       (float)snd[RXDA].block_frames;
2735 while(snd[RXDA].interrupt_rate < ui.min_dma_rate && snd[RXDA].block_frames>8)
2736   {
2737   snd[RXDA].interrupt_rate*=2;
2738   snd[RXDA].block_frames/=2;
2739   }
2740 while(snd[RXDA].interrupt_rate > ui.max_dma_rate)
2741   {
2742   snd[RXDA].interrupt_rate/=2;
2743   snd[RXDA].block_frames*=2;
2744   }
2745 DEB"\nRXout interrupt_rate: Desired %f",snd[RXDA].interrupt_rate);
2746 // Allocate buffers for minimum 0.3 seconds.
2747 snd[RXDA].block_bytes=snd[RXDA].block_frames*snd[RXDA].framesize;
2748 snd[RXDA].no_of_blocks=(int)(0.3F*snd[RXDA].interrupt_rate);
2749 make_power_of_two(&snd[RXDA].no_of_blocks);
2750 if(snd[RXDA].no_of_blocks < 8)snd[RXDA].no_of_blocks=8;
2751 snd[RXDA].tot_bytes=snd[RXDA].no_of_blocks*snd[RXDA].block_bytes;
2752 snd[RXDA].tot_frames=snd[RXDA].no_of_blocks*snd[RXDA].block_frames;
2753 if(ui.rx_dadev_no == DISABLED_DEVICE_CODE)return;
2754 if( (ui.use_alsa&PORTAUDIO_RX_OUT) != 0)
2755   {
2756   open_portaudio_rxda();
2757   if(kill_all_flag)return;
2758   goto bufalloc;
2759   }
2760 if( rx_audio_out != -1)
2761   {
2762   lirerr(1015);
2763   return;
2764   }
2765 if( (ui.rx_input_mode&NO_DUPLEX) != 0 && rx_audio_in != -1)return;
2766 if(ui.rx_dadev_no == UNDEFINED_DEVICE_CODE)
2767   {
2768   if(diskread_flag >=2)
2769     {
2770     if(rx_audio_in != -1)
2771       {
2772       lirerr(9865);
2773       return;
2774       }
2775 #if (ALSA_PRESENT == 1)
2776 //*********************************************************************
2777 //********************  OPEN ALSA PLAYBACK DEVICE *********************
2778 //*********************************************************************
2779     if( (ui.use_alsa&NATIVE_ALSA_USED)!=0)
2780       {
2781       char rx_out_plughw_pcm_name  [MAX_ALSADEV];
2782       char rx_out_hw_pcm_name  [MAX_ALSADEV];
2783       err=chk_open_alsa(ui.rx_dadev_no,
2784                         rx_daout_bytes,
2785                         genparm[DA_OUTPUT_SPEED],
2786                         rx_daout_channels,
2787                         SND_PCM_STREAM_PLAYBACK);
2788       if(err != 0)
2789         {
2790         lirerr(1151);
2791         return;
2792         }
2793 
2794 //get plughw_pcm_name corresponding with ui definition
2795       alsar_get_dev_pcm_names(ui.rx_dadev_no,rx_out_plughw_pcm_name,rx_out_hw_pcm_name);
2796       if((err=snd_pcm_open(&rx_da_handle, rx_out_plughw_pcm_name,
2797                                             SND_PCM_STREAM_PLAYBACK, 0)) < 0)
2798         {
2799         lirerr(1303);
2800         return;
2801         }
2802 // use rx_audio_out as switch for compatibility with the existing OSS logic
2803       rx_audio_out=1;//(int)rx_da_handle;
2804       }
2805     else
2806 #endif
2807       {
2808 #if HAVE_OSS == 1
2809 // There is no separate device for output which means that RDWR was not
2810 // selected for both input and output. Use the input device for our
2811 // output since input has to be from disk or network.
2812       make_devname(ui.rx_addev_no, ss);
2813       if(kill_all_flag)return;
2814       rx_audio_out=open( ss ,O_WRONLY|O_EXCL , 0);
2815 #endif
2816       }
2817     if(rx_audio_out == -1)
2818       {
2819       lirerr(1086);
2820       return;
2821       }
2822     goto set_da;
2823     }
2824   else
2825     {
2826     return;
2827     }
2828   }
2829 // *******************************************
2830 if(ui.rx_addev_no == ui.rx_dadev_no && ui.rx_admode == O_RDWR )
2831   {
2832   if(rx_audio_in == -1 )return;
2833   snd[RXDA]=snd[RXAD];
2834   rx_audio_out=rx_audio_in;
2835   }
2836 else
2837   {
2838 #if (ALSA_PRESENT == 1)
2839   if( (ui.use_alsa&NATIVE_ALSA_USED)!=0)
2840     {
2841     char rx_out_plughw_pcm_name  [MAX_ALSADEV];
2842     char rx_out_hw_pcm_name  [MAX_ALSADEV];
2843 // We have to call this first, otherwise linrad would exit after this error:
2844 // (snd_config_hooks_call) Cannot open shared library
2845 // libasound_module_conf_pulse.so (32 bit xlinrad under 64 bit debian wheezy)
2846     err=alsa_get_dev_names (ui.rx_dadev_no);
2847 //get plughw_pcm_name corresponding with ui definition
2848     alsar_get_dev_pcm_names(ui.rx_dadev_no,rx_out_plughw_pcm_name,rx_out_hw_pcm_name );
2849     err=snd_pcm_open(&rx_da_handle, rx_out_plughw_pcm_name,
2850                                                  SND_PCM_STREAM_PLAYBACK, 0);
2851     if(err < 0)
2852       {
2853       lirerr(1304);
2854       return;
2855       }
2856 // use rx_audio_out as switch for compatibility reasons with the existing OSS logic
2857     rx_audio_out=1; //(int)rx_da_handle;
2858     }
2859   else
2860 #endif
2861     {
2862 #if HAVE_OSS == 1
2863     make_devname(ui.rx_dadev_no, ss);
2864     if(kill_all_flag)return;
2865     rx_audio_out=open( ss ,ui.rx_damode|O_EXCL , 0);
2866 #endif
2867     }
2868   if(rx_audio_out == -1)
2869     {
2870     if(diskread_flag==2)
2871       {
2872       lirerr(1191);
2873       }
2874     else
2875       {
2876       lirerr(1017);
2877       }
2878     return;
2879     }
2880 set_da:;
2881 #if (ALSA_PRESENT == 1)
2882   if( (ui.use_alsa&NATIVE_ALSA_USED)!=0)
2883     {
2884 //*********************************************************************
2885 //******************** SET PLAYBACK PARAMETERS THE ALSA WAY ******
2886 //*********************************************************************
2887     err=snd_pcm_hw_params_malloc (&hw_da_params);
2888     if(err < 0)
2889       {
2890       lirerr(1305);
2891       return;
2892       }
2893     err=snd_pcm_hw_params_any(rx_da_handle, hw_da_params);
2894     if(err < 0)
2895       {
2896       lirerr(1306);
2897       return;
2898       }
2899 // Interleaved mode
2900     err=snd_pcm_hw_params_set_access(rx_da_handle, hw_da_params,
2901                                            SND_PCM_ACCESS_RW_INTERLEAVED);
2902     if(err < 0)
2903       {
2904       lirerr(1307);
2905       return;
2906       }
2907 // Set sample format
2908     if(rx_daout_bytes == 1)
2909       {
2910       format=SND_PCM_FORMAT_U8;
2911       }
2912     else
2913       {
2914       format=SND_PCM_FORMAT_S16_LE;
2915       }
2916     err=snd_pcm_hw_params_set_format(rx_da_handle, hw_da_params,format);
2917     if(err < 0)
2918       {
2919       lirerr(1308);
2920       return;
2921       }
2922 // Set number of da_channels
2923     err=snd_pcm_hw_params_set_channels(rx_da_handle,
2924                                        hw_da_params,
2925                                        (unsigned int)rx_daout_channels);
2926     if(err <0 )
2927       {
2928       lirerr(1309);
2929       return;
2930       }
2931 // Set sample rate
2932 // first disable  hardware resample
2933     resample=0;
2934     err=snd_pcm_hw_params_set_rate_resample(
2935                                    rx_da_handle,
2936                                    hw_da_params,
2937                                    (unsigned int)resample);
2938     if(err < 0)
2939       {
2940       lirerr(1310);
2941       return;
2942       }
2943 // now set sample rate
2944     val=(unsigned int)genparm[DA_OUTPUT_SPEED];
2945     err=snd_pcm_hw_params_set_rate_near(rx_da_handle,hw_da_params, &val, 0);
2946     if(err < 0)
2947       {
2948       lirerr(1311);
2949       return;
2950       }
2951     t1=(float)(val)/(float)genparm[DA_OUTPUT_SPEED];
2952     if(t1 > 1.05 || t1 < 0.95)
2953       {
2954       lirerr(1023);
2955       return;
2956       }
2957     genparm[DA_OUTPUT_SPEED]=(int)val;
2958     dir=0;
2959 // obtained value is <,=,> target-value, according value of  dir (-1,0,1)
2960     err=snd_pcm_hw_params_set_period_size_near(rx_da_handle, hw_da_params,
2961                  (snd_pcm_uframes_t*)((void*)&snd[RXDA].block_frames), &dir);
2962     if(err < 0)
2963       {
2964       lirerr(1312);
2965       return;
2966       }
2967 // check obtained  period size
2968     err=snd_pcm_hw_params_get_period_size(hw_da_params, (snd_pcm_uframes_t*)
2969                                       ((void*)&snd[RXDA].block_frames), &dir);
2970     if(err < 0)
2971      {
2972      DEB"\nopen_rx_sndout:Unable to get period size for playback: %s\n",
2973                                                        snd_strerror(err));
2974      lirerr(53841);
2975      return;
2976      }
2977 // set the hw parameters
2978     err=snd_pcm_hw_params(rx_da_handle, hw_da_params);
2979     if(err < 0)
2980       {
2981       lirerr(1313);
2982       return;
2983       }
2984 // free the memory for the hardware parameter struct
2985     snd_pcm_hw_params_free(hw_da_params);
2986 
2987     snd[RXDA].block_frames=snd[RXDA].block_bytes/snd[RXDA].framesize;
2988 // get buffersize
2989     err=snd_pcm_get_params ( rx_da_handle,
2990                 (snd_pcm_uframes_t*)((void*)&snd[RXDA].tot_frames),
2991                 (snd_pcm_uframes_t*)((void*)&snd[RXDA].block_frames) );
2992     snd[RXDA].tot_bytes=snd[RXDA].tot_frames*snd[RXDA].framesize;
2993     snd[RXDA].no_of_blocks=snd[RXDA].tot_frames/snd[RXDA].framesize;
2994     if(err < 0)
2995       {
2996       lirerr(1313);
2997       return;
2998       }
2999     goto alsacont;
3000     }
3001   else
3002 #endif
3003     {
3004 #if HAVE_OSS == 1
3005     frag=-1;
3006     i=snd[RXDA].block_bytes;
3007     while(i>0)
3008       {
3009       i>>=1;
3010       frag++;
3011       }
3012     if(frag < 4)frag=4;
3013     frag|=0x7fff0000;
3014     if(ioctl(rx_audio_out,SNDCTL_DSP_SETFRAGMENT,&frag)==-1)
3015       {
3016       lirerr(1018);
3017       return;
3018       }
3019     if(rx_daout_bytes == 1)
3020       {
3021       i=AFMT_U8;
3022       }
3023     else
3024       {
3025       i=AFMT_S16_LE;
3026       }
3027     j=i;
3028     if(ioctl(rx_audio_out, SNDCTL_DSP_SETFMT, &i) == -1)
3029       {
3030       lirerr(1020);
3031       return;
3032       }
3033     if(i != j)
3034       {
3035       lirerr(1021);
3036       return;
3037       }
3038     i=rx_daout_channels;
3039     if(ioctl(rx_audio_out, SNDCTL_DSP_CHANNELS, &i) == -1)
3040       {
3041       lirerr(1019);
3042       return;
3043       }
3044     if(i != rx_daout_channels)
3045       {
3046       lirerr(1099);
3047       return;
3048       }
3049     i=genparm[DA_OUTPUT_SPEED];
3050     if(i > 0)
3051       {
3052       if(ioctl(rx_audio_out, SNDCTL_DSP_SPEED, &i)==-1)
3053         {
3054         lirerr(1022);
3055         return;
3056         }
3057       t1=(float)(i)/(float)genparm[DA_OUTPUT_SPEED];
3058       if(t1 > 1.05 || t1 < 0.95)
3059         {
3060         lirerr(1023);
3061         return;
3062         }
3063       genparm[DA_OUTPUT_SPEED]=i;
3064       }
3065 #endif
3066     }
3067   }
3068 bufalloc:;
3069 if( (ui.use_alsa&PORTAUDIO_RX_OUT) != 0)
3070   {
3071   return;
3072   }
3073 #if HAVE_OSS == 1
3074 // We have to write to the output because
3075 // 4Front OSS requires a write before it will return
3076 // correct buffer information with the ioctl call.
3077 tmpbuf=malloc((size_t)snd[RXDA].block_bytes);
3078 if(rx_daout_bytes == 1)
3079   {
3080   cc=(char)0x80;
3081   }
3082 else
3083   {
3084   cc=0;
3085   }
3086 memset(tmpbuf,cc,(size_t)snd[RXDA].block_bytes);
3087 zrw=write(rx_audio_out,tmpbuf,(size_t)snd[RXDA].block_bytes);
3088 zrw=write(rx_audio_out,tmpbuf,(size_t)snd[RXDA].block_bytes);
3089 free(tmpbuf);
3090 if(ioctl(rx_audio_out,SNDCTL_DSP_GETOSPACE, &rx_da_info) == -1)lirerr(856432);
3091 snd[RXDA].tot_bytes=rx_da_info.fragstotal*rx_da_info.fragsize;
3092 snd[RXDA].tot_frames=snd[RXDA].tot_bytes/snd[RXDA].framesize;
3093 if(rx_da_info.fragsize != snd[RXDA].block_bytes)
3094   {
3095   snd[RXDA].block_bytes=rx_da_info.fragsize;
3096   }
3097 snd[RXDA].block_frames=snd[RXDA].block_bytes/snd[RXDA].framesize;
3098 #endif
3099 #if (ALSA_PRESENT == 1)
3100 alsacont:;
3101 #endif
3102 snd[RXDA].interrupt_rate=(float)
3103                      (snd[RXDA].framesize*genparm[DA_OUTPUT_SPEED])/
3104                       (float)(snd[RXDA].block_bytes);
3105 DEB"  Actual %f  \n",snd[RXDA].interrupt_rate);
3106 snd[RXDA].no_of_blocks=snd[RXDA].tot_bytes/snd[RXDA].block_bytes;
3107 }
3108 
3109 #define SDI_COL 78
3110 
display_sdi(void)3111 void display_sdi(void)
3112 {
3113 FILE *sdifile;
3114 char *p;
3115 char work_line [80];
3116 int  sdi_screen_line_counter;
3117 char sdi_intro_msg [26]= "SOUND DRIVER INFORMATION:" ;
3118 char sdi_error_msg [46]= "No OSS or ALSA sound-driver information found";
3119 char sndstat_filename [25];
3120 char sndlog_sep [80];
3121 if(screen_last_col < SDI_COL+30)return;
3122 memset (sndlog_sep,'-',sizeof(sndlog_sep));
3123 sndlog_sep[0]='\n';
3124 sndlog_sep[79]='\0';
3125 SNDLOG "%s",sndlog_sep);
3126 SNDLOG"\n%s ", sdi_intro_msg );
3127 settextcolor(YELLOW);
3128 lir_text(SDI_COL, 0, sdi_intro_msg );
3129 sdi_screen_line_counter=1;
3130 // Look for OSS-driver info
3131 strcpy (sndstat_filename,"/dev/sndstat");
3132 sdifile=fopen ( sndstat_filename,"r");
3133 // if OSS not active, try  ALSA
3134 if(sdifile==NULL)
3135   {
3136   strcpy (sndstat_filename,"/proc/asound/oss/sndstat");
3137   sdifile=fopen (sndstat_filename,"r");
3138   }
3139 if(sdifile!=NULL)
3140   {
3141   SNDLOG"\n(output of 'cat %s' command): \n\n",sndstat_filename );
3142   settextcolor(LIGHT_GREEN);
3143   while(fgets(work_line, sizeof(work_line)-1, sdifile) != NULL &&
3144                                       sdi_screen_line_counter < screen_last_line)
3145     {
3146 // check if work_line is ready for output processing
3147     p=strchr(work_line, '\n');
3148     if(p != NULL)p[0]=0;
3149     if(*work_line != '\0')
3150       {
3151 // display work_line only if it is not blank
3152 // and there are enough lines available on the screen
3153 // and there are at least 40 characters available on a line
3154       if(sdi_screen_line_counter < screen_last_line &&
3155                                                (screen_last_col - 40)>= 80)
3156         {
3157         sdi_screen_line_counter++;
3158         lir_text (SDI_COL, sdi_screen_line_counter, work_line);
3159         }
3160 // write  to soundboard_init.log
3161       SNDLOG"%s\n",work_line);
3162       }
3163     }
3164   fclose(sdifile);
3165   }
3166 else
3167   {
3168   settextcolor(LIGHT_RED);
3169   lir_text( SDI_COL, sdi_screen_line_counter++, sdi_error_msg);
3170   SNDLOG"\n%s",sdi_error_msg );
3171   }
3172 SNDLOG"%s",sndlog_sep);
3173 sndlog_sync();
3174 settextcolor(7);
3175 }
3176 
3177 #if HAVE_OSS == 1
ossdev_show(char * ss,int no,int minrate,int maxrate,int chan,int byte,char * modes)3178 void ossdev_show(char *ss, int no, int minrate, int maxrate,
3179                                            int chan, int byte, char *modes)
3180 {
3181 int i, j, k;
3182 sprintf(ss," %02d  %s                 ",no, dev_name);
3183 sprintf(&ss[22],"%d/%d                ",minrate,maxrate);
3184 i=40;
3185 k=1;
3186 while(k < 8)
3187   {
3188   if(chan&k)
3189     {
3190     sprintf(&ss[i],"%d               ",k);
3191     i+=2;
3192     }
3193   k*=2;
3194   }
3195 k=1;
3196 i=49;
3197 while(k < 8)
3198   {
3199   if(byte&k)
3200     {
3201     sprintf(&ss[i],"%d               ",k);
3202     i+=2;
3203     }
3204   k*=2;
3205   }
3206 if(modes == NULL)
3207   {
3208   i=57;
3209   for(j=0; j<3; j++)
3210     {
3211     k=1<<j;
3212     if( (dev_flag[no]&k) != 0)
3213       {
3214       sprintf(&ss[i],"%s ",devmode_txt[j]);
3215       while(ss[i] != 0)i++;
3216       }
3217     }
3218   }
3219 else
3220   {
3221   sprintf(&ss[57],"%s ",modes);
3222   }
3223 }
3224 
log_output_mode(int no)3225 void log_output_mode(int no)
3226 {
3227 SNDLOG"\n%s opened as %s ",dev_name, devmode_txt[no]);
3228 sndlog_sync();
3229 }
3230 
3231 
select_rdwr_mode(int * line,int no,int mode)3232 int select_rdwr_mode(int *line, int no, int mode)
3233 {
3234 int m, k;
3235 char s[80];
3236 if(mode == O_RDONLY)
3237   {
3238   k=DEVFLAG_R;
3239   }
3240 else
3241   {
3242   k=DEVFLAG_W;
3243   }
3244 m=mode;
3245 if( (dev_flag[no]&DEVFLAG_RW) != 0)
3246   {
3247   if( (dev_flag[no]&k) != 0)
3248     {
3249     line[0]++;
3250 gt_rdo:;
3251     sprintf(s,"Open %s as RDWR? (Y/N) =>",dev_name);
3252     lir_text(10,line[0],s);
3253     await_processed_keyboard();
3254     if(kill_all_flag)return 0;
3255     if(lir_inkey == 'Y')
3256       {
3257       line[0]++;
3258       settextcolor(14);
3259       lir_text(0,line[0],
3260         "RDWR mode is limited and less reliable.  Are you sure? (Y/N) =>");
3261       await_processed_keyboard();
3262       settextcolor(7);
3263       if(kill_all_flag)return 0;
3264       if(lir_inkey == 'Y')
3265         {
3266         goto rdwr;
3267         }
3268       clear_lines(line[0],line[0]);
3269       line[0]--;
3270       goto gt_rdo;
3271       }
3272     if(lir_inkey != 'N')goto gt_rdo;
3273     SNDLOG"\nUser selected RDONLY");
3274     }
3275   else
3276     {
3277 rdwr:;
3278     m=O_RDWR;
3279     SNDLOG"\nUser selected RDWR");
3280     }
3281   line[0]++;
3282   }
3283 else
3284   {
3285   SNDLOG"\nRDWR not available");
3286   }
3287 return m;
3288 }
3289 
show_oss_presel(int * line,int suggested_dev)3290 void show_oss_presel(int *line, int suggested_dev)
3291 {
3292 char s[80];
3293 clear_lines(0,0);
3294 line[0]++;
3295 make_devname(suggested_dev, dev_name);
3296 if(kill_all_flag)return;
3297 sprintf(s,"%s auto-selected. There is no other alternative.", dev_name);
3298 lir_text(0,line[0],s);
3299 line[0]++;
3300 }
3301 
select_ossdev(int * line,int sound_type)3302 void select_ossdev(int *line, int sound_type)
3303 {
3304 int iohandle;
3305 int caps;
3306 int i, j, k, m, n, nn;
3307 char ss[3*MAX_COLUMN];
3308 int mode, rdwr_fmt, device_no;
3309 int rdwr_min_speed;
3310 int rdwr_max_speed;
3311 audio_buf_info ad_info;
3312 char *rdtest_buffer;
3313 int rdwr_channels, suggested_dev;
3314 int dev_rdwr_channels[MAX_DEVNAMES];
3315 int dev_max_rdwr_speed[MAX_DEVNAMES];
3316 int dev_min_rdwr_speed[MAX_DEVNAMES];
3317 int dev_rdwr_bytes[MAX_DEVNAMES];
3318 int column, maxcolumn, bottom_line;
3319 int devflag_val;
3320 char s[256];
3321 char color[3];
3322 int h_test;
3323 int h_test2;
3324 h_test=-1;
3325 h_test2=-1;
3326 rdtest_buffer=malloc(2048);
3327 if(rdtest_buffer == NULL)
3328   {
3329   lirerr(1044);
3330   return;
3331   }
3332 n=0;
3333 suggested_dev=-1;
3334 maxcolumn=screen_last_xpixel/text_width-1;
3335 if(maxcolumn > MAX_COLUMN)maxcolumn=MAX_COLUMN;
3336 bottom_line=0;
3337 line[0]++;
3338 sprintf(s,"Dev     device          sample-rate    channels  bytes       modes");
3339 SNDLOG"%s\n",s);
3340 lir_text(0,line[0],s);
3341 line[0]++;
3342 sprintf(s," no      file           min / max");
3343 SNDLOG"%s\n",s);
3344 lir_text(0, line[0],s);
3345 line[0]++;
3346 sprintf(s," --  ---------------  --------------   -------  -------  -------------------" );
3347 SNDLOG"%s\n",s);
3348 lir_text(0,line[0],s);
3349 line[0]++;
3350 for(device_no=0; device_no<MAX_DEVNAMES; device_no++)
3351   {
3352   lir_sched_yield();
3353   dev_flag[device_no]=0;
3354   make_devname(device_no, dev_name);
3355   SNDLOG"Checking %s\n",dev_name);
3356   if(kill_all_flag)goto sel_ossdev_skip;
3357   if(device_no == (ui.rx_addev_no&255) && ui.rx_admode == O_RDWR)
3358     {
3359     if(ui.rx_dadev_no != device_no && ui.tx_dadev_no != device_no)
3360       {
3361       k=2;
3362       if(  (ui.rx_input_mode&DWORD_INPUT) )k=4;
3363       ossdev_show(ss, device_no, ui.rx_ad_speed, ui.rx_ad_speed,
3364                       ui.rx_ad_channels, k,"RDWR used by RXin");
3365       settextcolor(10);
3366       line[0]++;
3367       lir_text(0,line[0],ss);
3368       lir_refresh_screen();
3369       dev_flag[device_no]=DEVFLAG_RW;
3370       n++;
3371       suggested_dev=device_no;
3372       }
3373     else
3374       {
3375       dev_flag[device_no]=0;
3376       }
3377     goto used_rdwr;
3378     }
3379   if(sound_type == TXAD &&
3380      device_no == ui.rx_dadev_no &&
3381      ui.rx_damode == O_RDWR)
3382     {
3383     ossdev_show(ss, device_no, ui.rx_min_da_speed, ui.rx_max_da_speed,
3384                       ui.rx_min_da_channels, 2,"RDWR used by RXout");
3385     settextcolor(10);
3386     line[0] ++;
3387     lir_text(0,line[0],ss);
3388     lir_refresh_screen();
3389     dev_flag[device_no]=DEVFLAG_RW;
3390     goto used_rdwr;
3391     }
3392   sndlog_sync();
3393   for(mode=0; mode<3; mode++)
3394     {
3395     rdwr_max_speed=0;
3396     rdwr_min_speed=0;
3397     devflag_val=1<<mode;
3398     sprintf(s,
3399     "Trying to open %s %s. Device defective if system hangs here. Read %s   ",
3400     dev_name, devmode_txt[mode],rx_logfile_name);
3401     sndlog_sync();
3402     settextcolor(12);
3403     lir_text(0,line[0]+1,s);
3404     lir_refresh_screen();
3405     settextcolor(7);
3406     iohandle=open( dev_name, devmodes[mode]|O_NONBLOCK|O_EXCL, 0);
3407     clear_lines(line[0]+1,line[0]+1);
3408     if(iohandle != -1)
3409       {
3410 #ifdef SNDCTL_DSP_COOKEDMODE
3411       i=0;
3412       ioctl(iohandle, SNDCTL_DSP_COOKEDMODE, &i);
3413 #endif
3414       for(nn=0; nn<80; nn++)SNDLOG"-");
3415       log_output_mode(mode);
3416       rdwr_fmt=0;
3417       rdwr_channels=0;
3418 // Check for 16 bits
3419       if( ioctl(iohandle, SNDCTL_DSP_GETFMTS, &m) == -1)
3420         {
3421         SNDLOG"\nioctl(GETFMTS)  failed");
3422 baddev:;
3423         sndlog_sync();
3424         devflag_val=0;
3425         goto  cls;
3426         }
3427       if( (m&AFMT_U8) ==0)
3428         {
3429         SNDLOG"\n8bit format NOT supported");
3430         }
3431       else
3432         {
3433         SNDLOG"\n8bit format supported");
3434         rdwr_fmt|=1;
3435         }
3436       if( (m&AFMT_S16_LE) == 0)
3437         {
3438         SNDLOG"\n16bit format NOT supported");
3439         }
3440       else
3441         {
3442         SNDLOG"\n16bit format supported");
3443         rdwr_fmt|=2;
3444         }
3445 #ifdef AFMT_S32_LE
3446 // Check for 32 bits
3447       if( (m&AFMT_S32_LE) != 0)
3448         {
3449         rdwr_fmt|=4;
3450         devflag_val=1<<mode;
3451         SNDLOG"\n32bit format supported");
3452         }
3453       else
3454         {
3455         SNDLOG"\n32bit format NOT supported");
3456         }
3457 #endif
3458       sndlog_sync();
3459       if(rdwr_fmt == 0)
3460         {
3461         devflag_val=0;
3462         goto cls;
3463         }
3464 // Find max no of channels.
3465 // We never want more than 4 input channels!!
3466       rdwr_channels=0;
3467       m=4;
3468       while(m > 0)
3469         {
3470         k=m;
3471         j=ioctl(iohandle, SNDCTL_DSP_CHANNELS, &k);
3472         if(j != -1 && k == m)rdwr_channels|=k;
3473         m/=2;
3474         }
3475       if(rdwr_channels == 0)
3476         {
3477         k=0;
3478         SNDLOG"\nMax no of channels = 0");
3479         goto baddev;
3480         }
3481       else
3482         {
3483         SNDLOG"\nChannels = %d",rdwr_channels);
3484         }
3485       sndlog_sync();
3486 //
3487 // To allow a separate #ifdef __FreeBSD__
3488 // - Diane Bruce VA3DB, Sept 6, 2006
3489 //
3490 #ifdef __linux__
3491 // Find maximum speed
3492       rdwr_max_speed=ABOVE_MAX_SPEED;
3493       if(ioctl(iohandle, SNDCTL_DSP_SPEED, &rdwr_max_speed)==-1)
3494         {
3495         SNDLOG"\nioctl(SPEED)  failed (max)");
3496         goto baddev;
3497         }
3498       SNDLOG"\nMax speed %d Hz",rdwr_max_speed);
3499 // Find minimum speed
3500       i=0;
3501       while(i<MAX_LOWSPEED)
3502         {
3503         rdwr_min_speed=low_speeds[i];
3504         if(ioctl(iohandle, SNDCTL_DSP_SPEED, &rdwr_min_speed)!=-1)
3505                                                                   goto minok;
3506         i++;
3507         }
3508       lirerr(1040);
3509       goto sel_ossdev_skip;
3510 minok:;
3511 #endif
3512 //
3513 // This code finds min max speed of sound card for FreeBSD
3514 // It probably works for other BSDs as well
3515 // Diane Bruce, db@db.net VA3DB
3516 // Sept 7, 2006
3517 //
3518 #ifdef __FreeBSD__
3519         {
3520         snd_capabilities capab;
3521         int status;
3522         bzero((void *)&capab, sizeof(capab));
3523         status=ioctl(iohandle, AIOGCAP, &capab);
3524         if(status < 0)goto sel_ossdev_skip;
3525         rdwr_min_speed=capab.rate_min;
3526         rdwr_max_speed=capab.rate_max;
3527         SNDLOG"\nMax sampling speed %d", rdwr_max_speed);
3528         }
3529 #endif
3530       SNDLOG"\nMin sampling speed = %d Hz",rdwr_min_speed);
3531       sndlog_sync();
3532       if(sound_type == RXAD)
3533         {
3534 //devmode_txt[3]={"RDONLY","WRONLY","RDWR"};
3535         if(mode != DEVMODE_WRONLY)
3536           {
3537           if(ioctl(iohandle, SNDCTL_DSP_GETISPACE, &ad_info) == -1)
3538             {
3539             SNDLOG"\nioctl(GETISPACE)  failed");
3540             goto baddev;
3541             }
3542 // If it is  opened RDWR, check we have a chance to write while reading
3543 // Some devices allow write or read in rdwr mode - but not simultaneously.
3544           if(mode == DEVMODE_RDWR)
3545             {
3546             zrw=read(iohandle, rdtest_buffer, 128);
3547             if(ioctl(iohandle,SNDCTL_DSP_GETOSPACE, &ad_info) == -1)
3548                {
3549               SNDLOG"\nioctl(GETOSPACE)  failed while reading");
3550               goto baddev;
3551               }
3552             }
3553           }
3554         }
3555 cls:;
3556       if(close(iohandle)==-1)
3557         {
3558         sndlog_sync();
3559         lirerr(1037);
3560         goto sel_ossdev_skip;
3561         }
3562       if(devflag_val != 0)
3563         {
3564         if(sound_type == RXAD || sound_type == TXAD)
3565           {
3566           if(devflag_val != 2)
3567             {
3568             suggested_dev=device_no;
3569             n++;
3570             }
3571           }
3572         if( sound_type == RXDA || sound_type == TXDA)
3573           {
3574           if(devflag_val != 1)
3575             {
3576             suggested_dev=device_no;
3577             n++;
3578             }
3579           }
3580         dev_flag[device_no]|=devflag_val;
3581         switch (mode)
3582           {
3583           case DEVMODE_RDONLY:
3584           dev_rd_channels[device_no]=rdwr_channels;
3585           dev_max_rd_speed[device_no]=rdwr_max_speed;
3586           dev_min_rd_speed[device_no]=rdwr_min_speed;
3587           dev_rd_bytes[device_no]=rdwr_fmt;
3588           break;
3589 
3590            case DEVMODE_WRONLY:
3591           dev_wr_channels[device_no]=rdwr_channels;
3592           dev_max_wr_speed[device_no]=rdwr_max_speed;
3593           dev_min_wr_speed[device_no]=rdwr_min_speed;
3594           dev_wr_bytes[device_no]=rdwr_fmt;
3595           break;
3596 
3597           case DEVMODE_RDWR:
3598           dev_rdwr_channels[device_no]=rdwr_channels;
3599            dev_max_rdwr_speed[device_no]=rdwr_max_speed;
3600           dev_min_rdwr_speed[device_no]=rdwr_min_speed;
3601           dev_rdwr_bytes[device_no]=rdwr_fmt;
3602           break;
3603           }
3604         }
3605       SNDLOG"\n");
3606       }
3607     }
3608   if(dev_flag[device_no] != 0)
3609     {
3610     SNDLOG"\nFLAG= %d",dev_flag[device_no]);
3611 // One device may be different hardwares for input and output.
3612 // Put them on different lines if characteristics differ.
3613     k=0;
3614     j=0;
3615 // Store equal pairs in k
3616 // bit 0=1 => READ==WRITE
3617 // bit 1=1 => READ==RDWR
3618 // bit 2=1 => WRITE==RDWR
3619     if( (dev_flag[device_no]&(DEVFLAG_R+DEVFLAG_W)) == DEVFLAG_R+DEVFLAG_W)
3620       {
3621       j|=1;
3622       if(dev_rd_channels[device_no]==dev_wr_channels[device_no] &&
3623          dev_max_rd_speed[device_no]==dev_max_wr_speed[device_no] &&
3624          dev_min_rd_speed[device_no]==dev_min_wr_speed[device_no] &&
3625          dev_rd_bytes[device_no]==dev_wr_bytes[device_no]) k|=1;
3626       }
3627     if( (dev_flag[device_no]&(DEVFLAG_R+DEVFLAG_RW)) == DEVFLAG_R+DEVFLAG_RW)
3628       {
3629       j|=2;
3630       if(dev_rd_channels[device_no]==dev_rdwr_channels[device_no] &&
3631          dev_max_rd_speed[device_no]==dev_max_rdwr_speed[device_no] &&
3632          dev_min_rd_speed[device_no]==dev_min_rdwr_speed[device_no] &&
3633          dev_rd_bytes[device_no]==dev_rdwr_bytes[device_no])k|=2;
3634       }
3635     if( (dev_flag[device_no]&(DEVFLAG_W+DEVFLAG_RW)) == DEVFLAG_W+DEVFLAG_RW)
3636       {
3637       j|=4;
3638       if(dev_wr_channels[device_no]==dev_rdwr_channels[device_no] &&
3639          dev_max_wr_speed[device_no]==dev_max_rdwr_speed[device_no] &&
3640          dev_min_wr_speed[device_no]==dev_min_rdwr_speed[device_no] &&
3641          dev_wr_bytes[device_no]==dev_rdwr_bytes[device_no])k|=4;
3642       }
3643     SNDLOG"\nj=%d   k=%d",j,k);
3644     if(j == k)
3645       {
3646 // There are no differences between devices. Put everything on one line.
3647       m=1;
3648       if( (dev_flag[device_no]&DEVFLAG_R) == DEVFLAG_R)
3649         {
3650         ossdev_show(ss, device_no,
3651                         dev_min_rd_speed[device_no],
3652                         dev_max_rd_speed[device_no],
3653                         dev_rd_channels[device_no],
3654                         dev_rd_bytes[device_no],NULL);
3655         }
3656       else
3657         {
3658         if( (dev_flag[device_no]&DEVFLAG_W) == DEVFLAG_W)
3659           {
3660           ossdev_show(ss, device_no,
3661                          dev_min_wr_speed[device_no],
3662                          dev_max_wr_speed[device_no],
3663                          dev_wr_channels[device_no],
3664                          dev_wr_bytes[device_no],NULL);
3665           }
3666         }
3667       if(sound_type == RXAD || sound_type == TXAD)
3668         {
3669         if( (dev_flag[device_no]&(DEVFLAG_R+DEVFLAG_RW)) == 0)
3670           {
3671           color[0]=0x17;
3672           }
3673         else
3674           {
3675           color[0]=0x1c;
3676           }
3677         }
3678       else
3679         {
3680         if( (dev_flag[device_no]&(DEVFLAG_W+DEVFLAG_RW)) == 0)
3681           {
3682           color[0]=0x17;
3683           }
3684         else
3685           {
3686           color[0]=0x1c;
3687           }
3688         }
3689       }
3690     else
3691       {
3692 // There are differences.
3693 // We can not arrive here unless there are at least two modes
3694 // and consequently j can not be zero.
3695       if( (j&1) == 0)
3696         {
3697 // We do not have both read and write so it is one of them plus rdwr.
3698 // This does not seem right, but we present the info we get to the user.
3699         color[0]=0x1c;
3700         m=2;
3701         ossdev_show(ss, device_no,
3702                         dev_min_rdwr_speed[device_no],
3703                         dev_max_rdwr_speed[device_no],
3704                         dev_rdwr_channels[device_no],
3705                         dev_rdwr_bytes[device_no],devmode_txt[2]);
3706         if( (dev_flag[device_no]&DEVFLAG_R) == 0)
3707           {
3708           if(sound_type == RXAD || sound_type == TXAD)
3709             {
3710             color[1]=0x17;
3711             }
3712           else
3713             {
3714             color[1]=0x1c;
3715             }
3716           ossdev_show(&ss[maxcolumn], device_no,
3717                           dev_min_wr_speed[device_no],
3718                           dev_max_wr_speed[device_no],
3719                           dev_wr_channels[device_no],
3720                           dev_wr_bytes[device_no],devmode_txt[1]);
3721           }
3722         else
3723           {
3724           if(sound_type == RXAD || sound_type == TXAD)
3725             {
3726             color[1]=0x1c;
3727             }
3728           else
3729             {
3730             color[1]=0x17;
3731             }
3732           ossdev_show(&ss[maxcolumn], device_no,
3733                           dev_min_rd_speed[device_no],
3734                           dev_max_rd_speed[device_no],
3735                           dev_rd_channels[device_no],
3736                           dev_rd_bytes[device_no],devmode_txt[0]);
3737           }
3738         }
3739       else
3740         {
3741 // There is both read and write.
3742         if( (dev_flag[device_no]&DEVFLAG_RW) == 0)
3743           {
3744 // but there is no rdwr
3745           m=2;
3746           if(sound_type == RXAD || sound_type == TXAD)
3747             {
3748             color[1]=0x17;
3749             color[0]=0x1c;
3750             }
3751           else
3752             {
3753             color[1]=0x1c;
3754             color[0]=0x17;
3755             }
3756           ossdev_show(&ss[maxcolumn], device_no,
3757                           dev_min_wr_speed[device_no],
3758                           dev_max_wr_speed[device_no],
3759                           dev_wr_channels[device_no],
3760                           dev_wr_bytes[device_no],devmode_txt[1]);
3761           ossdev_show(ss, device_no,
3762                           dev_min_rd_speed[device_no],
3763                           dev_max_rd_speed[device_no],
3764                           dev_rd_channels[device_no],
3765                           dev_rd_bytes[device_no],devmode_txt[0]);
3766           }
3767         else
3768           {
3769 // There is rdwr, read and write.
3770           if(k == 0)
3771             {
3772 // They are  all different
3773             m=3;
3774             if(sound_type == RXAD || sound_type == TXAD)
3775               {
3776               color[2]=0x17;
3777               color[1]=0x1c;
3778               }
3779             else
3780               {
3781               color[2]=0x1c;
3782               color[1]=0x17;
3783               }
3784             ossdev_show(&ss[2*maxcolumn], device_no,
3785                           dev_min_wr_speed[device_no],
3786                           dev_max_wr_speed[device_no],
3787                            dev_wr_channels[device_no],
3788                           dev_wr_bytes[device_no],devmode_txt[1]);
3789             ossdev_show(&ss[maxcolumn], device_no,
3790                           dev_min_rd_speed[device_no],
3791                           dev_max_rd_speed[device_no],
3792                           dev_rd_channels[device_no],
3793                           dev_rd_bytes[device_no],devmode_txt[0]);
3794             color[0]=0x1c;
3795             ossdev_show(ss, device_no,
3796                           dev_min_rdwr_speed[device_no],
3797                           dev_max_rdwr_speed[device_no],
3798                           dev_rdwr_channels[device_no],
3799                           dev_rdwr_bytes[device_no],devmode_txt[2]);
3800             }
3801           else
3802             {
3803 // rdwr equals read or write.
3804             m=2;
3805             if( (k&4) == 0)
3806               {
3807             if(sound_type == RXAD || sound_type == TXAD)
3808               {
3809               color[1]=0x17;
3810               color[0]=0x1c;
3811               }
3812             else
3813               {
3814               color[1]=0x1c;
3815               color[0]=0x1c;
3816               }
3817               ossdev_show(&ss[maxcolumn], device_no,
3818                            dev_min_wr_speed[device_no],
3819                            dev_max_wr_speed[device_no],
3820                            dev_wr_channels[device_no],
3821                            dev_wr_bytes[device_no],devmode_txt[1]);
3822               ossdev_show(ss, device_no,
3823                            dev_min_rd_speed[device_no],
3824                            dev_max_rd_speed[device_no],
3825                            dev_rd_channels[device_no],
3826                            dev_rd_bytes[device_no],
3827                            devmode_txt[0]);
3828               strcat(ss,devmode_txt[2]);
3829               }
3830              else
3831               {
3832               if(sound_type == RXAD || sound_type == TXAD)
3833                 {
3834                 color[1]=0x17;
3835                 color[0]=0x1c;
3836                 }
3837               else
3838                 {
3839                 color[1]=0x1c;
3840                 color[0]=0x1c;
3841                 }
3842               ossdev_show(&ss[maxcolumn], device_no,
3843                       dev_min_wr_speed[device_no],
3844                       dev_max_wr_speed[device_no],
3845                       dev_wr_channels[device_no], dev_wr_bytes[device_no],
3846                       devmode_txt[1]);
3847               strcat(ss,devmode_txt[2]);
3848                ossdev_show(ss, device_no,
3849                       dev_min_rd_speed[device_no],
3850                       dev_max_rd_speed[device_no],
3851                       dev_rd_channels[device_no],
3852                       dev_rd_bytes[device_no],
3853                       devmode_txt[0]);
3854               }
3855             }
3856           }
3857         }
3858       }
3859     while (m >0)
3860       {
3861       m--;
3862       line[0]++;
3863       if(line[0] >= screen_last_line-1)
3864         {
3865         for(column=0; column<maxcolumn; column++)s[column]=' ';
3866         s[maxcolumn]=0;
3867         lir_text(0,line[0],s);
3868         settextcolor(14);
3869         lir_text(10,line[0],"(press ENTER to continue)");
3870         settextcolor(7);
3871         await_keyboard();
3872         if(kill_all_flag) goto sel_ossdev_skip;
3873         lir_text(0,line[0],s);
3874         bottom_line=screen_last_line-1;
3875         line[0]=1;
3876         }
3877       column=0;
3878       while(ss[m*maxcolumn+column]!=0)column++;
3879       while(column < maxcolumn)
3880         {
3881         ss[m*maxcolumn+column]=' ';
3882         column++;
3883         }
3884       ss[(m+1)*maxcolumn-1]=0;
3885       settextcolor((unsigned char)color[m]);
3886       lir_text(0,line[0],&ss[m*maxcolumn]);
3887       lir_refresh_screen();
3888       SNDLOG"\n%s    color=%d m=%d",&ss[m*maxcolumn],color[m],m);
3889       }
3890     SNDLOG"\n");
3891     }
3892 used_rdwr: ;
3893   }
3894 settextcolor(7);
3895 line[0]++;
3896 clear_lines(line[0],line[0]);
3897 if(bottom_line > line[0])line[0]=bottom_line;
3898 display_sdi();
3899 if(sound_type == TXDA)
3900   {
3901   if(n == 0)
3902     {
3903     ui.tx_dadev_no=UNDEFINED_DEVICE_CODE;
3904     lir_text(0,line[0],"No device found for Tx output");
3905     lir_text(2,line[0]+1,"ERROR (press any key)");
3906     await_keyboard();
3907     goto sel_ossdev_skip;
3908     }
3909   line[0]++;
3910   lir_text(10,line[0],"=>");
3911 get_tx_dadev:;
3912   ui.tx_dadev_no=lir_get_integer(13, line[0], 3, 0,MAX_DEVNAMES-1);
3913   if(kill_all_flag) goto sel_ossdev_skip;
3914   if( (dev_flag[ui.tx_dadev_no]&(DEVFLAG_W+DEVFLAG_RW)) == 0)
3915     {
3916     settextcolor(15);
3917     lir_text(29,line[0],"???");
3918     lir_text(25,line[0]+1,"ERROR (press any key)");
3919     await_keyboard();
3920     if(kill_all_flag) goto sel_ossdev_skip;
3921     clear_lines(line[0]+1,line[0]+1);
3922     goto  get_tx_dadev;
3923     }
3924   line[0]+=2;
3925   }
3926 if(sound_type == RXDA)
3927   {
3928   if(n  == 0)
3929     {
3930     if(soundcard_test_cmd_flag[RXAD] != THRFLAG_ACTIVE)
3931       {
3932       line[0]++;
3933       lir_text(0,line[0],"No usable device found");
3934       goto sel_ossdev_skip;
3935       }
3936     if(line[0] > screen_last_line-6)line[0]=screen_last_line-6;
3937     lir_text(0,line[0],
3938            "No device found for 1/2 byte output while input is open.");
3939     lir_text(0,line[0]+1,
3940             "You may use Linrad to watch spectra and record raw data.");
3941     lir_text(0,line[0]+2,
3942            "Linrad will now look for devices that can be used to");
3943     lir_text(0,line[0]+3,
3944            "output sound while processing recorded data.");
3945     lir_text(0,line[0]+4,press_any_key);
3946     SNDLOG"\nNo output device found while input is open.");
3947     await_keyboard();
3948     clear_lines(line[0],line[0]+4);
3949     goto sel_ossdev_skip;
3950     }
3951   if(n == 1)
3952     {
3953     ui.rx_dadev_no=suggested_dev;
3954     show_oss_presel(line,suggested_dev);
3955     }
3956   if(n > 1)
3957     {
3958     line[0]++;
3959     lir_text(10,line[0],"=>");
3960 get_rx_dadev:;
3961     display_sdi() ;
3962     ui.rx_dadev_no=lir_get_integer(13, line[0], 3, 0,MAX_DEVNAMES-1);
3963     if(kill_all_flag)goto sel_ossdev_skip;
3964     if( (dev_flag[ui.rx_dadev_no]&(DEVFLAG_W+DEVFLAG_RW)) == 0)
3965       {
3966       settextcolor(15);
3967       lir_text(51,line[0],"???");
3968       lir_text(35,line[0]+1,"ERROR (press any key)");
3969       await_keyboard();
3970       if(kill_all_flag) goto sel_ossdev_skip;
3971       clear_lines(line[0],line[0]+1);
3972       goto get_rx_dadev;
3973       }
3974     }
3975   goto sel_ossdev_skip;
3976   }
3977 if(sound_type == TXAD)
3978   {
3979   if(n == 0)
3980     {
3981     lir_text(0,line[0],"No device found for microphone input.");
3982     line[0]++;
3983     lir_text(2,line[0]+1,"ERROR (press any key)");
3984     await_keyboard();
3985     goto sel_ossdev_skip;
3986     }
3987   line[0]++;
3988   lir_text(10,line[0],"=>");
3989   get_micdev:;
3990   ui.tx_addev_no=lir_get_integer(13, line[0], 3, 0,MAX_DEVNAMES-1);
3991   if( (dev_flag[ui.tx_addev_no]&(DEVFLAG_R+DEVFLAG_RW)) == 0)
3992     {
3993     settextcolor(15);
3994     lir_text(37,line[0],"???");
3995     lir_text(25,line[0]+1,"ERROR (press any key)");
3996     await_keyboard();
3997     if(kill_all_flag)goto sel_ossdev_skip;
3998     clear_lines(line[0]+1,line[0]+1);
3999     goto get_micdev;
4000     }
4001   goto sel_ossdev_skip;
4002   }
4003 if(sound_type  == RXAD)
4004   {
4005   if(n == 0)
4006     {
4007     if(line[0] > screen_last_line-5)
4008       {
4009       line[0]=screen_last_line-5;
4010       clear_lines(line[0], screen_last_line);
4011       }
4012     lir_text(0,line[0],"No OSS sound device found (for 2/4 byte input).");
4013     line[0]+=2;
4014 #if (ALSA_PRESENT == 1)
4015     lir_text(0,line[0],"ALSA is available, you may press 'Y' to use it.");
4016 #else
4017     lir_text(10,line[0],"ALSA is not available.");
4018     line[0]++;
4019 #endif
4020     line[0]+=2;
4021     lir_text(0,line[0],press_f1_for_info);
4022     line[0]++;
4023     lir_text(20,line[0],press_any_key);
4024     await_processed_keyboard();
4025     if(lir_inkey == F1_KEY || lir_inkey == '!')
4026       {
4027 #if (ALSA_PRESENT == 1)
4028       help_message(332);
4029 #else
4030       help_message(333);
4031 #endif
4032       }
4033     SNDLOG"\nNo input device found");
4034     ui.rx_addev_no=UNDEFINED_DEVICE_CODE;
4035     goto sel_ossdev_skip;
4036     }
4037   if(n == 1)
4038     {
4039     ui.rx_addev_no=suggested_dev;
4040     show_oss_presel(line,suggested_dev);
4041     }
4042   if(n > 1)
4043     {
4044     line[0]++;
4045     lir_text(10,line[0],"=>");
4046 get_rx_addev:;
4047     display_sdi();
4048     ui.rx_addev_no=lir_get_integer(13, line[0], 3, 0,MAX_DEVNAMES-1);
4049     if(kill_all_flag)goto sel_ossdev_skip;
4050     if( (dev_flag[ui.rx_addev_no]&(DEVFLAG_R+DEVFLAG_RW)) == 0)
4051       {
4052       settextcolor(15);
4053       lir_text(51,line[0],"???");
4054       lir_text(35 ,line[0]+1,"ERROR (press any key)");
4055       await_keyboard();
4056       if(kill_all_flag) goto sel_ossdev_skip;
4057       clear_lines(line[0],line[0]+1);
4058       goto get_rx_addev;
4059       }
4060     }
4061   make_devname(ui.rx_addev_no, dev_name);
4062   if(kill_all_flag)goto sel_ossdev_skip;
4063   SNDLOG"\n\n %s selected by user for input.",dev_name);
4064   SNDLOG"   dev_flag=%d",dev_flag[ui.rx_addev_no]);
4065   sndlog_sync();
4066 // High end users might need two devices to read four A/D channels.
4067 // This is an option introduced April 2004 to allow two receive
4068 // channels with the Lynx Two card (model A).
4069 // Do not confus e other users by asking for a second input device
4070 // unless the selected device has 32 bits but only allows 2 channels.
4071   if(dev_rd_bytes[ui.rx_addev_no] >= 4 &&
4072      dev_rd_channels[ui.rx_addev_no]==2 &&
4073      (dev_flag[ui.rx_addev_no]&DEVFLAG_R) != 0)
4074     {
4075     SNDLOG"\n\n User selected 4 byte device with max two channels.");
4076     j=0;
4077     clear_lines(1,line[0]);
4078     line[0]=1;
4079     for(i=0; i<MAX_DEVNAMES; i++)
4080       {
4081       if(i != ui.rx_addev_no &&
4082          dev_max_rd_speed[i] == dev_max_rd_speed[ui.rx_addev_no] &&
4083          dev_rd_bytes[i] >= 4 &&
4084          (dev_flag[i]&DEVFLAG_R) != 0)
4085         {
4086 // This device can also read 32 bits at the same speed.
4087 // Check if it  can be opened simultaneously in read mode.
4088         if(j==0)
4089           {
4090           line[0]++;
4091           lir_text(5,line[0],"This device allows two channels only.");
4092           line[0]++;
4093           lir_text(5,line[0],"Do you want to use a second device to run two");
4094           line[0]++;
4095           lir_text(5,line[0],"receive channels with four audio channels ?");
4096           line[0]++;
4097           lir_text(5,line[0],"(Y/N)=>");
4098           line[0]++;
4099 gt_dual:;
4100           await_processed_keyboard();
4101           line[0]+=2;
4102           if( kill_all_flag) goto sel_ossdev_skip;
4103           if(lir_inkey == 'N')
4104             {
4105             SNDLOG"\nUser skipped dual devices");
4106             goto skip_dual_devices;
4107             }
4108           if(lir_inkey != 'Y')goto gt_dual;
4109           SNDLOG"\nUser wants to try to open two read devices");
4110           make_devname(ui.rx_addev_no, dev_name);
4111           if(kill_all_flag)goto sel_ossdev_skip;
4112           h_test=open( dev_name, O_RDONLY|O_EXCL, 0);
4113           if(h_test == -1)
4114             {
4115             lirerr(1102);
4116             goto sel_ossdev_skip;
4117             }
4118 #ifdef SNDCTL_DSP_COOKEDMODE
4119           k=0;
4120           ioctl(h_test, SNDCTL_DSP_COOKEDMODE, &k);
4121 #endif
4122 // Check for DSP_CAP_TRIGGER capability
4123           if(ioctl(h_test, SNDCTL_DSP_GETCAPS,&caps) == -1)
4124             {
4125             lirerr(1182);
4126             goto sel_ossdev_skip;
4127             }
4128           if( (caps&DSP_CAP_TRIGGER) == 0)
4129             {
4130             SNDLOG"\nDevice does not have DSP_CAP_TRIGGER");
4131             close(h_test);
4132              goto skip_dual_devices;
4133             }
4134           j=2;
4135           if(ioctl(h_test, SNDCTL_DSP_CHANNELS, &j) == -1)
4136             {
4137             lirerr(1185);
4138             goto sel_ossdev_skip;
4139             }
4140           if(j != 2)
4141             {
4142             lirerr(1186);
4143             goto sel_ossdev_skip;
4144             }
4145           }
4146         make_devname(i, dev_name);
4147         if(kill_all_flag)goto sel_ossdev_skip;
4148         h_test2=open( dev_name, O_RDONLY|O_NONBLOCK|O_EXCL, 0);
4149         if(h_test2 != -1)
4150            {
4151 #ifdef SNDCTL_DSP_COOKEDMODE
4152           k=0;
4153           ioctl(h_test2, SNDCTL_DSP_COOKEDMODE, &k);
4154 #endif
4155           line[0]++;
4156           SNDLOG"\n%s opened as second read device",dev_name);
4157           sprintf(s,"%2d:%12s  %7d - %7d Hz   %d Chan.   %d bit",
4158                     i,dev_name,
4159                     dev_min_rd_speed[i],
4160                     dev_max_rd_speed[i],
4161                     dev_rd_channels[i],
4162                      dev_rd_bytes[i]);
4163           lir_text(0,line[0],s);
4164           close(h_test2);
4165           dev_flag[i]|=256;
4166           }
4167         }
4168       }
4169     if(j == 0)goto skip_dual_devices;
4170     settextcolor(14);
4171     lir_text(0,line[0]+1,"Select second input device by Dev no.");
4172 get_addev2:;
4173     settextcolor(7);
4174     i=lir_get_integer(51, line[0]+1, 3, 0,MAX_DEVNAMES-1);
4175     if(kill_all_flag)goto sel_ossdev_skip;
4176     if( (256 & dev_flag[i]) == 0)
4177       {
4178       settextcolor(15);
4179       lir_text(40,line[0],"???");
4180       lir_text(35,line[0]+1,"ERROR (press any key)");
4181       await_keyboard();
4182       if(kill_all_flag) goto sel_ossdev_skip;
4183       clear_lines(line[0]+1,line[0]+1);
4184       settextcolor(7);
4185       goto get_addev2;
4186       }
4187 // We store the second A/D device in the second byte of ad_device_no
4188     make_devname(i, dev_name);
4189     if(kill_all_flag)goto sel_ossdev_skip;
4190     ui.rx_addev_no+=256*(i+1);
4191     dev_flag[i]&=255;
4192     h_test2=open( dev_name, O_RDONLY|O_NONBLOCK|O_EXCL, 0);
4193     if(h_test2 == -1)
4194       {
4195       lirerr(1172);
4196       goto sel_ossdev_skip;
4197       }
4198 #ifdef SNDCTL_DSP_COOKEDMODE
4199     k=0;
4200     ioctl(h_test2, SNDCTL_DSP_COOKEDMODE, &k);
4201 #endif
4202 // Check for DSP_CAP_TRIGGER capability
4203     if(ioctl(h_test2, SNDCTL_DSP_GETCAPS,&caps) == -1)
4204       {
4205       lirerr(1182);
4206       goto sel_ossdev_skip;
4207        }
4208     if( (caps&DSP_CAP_TRIGGER) == 0)
4209       {
4210       SNDLOG"\nSecond input device does not have DSP_CAP_TRIGGER");
4211       close(h_test);
4212       close(h_test2);
4213       goto skip_dual_devices;
4214       }
4215     SNDLOG"\n %s is second input device.",dev_name);
4216     ui.rx_input_mode=TWO_CHANNELS+IQ_DATA;
4217     ui.rx_rf_channels=2;
4218     ui.rx_ad_channels=4;
4219     clear_screen();
4220     goto continue_dual;
4221 skip_dual_devices:;
4222     clear_screen();
4223     }
4224 // Now that we decided what device to use for input, open it and let
4225 // the user decide how to use it.
4226   if(ui.rx_addev_no != UNDEFINED_DEVICE_CODE)
4227     {
4228     make_devname(ui.rx_addev_no, dev_name);
4229     if(kill_all_flag)goto sel_ossdev_skip;
4230     sndlog_sync();
4231     line[0]++;
4232     ui.rx_admode=select_rdwr_mode(line, ui.rx_addev_no, O_RDONLY);
4233     if(kill_all_flag) goto sel_ossdev_skip;
4234     sndlog_sync();
4235     }
4236   clear_screen();
4237   line[0]=0;
4238   mode=0;
4239   if(ui.rx_admode == O_RDWR)mode=2;
4240   sprintf(s,"For analog input: %s opened in %s mode",
4241                                                dev_name,devmode_txt[mode]);
4242   lir_text(0,line[0],s);
4243   line[0]+=2;
4244   rx_audio_in=open( dev_name, ui.rx_admode|O_EXCL, 0);
4245   if(rx_audio_in == -1)
4246      {
4247     lirerr(1038);
4248     goto sel_ossdev_skip;
4249     }
4250 continue_dual:;
4251   clear_lines(10,11+j);
4252 #ifdef SOUND_OSS
4253   sprintf(s,"Use ossmix");
4254 #else
4255   sprintf(s,"Use system mixer program");
4256 #endif
4257   column=0;
4258   while(s[column] != 0)column++;
4259   sprintf(&s[column]," to select input and");
4260   lir_text(0,line[0],s);
4261   line[0]++;
4262   lir_text(0,line[0],"to disable direct connection from input to output etc.");
4263   line[0]+=2;
4264    lir_text(0,line[0],"In case selection of sampling frequencies is not what you");
4265   line[0]++;
4266   lir_text(0,line[0],
4267         "expect, check README files for your board - there may be ways");
4268   line[0]++;
4269   lir_text(0,line[0],"to reconfigure the hardware. (Under OSS, run ossmix)");
4270   }
4271 sel_ossdev_skip:;
4272 free(rdtest_buffer);
4273 line[0]+=2;
4274 }
4275 #endif
4276 
4277 
set_rx_dadev_parms(int * line)4278 void set_rx_dadev_parms(int *line)
4279 {
4280 if(ui.rx_dadev_no == UNDEFINED_DEVICE_CODE)return;
4281 ui.rx_min_da_channels=1;
4282 ui.rx_max_da_channels=2;
4283 if( (dev_wr_channels[ui.rx_dadev_no]&3) == 0)
4284    {
4285   lir_text(0,line[0],
4286             "Error: Device must have 1 or 2 channels (or both).");
4287   line[0]++;
4288   lir_text(0,line[0],wish_anyway);
4289 anyway:;
4290   await_processed_keyboard();
4291   if(lir_inkey=='N')
4292     {
4293     ui.rx_dadev_no=UNDEFINED_DEVICE_CODE;
4294     return;
4295     }
4296   if(lir_inkey != 'Y')goto anyway;
4297   }
4298 else
4299   {
4300   if( (dev_wr_channels[ui.rx_dadev_no]&1) == 0)ui.rx_min_da_channels=2;
4301   if( (dev_wr_channels[ui.rx_dadev_no]&2) == 0)ui.rx_max_da_channels=1;
4302   }
4303 ui.rx_min_da_speed=dev_min_wr_speed[ui.rx_dadev_no];
4304 ui.rx_max_da_speed=dev_max_wr_speed[ui.rx_dadev_no];
4305 ui.rx_min_da_bytes=1;
4306 if( (dev_wr_bytes[ui.rx_dadev_no]&1) == 0)ui.rx_min_da_bytes=2;
4307 ui.rx_max_da_bytes=ui.rx_min_da_bytes;
4308 if( (dev_wr_bytes[ui.rx_dadev_no]&2) != 0)ui.rx_max_da_bytes=2;
4309 }
4310 
stop_iotest(int mode)4311 void stop_iotest(int mode)
4312 {
4313 soundcard_test_cmd_flag[mode]=THRFLAG_KILL;
4314 pthread_join(thread_identifier_soundcard_test[mode],0);
4315 }
4316 
start_iotest(int * line,int mode)4317 int start_iotest(int *line, int mode)
4318 {
4319 char *mode_text[3]={"RX INPUT", "RX OUTPUT", "TX OUTPUT"};
4320 char s[80];
4321 int i;
4322 // To make sure that the devices we select for tx or for rx output can
4323 // be used while the rx input is running we start a separate thread that
4324 // uses the rx input so we will fail on devices that do not
4325 // allow simultaneous read and write.
4326 soundcard_test_block_count[mode]=0;
4327 soundcard_test_cmd_flag[mode]=THRFLAG_ACTIVE;
4328 pthread_create(&thread_identifier_soundcard_test[mode],
4329                                    NULL,(void*)thread_iotest[mode], NULL);
4330 i=0;
4331 while(i < 100 && soundcard_test_block_count[mode] < 8)
4332   {
4333   lir_sleep(10000);
4334   if(kill_all_flag)return FALSE;
4335   i++;
4336   }
4337 if(i >= 100)
4338   {
4339   line[0]+=2;
4340   settextcolor(12);
4341   sprintf(s,"FAILED TO RUN THE %s",mode_text[mode]);
4342   lir_text(0,line[0],s);
4343   line[0]++;
4344   if(mode == RXAD)
4345     {
4346     lir_text(0,line[0],"Set a working input or force no soundcard by");
4347     line[0]++;
4348     lir_text(0,line[0],"selecting network input, then soundcard select.");
4349     line[0]++;
4350     lir_text(0,line[0],press_any_key);
4351     await_keyboard();
4352     settextcolor(7);
4353     return FALSE;
4354     }
4355   }
4356 settextcolor(7);
4357 return TRUE;
4358 }
4359 
set_rx_io(void)4360 void set_rx_io(void)
4361 {
4362 char *tmptxt;
4363 char *tmptxt1;
4364 int dev_max_channels;
4365 int dev_min_channels;
4366 int i, j, k;
4367 int n1, n2, m1, m2;
4368 #if HAVE_OSS == 1
4369 int speed_warning;
4370 int min, max;
4371 int trySpeed, deltaSpeed;
4372 int rdwr_max_speed;
4373 int column;
4374 #endif
4375 int line, refline;
4376 char s[256];
4377 char s1[256];
4378 #if (ALSA_PRESENT == 1)
4379 unsigned int new_sample_rate;
4380 #endif
4381 int err;
4382 char pa_device_name[128];
4383 char pa_device_hostapi  [128];
4384 double pa_device_max_speed;
4385 double pa_device_min_speed;
4386 int pa_device_max_bytes;
4387 int pa_device_min_bytes;
4388 int pa_device_max_channels;
4389 int pa_device_min_channels;
4390 dev_max_channels=1;
4391 dev_min_channels=1;
4392 memset(blanks, ' ',58);
4393 blanks[59]=0;
4394 refline=0;
4395 sndlog=fopen(rx_logfile_name, "w");
4396 if(sndlog == NULL)
4397   {
4398   lirerr(1016);
4399   return;
4400   }
4401 write_log=TRUE;
4402 if(ui.rx_addev_no != DISABLED_DEVICE_CODE)
4403   {
4404   if(ui.rx_ad_channels == 0 && ui.rx_dadev_no != DISABLED_DEVICE_CODE)
4405     {
4406     if(ui.rx_max_da_channels == 0 )
4407       {
4408       ui.use_alsa=0;
4409       }
4410     ui.rx_addev_no=UNDEFINED_DEVICE_CODE;
4411     }
4412   if(ui.rx_max_da_channels == 0)
4413     {
4414     ui.rx_dadev_no=UNDEFINED_DEVICE_CODE;
4415     }
4416   }
4417 ui.use_alsa&=NATIVE_ALSA_USED;
4418 #if (ALSA_PRESENT == 1)
4419 if(ui.rx_addev_no < 0)ui.use_alsa|=NATIVE_ALSA_USED;
4420 #endif
4421 begin_rx_set_io:;
4422 clear_screen();
4423 settextcolor(14);
4424 line=0;
4425 lir_text(2,line,"CURRENT A/D and D/A SETUP FOR RX");
4426 if(ui.use_extio != 0)
4427   {
4428   get_extio_name(&s[0]);
4429   lir_text(35,line,"using");
4430   lir_text(41,line,s);
4431   if(ui.extio_type == 4)
4432     {
4433     lir_text((int)(42+strlen(s)),line,"with soundcard input.");
4434     }
4435   else
4436     {
4437     if(ui.extio_type >= 3 && ui.extio_type <= 7)
4438       {
4439       goto display_rx_out;
4440       }
4441     else
4442       {
4443       lirerr(1237);
4444       return;
4445       }
4446     }
4447   }
4448 line+=2;
4449 settextcolor(7);
4450 // ******************************************
4451 // Start by writing what sound system we use
4452 // ******************************************
4453 #if (ALSA_PRESENT == 1)
4454 lir_text(2,line,"The current sound system is:");
4455 settextcolor(10);
4456 if( (ui.use_alsa&NATIVE_ALSA_USED)!=0)
4457   {
4458   lir_text(31,line,"native ALSA");
4459   SNDLOG"\nsound system = native ALSA ");
4460   }
4461 else
4462   {
4463 #ifdef SOUND_OSS
4464   lir_text(31,line,"4Front OSS");
4465 #else
4466   lir_text(31,line,"alsa-oss");
4467 #endif
4468   SNDLOG"\nsound system = alsa-oss emulation ");
4469   }
4470 #ifndef SOUND_OSS
4471 sprintf(s,"(ALSA library version:%s)",SND_LIB_VERSION_STR);
4472 settextcolor(7);
4473 lir_text(43,line,s);
4474 #endif
4475 #else
4476 ui.use_alsa&=~NATIVE_ALSA_USED;
4477 lir_text(2,line,"This system uses OSS or legacy sound.");
4478 SNDLOG"\nsound system= OSS or legacy sound ");
4479 #endif
4480 line+=2;
4481 if( show_rx_input_settings(&line) )goto display_rx_out;
4482 // check for input soundcards
4483 if(ui.rx_addev_no == UNDEFINED_DEVICE_CODE)
4484   {
4485   settextcolor(12);
4486   if (ui.operator_skil != OPERATOR_SKIL_NEWCOMER)
4487     {
4488     sprintf(s,"NOT YET SELECTED (Select Menu Option ""A"")");
4489     }
4490   else
4491     {
4492     sprintf(s,"SOUNDCARD NOT YET SELECTED: Select Menu Option A ");
4493     }
4494   lir_text(24,line,s);
4495   SNDLOG"\n%s",s);
4496   goto display_rx_out;
4497   }
4498 if ( (ui.use_alsa&PORTAUDIO_RX_IN) != 0)
4499   {
4500   err=pa_get_device_info (ui.rx_addev_no,
4501                           RXAD,
4502                           &pa_device_name,
4503                           &pa_device_hostapi,
4504 			  &pa_device_max_speed,
4505 			  &pa_device_min_speed,
4506 			  &pa_device_max_bytes,
4507 			  &pa_device_min_bytes,
4508 			  &pa_device_max_channels,
4509 			  &pa_device_min_channels );
4510   if (err >= 0)
4511     {
4512     sprintf(s,"SOUNDCARD device   = %s ", pa_device_name);
4513     lir_text(24,line,s);
4514     SNDLOG"\n%s",s);
4515     line+=1;
4516     sprintf(s,"device number      = %d", ui.rx_addev_no);
4517     lir_text(24,line,s);
4518     SNDLOG"\n%s",s);
4519     line+=1;
4520     sprintf(s,"hostapi            = Portaudio (%s)", pa_device_hostapi);
4521     lir_text(24,line,s);
4522     SNDLOG"\n%s",s);
4523     }
4524   else
4525     {
4526     sprintf (s,"PORTAUDIO device number %d : INVALID DEVICE ",ui.rx_addev_no );
4527     settextcolor(12);
4528     lir_text(24,line,s);
4529     SNDLOG"\n%s",s);
4530     ui.rx_addev_no=UNDEFINED_DEVICE_CODE;
4531     goto  set_rx_io_ask;
4532     }
4533   }
4534 #if (ALSA_PRESENT == 1)
4535 if(( (ui.use_alsa&NATIVE_ALSA_USED)!=0) && ((ui.use_alsa&PORTAUDIO_RX_IN) == 0))
4536   {
4537   err=alsa_get_dev_names (ui.rx_addev_no);
4538   if(err < 0)
4539     {
4540     sprintf(s,"SOUNDCARD device number %i : INVALID DEVICE ", ui.rx_addev_no );
4541     settextcolor(12);
4542     lir_text(24,line,s);
4543     SNDLOG"\n%s\n",s);
4544     ui.rx_addev_no=UNDEFINED_DEVICE_CODE;
4545     goto display_rx_out;
4546     }
4547   else
4548     {
4549     sprintf(s,"SOUNDCARD          =%s",alsa_dev_soundcard_name);
4550     lir_text(24,line,s);
4551     SNDLOG"\n%s",s);
4552     sprintf(s,"device             =%s (%s)",alsa_dev_name,alsa_dev_plughw_pcm_name);
4553     line+=1;
4554     lir_text(24,line,s);
4555     SNDLOG"\n%s",s);
4556     sprintf(s,"device number      = %i", alsa_dev_seq_nmbr);
4557     line+=1;
4558     lir_text(24,line,s);
4559     line+=1;
4560     sprintf(s,"hostapi            = Native ALSA");
4561     lir_text(24,line,s);
4562     SNDLOG"\n%s",s);
4563     }
4564   }
4565 else
4566 #endif
4567   {
4568   if((ui.use_alsa&PORTAUDIO_RX_IN) == 0)
4569     {
4570 #if HAVE_OSS == 1
4571 // no validation available for alsa-oss or OSS
4572     sprintf(dev_name,"%s",SND_DEV);
4573     if(dev_name[0] != 'u')make_devname(ui.rx_addev_no, dev_name);
4574     if(kill_all_flag)goto set_rx_io_errexit;
4575     sprintf(s,"SOUNDCARD device   = %s",dev_name);
4576     lir_text(24,line,s);
4577     line+=1;
4578     sprintf(s,"hostapi            = alsa-oss");
4579     lir_text(24,line,s);
4580     SNDLOG"\n%s",s);
4581 #else
4582     lir_text(24,line,"ERROR");
4583     line+=1;
4584 #endif
4585     }
4586   }
4587 line++;
4588 settextcolor(7);
4589 sprintf(s,"associated radio   = %s",soundcard_radio_names[ui.soundcard_radio]);
4590 lir_text(24,line,s);
4591 line++;
4592 if(ui.soundcard_radio == SOUNDCARD_RADIO_WSE)
4593   {
4594   sprintf(s,"Port=%d Pin =%d",wse.parport,wse.parport_pin);
4595   lir_text(50,line,s);
4596   if (wse.parport==USB2LPT16_PORT_NUMBER)
4597     {
4598     settextcolor(10);
4599     if(libusb1_library_flag == TRUE || libusb0_library_flag == TRUE)
4600       {
4601       sprintf(s,"USB2LPT 1.6 SELECTED");
4602       lir_text(70,line,s);
4603       }
4604     else
4605       {
4606       clear_lines(line,line);
4607       lir_text(15,line,"For USB2LTP you must install libusb or libusb-1.0");
4608       }
4609     settextcolor(7);
4610     }
4611   }
4612 line+=1;
4613 sprintf(s,"sample rate        = %i ",ui.rx_ad_speed );
4614 SNDLOG"\n%s",s);
4615 lir_text(24,line,s);
4616 line++;
4617 if ( (ui.use_alsa&PORTAUDIO_RX_IN) != 0)
4618   {
4619   sprintf(s,"latency factor     = %i ",ui.rx_ad_latency );
4620   SNDLOG"\n%s",s);
4621   lir_text(24,line,s);
4622   line++;
4623   }
4624 sprintf(s,"No of input bytes  = 2 (16 bits)");
4625 if( (ui.rx_input_mode&DWORD_INPUT) != 0)
4626   {
4627   sprintf(&s[21],"4 (32 bits)");
4628   }
4629 SNDLOG"\n%s",s);
4630 lir_text(24,line,s);
4631 line+=1;
4632 tmptxt=" ";
4633 tmptxt1=" ";
4634 if( ((ui.rx_input_mode&TWO_CHANNELS) == 0)&&((ui.rx_input_mode&IQ_DATA) == 0))
4635   {
4636   tmptxt="radio interface    = One Rx channel, one audio channels ";
4637   tmptxt1="                     (normal audio)";
4638   }
4639 if( ((ui.rx_input_mode&TWO_CHANNELS) == 0)&&((ui.rx_input_mode&IQ_DATA) != 0))
4640   {
4641   tmptxt="radio interface    = One Rx channel, two audio channels ";
4642   sprintf(s,"                     (direct conversion, time shift=%d)",
4643                       ui.sample_shift );
4644   tmptxt1=s;
4645   }
4646 if( ((ui.rx_input_mode&TWO_CHANNELS) != 0)&&((ui.rx_input_mode&IQ_DATA) != 0))
4647   {
4648   tmptxt="radio interface    = Two Rx channels, four audio channels ";
4649   tmptxt1="                     (direct conversion, adaptive polarization)";
4650   }
4651 if( ((ui.rx_input_mode&TWO_CHANNELS) != 0)&&((ui.rx_input_mode&IQ_DATA) == 0))
4652   {
4653   tmptxt="radio interface    = Two Rx channels, two audio channels ";
4654   tmptxt1="                     (normal audio, adaptive polarization)";
4655   }
4656 lir_text(24,line,tmptxt);
4657 SNDLOG"\n%s",tmptxt);
4658 line+=1;
4659 lir_text(24,line,tmptxt1);
4660 SNDLOG"\n%s\n",tmptxt1);
4661 display_rx_out:;
4662 // ************************************************************************************
4663 // Show the current RX output settings on the screen and do some validation if possible
4664 // ************************************************************************************
4665 settextcolor(7);
4666 line+=2;
4667 lir_text(2,line,"Linrad RX output to:");
4668 SNDLOG"\nSETUP FOR RX OUTPUT IS NOW:\n");
4669 settextcolor(10);
4670 //check if network output mode
4671 s[0]='\0';
4672 if((ui.network_flag & NET_RXOUT_RAW16) != 0)  strncat ( s,"RAW16 ",6);
4673 if((ui.network_flag & NET_RXOUT_RAW18) != 0)  strncat ( s,"RAW18 ",6);
4674 if((ui.network_flag & NET_RXOUT_RAW24) != 0)  strncat ( s,"RAW24 ",6);
4675 if((ui.network_flag & NET_RXOUT_FFT1)  != 0)  strncat ( s,"FFT1 ",6);
4676 if((ui.network_flag & NET_RXOUT_TIMF2) != 0)  strncat ( s,"TIMF2 ",6);
4677 if((ui.network_flag & NET_RXOUT_FFT2)  != 0)  strncat ( s,"FFT2 ",6);
4678 if((ui.network_flag & NET_RXOUT_BASEB)  != 0)  strncat ( s,"BASEB16 ",9);
4679 if((ui.network_flag & NET_RXOUT_BASEBRAW) != 0)  strncat ( s,"BASEB24 ",9);
4680 if (strlen(s) != 0)
4681   {
4682   sprintf(s1,"NETWORK");
4683   lir_text(24,line,s1);
4684   SNDLOG"\n%s",s1);
4685   settextcolor(7);
4686   line+=1;
4687   sprintf(s1,"send format        = %s",s);
4688   lir_text(24,line,s1);
4689   SNDLOG"\n%s\n",s1);
4690   line+=2;
4691   settextcolor(10);
4692 //disable output soundcard if not yet selected
4693   if(ui.rx_dadev_no == UNDEFINED_DEVICE_CODE) ui.rx_dadev_no=DISABLED_DEVICE_CODE;
4694   }
4695 //check for output soundcards
4696 if(ui.rx_dadev_no < 0)
4697   {
4698   if(ui.rx_dadev_no == UNDEFINED_DEVICE_CODE)
4699     {
4700     settextcolor(12);
4701     if (ui.operator_skil != OPERATOR_SKIL_NEWCOMER)
4702       {
4703       sprintf(s,"NOT YET SELECTED (SHOULD BE EITHER SOUNDCARD OR DISABLED, AND/OR NETWORK)");
4704       }
4705     else
4706       {
4707       sprintf(s,"SOUNDCARD NOT YET SELECTED OR DISABLED: Select Menu Option B or Z ");
4708       }
4709     lir_text(24,line,s);
4710     SNDLOG"\n%s",s);
4711     goto set_rx_io_ask;
4712     }
4713   else
4714     {
4715     ui.rx_dadev_no=DISABLED_DEVICE_CODE;
4716     sprintf(s,"SOUNDCARD DISABLED");
4717     lir_text(24,line,s);
4718     SNDLOG"\n%s",s);
4719     goto set_rx_io_ask;
4720     }
4721   }
4722 else
4723   {
4724 if( (ui.use_alsa&PORTAUDIO_RX_OUT) != 0)
4725   {
4726   err=pa_get_device_info (ui.rx_dadev_no,
4727                           RXDA,
4728                           &pa_device_name,
4729                           &pa_device_hostapi,
4730 			  &pa_device_max_speed,
4731 			  &pa_device_min_speed,
4732 			  &pa_device_max_bytes,
4733 			  &pa_device_min_bytes,
4734 			  &pa_device_max_channels,
4735 			  &pa_device_min_channels
4736 						 );
4737   if (err == 0 )
4738     {
4739     sprintf(s,"SOUNDCARD device   = %s  ", pa_device_name );
4740     lir_text(24,line,s);
4741     SNDLOG"\n%s",s);
4742     line++;
4743     sprintf(s,"device  number     = %d", ui.rx_dadev_no);
4744     lir_text(24,line,s);
4745     SNDLOG"\n%s",s);
4746     line++;
4747     sprintf(s,"hostapi            = Portaudio (%s) ", pa_device_hostapi);
4748     lir_text(24,line,s);
4749     SNDLOG"\n%s",s);
4750     ui.rx_min_da_speed=(int)pa_device_min_speed;
4751     ui.rx_max_da_speed=(int)pa_device_max_speed;
4752     ui.rx_min_da_bytes=pa_device_min_bytes;
4753     ui.rx_max_da_bytes=pa_device_max_bytes;
4754     ui.rx_min_da_channels=pa_device_min_channels;
4755     ui.rx_max_da_channels=pa_device_max_channels;
4756     }
4757   else
4758     {
4759     sprintf(s,"INVALID DEVICE (Portaudio device number= %d )", ui.rx_dadev_no );
4760     settextcolor(12);
4761     lir_text(24,line,s);
4762     SNDLOG"\n%s\n",s);
4763     ui.rx_dadev_no=UNDEFINED_DEVICE_CODE;
4764     goto  set_rx_io_ask;
4765     }
4766   }
4767 else
4768   {
4769 #if (ALSA_PRESENT == 1)
4770     if( (ui.use_alsa&NATIVE_ALSA_USED)!=0)
4771      {
4772      err=alsa_get_dev_names (ui.rx_dadev_no);
4773       if(err < 0)
4774         {
4775         sprintf(s,"SOUNDCARD device number %i : INVALID DEVICE ",
4776                                                             ui.rx_dadev_no );
4777         settextcolor(12);
4778         lir_text(24,line,s);
4779         SNDLOG"\n%s\n",s);
4780         ui.rx_dadev_no=UNDEFINED_DEVICE_CODE;
4781         goto  set_rx_io_ask;
4782         }
4783       else
4784         {
4785         sprintf(s,"SOUNDCARD          =%s",alsa_dev_soundcard_name);
4786         lir_text(24,line,s);
4787         line++;
4788         SNDLOG"\n%s",s);
4789         sprintf(s,"device             =%s (%s)",alsa_dev_name,alsa_dev_plughw_pcm_name);
4790         lir_text(24,line,s);
4791         line++;
4792         SNDLOG"\n%s",s);
4793         sprintf(s,"device number      = %i",alsa_dev_seq_nmbr);
4794         lir_text(24,line,s);
4795         line++;
4796         SNDLOG"\n%s",s);
4797         sprintf(s,"hostapi            = Native ALSA");
4798         lir_text(24,line,s);
4799         SNDLOG"\n%s",s);
4800         settextcolor(7);
4801         }
4802       }
4803     else
4804 #endif
4805       {
4806 #if HAVE_OSS == 1
4807       make_devname(ui.rx_dadev_no, dev_name);
4808       if(kill_all_flag)goto set_rx_io_errexit;
4809       sprintf(s,"SOUNDCARD device   = %s",dev_name);
4810       lir_text(24,line,s);
4811       SNDLOG"\n%s",s);
4812       settextcolor(7);
4813 #else
4814       lir_text(24,line,"ERROR");
4815 #endif
4816       }
4817     }
4818   }
4819 line++;
4820 settextcolor(7);
4821 sprintf(s,"min da sample rate = %i",ui.rx_min_da_speed);
4822 SNDLOG"\n%s",s);
4823 lir_text(24,line,s);
4824 line++;
4825 sprintf(s,"max da sample rate = %i ", ui.rx_max_da_speed);
4826 SNDLOG"\n%s",s);
4827 lir_text(24,line,s);
4828 line++;
4829 if ( (ui.use_alsa&PORTAUDIO_RX_OUT) != 0)
4830   {
4831   sprintf(s,"Latency factor     = %i ",ui.rx_da_latency );
4832   SNDLOG"\n%s",s);
4833   lir_text(24,line,s);
4834   line++;
4835   }
4836 sprintf(s,"min da bytes       = %i",ui.rx_min_da_bytes);
4837 SNDLOG"\n%s",s);
4838 lir_text(24,line,s);
4839 line++;
4840 sprintf(s,"max da bytes       = %i ", ui.rx_max_da_bytes);
4841 SNDLOG"\n%s",s);
4842 lir_text(24,line,s);
4843 line++;
4844 sprintf(s,"min da channels    = %i",ui.rx_min_da_channels);
4845 SNDLOG"\n%s",s);
4846 lir_text(24,line,s);
4847 line++;
4848 sprintf(s,"max da channels    = %i", ui.rx_max_da_channels);
4849 SNDLOG"\n%s",s);
4850 lir_text(24,line,s);
4851 set_rx_io_ask:;
4852 settextcolor(7);
4853 line+=2;
4854 if(ui.converter_mode != 0)
4855   {
4856   compute_converter_parameters();
4857   settextcolor(10);
4858   line+=2;
4859   if( (ui.converter_mode&CONVERTER_UP) !=0 )
4860     {
4861     lir_text(2,line,"UP");
4862     j=4;
4863     }
4864   else
4865     {
4866     lir_text(2,line,"DOWN");
4867     j=6;
4868     }
4869   lir_text(j,line,"CONVERTER:");
4870   settextcolor(7);
4871   sprintf(s,"LO frequency %.6f",converter_offset_mhz);
4872   i=0;
4873   while(s[i] != 0)i++;
4874   while(s[i-1] == '0')i--;
4875   if(s[i-1] == '.')i--;
4876   if( (ui.converter_mode&CONVERTER_UP) !=0 )
4877     {
4878     sprintf(&s[i]," MHz.");
4879     }
4880   else
4881     {
4882     sprintf(&s[i]," MHz.  LO is ");
4883     if( (ui.converter_mode&CONVERTER_LO_BELOW) != 0)
4884       {
4885       strcat(s,"below");
4886       }
4887     else
4888       {
4889       strcat(s,"above");
4890       }
4891     strcat(s," signal frequency.");
4892     }
4893   lir_text(j+11,line,s);
4894   }
4895 line+=2;
4896 sprintf(s,"DMA rate   min=%i    max=%i" ,ui.min_dma_rate, ui.max_dma_rate);
4897 SNDLOG"\n%s\n",s);
4898 lir_text(2,line,s);
4899 // *******************************************************************
4900 // Ask whether the user wants to change something and act accordingly.
4901 // *******************************************************************
4902 line+=2;
4903 sndlog_sync();
4904 lir_text(2,line,"A = Change the input settings and reset the output soundcard settings if a soundcard is selected as input.");
4905 line++;
4906 lir_text(2,line,"B = Change the output soundcard settings.");
4907 line++;
4908 if(ui.operator_skil != OPERATOR_SKIL_NEWCOMER)
4909   {
4910   lir_text(2,line,"C = Change min and max dma rate .");
4911   line++;
4912   }
4913 if(ui.soundcard_radio != SOUNDCARD_RADIO_UNDEFINED &&
4914    ui.soundcard_radio != SOUNDCARD_RADIO_UNDEFINED_REVERSED)
4915   {
4916   lir_text(2,line,"D = Set parameters for soundcard radio hardware.");
4917   line++;
4918   }
4919 if(ui.operator_skil != OPERATOR_SKIL_NEWCOMER)
4920   {
4921   lir_text(2,line,"E = Enable/Disable frequency converter and set LO.");
4922   line++;
4923   }
4924 lir_text(2,line,"Z = Disable the output soundcard.");
4925 line++;
4926 #if (ALSA_PRESENT == 1)
4927 lir_text(2,line,"Y = Toggle soundsystem between native ALSA and alsa-oss and reset all soundcard settings.");
4928 line++;
4929 #endif
4930 if(line >= screen_last_line)
4931   {
4932   clear_lines(screen_last_line,screen_last_line);
4933   settextcolor(12);
4934   lir_text(2,screen_last_line,"SCREEN TOO LOW FOR SELECTED FONT SIZE");
4935   settextcolor(7);
4936   }
4937 else
4938   {
4939   lir_text(2,line,"X = To main menu.");
4940   }
4941 await_processed_keyboard();
4942 if(kill_all_flag)goto set_rx_io_errexit;
4943 clear_screen();
4944 switch(lir_inkey)
4945   {
4946   case 'A':
4947 // ************************* CHANGE INPUT SETTINGS ************************************ //
4948   ui.sample_shift=0;
4949   line=2;
4950   SNDLOG"\nUSER STARTED THE SELECTION OF A NEW INPUT DEVICE \n");
4951   if(ui.use_extio != 0)
4952     {
4953     if(extio_handle != NULL)
4954       {
4955       command_extio_library(EXTIO_COMMAND_UNLOAD_DLL);
4956       }
4957     ui.use_extio=0;
4958     }
4959   ui.rx_addev_no =UNDEFINED_DEVICE_CODE;
4960   lir_text(10,line,"SELECT HARDWARE FOR INPUT");
4961   line+=2;
4962   lir_text(4,line,"A = Soundcard");
4963   line++;
4964   lir_text(4,line,"B = SDR-14 or SDR-IQ");
4965   line++;
4966   lir_text(4,line,"C = Perseus");
4967   line++;
4968   lir_text(4,line,"D = SDR-IP");
4969   line++;
4970   lir_text(4,line,"E = Excalibur");
4971   line++;
4972   lir_text(4,line,"F = libExtIO hardwares");
4973   line++;
4974   lir_text(4,line,"H = RTL2832 USB dongle");
4975   line++;
4976   lir_text(4,line,"I = Mirics USB dongle");
4977   line++;
4978   lir_text(4,line,"J = bladeRF");
4979   line++;
4980   lir_text(4,line,"K = PCIe 9842");
4981   line++;
4982   lir_text(4,line,"L = OpenHPSDR");
4983   line++;
4984   lir_text(4,line,"M = Afedri-NET");
4985   line++;
4986   if(ui.operator_skil != OPERATOR_SKIL_NEWCOMER)
4987     {
4988     lir_text(4,line,"Y = Network");
4989     line++;
4990     }
4991   lir_text(4,line,"Z = Disable (Disk input allowed)");
4992   await_processed_keyboard();
4993   if(kill_all_flag)goto set_rx_io_errexit;
4994   clear_screen();
4995   ui.soundcard_radio=0;
4996   ui.use_extio=0;
4997   switch (lir_inkey)
4998     {
4999     case 'A':
5000 use_sndcard:;
5001     clear_screen();
5002 // reset the output soundcard
5003     ui.use_alsa&=~PORTAUDIO_RX_IN;
5004     ui.rx_dadev_no=UNDEFINED_DEVICE_CODE;
5005 #if (ALSA_PRESENT == 1 || HAVE_OSS == 1)
5006     lir_text(10,5,
5007     "Use Portaudio (allows all/slow devices) for rx input? (Y/N) =>");
5008     lir_text(15,7,press_f1_for_info);
5009     await_processed_keyboard();
5010     if(kill_all_flag)goto set_rxin_exit;
5011     if(lir_inkey == F1_KEY || lir_inkey == '!')
5012       {
5013       help_message(343);
5014       goto use_sndcard;
5015       }
5016     if(lir_inkey == 'Y')
5017       {
5018       ui.use_alsa|=PORTAUDIO_RX_IN;
5019       }
5020     else
5021       {
5022       if(lir_inkey != 'N')
5023         {
5024         goto use_sndcard;
5025         }
5026       }
5027 #else
5028     ui.use_alsa|=PORTAUDIO_RX_IN;
5029 #endif
5030     if(!portaudio_startstop())goto use_sndcard;
5031 //get a 'portaudio' selection list
5032     clear_screen();
5033     line=1;
5034     if( (ui.use_alsa&PORTAUDIO_RX_IN) != 0)
5035       {
5036       set_portaudio(RXAD, &line);
5037       goto set_rxin_exit;
5038       }
5039 // look for input soundcards
5040     sprintf(s,"SELECT SOUNDCARD DEVICE FOR RX INPUT FROM LIST:");
5041     SNDLOG"%s\n",s);
5042     line=1;
5043     settextcolor(14);
5044     lir_text(2,line,s);
5045     settextcolor(7);
5046     line++;
5047 #if (ALSA_PRESENT == 1)
5048     if( (ui.use_alsa&NATIVE_ALSA_USED)!=0)
5049       {
5050       ui.rx_addev_no=select_alsadev(SND_PCM_STREAM_CAPTURE, &line);
5051       if(kill_all_flag)goto set_rx_io_errexit;
5052       alsa_get_native_samplerate(ui.rx_addev_no,SND_PCM_STREAM_CAPTURE,&line,&new_sample_rate);
5053       if(kill_all_flag)return;
5054       ui.rx_ad_speed=(int)new_sample_rate;
5055 //get number of bytes and check
5056       if(alsa_dev_max_bytes > 2)
5057         {
5058         if(alsa_dev_max_bytes != 4)
5059           {
5060           lirerr(872341);
5061           return;
5062           }
5063         if(alsa_dev_min_bytes == 4)
5064           {
5065           ui.rx_input_mode=DWORD_INPUT;
5066           }
5067         else
5068           {
5069           if(ui.operator_skil != OPERATOR_SKIL_NEWCOMER)
5070             {
5071             sprintf(s,"Enter number of input bytes (2 or 4) >");
5072 select_number_input_bytes:;
5073             SNDLOG"%s\n",s);
5074             lir_text(0,line,s);
5075             i=lir_get_integer(39, line, 1,2,4);
5076             if(kill_all_flag)goto set_rx_io_errexit;
5077             sprintf(s,"User selected  %i",i);
5078             SNDLOG"%s\n",s);
5079             lir_text(44,line,blanks);
5080             switch (i)
5081               {
5082               case 2:
5083               ui.rx_input_mode=0;
5084               break;
5085 
5086               case 4:
5087               ui.rx_input_mode=DWORD_INPUT;
5088               break;
5089 
5090               default:
5091               settextcolor(12);
5092               sprintf(s,"invalid selection, try again");
5093               SNDLOG"%s\n",s);
5094               lir_text(44,line,s);
5095               settextcolor(7);
5096               goto select_number_input_bytes;
5097               }
5098             }
5099           else
5100             {
5101             ui.rx_input_mode=DWORD_INPUT;
5102             }
5103           }
5104         }
5105       else
5106         {
5107         ui.rx_input_mode=0;
5108         SNDLOG"\n\n");
5109         }
5110       dev_min_channels=1;
5111       dev_max_channels=alsa_dev_max_channels;
5112       if(dev_max_channels > 4)dev_max_channels=4;
5113 //  With native alsa, always set ui.rx_admode to 0
5114       ui.rx_admode=0;
5115       line+=2;
5116       }
5117     else
5118 #endif
5119 //OSS or alsa-oss
5120       {
5121 #if HAVE_OSS == 1
5122       column=0;
5123       speed_warning=0;
5124       if(ui.process_priority != 0)
5125         {
5126         if(ui.operator_skil == OPERATOR_SKIL_EXPERT)
5127           {
5128           settextcolor(12);
5129           lir_text(0,line+2,"WARNING!! SETTING PRIORITY ABOVE 0 WILL PROBABLY CAUSE");
5130           lir_text(0,line+3,"YOUR SYSTEM TO FREEZE IF YOU ARE USING 4FRONT OSS");
5131           sprintf(s,"Press y to keep priority=%d",ui.process_priority);
5132           lir_text(0,line+5,s);
5133           lir_text(0,line+6,"Any other key to set priority to zero.");
5134           await_processed_keyboard();
5135           if(lir_inkey != 'Y')ui.process_priority=0;
5136           settextcolor(7);
5137           clear_lines(line+2,line+6);
5138           }
5139         else
5140           {
5141           ui.process_priority=0;
5142           }
5143         }
5144       select_ossdev(&line, RXAD);
5145       if(kill_all_flag)goto set_rx_io_errexit;
5146       if(ui.rx_addev_no == UNDEFINED_DEVICE_CODE)goto begin_rx_set_io;
5147       max=dev_max_rd_speed[ui.rx_addev_no&255];
5148       min=dev_min_rd_speed[ui.rx_addev_no&255];
5149       if(max == ABOVE_MAX_SPEED || max < 1000)
5150         {
5151         max=ABOVE_MAX_SPEED;
5152         speed_warning=1;
5153         }
5154       sprintf(s,"Select sampling speed(%d to %d)", min,max);
5155       lir_text(0,line,s);
5156       if(speed_warning != 0)
5157         {
5158         settextcolor(12);
5159         lir_text(0,line+2,
5160          "WARNING!! device does not respond correctly to speed setting command");
5161         lir_text(0,line+3,
5162              "Incorrect (unsupported) values may cause system to hang");
5163         settextcolor(7);
5164         }
5165       column=0;
5166       while(s[column] != 0)column++;
5167       ui.rx_ad_speed=lir_get_integer(column+2, line, 8, min,max);
5168       lir_refresh_screen();
5169       if(kill_all_flag)goto set_rx_io_errexit;
5170       rdwr_max_speed=ui.rx_ad_speed;
5171       SNDLOG"\n%d Hz selected by user",ui.rx_ad_speed);
5172       line++;
5173       clear_lines(line,line+3);
5174       if(ioctl(rx_audio_in, SNDCTL_DSP_SPEED, &ui.rx_ad_speed)==-1)
5175         {
5176         lirerr(1041);
5177         goto set_rx_io_errexit;
5178         }
5179       if(ui.rx_ad_speed > (int)(rdwr_max_speed*1.05) ||
5180          ui.rx_ad_speed < (int)(rdwr_max_speed*0.95) )
5181         {
5182 // The user selected something that was unacceptable to the device driver.
5183 // Rather than just accepting whatever value goto set_rx_io_errexited,
5184 // could be -22 (an unspecified error code) we step the desired speed
5185 // upwards, looking for a valid speed.
5186 // In case we fail, an attempt is made downwards as well.
5187 // ****************************************************************
5188 // This code is written by Ulf, SM0LCB
5189         SNDLOG"\nReqested speed didn't work");
5190 // This code will search up/down from requested speed
5191 // until the driver will respond with valid code
5192 // Search use delta stepping of 3% from current speed
5193 // This to speed up the search for a valid speed
5194 // First search up in fq
5195         SNDLOG"\nSearch up : ");
5196         for( trySpeed=rdwr_max_speed,
5197                        deltaSpeed=(int)((float)(rdwr_max_speed)*0.03F);
5198                        trySpeed<192000;
5199                        trySpeed+=deltaSpeed )
5200           {
5201           ui.rx_ad_speed=trySpeed;
5202           if(ioctl(rx_audio_in, SNDCTL_DSP_SPEED, &ui.rx_ad_speed)==-1)
5203             {
5204             lirerr(1024);
5205             goto set_rx_io_errexit;
5206             }
5207 // test if valid speed
5208           if(ui.rx_ad_speed < (int)(trySpeed*1.05) &&
5209              ui.rx_ad_speed > (int)(trySpeed*0.95) )
5210             {
5211             SNDLOG"try speed %d Hz ", trySpeed);
5212             goto spok;
5213             }
5214           deltaSpeed=(int)((float)(trySpeed)*0.03F);
5215           }
5216         SNDLOG"no speed found");
5217 // Then search down in fq
5218         SNDLOG"\nSearch down : ");
5219         for( trySpeed=rdwr_max_speed,
5220                      deltaSpeed=(int)((float)(rdwr_max_speed)*0.03F);
5221                      trySpeed>5000;
5222                      trySpeed-=deltaSpeed )
5223           {
5224           ui.rx_ad_speed=trySpeed;
5225           if(ioctl(rx_audio_in, SNDCTL_DSP_SPEED, &ui.rx_ad_speed)==-1)
5226             {
5227             lirerr(1135);
5228             goto set_rx_io_errexit;
5229             }
5230 // test if valid speed
5231           if(ui.rx_ad_speed < (int)(trySpeed*1.05) &&
5232              ui.rx_ad_speed > (int)(trySpeed*0.95) )
5233             {
5234             SNDLOG"try speed %d Hz ", trySpeed);
5235             goto spok;
5236             }
5237           deltaSpeed=(int)((float)(trySpeed)*0.03F);
5238           }
5239         SNDLOG"no speed found");
5240 // If we didn't find any vaid speed
5241         SNDLOG"\nNo valid speed found !");
5242 // Exit program
5243         lirerr(1134);
5244         goto set_rx_io_errexit;
5245         }
5246 spok:;
5247       close(rx_audio_in);
5248       rx_audio_in=-1;
5249       SNDLOG"\n%d Hz reported by device",ui.rx_ad_speed);
5250       sndlog_sync();
5251       sprintf(s,"Input speed: %.3fkHz",0.001*(float)(ui.rx_ad_speed));
5252       lir_text(0,line,s);
5253       line++;
5254       if(ui.operator_skil != OPERATOR_SKIL_NEWCOMER)
5255         {
5256         if( (dev_rd_bytes[ui.rx_addev_no&255]&6) == 6)
5257           {
5258           line++;
5259           lir_text(0,line,"Select A/D number of bytes (2 or 4):");
5260           line++;
5261 selfmt:;
5262           await_processed_keyboard();
5263           if(kill_all_flag) goto set_rx_io_errexit;
5264           if(lir_inkey == '4')
5265             {
5266             ui.rx_input_mode=DWORD_INPUT;
5267             }
5268           else
5269             {
5270             if(lir_inkey != '2')goto selfmt;
5271             ui.rx_input_mode=0;
5272             }
5273           goto fmtok;
5274           }
5275         }
5276       if( (dev_rd_bytes[ui.rx_addev_no&255]&6) == 4)
5277         {
5278         ui.rx_input_mode=DWORD_INPUT;
5279         }
5280       else
5281         {
5282         ui.rx_input_mode=0;
5283         }
5284 fmtok:;
5285       dev_max_channels=0;
5286       k=4;
5287       while(dev_max_channels == 0 && k> 0)
5288         {
5289         dev_max_channels|=dev_rd_channels[ui.rx_addev_no]&k;
5290         k/=2;
5291         }
5292       dev_min_channels=1;
5293 #endif
5294       }
5295     if(ui.rx_addev_no < 256)
5296       {
5297       refline=line;
5298 sel_radio:;
5299       line=refline;
5300       j=dev_max_channels;
5301       k=dev_min_channels;
5302       line++;
5303       lir_text(0,line,"Select radio interface:");
5304       line=line+k+1;
5305       if(j == 2)j=3;
5306       for(i=k; i<=j; i++)
5307         {
5308         sprintf(s,"%d: %s",i,audiomode_text[i-1]);
5309         lir_text(5,line,s);
5310         line++;
5311         }
5312       line++;
5313       lir_text(1,line,"F1 for help/info");
5314 chsel:;
5315       await_processed_keyboard();
5316       if(kill_all_flag) goto set_rx_io_errexit;
5317       if(lir_inkey == F1_KEY || lir_inkey == '!')
5318         {
5319         help_message(89);
5320         clear_screen();
5321         goto sel_radio;
5322         }
5323       if(lir_inkey-'0'<k || lir_inkey-'0'>j)goto chsel;
5324       switch (lir_inkey)
5325         {
5326         case '1':
5327         ui.rx_rf_channels=1;
5328         ui.rx_ad_channels=1;
5329         break;
5330 
5331         case '2':
5332         ui.rx_input_mode|=IQ_DATA;
5333         ui.rx_rf_channels=1;
5334         ui.rx_ad_channels=2;
5335         break;
5336 
5337         case '3':
5338         ui.rx_input_mode|=TWO_CHANNELS;
5339         ui.rx_rf_channels=2;
5340         ui.rx_ad_channels=2;
5341         break;
5342 
5343         case '4':
5344         ui.rx_input_mode|=TWO_CHANNELS+IQ_DATA;
5345         ui.rx_rf_channels=2;
5346         ui.rx_ad_channels=4;
5347         break;
5348 
5349         default:
5350         goto chsel;
5351         }
5352       SNDLOG"\nui.rx_input_mode=%d  ui.rx_rf_channels=%d  ui.rx_ad_channels =%d",
5353                          ui.rx_input_mode, ui.rx_rf_channels, ui.rx_ad_channels);
5354       if(ui.rx_addev_no == ui.rx_dadev_no)ui.rx_dadev_no=UNDEFINED_DEVICE_CODE;
5355       if(ui.rx_addev_no == ui.tx_dadev_no)ui.tx_dadev_no=UNDEFINED_DEVICE_CODE;
5356       if(ui.rx_addev_no == ui.tx_addev_no)ui.tx_addev_no=UNDEFINED_DEVICE_CODE;
5357       }
5358     if(ui.rx_rf_channels == 1 && ui.rx_ad_channels == 2)
5359       {
5360       line+=2;
5361       lir_text(0,line,"Number of points to time shift between I and Q? (-4 to +4)");
5362       ui.sample_shift=lir_get_integer(60,line, 2, -4, 4);
5363       }
5364 set_rxin_exit:
5365     clear_screen();
5366     line=4;
5367     lir_text(9,line,"Select receiver hardware to use with soundcard.");
5368     line+=3;
5369     for(i=0; i<MAX_SOUNDCARD_RADIO; i++)
5370       {
5371       sprintf(s,"%d   %s",i,soundcard_radio_names[i]);
5372       lir_text(5,line,s);
5373       line++;
5374       }
5375     line++;
5376     lir_text(0,line,"Select by line number=>");
5377     ui.soundcard_radio=lir_get_integer(25,line,1,0,MAX_SOUNDCARD_RADIO);
5378     break;
5379 
5380 
5381     case 'B':
5382     timf1_char=malloc(0x8000);
5383     if(timf1_char == NULL)
5384       {
5385       lirerr(1231231);
5386       return;
5387       }
5388     init_sdr14();
5389     free(timf1_char);
5390     break;
5391 
5392     case 'C':
5393     init_perseus();
5394     if(sdr == -1)
5395       {
5396       clear_screen();
5397       lir_text(5,5,"Perseus init failed.");
5398       lir_text(5,6,"Is the unit connected and properly powered?");
5399       lir_text(7,8,press_any_key);
5400       await_processed_keyboard();
5401       }
5402     else
5403       {
5404       sdr=-1;
5405       }
5406     break;
5407 
5408     case 'D':
5409     init_sdrip();
5410     break;
5411 
5412     case 'E':
5413     lir_text(5,5,"No Excalibur yet under Linux.");
5414     lir_text(7,8,press_any_key);
5415     await_processed_keyboard();
5416     break;
5417 
5418     case 'F':
5419     init_extio();
5420     if(kill_all_flag)goto set_rx_io_errexit;
5421     if(ui.extio_type == 4)goto use_sndcard;
5422     break;
5423 
5424     case 'H':
5425     init_rtl2832();
5426     break;
5427 
5428     case 'I':
5429     init_mirics();
5430     break;
5431 
5432     case 'J':
5433     init_bladerf();
5434     break;
5435 
5436     case 'K':
5437     init_pcie9842();
5438     break;
5439 
5440     case 'L':
5441     init_openhpsdr();
5442     break;
5443 
5444     case 'M':
5445     init_netafedri();
5446     break;
5447 
5448     case 'Y':
5449     if(ui.operator_skil != OPERATOR_SKIL_NEWCOMER)
5450       {
5451       ui.rx_addev_no=NETWORK_DEVICE_CODE;
5452       ui.use_alsa&=~PORTAUDIO_RX_IN;
5453       ui.network_flag=(int)((unsigned int)ui.network_flag|NET_RX_INPUT);
5454       verify_network(TRUE);
5455       }
5456     break;
5457 
5458     case 'Z':
5459     ui.rx_addev_no=DISABLED_DEVICE_CODE;
5460     break;
5461     }
5462   if(kill_all_flag)goto set_rx_io_errexit;
5463   if(ui.rx_addev_no == UNDEFINED_DEVICE_CODE)goto begin_rx_set_io;
5464   break;
5465 
5466   case 'B':
5467 // ************************* CHANGE OUTPUT SETTINGS ************************************ //
5468   if (ui.rx_addev_no == UNDEFINED_DEVICE_CODE)
5469     {
5470     settextcolor(11);
5471     line+=2;
5472     lir_text(2,line,"Option B selected, but RX input must be set first:");
5473     line+=1;
5474     lir_text(2,line,"Hit any key to go back to this menu and select option A");
5475     settextcolor(7);
5476     await_processed_keyboard();
5477     if(kill_all_flag) goto set_rx_io_errexit;
5478     break;
5479     }
5480   SNDLOG"\nUSER STARTED THE SELECTION OF A NEW OUTPUT DEVICE \n");
5481 pa_rxda:;
5482   clear_screen();
5483   line=3;
5484   ui.rx_dadev_no=UNDEFINED_DEVICE_CODE;
5485   ui.use_alsa&=~PORTAUDIO_RX_OUT;
5486 #if (ALSA_PRESENT == 1 || HAVE_OSS == 1)
5487   lir_text(2,line,
5488   "Use Portaudio (allows all/slow devices) for rx output? (Y/N) =>");
5489     lir_text(7,line+2,press_f1_for_info);
5490   await_processed_keyboard();
5491   if(kill_all_flag) goto set_rx_io_errexit;
5492   if(lir_inkey == F1_KEY || lir_inkey == '!')
5493     {
5494     help_message(343);
5495     goto pa_rxda;
5496     }
5497   if(lir_inkey == 'Y')
5498     {
5499     ui.use_alsa|=PORTAUDIO_RX_OUT;
5500     }
5501   else
5502     {
5503     if(lir_inkey != 'N')
5504       {
5505       goto pa_rxda;
5506       }
5507     }
5508 #else
5509   ui.use_alsa|=PORTAUDIO_RX_OUT;
5510 #endif
5511   if(!portaudio_startstop())goto pa_rxda;
5512 // Start test-thread with input soundcard device
5513   if( (double)(ui.rx_addev_no >=0 && ui.rx_addev_no < SPECIFIC_DEVICE_CODES) &&
5514                                        ((unsigned int)ui.network_flag&NET_RX_INPUT) == 0)
5515     {
5516     if(start_iotest(&line,RXAD) == FALSE)goto set_rxout_exit;
5517     }
5518 //get a 'portaudio' selection list for output soundcards
5519   if( (ui.use_alsa&PORTAUDIO_RX_OUT) != 0)
5520     {
5521     set_portaudio(RXDA, &line);
5522     if(kill_all_flag) goto set_rx_io_errexit;
5523     goto set_rxout_exit;
5524     }
5525 //get an 'ALSA' or 'OSS' selection list for output soundcards
5526   sprintf(s,"SELECT SOUNDCARD DEVICE FOR RX OUTPUT FROM LIST:");
5527   SNDLOG"%s\n",s);
5528   line=1;
5529   settextcolor(14);
5530   lir_text(2,line,s);
5531   settextcolor(7);
5532   line++;
5533 #if (ALSA_PRESENT == 1)
5534   if( (ui.use_alsa&NATIVE_ALSA_USED)!=0)
5535     {
5536     ui.rx_dadev_no=select_alsadev(SND_PCM_STREAM_PLAYBACK, &line);
5537     if(kill_all_flag)goto set_rxout_exit;
5538     ui.rx_min_da_speed=alsa_dev_min_rate[ui.rx_dadev_no];
5539     ui.rx_max_da_speed=alsa_dev_max_rate[ui.rx_dadev_no];
5540     if(alsa_dev_min_bytes > 2 )
5541       {
5542       lir_text(0,line, "RX output only allowed with 8 or 16 bit data.");
5543       line++;
5544       lir_text(0,line, wish_anyway);
5545       line++;
5546 anyw:;
5547       await_processed_keyboard();
5548       if(kill_all_flag) goto set_rx_io_errexit;
5549       if(lir_inkey == 'N')
5550         {
5551         ui.rx_dadev_no=UNDEFINED_DEVICE_CODE;
5552         lir_text(10,line,press_any_key);
5553         goto set_rxout_exit;
5554         }
5555       if(lir_inkey != 'Y')goto anyw;
5556       alsa_dev_min_bytes=1;
5557       }
5558     ui.rx_min_da_bytes=alsa_dev_min_bytes;
5559     ui.rx_max_da_bytes=alsa_dev_max_bytes;
5560     if(ui.rx_max_da_bytes > 2)
5561       {
5562       ui.rx_max_da_bytes=2;
5563       }
5564     if(alsa_dev_min_channels >=  2 )ui.rx_min_da_channels=2;
5565        else ui.rx_min_da_channels=1;
5566     if(alsa_dev_max_channels <  2 )ui.rx_max_da_channels=1;
5567        else ui.rx_max_da_channels=2;
5568     }
5569   else
5570 #endif
5571     {
5572 #if HAVE_OSS == 1
5573     refline=line;
5574     select_ossdev(&line, RXDA);
5575     if(kill_all_flag)goto set_rx_io_errexit;
5576     if(ui.rx_dadev_no == (ui.rx_addev_no&255) && ui.rx_admode == O_RDWR)
5577       {
5578       if( (ui.rx_ad_channels == 4) || (ui.rx_input_mode&DWORD_INPUT) != 0)
5579         {
5580         lir_text(0,line,
5581         "RDWR for output not possible with 32 bit data or 4 channels.");
5582         line++;
5583         ui.rx_dadev_no=UNDEFINED_DEVICE_CODE;
5584         lir_text(10,line,press_any_key);
5585         await_processed_keyboard();
5586         if(kill_all_flag) goto set_rx_io_errexit;
5587         goto set_rxout_exit;
5588         }
5589       ui.rx_min_da_speed=ui.rx_ad_speed;
5590       ui.rx_max_da_speed=ui.rx_ad_speed;
5591       ui.rx_min_da_bytes=2;
5592       ui.rx_max_da_bytes=2;
5593       ui.rx_max_da_channels=ui.rx_ad_channels;
5594       ui.rx_min_da_channels=ui.rx_ad_channels;
5595       }
5596     else
5597       {
5598       set_rx_dadev_parms(&line);
5599       }
5600 // Now that we decided what device to use for output, let
5601 // the user decide how to use it. (It may become microphone input).
5602     if(ui.rx_dadev_no != UNDEFINED_DEVICE_CODE)
5603       {
5604       make_devname(ui.rx_dadev_no, dev_name);
5605       if(kill_all_flag)goto set_rx_io_errexit;
5606       sndlog_sync();
5607       ui.rx_damode=select_rdwr_mode(&line, ui.rx_dadev_no, O_WRONLY);
5608       }
5609 #endif
5610     }
5611 set_rxout_exit:;
5612   if((ui.rx_addev_no >=0 && ui.rx_addev_no < SPECIFIC_DEVICE_CODES)&&
5613                                        ((unsigned int)ui.network_flag&NET_RX_INPUT) == 0)
5614     {
5615     stop_iotest(RXAD);
5616     if(kill_all_flag)goto set_rx_io_errexit;
5617 #if HAVE_OSS == 1
5618     if((ui.use_alsa&NATIVE_ALSA_USED)==0)
5619       {
5620       if(ui.rx_dadev_no == UNDEFINED_DEVICE_CODE)
5621         {
5622         clear_lines(refline,line+4);
5623         line=refline;
5624         select_ossdev(&line, RXDA);
5625         if(kill_all_flag)goto set_rx_io_errexit;
5626         set_rx_dadev_parms(&line);
5627         if(kill_all_flag)goto set_rx_io_errexit;
5628         if(ui.rx_dadev_no != UNDEFINED_DEVICE_CODE)
5629           {
5630           ui.rx_input_mode|=NO_DUPLEX;
5631           }
5632         else
5633           {
5634           break;
5635           }
5636         }
5637       }
5638 #endif
5639     }
5640   if(ui.rx_dadev_no == UNDEFINED_DEVICE_CODE)break;
5641   line++;
5642   if(ui.rx_dadev_no == ui.tx_dadev_no)ui.tx_dadev_no=UNDEFINED_DEVICE_CODE;
5643   if(ui.rx_dadev_no == ui.tx_addev_no)ui.tx_addev_no=UNDEFINED_DEVICE_CODE;
5644   break;
5645 
5646   case 'C':
5647 // ************************ CHANGE DMA RATE  SETTINGS ******************************
5648   if(ui.operator_skil != OPERATOR_SKIL_NEWCOMER)
5649     {
5650     line=5;
5651     SNDLOG"\nUSER STARTED A CHANGE OF MIN/MAX DMA RATE\n");
5652     sprintf(s,"Current  min, max DMA rates in Hz       : %i, %i ",
5653                                                ui.min_dma_rate, ui.max_dma_rate);
5654     lir_text(10,line,s);
5655     SNDLOG"%s\n",s);
5656     line+=2;
5657     if(ui.operator_skil == OPERATOR_SKIL_EXPERT)
5658       {
5659       n1=MIN_DMA_RATE_EXP;
5660       m1=DMA_MIN_DIGITS_EXP;
5661       n2=MAX_DMA_RATE_EXP;
5662       m2=DMA_MAX_DIGITS_EXP;
5663       }
5664     else
5665       {
5666       n1=MIN_DMA_RATE;
5667       m1=DMA_MIN_DIGITS;
5668       n2=MAX_DMA_RATE;
5669       m2=DMA_MAX_DIGITS;
5670       }
5671     sprintf(s,"Enter new min DMA rate in Hz (%d-%d) > ",n1,n2);
5672     SNDLOG"%s\n",s);
5673     lir_text(10,line,s);
5674     i=lir_get_integer(45+m1+m2, line, m2,n1,n2);
5675     if(kill_all_flag)goto set_rx_io_errexit;
5676     sprintf(s,"User selected  %i",i);
5677     SNDLOG"%s\n",s);
5678     ui.min_dma_rate=i;
5679     line+=4;
5680     sprintf(s,"%i",i);
5681     m1=strlen(s);
5682     sprintf(s,"Enter new max DMA rate in Hz (%d-%d) > ",ui.min_dma_rate,n2);
5683     SNDLOG"%s\n",s);
5684     lir_text(10,line,s);
5685     i=lir_get_integer(43+m1+m2, line, m2, ui.min_dma_rate, n2);
5686     if(kill_all_flag)goto set_rx_io_errexit;
5687     sprintf(s,"User selected  %i",i);
5688     SNDLOG"%s\n",s);
5689     ui.max_dma_rate=i;
5690     }
5691   break;
5692 
5693   case 'D':
5694   switch (ui.soundcard_radio)
5695     {
5696     case SOUNDCARD_RADIO_WSE:
5697     wse_setup();
5698     break;
5699 
5700     case SOUNDCARD_RADIO_SI570:
5701     si570_setup();
5702     break;
5703 
5704     case SOUNDCARD_RADIO_SOFT66:
5705     soft66_setup();
5706     break;
5707 
5708     case SOUNDCARD_RADIO_ELEKTOR:
5709     elektor_setup();
5710     break;
5711 
5712     case SOUNDCARD_RADIO_FCDPROPLUS:
5713 #if LIBUDEV_PRESENT == 1
5714     fcdproplus_setup();
5715 #else
5716     clear_screen();
5717     lir_text(5,5,"FCDProPlus not supported");
5718     lir_text(5,7,"Install the libudev package");
5719     lir_text(5,8,"Then run configure and make.");
5720     lir_text(8,10,press_any_key);
5721     await_processed_keyboard();
5722     if(kill_all_flag) goto set_rx_io_errexit;
5723 #endif
5724     break;
5725 
5726     case SOUNDCARD_RADIO_AFEDRI_USB:
5727 #if LIBUDEV_PRESENT == 1
5728     afedriusb_setup();
5729 #else
5730     clear_screen();
5731     lir_text(5,5,"Afedri USB not supported");
5732     lir_text(5,7,"Install the libudev package");
5733     lir_text(5,8,"Then run configure and make.");
5734     lir_text(8,10,press_any_key);
5735     await_processed_keyboard();
5736     if(kill_all_flag) goto set_rx_io_errexit;
5737 #endif
5738     }
5739   break;
5740 
5741   case 'E':
5742 // *************************  CONVERTER SETUP FOR RX ****************************
5743   lir_text(5,3,"Do you wish to use a converter in front of your receiver (Y/N)?");
5744 get_convuse:;
5745   await_processed_keyboard();
5746   if(kill_all_flag) goto set_rx_io_errexit;
5747   ui.converter_mode=0;
5748   if(lir_inkey=='N')
5749     {
5750     ui.converter_hz=0;
5751     ui.converter_mhz=0;
5752     converter_offset_mhz=0;
5753     break;
5754     }
5755   else
5756     {
5757     if(lir_inkey != 'Y')goto get_convuse;
5758     }
5759   ui.converter_mode=CONVERTER_USE;
5760   lir_text(5,5,"Enter converter LO frequency in MHz:");
5761   converter_offset_mhz=(float)lir_get_float(42,5,14,0.001F,200000.);
5762   ui.converter_mhz=(unsigned int)converter_offset_mhz;
5763   ui.converter_hz=(int)(round(1000000*(converter_offset_mhz-ui.converter_mhz)));
5764 get_updown:;
5765   lir_text(5,7,"Up or down conversion? (U/D)?");
5766   await_processed_keyboard();
5767   if(kill_all_flag) goto set_rx_io_errexit;
5768   if(lir_inkey=='U')
5769     {
5770     ui.converter_mode|=CONVERTER_UP;
5771     }
5772   else
5773     {
5774     if(lir_inkey != 'D')goto get_updown;
5775     }
5776   if( (ui.converter_mode&CONVERTER_UP) == 0)
5777     {
5778 get_losign:;
5779     lir_text(5,9,"Is LO below signal frequency (Y/N)?");
5780     await_processed_keyboard();
5781     if(kill_all_flag) goto set_rx_io_errexit;
5782     if(lir_inkey=='Y')
5783       {
5784       ui.converter_mode|=CONVERTER_LO_BELOW;
5785       }
5786     else
5787       {
5788       if(lir_inkey != 'N')goto get_losign;
5789       }
5790     }
5791   compute_converter_parameters();
5792   break;
5793 
5794   case 'Z':
5795 // ************************* DISABLE OUTPUT *************************************
5796   SNDLOG"\nUSER DISABLED THE OUPUT SOUNDCARD \n");
5797   ui.rx_dadev_no=DISABLED_DEVICE_CODE;
5798   ui.rx_max_da_bytes=2;
5799   ui.rx_max_da_channels=2;
5800   ui.rx_min_da_bytes=1;
5801   ui.rx_min_da_channels=1;
5802   ui.rx_min_da_speed=5000;
5803   ui.rx_max_da_speed=1000000;
5804   break;
5805 
5806 #if (ALSA_PRESENT == 1)
5807   case 'Y':
5808 // ************************** TOGGLE SOUNDSYSTEM ********************************** //
5809 // toggle between alsa-oss and native ALSA
5810 // and reset all the previous selections
5811   SNDLOG"\nUSER TOGGLED BETWEEN NATIVE-ALSA AND ALSA-OSS EMULATION\n");
5812   if( (ui.use_alsa&NATIVE_ALSA_USED)!=0)
5813     {
5814     ui.use_alsa&=~NATIVE_ALSA_USED;
5815     }
5816   else
5817     {
5818     ui.use_alsa |= NATIVE_ALSA_USED;
5819     }
5820   ui.rx_dadev_no=UNDEFINED_DEVICE_CODE;
5821   ui.rx_addev_no=UNDEFINED_DEVICE_CODE;
5822   ui.tx_dadev_no=UNDEFINED_DEVICE_CODE;
5823   ui.tx_addev_no=UNDEFINED_DEVICE_CODE;
5824   ui.max_dma_rate=DEFAULT_MAX_DMA_RATE;
5825   ui.min_dma_rate=DEFAULT_MIN_DMA_RATE;
5826   goto begin_rx_set_io;
5827 #endif
5828 
5829   case 'X':
5830 // ************************* EXIT TO MAIN MENU *********************************** //
5831 //validate input settings
5832   if((ui.rx_addev_no == -1) && (((unsigned int)ui.network_flag&NET_RX_INPUT) == 0))
5833     {
5834     settextcolor(12);
5835     line+=2;
5836     lir_text(2,line,"Invalid input settings: NOT YET SELECTED");
5837     line+=1;
5838     lir_text(2,line,
5839       "Hit any key to go back to the main menu and select a network input");
5840     line+=1;
5841     lir_text(2,line,
5842       "or hit U on the main menu to go back to this menu and hit A.");
5843     settextcolor(7);
5844     }
5845   else
5846     {
5847 //validate output settings
5848     if(ui.rx_dadev_no == UNDEFINED_DEVICE_CODE)
5849       {
5850       settextcolor(12);
5851       line+=2;
5852       lir_text(2,line,"Invalid output settings: NOT YET SELECTED");
5853       line+=1;
5854       lir_text(2,line,
5855             "Hit any key to go back to this menu and select option B or Z");
5856       settextcolor(7);
5857       await_processed_keyboard();
5858       if(kill_all_flag) goto set_rx_io_errexit;
5859       break;
5860       }
5861     clear_screen();
5862     lir_text(2,5,remind_parsave);
5863     lir_text(2,7,press_any_key);
5864     }
5865   await_keyboard();
5866   goto set_rx_io_exit;
5867 
5868   default:
5869   break;
5870   }
5871 // ******************************************************************************** //
5872 SNDLOG"\ngoto begin_rx_set_io\n\n");
5873 if(kill_all_flag)goto set_rx_io_errexit;
5874 sndlog_sync();
5875 goto begin_rx_set_io;
5876 set_rx_io_exit:;
5877 SNDLOG"\nNormal end");
5878 set_rx_io_errexit:;
5879 SNDLOG"\n");
5880 fclose(sndlog);
5881 write_log=FALSE;
5882 }
5883 
get_mic_speed(int * line,int min,int max)5884 int get_mic_speed(int *line, int min, int max)
5885 {
5886 int i,mm;
5887 char s[80];
5888 line[0]++;
5889 lir_text(2,line[0],
5890             "Note that sampling speed should be at least 8 times higher");
5891 line[0]++;
5892 lir_text(2,line[0],"than the highest voice frequency.");
5893 line[0]+=2;
5894 sprintf(s,"Select microphone A/D speed %d to %d",min, max);
5895 lir_text(5,line[0],s);
5896 i=0;
5897 while(s[i] != 0)i++;
5898 mm=lir_get_integer(i+7, line[0], 6, min, max);
5899 line[0]++;
5900 return mm;
5901 }
5902 
select_txout_format(int * line)5903 void select_txout_format(int *line)
5904 {
5905 line[0]++;
5906 lir_text(3,line[0],"Select tx format");
5907 line[0]+=2;
5908 lir_text(7,line[0],"1=Single channel (normal audio)");
5909 line[0]++;
5910 lir_text(7,line[0],"2=Two channels (I and Q, frequency shifted)");
5911 line[0]++;
5912 get_txout_dachan:;
5913 await_processed_keyboard();
5914 if(kill_all_flag)return;
5915 if(lir_inkey=='1')
5916   {
5917   ui.tx_da_channels=1;
5918   }
5919 else
5920   {
5921   if(lir_inkey=='2')
5922     {
5923     ui.tx_da_channels=2;
5924     }
5925   else
5926     {
5927     goto get_txout_dachan;
5928     }
5929   }
5930 }
5931 
5932 
set_tx_io(void)5933 void set_tx_io(void)
5934 {
5935 char *tmptxt;
5936 int i, j, k;
5937 #if (ALSA_PRESENT == 1)
5938 int err;
5939 #endif
5940 int line;
5941 char s[256];
5942 char *tx_logfile_name="soundboard_tx_init.log";
5943 clear_screen();
5944 if(((unsigned int)ui.network_flag&NET_RX_INPUT) != 0)
5945   {
5946   lir_text(0,0,"Input from the network is currently selected.");
5947   goto not_now;
5948   }
5949 if(ui.rx_ad_channels == 0 ||
5950    ui.rx_addev_no == -1 ||
5951    ui.rx_max_da_channels == 0 ||
5952    ui.rx_dadev_no == UNDEFINED_DEVICE_CODE)
5953   {
5954   lir_text(0,0,"The RX input and output must be set up before the TX.");
5955 not_now:;
5956   lir_text(0,1,"TX is now disabled.");
5957   ui.tx_addev_no=UNDEFINED_DEVICE_CODE;
5958   ui.tx_dadev_no=UNDEFINED_DEVICE_CODE;
5959   lir_text(10,3,press_any_key);
5960   await_processed_keyboard();
5961   return;
5962   }
5963 memset(blanks, ' ',58);
5964 blanks[59]=0;
5965 if(ui.tx_ad_channels == 0)ui.tx_addev_no=UNDEFINED_DEVICE_CODE;
5966 if(ui.tx_da_channels == 0)ui.tx_dadev_no=UNDEFINED_DEVICE_CODE;
5967 sndlog=fopen(tx_logfile_name, "w");
5968 if(sndlog == NULL)
5969   {
5970   lirerr(1016);
5971   return;
5972   }
5973 write_log=TRUE;
5974 begin_tx_set_io:;
5975 clear_screen();
5976 if(kill_all_flag)goto set_tx_io_errexit;
5977 #if (ALSA_PRESENT == 1)
5978 lir_text(0,0,"The current setting is:");
5979 lir_text(0,1,"Use RX setup menu to toggle between native ALSA and alsa-oss.");
5980 i=ui.use_alsa;
5981 settextcolor(10);
5982 if( (ui.use_alsa&NATIVE_ALSA_USED)!=0)
5983   {
5984   lir_text(24,0,"native ALSA");
5985   }
5986 else
5987   {
5988   lir_text(24,0,"alsa-oss   ");
5989   }
5990 sprintf(s,"ALSA library version:%s",SND_LIB_VERSION_STR);
5991 settextcolor(7);
5992 lir_text(37,0,s);
5993 #else
5994 ui.use_alsa&=~NATIVE_ALSA_USED;
5995 lir_text(0,0,"This system uses OSS, alsa-oss or legacy sound.");
5996 #endif
5997 clear_lines(1,4);
5998 line=2;
5999 // **************************************************************
6000 // Show the current TX output settings on the screen.
6001 // **************************************************************
6002 lir_text(0,line,"Linrad TX output from:");
6003 settextcolor(10);
6004 sprintf(s,"UNKNOWN (no=%d)",ui.tx_dadev_no);
6005 tmptxt=s;
6006 i=0;
6007 j=1;
6008 if(ui.tx_dadev_no == UNDEFINED_DEVICE_CODE)
6009   {
6010   tmptxt="NOT YET SELECTED";
6011   j=0;
6012   }
6013 else
6014   {
6015 #if (ALSA_PRESENT == 1)
6016   if( (ui.use_alsa&NATIVE_ALSA_USED)!=0)
6017     {
6018     err=alsa_get_dev_names (ui.tx_dadev_no);
6019     if(err < 0)
6020       {
6021       sprintf(s,"invalid card/device  ( alsa-device-seq-nmbr = %i )",
6022                                                             ui.tx_dadev_no );
6023       tmptxt=s;
6024       j=0;
6025       }
6026     else
6027       {
6028       sprintf(s,"Soundcard =%s",alsa_dev_soundcard_name);
6029       lir_text(22,line,s);
6030       settextcolor(7);
6031       i++;
6032       SNDLOG"Initial TXout setting: %s\n",s);
6033       sprintf(s,"Dev name = %s",alsa_dev_name);
6034       lir_text(2,line+i,s);
6035       i++;
6036       SNDLOG"%s\n",s);
6037       sprintf(s,"Pcm name = %s",alsa_dev_plughw_pcm_name);
6038       lir_text(2,line+i,s);
6039       i++;
6040       SNDLOG"%s\n",s);
6041       sprintf(s,"Seq nmbr = %i",alsa_dev_seq_nmbr);
6042       lir_text(2,line+i,s);
6043       SNDLOG"%s\n",s);
6044       }
6045     }
6046   else
6047 #endif
6048     {
6049 #if HAVE_OSS == 1
6050     make_devname(ui.tx_dadev_no, dev_name);
6051     if(kill_all_flag)goto set_tx_io_errexit;
6052     sprintf(s,"Device name =%s",dev_name);
6053     tmptxt=s;
6054 #endif
6055     }
6056   }
6057 if(i == 0)
6058   {
6059   lir_text(22,line,tmptxt);
6060   settextcolor(7);
6061   SNDLOG"Initial TXout setting: %s\n",tmptxt);
6062   }
6063 line+=i+1;
6064 if(j)
6065   {
6066   sprintf(s,"sample rate        = %i ",ui.tx_da_speed );
6067   SNDLOG"%s\n",s);
6068   lir_text(2,line,s);
6069   line++;
6070   sprintf(s,"No of output bytes = %d (%d bits)",
6071                 ui.tx_da_bytes, 8*ui.tx_da_bytes);
6072   SNDLOG"%s\n",s);
6073   lir_text(2,line,s);
6074   line++;
6075   sprintf(s,"No of output chans = %d", ui.tx_da_channels);
6076   SNDLOG"%s\n",s);
6077   lir_text(2,line,s);
6078   line++;
6079   }
6080 line+=2;
6081 // **************************************************************
6082 // Show the current TX input settings on the screen.
6083 // **************************************************************
6084 lir_text(0,line,"Linrad TX input to:");
6085 settextcolor(10);
6086 sprintf(s,"UNKNOWN (no=%d)",ui.tx_addev_no);
6087 tmptxt=s;
6088 i=0;
6089 k=1;
6090 if(ui.tx_addev_no == UNDEFINED_DEVICE_CODE)
6091   {
6092   tmptxt="NOT YET SELECTED";
6093   k=0;
6094   }
6095 else
6096   {
6097 #if (ALSA_PRESENT == 1)
6098   if( (ui.use_alsa&NATIVE_ALSA_USED)!=0)
6099     {
6100     err=alsa_get_dev_names (ui.tx_addev_no);
6101     if(err < 0)
6102       {
6103       sprintf(s,"invalid card/device  ( alsa-device-seq-nmbr = %i )",
6104                                                             ui.tx_addev_no );
6105       tmptxt=s;
6106       k=0;
6107       }
6108     else
6109       {
6110       sprintf(s,"Soundcard =%s",alsa_dev_soundcard_name);
6111       lir_text(22,line,s);
6112       settextcolor(7);
6113       i++;
6114       SNDLOG"Initial TXin setting: %s\n",s);
6115       sprintf(s,"Dev name = %s",alsa_dev_name);
6116       lir_text(2,line+i,s);
6117       i++;
6118       SNDLOG"%s\n",s);
6119       sprintf(s,"Pcm name = %s",alsa_dev_plughw_pcm_name);
6120       lir_text(2,line+i,s);
6121       i++;
6122       SNDLOG"%s\n",s);
6123       sprintf(s,"Seq nmbr = %i",alsa_dev_seq_nmbr);
6124       lir_text(2,line+i,s);
6125       SNDLOG"%s\n",s);
6126       }
6127     }
6128   else
6129 #endif
6130     {
6131 #if HAVE_OSS == 1
6132     make_devname(ui.tx_addev_no, dev_name);
6133     sprintf(s,"Device name =%s",dev_name);
6134     tmptxt=s;
6135 #endif
6136     }
6137   }
6138 if(i == 0)
6139   {
6140   lir_text(22,line,tmptxt);
6141   settextcolor(7);
6142   SNDLOG"Initial TXin setting: %s\n",tmptxt);
6143   }
6144 line+=i+1;
6145 if(k)
6146   {
6147   sprintf(s,"sample rate        = %i ",ui.tx_ad_speed);
6148   SNDLOG"%s\n",s);
6149   lir_text(2,line,s);
6150   line++;
6151   sprintf(s,"No of input bytes  = %d (%d bits)",
6152                 ui.tx_ad_bytes, 8*ui.tx_ad_bytes);
6153   SNDLOG"%s\n",s);
6154   lir_text(2,line,s);
6155   line++;
6156   sprintf(s,"No of input chans  = %d", ui.tx_ad_channels);
6157   SNDLOG"%s\n",s);
6158   lir_text(2,line,s);
6159   }
6160 line+=2;
6161 sndlog_sync();
6162 // **************************************************************
6163 // Ask whether the user wants to change something and act accordingly.
6164 // **************************************************************
6165 lir_text(0,line,"A = Change the output settings.");
6166 line++;
6167 lir_text(0,line,"B = Change the input settings.");
6168 line++;
6169 lir_text(0,line,"X = To main menu.");
6170 setup_menu:;
6171 await_processed_keyboard();
6172 if(kill_all_flag)goto set_tx_io_errexit;
6173 line=0;
6174 switch(lir_inkey)
6175   {
6176   case 'A':
6177   clear_screen();
6178   if(ui.rx_addev_no >=0 && ui.rx_addev_no < SPECIFIC_DEVICE_CODES)
6179     {
6180     if(start_iotest(&line,RXAD) == FALSE)goto set_txout_exit;
6181     }
6182   if(ui.rx_dadev_no >=0 && ui.rx_dadev_no < SPECIFIC_DEVICE_CODES)
6183     {
6184     if(start_iotest(&line,RXDA) == FALSE)goto set_txout_exit;
6185     }
6186   sprintf(s,"SELECT SOUNDCARD/DEVICE FOR TX OUTPUT FROM LIST:");
6187   SNDLOG"%s\n",s);
6188   lir_text(0,line,s);
6189   line++;
6190 #if (ALSA_PRESENT == 1)
6191   if( (ui.use_alsa&NATIVE_ALSA_USED)!=0)
6192     {
6193     ui.tx_dadev_no=select_alsadev(SND_PCM_STREAM_PLAYBACK, &line);
6194     if(kill_all_flag)goto set_txout_exit;
6195     if(alsa_dev_min_rate[ui.tx_dadev_no] !=
6196                                       alsa_dev_max_rate[ui.tx_dadev_no])
6197       {
6198       sprintf(s,"Select Tx D/A speed %d to %d",
6199                                  alsa_dev_min_rate[ui.tx_dadev_no],
6200                                  alsa_dev_max_rate[ui.tx_dadev_no]);
6201       lir_text(5,line,s);
6202       i=0;
6203       while(s[i] != 0)i++;
6204       ui.tx_da_speed=lir_get_integer(i+7, line, 6,
6205                                  alsa_dev_min_rate[ui.tx_dadev_no],
6206                                  alsa_dev_max_rate[ui.tx_dadev_no]);
6207       if(kill_all_flag)goto set_txout_exit;
6208       line++;
6209       }
6210     else
6211       {
6212       ui.tx_da_speed=alsa_dev_min_rate[ui.tx_dadev_no];
6213       }
6214     select_txout_format(&line);
6215     if(kill_all_flag)goto set_txout_exit;
6216     if(alsa_dev_max_bytes > 2)
6217       {
6218       if(alsa_dev_max_bytes != 4)
6219         {
6220         lirerr(327761);
6221         return;
6222         }
6223       if(alsa_dev_min_bytes == 4)
6224         {
6225         ui.tx_da_bytes=4;
6226         }
6227       else
6228         {
6229         line++;
6230         lir_text(5,line,"Select tx no of bytes (2 or 4)");
6231 alsa_get_tx_dabytes:;
6232         ui.tx_da_bytes=lir_get_integer(36,line,2,2,4);
6233         if(ui.tx_da_bytes==3)goto alsa_get_tx_dabytes;
6234         }
6235       }
6236     else
6237       {
6238       ui.tx_da_bytes=2;
6239       }
6240     }
6241   else
6242 #endif
6243     {
6244 #if HAVE_OSS == 1
6245     select_ossdev(&line, TXDA);
6246     if(kill_all_flag)goto set_tx_io_errexit;
6247     if(ui.tx_dadev_no == (ui.rx_addev_no&255) && ui.rx_admode == O_RDWR)
6248       {
6249       if(ui.tx_dadev_no == ui.rx_dadev_no)
6250         {
6251         lir_text(line,0,"Device used for RX input and output.");
6252         goto nodup;
6253         }
6254       if(ui.rx_ad_channels == 4)
6255         {
6256         lir_text(0,line,"RDWR for TX output not possible with 4 channels.");
6257 nodup:;
6258         line++;
6259         ui.tx_dadev_no=UNDEFINED_DEVICE_CODE;
6260         lir_text(10,line,press_any_key);
6261         await_processed_keyboard();
6262         goto set_txout_exit;
6263         }
6264 //set speed
6265       ui.tx_da_speed=ui.rx_ad_speed;
6266       ui.tx_da_bytes=2;
6267       if( (ui.rx_input_mode&DWORD_INPUT) != 0)ui.tx_da_bytes=4;
6268       ui.tx_da_channels=2;
6269       }
6270     else
6271       {
6272       if(dev_min_wr_speed[ui.tx_dadev_no] != dev_max_wr_speed[ui.tx_dadev_no])
6273         {
6274         sprintf(s,"Select Tx D/A speed %d to %d",
6275           dev_min_wr_speed[ui.tx_dadev_no], dev_max_wr_speed[ui.tx_dadev_no]);
6276         lir_text(5,line,s);
6277         i=0;
6278         while(s[i] != 0)i++;
6279         ui.tx_da_speed=lir_get_integer(i+7, line, 6,
6280           dev_min_wr_speed[ui.tx_dadev_no], dev_max_wr_speed[ui.tx_dadev_no]);
6281         line++;
6282         }
6283       else
6284         {
6285         ui.tx_da_speed=dev_min_wr_speed[ui.tx_dadev_no];
6286         }
6287 // Rely on the driver to allow one or two channels.
6288 // 4Front returns 4 for a Delta44 in cooked mode so
6289 // the "clever" code does not work.
6290       dev_wr_channels[ui.tx_dadev_no]=3;
6291       select_txout_format(&line);
6292       if( (dev_wr_bytes[ui.tx_dadev_no]&6) == 6)
6293         {
6294         line++;
6295         lir_text(5,line,"Select tx no of bytes (2 or 4)");
6296 get_tx_dabytes:;
6297         ui.tx_da_bytes=lir_get_integer(36,line,2,2,4);
6298         if(ui.tx_da_bytes==3)goto get_tx_dabytes;
6299         }
6300       else
6301         {
6302         ui.tx_da_bytes=dev_wr_bytes[ui.tx_dadev_no]&6;
6303         }
6304       }
6305 #endif
6306     }
6307 set_txout_exit:;
6308   if(ui.rx_dadev_no >=0 && ui.rx_dadev_no < SPECIFIC_DEVICE_CODES)
6309     {
6310     stop_iotest(RXDA);
6311     }
6312   if(ui.rx_addev_no >=0 && ui.rx_addev_no < SPECIFIC_DEVICE_CODES)
6313     {
6314     stop_iotest(RXAD);
6315     }
6316   break;
6317 
6318   case 'B':
6319   clear_screen();
6320   if(ui.tx_dadev_no == UNDEFINED_DEVICE_CODE)
6321     {
6322     lir_text(0,line,"Set tx output device first.");
6323     line+=2;
6324     lir_text(10,line,press_any_key);
6325     await_processed_keyboard();
6326     break;
6327     }
6328   ui.tx_addev_no=UNDEFINED_DEVICE_CODE;
6329   if(ui.rx_addev_no >=0 && ui.rx_addev_no < SPECIFIC_DEVICE_CODES)
6330     {
6331     if(start_iotest(&line,RXAD) == FALSE)goto set_txin_exit;
6332     }
6333   if(start_iotest(&line,RXDA) == FALSE)goto set_txin_exit;
6334   if(start_iotest(&line,TXDA) == FALSE)goto set_txin_exit;
6335   sprintf(s,"SELECT SOUNDCARD/DEVICE FOR TX INPUT FROM LIST:");
6336   SNDLOG"%s\n",s);
6337   lir_text(0,line,s);
6338   line++;
6339 #if (ALSA_PRESENT == 1)
6340   if( (ui.use_alsa&NATIVE_ALSA_USED)!=0)
6341     {
6342     ui.tx_addev_no=select_alsadev(SND_PCM_STREAM_CAPTURE, &line);
6343     if(kill_all_flag)goto set_tx_io_errexit;
6344     sprintf(s,"Enter sample-rate >");
6345     lir_text(0,line,s);
6346     SNDLOG"%s\n",s);
6347     ui.tx_ad_speed=lir_get_integer(21, line, 6,
6348                                   alsa_dev_min_rate[ui.tx_addev_no],
6349                                   alsa_dev_max_rate[ui.tx_addev_no]);
6350     if(kill_all_flag)goto set_tx_io_errexit;
6351     sprintf(s,"User selected  %i",i);
6352     SNDLOG"%s\n",s);
6353     lir_text(29,line,blanks);
6354     line++;
6355     SNDLOG"\n\n");
6356 //get number of bytes and check
6357     if(alsa_dev_max_bytes > 2)
6358       {
6359       sprintf(s,"Enter number of input bytes (2 or 4) >");
6360 select_number_input_bytes:;
6361       SNDLOG"%s\n",s);
6362       lir_text(0,line,s);
6363       ui.tx_ad_bytes=lir_get_integer(39, line, 1,2,4);
6364       if(kill_all_flag)goto set_tx_io_errexit;
6365       if(ui.tx_ad_bytes==3)
6366         {
6367         settextcolor(12);
6368         sprintf(s,"invalid selection, try again");
6369         SNDLOG"%s\n",s);
6370         lir_text(44,line,s);
6371         settextcolor(7);
6372         goto select_number_input_bytes;
6373         }
6374       line++;
6375       }
6376     else
6377       {
6378       ui.tx_ad_bytes=2;
6379       SNDLOG"\n\n");
6380       }
6381     ui.tx_ad_channels=1;
6382     line+=2;
6383     }
6384   else
6385 #endif
6386     {
6387 #if HAVE_OSS == 1
6388     select_ossdev(&line, TXAD);
6389     if(kill_all_flag)goto set_tx_io_errexit;
6390     if(ui.tx_addev_no == ui.rx_dadev_no && ui.rx_damode == O_RDWR)
6391       {
6392       if(ui.rx_max_da_bytes != 2)
6393         {
6394         ui.tx_addev_no=UNDEFINED_DEVICE_CODE;
6395         lir_text(0,line,"Useless device. Only 8 bit.");
6396         }
6397       else
6398         {
6399         lir_text(0,line,"Rx output parameters modified for RDWR usage");
6400         ui.rx_min_da_bytes=2;
6401         ui.tx_ad_bytes=2;
6402         if(ui.rx_max_da_channels == 2)
6403           {
6404           ui.rx_min_da_channels=2;
6405           ui.tx_ad_channels=2;
6406           }
6407         else
6408           {
6409           ui.rx_max_da_channels=1;
6410           ui.tx_ad_channels=1;
6411           }
6412         ui.tx_ad_speed=get_mic_speed(&line, ui.rx_min_da_speed,
6413                                                         ui.rx_max_da_speed);
6414         ui.rx_min_da_speed=ui.tx_ad_speed;
6415         ui.rx_max_da_speed=ui.tx_ad_speed;
6416         }
6417       line++;
6418       lir_text(5,line,press_any_key);
6419       await_processed_keyboard();
6420       goto set_txin_exit;
6421       }
6422 // Use one channel if the device can do both one and two channels.
6423     if( (3 & dev_rd_channels[ui.tx_addev_no]) == 3)
6424       {
6425       ui.tx_ad_channels=1;
6426       }
6427     else
6428       {
6429       ui.tx_ad_channels=3&dev_rd_channels[ui.tx_addev_no];
6430       }
6431     if( (dev_rd_channels[ui.tx_addev_no]&3) == 3)
6432       {
6433       line++;
6434       lir_text(0,line,"Select microphone no of bytes (2 or 4)");
6435 get_micbytes:;
6436       ui.tx_ad_bytes=lir_get_integer(39,line,2,2,4);
6437       if(ui.tx_ad_bytes==3)goto get_micbytes;
6438       line++;
6439       }
6440     else
6441       {
6442       ui.tx_ad_bytes=dev_rd_channels[ui.tx_addev_no]&3;
6443       }
6444     if(dev_min_rd_speed[ui.tx_addev_no] != dev_max_rd_speed[ui.tx_addev_no])
6445       {
6446       ui.tx_ad_speed=get_mic_speed(&line, dev_min_rd_speed[ui.tx_addev_no],
6447                                          dev_max_rd_speed[ui.tx_addev_no]);
6448       }
6449     else
6450       {
6451       ui.tx_ad_speed=dev_min_rd_speed[ui.tx_addev_no];
6452       }
6453 #endif
6454     }
6455 set_txin_exit:;
6456   stop_iotest(TXDA);
6457   stop_iotest(RXDA);
6458   if(ui.rx_addev_no >=0 && ui.rx_addev_no < SPECIFIC_DEVICE_CODES)
6459     {
6460     stop_iotest(RXAD);
6461     }
6462   if(ui.tx_addev_no != UNDEFINED_DEVICE_CODE)
6463     {
6464     line=0;
6465     clear_screen();
6466 get_enable:;
6467     if(kill_all_flag)break;
6468     lir_text(4,line,"Enable Tx while running receive modes ? (Y/N) =>");
6469     await_processed_keyboard();
6470     if(lir_inkey == 'Y')
6471       {
6472       ui.tx_enable=1;
6473       line+=2;
6474       lir_text(0,line,"Parameters for speech processor, keying, etc. have to");
6475       line++;
6476       lir_text(0,line,"be set up and saved before Tx becomes enabled in Rx modes.");
6477       line++;
6478       }
6479     else
6480       {
6481       if(lir_inkey != 'N')goto get_enable;
6482       ui.tx_enable=0;
6483       }
6484     line+=2;
6485     lir_text(0,line,"The tx pilot tone may control fast Rx/Tx switching.");
6486     line++;
6487     lir_text(0,line,"Set pilot tone level in dB below signal (50-130)");
6488     ui.tx_pilot_tone_db=lir_get_integer(49, line, 3, 50, 130);
6489     line+=2;
6490     lir_text(0,line,"Set prestart in microseconds (0-100000)");
6491     ui.tx_pilot_tone_prestart=lir_get_integer(39, line, 6, 0, 100000);
6492     line+=2;
6493     settextcolor(15);
6494     lir_text(5,line,remind_parsave);
6495     settextcolor(7);
6496     line+=2;
6497     lir_text(5,line,press_any_key);
6498     await_processed_keyboard();
6499     }
6500   break;
6501 
6502   case 'X':
6503   goto set_tx_io_exit;
6504 
6505   default:
6506   goto setup_menu;
6507   }
6508 SNDLOG"goto begin_tx_set_io\n\n");
6509 sndlog_sync();
6510 goto begin_tx_set_io;
6511 set_tx_io_exit:;
6512 SNDLOG"\nNormal end");
6513 set_tx_io_errexit:;
6514 SNDLOG"\n");
6515 fclose(sndlog);
6516 write_log=FALSE;
6517 }
6518 
6519 
6520