mirror of
				https://github.com/saitohirga/WSJT-X.git
				synced 2025-11-03 21:40:52 -05:00 
			
		
		
		
	Update the list of Fortran LUs.
Remove several unused files. Replace use of rfile2 with fortran I/O using access='stream'. git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/map65@604 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
This commit is contained in:
		
							parent
							
								
									08e095252a
								
							
						
					
					
						commit
						7bd9e32f04
					
				
							
								
								
									
										7
									
								
								astro.F
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								astro.F
									
									
									
									
									
								
							@ -34,8 +34,11 @@ C  NB: may want to smooth the Tsky map to 10 degrees or so.
 | 
				
			|||||||
        read(13) nsky
 | 
					        read(13) nsky
 | 
				
			||||||
        close(13)
 | 
					        close(13)
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
        call rfile2(fname,nsky,129600,nr)
 | 
					        open(13,file=fname,status='old',access='stream',err=10)
 | 
				
			||||||
        if(nr.ne.129600) go to 10
 | 
					        read(13) nsky
 | 
				
			||||||
 | 
					        close(13)
 | 
				
			||||||
 | 
					!        call rfile2(fname,nsky,129600,nr)
 | 
				
			||||||
 | 
					!        if(nr.ne.129600) go to 10
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
        ltsky=.true.
 | 
					        ltsky=.true.
 | 
				
			||||||
        first=.false.
 | 
					        first=.false.
 | 
				
			||||||
 | 
				
			|||||||
@ -1,13 +1,13 @@
 | 
				
			|||||||
! Fortran logical units used in WSJT6
 | 
					! Fortran logical units used in WSJT6
 | 
				
			||||||
!
 | 
					!
 | 
				
			||||||
!   10  wave files read from disk
 | 
					!   10
 | 
				
			||||||
!   11  decoded.txt
 | 
					!   11  decoded.txt
 | 
				
			||||||
!   12  decoded.ave
 | 
					!   12  decoded.ave
 | 
				
			||||||
!   13  tsky.dat
 | 
					!   13  tsky.dat
 | 
				
			||||||
!   14  azel.dat
 | 
					!   14  azel.dat
 | 
				
			||||||
!   15  
 | 
					!   15  
 | 
				
			||||||
!   16  c:/wsjt.reg 
 | 
					!   16
 | 
				
			||||||
!   17  wave files written to disk
 | 
					!   17  saved *.tf2 files
 | 
				
			||||||
!   18  test file to be transmitted (wsjtgen.f90)
 | 
					!   18  test file to be transmitted (wsjtgen.f90)
 | 
				
			||||||
!   19  messages.txt
 | 
					!   19  messages.txt
 | 
				
			||||||
!   20  bandmap.txt
 | 
					!   20  bandmap.txt
 | 
				
			||||||
@ -18,7 +18,7 @@
 | 
				
			|||||||
!   25  meas25.dat
 | 
					!   25  meas25.dat
 | 
				
			||||||
!   26  tmp26.txt
 | 
					!   26  tmp26.txt
 | 
				
			||||||
!   27  dphi.txt
 | 
					!   27  dphi.txt
 | 
				
			||||||
!   28  saved *.tf2 files
 | 
					!   28  
 | 
				
			||||||
!   29  debug.txt
 | 
					!   29  debug.txt
 | 
				
			||||||
!------------------------------------------------ ftn_init
 | 
					!------------------------------------------------ ftn_init
 | 
				
			||||||
subroutine ftn_init
 | 
					subroutine ftn_init
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										2
									
								
								map65.py
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								map65.py
									
									
									
									
									
								
							@ -1,4 +1,4 @@
 | 
				
			|||||||
#---------------------------------------------------------------------- MAP65
 | 
					#--------------------------------------------------------------------- MAP65
 | 
				
			||||||
# $Date$ $Revision$
 | 
					# $Date$ $Revision$
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
from Tkinter import *
 | 
					from Tkinter import *
 | 
				
			||||||
 | 
				
			|||||||
@ -91,6 +91,7 @@ subroutine recvpkt(iarg)
 | 
				
			|||||||
  rxnoise=10.0*log10(sqave) - 48.0
 | 
					  rxnoise=10.0*log10(sqave) - 48.0
 | 
				
			||||||
  kxp=k
 | 
					  kxp=k
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					!  This may be a bad idea, because of non-reentrant Fortran I/O?
 | 
				
			||||||
  if(mode.eq.'Measur') then
 | 
					  if(mode.eq.'Measur') then
 | 
				
			||||||
     npkt=npkt+1
 | 
					     npkt=npkt+1
 | 
				
			||||||
     if(npkt.ge.551) then
 | 
					     if(npkt.ge.551) then
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										568
									
								
								start_alsa.c
									
									
									
									
									
								
							
							
						
						
									
										568
									
								
								start_alsa.c
									
									
									
									
									
								
							@ -1,568 +0,0 @@
 | 
				
			|||||||
#include <stdio.h>
 | 
					 | 
				
			||||||
#include <stdlib.h>
 | 
					 | 
				
			||||||
#include <pthread.h>
 | 
					 | 
				
			||||||
#include <alsa/asoundlib.h>
 | 
					 | 
				
			||||||
#include <inttypes.h>
 | 
					 | 
				
			||||||
#include <time.h>
 | 
					 | 
				
			||||||
#include <sys/time.h>
 | 
					 | 
				
			||||||
#include "fivehz.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#if 1
 | 
					 | 
				
			||||||
#define ALSA_LOG
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
#if 0
 | 
					 | 
				
			||||||
#define ALSA_LOG_BUFFERS
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
#if 0
 | 
					 | 
				
			||||||
#define ALSA_PLAYBACK_LOG
 | 
					 | 
				
			||||||
#define ALSA_CAPTURE_LOG
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
#define BUFFER_TIME               2000*1000
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
typedef struct alsa_driver_s {
 | 
					 | 
				
			||||||
	snd_pcm_t	*audio_fd;
 | 
					 | 
				
			||||||
	int		 capabilities;
 | 
					 | 
				
			||||||
	int		 open_mode;
 | 
					 | 
				
			||||||
	int		 has_pause_resume;
 | 
					 | 
				
			||||||
	int		 is_paused;
 | 
					 | 
				
			||||||
	uint32_t		 output_sample_rate, input_sample_rate;
 | 
					 | 
				
			||||||
	double		 sample_rate_factor;
 | 
					 | 
				
			||||||
	uint32_t	 num_channels;
 | 
					 | 
				
			||||||
	uint32_t	 bits_per_sample;
 | 
					 | 
				
			||||||
	uint32_t	 bytes_per_frame;
 | 
					 | 
				
			||||||
	uint32_t	 bytes_in_buffer;      /* number of bytes writen to audio hardware   */
 | 
					 | 
				
			||||||
	int16_t		*app_buffer_y1;
 | 
					 | 
				
			||||||
	int16_t		*app_buffer_y2;
 | 
					 | 
				
			||||||
	int		*app_buffer_offset;
 | 
					 | 
				
			||||||
	int		 app_buffer_length;
 | 
					 | 
				
			||||||
	double		*Tsec;
 | 
					 | 
				
			||||||
	double		*tbuf;
 | 
					 | 
				
			||||||
	int		*ibuf;
 | 
					 | 
				
			||||||
	int		*ndsec;
 | 
					 | 
				
			||||||
	int		*tx_ok;
 | 
					 | 
				
			||||||
	int		 tx_starting;
 | 
					 | 
				
			||||||
	int		 tx_offset;
 | 
					 | 
				
			||||||
	int		*tr_period;
 | 
					 | 
				
			||||||
	int		*nwave;
 | 
					 | 
				
			||||||
	int		*nmode;
 | 
					 | 
				
			||||||
	int		*transmitting;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	snd_pcm_uframes_t  buffer_size;
 | 
					 | 
				
			||||||
	snd_pcm_uframes_t  period_size;
 | 
					 | 
				
			||||||
	int32_t		 mmap; 
 | 
					 | 
				
			||||||
} alsa_driver_t;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
alsa_driver_t alsa_driver_playback;
 | 
					 | 
				
			||||||
alsa_driver_t alsa_driver_capture;
 | 
					 | 
				
			||||||
void *alsa_capture_buffers[2];
 | 
					 | 
				
			||||||
void *alsa_playback_buffers[2];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static snd_output_t *jcd_out;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * open the audio device for writing to
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static int ao_alsa_open(alsa_driver_t *this_gen, int32_t *input_rate, snd_pcm_stream_t direction ) {
 | 
					 | 
				
			||||||
  alsa_driver_t        *this = (alsa_driver_t *) this_gen;
 | 
					 | 
				
			||||||
  char                 *pcm_device;
 | 
					 | 
				
			||||||
  snd_pcm_hw_params_t  *params;
 | 
					 | 
				
			||||||
  snd_pcm_sw_params_t  *swparams;
 | 
					 | 
				
			||||||
  snd_pcm_access_mask_t *mask;
 | 
					 | 
				
			||||||
  snd_pcm_uframes_t     period_size_min; 
 | 
					 | 
				
			||||||
  snd_pcm_uframes_t     period_size_max; 
 | 
					 | 
				
			||||||
  snd_pcm_uframes_t     buffer_size_min;
 | 
					 | 
				
			||||||
  snd_pcm_uframes_t     buffer_size_max;
 | 
					 | 
				
			||||||
  snd_pcm_format_t      format;
 | 
					 | 
				
			||||||
  uint32_t              buffer_time=BUFFER_TIME;
 | 
					 | 
				
			||||||
  snd_pcm_uframes_t     buffer_time_to_size;
 | 
					 | 
				
			||||||
  int                   err, dir;
 | 
					 | 
				
			||||||
  int                 open_mode=1; /* NONBLOCK */
 | 
					 | 
				
			||||||
  /* int                   open_mode=0;  BLOCK */
 | 
					 | 
				
			||||||
  uint32_t            rate=*input_rate;
 | 
					 | 
				
			||||||
  this->input_sample_rate=*input_rate;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  snd_pcm_hw_params_alloca(¶ms);
 | 
					 | 
				
			||||||
  snd_pcm_sw_params_alloca(&swparams);
 | 
					 | 
				
			||||||
  err = snd_output_stdio_attach(&jcd_out, stdout, 0);
 | 
					 | 
				
			||||||
  
 | 
					 | 
				
			||||||
  this->num_channels = 2;
 | 
					 | 
				
			||||||
  if (direction == SND_PCM_STREAM_PLAYBACK) {
 | 
					 | 
				
			||||||
    pcm_device="plug:front";
 | 
					 | 
				
			||||||
  } else {
 | 
					 | 
				
			||||||
    pcm_device="default";
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef ALSA_LOG
 | 
					 | 
				
			||||||
  printf("audio_alsa_out: Audio Device name = %s\n",pcm_device);
 | 
					 | 
				
			||||||
  printf("audio_alsa_out: Number of channels = %d\n",this->num_channels);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (this->audio_fd) {
 | 
					 | 
				
			||||||
    printf("audio_alsa_out:Already open...WHY!");
 | 
					 | 
				
			||||||
    snd_pcm_close (this->audio_fd);
 | 
					 | 
				
			||||||
    this->audio_fd = NULL;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  this->bytes_in_buffer        = 0;
 | 
					 | 
				
			||||||
  /*
 | 
					 | 
				
			||||||
   * open audio device
 | 
					 | 
				
			||||||
   */
 | 
					 | 
				
			||||||
  err=snd_pcm_open(&this->audio_fd, pcm_device, direction, open_mode);      
 | 
					 | 
				
			||||||
  if(err <0 ) {                                                           
 | 
					 | 
				
			||||||
    printf ("audio_alsa_out: snd_pcm_open() of %s failed: %s\n", pcm_device, snd_strerror(err));               
 | 
					 | 
				
			||||||
    printf ("audio_alsa_out: >>> check if another program already uses PCM <<<\n");
 | 
					 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  /* printf ("audio_alsa_out: snd_pcm_open() opened %s\n", pcm_device); */ 
 | 
					 | 
				
			||||||
  /* We wanted non blocking open but now put it back to normal */
 | 
					 | 
				
			||||||
  //snd_pcm_nonblock(this->audio_fd, 0);
 | 
					 | 
				
			||||||
  snd_pcm_nonblock(this->audio_fd, 1);
 | 
					 | 
				
			||||||
  /*
 | 
					 | 
				
			||||||
   * configure audio device
 | 
					 | 
				
			||||||
   */
 | 
					 | 
				
			||||||
  err = snd_pcm_hw_params_any(this->audio_fd, params);
 | 
					 | 
				
			||||||
  if (err < 0) {
 | 
					 | 
				
			||||||
    printf ("audio_alsa_out: broken configuration for this PCM: no configurations available: %s\n",
 | 
					 | 
				
			||||||
	     snd_strerror(err));
 | 
					 | 
				
			||||||
    goto close;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  /* set interleaved access */
 | 
					 | 
				
			||||||
  if (this->mmap != 0) {
 | 
					 | 
				
			||||||
    mask = alloca(snd_pcm_access_mask_sizeof());
 | 
					 | 
				
			||||||
    snd_pcm_access_mask_none(mask);
 | 
					 | 
				
			||||||
    snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_INTERLEAVED);
 | 
					 | 
				
			||||||
    snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED);
 | 
					 | 
				
			||||||
    snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_COMPLEX);
 | 
					 | 
				
			||||||
    err = snd_pcm_hw_params_set_access_mask(this->audio_fd, params, mask);
 | 
					 | 
				
			||||||
    if (err < 0) {
 | 
					 | 
				
			||||||
      printf ( "audio_alsa_out: mmap not availiable, falling back to compatiblity mode\n");
 | 
					 | 
				
			||||||
      this->mmap=0;
 | 
					 | 
				
			||||||
      err = snd_pcm_hw_params_set_access(this->audio_fd, params,
 | 
					 | 
				
			||||||
                                     SND_PCM_ACCESS_RW_NONINTERLEAVED);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  } else {
 | 
					 | 
				
			||||||
    err = snd_pcm_hw_params_set_access(this->audio_fd, params,
 | 
					 | 
				
			||||||
                                     SND_PCM_ACCESS_RW_NONINTERLEAVED);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
      
 | 
					 | 
				
			||||||
  if (err < 0) {
 | 
					 | 
				
			||||||
    printf ( "audio_alsa_out: access type not available: %s\n", snd_strerror(err));
 | 
					 | 
				
			||||||
    goto close;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  /* set the sample format S16 */
 | 
					 | 
				
			||||||
  /* ALSA automatically appends _LE or _BE depending on the CPU */
 | 
					 | 
				
			||||||
  format = SND_PCM_FORMAT_S16;
 | 
					 | 
				
			||||||
  err = snd_pcm_hw_params_set_format(this->audio_fd, params, format );
 | 
					 | 
				
			||||||
  if (err < 0) {
 | 
					 | 
				
			||||||
    printf ( "audio_alsa_out: sample format non available: %s\n", snd_strerror(err));
 | 
					 | 
				
			||||||
    goto close;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  /* set the number of channels */
 | 
					 | 
				
			||||||
  err = snd_pcm_hw_params_set_channels(this->audio_fd, params, this->num_channels);
 | 
					 | 
				
			||||||
  if (err < 0) {
 | 
					 | 
				
			||||||
    printf ( "audio_alsa_out: Cannot set number of channels to %d (err=%d:%s)\n", 
 | 
					 | 
				
			||||||
	     this->num_channels, err, snd_strerror(err));
 | 
					 | 
				
			||||||
    goto close;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
#if SND_LIB_VERSION >= 0x010009
 | 
					 | 
				
			||||||
  /* Restrict a configuration space to contain only real hardware rates */
 | 
					 | 
				
			||||||
  err = snd_pcm_hw_params_set_rate_resample(this->audio_fd, params, 0);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
  /* set the stream rate [Hz] */
 | 
					 | 
				
			||||||
  dir=0;
 | 
					 | 
				
			||||||
  err = snd_pcm_hw_params_set_rate_near(this->audio_fd, params, &rate, &dir);
 | 
					 | 
				
			||||||
  if (err < 0) {
 | 
					 | 
				
			||||||
    printf ( "audio_alsa_out: rate not available: %s\n", snd_strerror(err));
 | 
					 | 
				
			||||||
    goto close;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  this->output_sample_rate = (uint32_t)rate;
 | 
					 | 
				
			||||||
  if (this->input_sample_rate != this->output_sample_rate) {
 | 
					 | 
				
			||||||
    printf ( "audio_alsa_out: audio rate : %d requested, %d provided by device/sec\n",
 | 
					 | 
				
			||||||
	     this->input_sample_rate, this->output_sample_rate);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  buffer_time_to_size = ( (uint64_t)buffer_time * rate) / 1000000;
 | 
					 | 
				
			||||||
  err = snd_pcm_hw_params_get_buffer_size_min(params, &buffer_size_min);
 | 
					 | 
				
			||||||
  err = snd_pcm_hw_params_get_buffer_size_max(params, &buffer_size_max);
 | 
					 | 
				
			||||||
  dir=0;
 | 
					 | 
				
			||||||
  err = snd_pcm_hw_params_get_period_size_min(params, &period_size_min,&dir);
 | 
					 | 
				
			||||||
  dir=0;
 | 
					 | 
				
			||||||
  err = snd_pcm_hw_params_get_period_size_max(params, &period_size_max,&dir);
 | 
					 | 
				
			||||||
#ifdef ALSA_LOG_BUFFERS
 | 
					 | 
				
			||||||
  printf("Buffer size range from %lu to %lu\n",buffer_size_min, buffer_size_max);
 | 
					 | 
				
			||||||
  printf("Period size range from %lu to %lu\n",period_size_min, period_size_max);
 | 
					 | 
				
			||||||
  printf("Buffer time size %lu\n",buffer_time_to_size);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
  this->buffer_size = buffer_time_to_size;
 | 
					 | 
				
			||||||
  if (buffer_size_max < this->buffer_size)
 | 
					 | 
				
			||||||
	this->buffer_size = buffer_size_max;
 | 
					 | 
				
			||||||
  if (buffer_size_min > this->buffer_size)
 | 
					 | 
				
			||||||
	this->buffer_size = buffer_size_min;
 | 
					 | 
				
			||||||
  this->period_size = this->buffer_size/8;
 | 
					 | 
				
			||||||
  if (this->period_size > 2048)
 | 
					 | 
				
			||||||
	this->period_size = 2048;
 | 
					 | 
				
			||||||
  this->buffer_size = this->period_size*8;
 | 
					 | 
				
			||||||
#ifdef ALSA_LOG_BUFFERS
 | 
					 | 
				
			||||||
  printf("To choose buffer_size = %ld\n",this->buffer_size);
 | 
					 | 
				
			||||||
  printf("To choose period_size = %ld\n",this->period_size);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#if 0
 | 
					 | 
				
			||||||
  /* Set period to buffer size ratios at 8 periods to 1 buffer */
 | 
					 | 
				
			||||||
  dir=-1;
 | 
					 | 
				
			||||||
  periods=8;
 | 
					 | 
				
			||||||
  err = snd_pcm_hw_params_set_periods_near(this->audio_fd, params, &periods ,&dir);
 | 
					 | 
				
			||||||
  if (err < 0) {
 | 
					 | 
				
			||||||
    xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, 
 | 
					 | 
				
			||||||
	     "audio_alsa_out: unable to set any periods: %s\n", snd_strerror(err));
 | 
					 | 
				
			||||||
    goto close;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  /* set the ring-buffer time [us] (large enough for x us|y samples ...) */
 | 
					 | 
				
			||||||
  dir=0;
 | 
					 | 
				
			||||||
  err = snd_pcm_hw_params_set_buffer_time_near(this->audio_fd, params, &buffer_time, &dir);
 | 
					 | 
				
			||||||
  if (err < 0) {
 | 
					 | 
				
			||||||
    xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, 
 | 
					 | 
				
			||||||
	     "audio_alsa_out: buffer time not available: %s\n", snd_strerror(err));
 | 
					 | 
				
			||||||
    goto close;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
#if 1
 | 
					 | 
				
			||||||
  /* set the period time [us] (interrupt every x us|y samples ...) */
 | 
					 | 
				
			||||||
  dir=0;
 | 
					 | 
				
			||||||
  err = snd_pcm_hw_params_set_period_size_near(this->audio_fd, params, &(this->period_size), &dir);
 | 
					 | 
				
			||||||
  if (err < 0) {
 | 
					 | 
				
			||||||
    printf ( "audio_alsa_out: period time not available: %s\n", snd_strerror(err));
 | 
					 | 
				
			||||||
    goto close;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
  dir=0;
 | 
					 | 
				
			||||||
  err = snd_pcm_hw_params_get_period_size(params, &(this->period_size), &dir);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  dir=0;
 | 
					 | 
				
			||||||
  err = snd_pcm_hw_params_set_buffer_size_near(this->audio_fd, params, &(this->buffer_size));
 | 
					 | 
				
			||||||
  if (err < 0) {
 | 
					 | 
				
			||||||
    printf ( "audio_alsa_out: buffer time not available: %s\n", snd_strerror(err));
 | 
					 | 
				
			||||||
    goto close;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  err = snd_pcm_hw_params_get_buffer_size(params, &(this->buffer_size));
 | 
					 | 
				
			||||||
#ifdef ALSA_LOG_BUFFERS
 | 
					 | 
				
			||||||
  printf("was set period_size = %ld\n",this->period_size);
 | 
					 | 
				
			||||||
  printf("was set buffer_size = %ld\n",this->buffer_size);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
  if (2*this->period_size > this->buffer_size) {
 | 
					 | 
				
			||||||
    printf ( "audio_alsa_out: buffer to small, could not use\n");
 | 
					 | 
				
			||||||
    goto close;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  
 | 
					 | 
				
			||||||
  /* write the parameters to device */
 | 
					 | 
				
			||||||
  err = snd_pcm_hw_params(this->audio_fd, params);
 | 
					 | 
				
			||||||
  if (err < 0) {
 | 
					 | 
				
			||||||
    printf ( "audio_alsa_out: pcm hw_params failed: %s\n", snd_strerror(err));
 | 
					 | 
				
			||||||
    goto close;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  /* Check for pause/resume support */
 | 
					 | 
				
			||||||
  this->has_pause_resume = ( snd_pcm_hw_params_can_pause (params)
 | 
					 | 
				
			||||||
			    && snd_pcm_hw_params_can_resume (params) );
 | 
					 | 
				
			||||||
  //  printf( "audio_alsa_out:open pause_resume=%d\n", this->has_pause_resume);
 | 
					 | 
				
			||||||
  this->sample_rate_factor = (double) this->output_sample_rate / (double) this->input_sample_rate;
 | 
					 | 
				
			||||||
  this->bytes_per_frame = snd_pcm_frames_to_bytes (this->audio_fd, 1);
 | 
					 | 
				
			||||||
  /*
 | 
					 | 
				
			||||||
   * audio buffer size handling
 | 
					 | 
				
			||||||
   */
 | 
					 | 
				
			||||||
  /* Copy current parameters into swparams */
 | 
					 | 
				
			||||||
  err = snd_pcm_sw_params_current(this->audio_fd, swparams);
 | 
					 | 
				
			||||||
  if (err < 0) {
 | 
					 | 
				
			||||||
    printf ( "audio_alsa_out: Unable to determine current swparams: %s\n", snd_strerror(err));
 | 
					 | 
				
			||||||
    goto close;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  /* align all transfers to 1 sample */
 | 
					 | 
				
			||||||
  err = snd_pcm_sw_params_set_xfer_align(this->audio_fd, swparams, 1);
 | 
					 | 
				
			||||||
  if (err < 0) {
 | 
					 | 
				
			||||||
    printf ( "audio_alsa_out: Unable to set transfer alignment: %s\n", snd_strerror(err));
 | 
					 | 
				
			||||||
    goto close;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  /* allow the transfer when at least period_size samples can be processed */
 | 
					 | 
				
			||||||
  err = snd_pcm_sw_params_set_avail_min(this->audio_fd, swparams, this->period_size);
 | 
					 | 
				
			||||||
  if (err < 0) {
 | 
					 | 
				
			||||||
    printf ( "audio_alsa_out: Unable to set available min: %s\n", snd_strerror(err));
 | 
					 | 
				
			||||||
    goto close;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  if (direction == SND_PCM_STREAM_PLAYBACK) {
 | 
					 | 
				
			||||||
  	/* start the transfer when the buffer contains at least period_size samples */
 | 
					 | 
				
			||||||
	err = snd_pcm_sw_params_set_start_threshold(this->audio_fd, swparams, this->buffer_size);
 | 
					 | 
				
			||||||
  } else {
 | 
					 | 
				
			||||||
	err = snd_pcm_sw_params_set_start_threshold(this->audio_fd, swparams, -1);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  if (err < 0) {
 | 
					 | 
				
			||||||
    printf ( "audio_alsa_out: Unable to set start threshold: %s\n", snd_strerror(err));
 | 
					 | 
				
			||||||
    goto close;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (direction == SND_PCM_STREAM_PLAYBACK) {
 | 
					 | 
				
			||||||
        /* never stop the transfer, even on xruns */
 | 
					 | 
				
			||||||
  	err = snd_pcm_sw_params_set_stop_threshold(this->audio_fd, swparams, this->buffer_size);
 | 
					 | 
				
			||||||
  } else {
 | 
					 | 
				
			||||||
  	err = snd_pcm_sw_params_set_stop_threshold(this->audio_fd, swparams, this->buffer_size);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  if (err < 0) {
 | 
					 | 
				
			||||||
    printf ( "audio_alsa_out: Unable to set stop threshold: %s\n", snd_strerror(err));
 | 
					 | 
				
			||||||
    goto close;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /* Install swparams into current parameters */
 | 
					 | 
				
			||||||
  err = snd_pcm_sw_params(this->audio_fd, swparams);
 | 
					 | 
				
			||||||
  if (err < 0) {
 | 
					 | 
				
			||||||
    printf ( "audio_alsa_out: Unable to set swparams: %s\n", snd_strerror(err));
 | 
					 | 
				
			||||||
    goto close;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
#ifdef ALSA_LOG
 | 
					 | 
				
			||||||
  snd_pcm_dump_setup(this->audio_fd, jcd_out); 
 | 
					 | 
				
			||||||
  snd_pcm_sw_params_dump(swparams, jcd_out);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
  
 | 
					 | 
				
			||||||
  return this->output_sample_rate;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
close:
 | 
					 | 
				
			||||||
  snd_pcm_close (this->audio_fd);
 | 
					 | 
				
			||||||
  this->audio_fd=NULL;
 | 
					 | 
				
			||||||
  return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int16_t zero_buffer[65536];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int playback_callback(alsa_driver_t *alsa_driver_playback) {
 | 
					 | 
				
			||||||
	alsa_driver_t *this = alsa_driver_playback;
 | 
					 | 
				
			||||||
	int result;
 | 
					 | 
				
			||||||
	struct timeval tv;
 | 
					 | 
				
			||||||
	double stime;
 | 
					 | 
				
			||||||
	int nsec;
 | 
					 | 
				
			||||||
	int i,n;
 | 
					 | 
				
			||||||
	static int ic;
 | 
					 | 
				
			||||||
	snd_pcm_sframes_t delay;	
 | 
					 | 
				
			||||||
	static short int n2;
 | 
					 | 
				
			||||||
	int16_t b0[2048];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//	printf("playback callback\n");
 | 
					 | 
				
			||||||
	snd_pcm_delay(this->audio_fd, &delay);
 | 
					 | 
				
			||||||
	gettimeofday(&tv, NULL);
 | 
					 | 
				
			||||||
	stime = (double) tv.tv_sec + ((double)tv.tv_usec / 1000000.0) +
 | 
					 | 
				
			||||||
		*(this->ndsec) * 0.1;
 | 
					 | 
				
			||||||
	//	stime = stime + ((double)delay / (double)(this->output_sample_rate));
 | 
					 | 
				
			||||||
	*(this->Tsec) = stime;
 | 
					 | 
				
			||||||
	//printf("PLAY:TIME, %lf, %ld, %ld, %d\n", stime, delay, this->output_sample_rate, *this->ndsec);
 | 
					 | 
				
			||||||
	if(!(this->tx_starting) && (*(this->tx_ok)) ) {
 | 
					 | 
				
			||||||
		nsec = (int)stime;
 | 
					 | 
				
			||||||
		n = nsec / *(this->tr_period);  
 | 
					 | 
				
			||||||
		ic = (int)(stime - *(this->tr_period) * n) * this->output_sample_rate;
 | 
					 | 
				
			||||||
		ic = ic % *(this->nwave);
 | 
					 | 
				
			||||||
		this->tx_offset = ic;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	this->tx_starting = *(this->tx_ok);
 | 
					 | 
				
			||||||
	*(this->transmitting) = *(this->tx_ok);
 | 
					 | 
				
			||||||
	if(*(this->tx_ok)) {
 | 
					 | 
				
			||||||
	  /*
 | 
					 | 
				
			||||||
		alsa_playback_buffers[0] = this->app_buffer_y1 + this->tx_offset;
 | 
					 | 
				
			||||||
		alsa_playback_buffers[1] = this->app_buffer_y1 + this->tx_offset;
 | 
					 | 
				
			||||||
	  */
 | 
					 | 
				
			||||||
	  alsa_playback_buffers[0] = b0;
 | 
					 | 
				
			||||||
	  alsa_playback_buffers[1] = b0;
 | 
					 | 
				
			||||||
	  for(i=0; i<this->period_size; i++) {
 | 
					 | 
				
			||||||
	    n2=this->app_buffer_y1[ic];
 | 
					 | 
				
			||||||
	    addnoise_(&n2);
 | 
					 | 
				
			||||||
	    b0[i]=n2;
 | 
					 | 
				
			||||||
	    ic++;
 | 
					 | 
				
			||||||
	    if(ic>=*this->nwave) {
 | 
					 | 
				
			||||||
	      if(*this->nmode==2) {
 | 
					 | 
				
			||||||
		*this->tx_ok=0;
 | 
					 | 
				
			||||||
		ic--;
 | 
					 | 
				
			||||||
	      }
 | 
					 | 
				
			||||||
	      else
 | 
					 | 
				
			||||||
		ic = ic % *this->nwave;       //Wrap buffer pointer
 | 
					 | 
				
			||||||
	    }
 | 
					 | 
				
			||||||
	  }
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		alsa_playback_buffers[0] = zero_buffer;
 | 
					 | 
				
			||||||
		alsa_playback_buffers[1] = zero_buffer;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	result = snd_pcm_writen(this->audio_fd, alsa_playback_buffers, this->period_size);
 | 
					 | 
				
			||||||
	this->tx_offset += this->period_size;
 | 
					 | 
				
			||||||
	if (result != this->period_size) {
 | 
					 | 
				
			||||||
		printf("Playback write failed. Expected %lu samples, sent only %d\n", this->period_size, result);
 | 
					 | 
				
			||||||
#ifdef ALSA_PLAYBACK_LOG
 | 
					 | 
				
			||||||
		snd_pcm_status_t *pcm_stat;
 | 
					 | 
				
			||||||
		snd_pcm_status_alloca(&pcm_stat);
 | 
					 | 
				
			||||||
		snd_pcm_status(this->audio_fd, pcm_stat);
 | 
					 | 
				
			||||||
		snd_pcm_status_dump(pcm_stat, jcd_out);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
  	fivehztx_();                             //Call fortran routine
 | 
					 | 
				
			||||||
	return result;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int capture_callback(alsa_driver_t *alsa_driver_capture) {
 | 
					 | 
				
			||||||
	alsa_driver_t *this = alsa_driver_capture;
 | 
					 | 
				
			||||||
	int result;
 | 
					 | 
				
			||||||
	struct timeval tv;
 | 
					 | 
				
			||||||
	double stime;
 | 
					 | 
				
			||||||
	int ib;
 | 
					 | 
				
			||||||
	snd_pcm_sframes_t delay;	
 | 
					 | 
				
			||||||
#ifdef ALSA_CAPTURE_LOG
 | 
					 | 
				
			||||||
	printf("capture callback %d samples\n", this->period_size);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
#ifdef ALSA_CAPTURE_LOG
 | 
					 | 
				
			||||||
	snd_pcm_status_t *pcm_stat;
 | 
					 | 
				
			||||||
	snd_pcm_status_alloca(&pcm_stat);
 | 
					 | 
				
			||||||
	snd_pcm_status(this->audio_fd, pcm_stat);
 | 
					 | 
				
			||||||
        snd_pcm_status_dump(pcm_stat, jcd_out);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
	snd_pcm_delay(this->audio_fd, &delay);
 | 
					 | 
				
			||||||
	gettimeofday(&tv, NULL);
 | 
					 | 
				
			||||||
	stime = (double) tv.tv_sec + ((double)tv.tv_usec / 1000000.0) +
 | 
					 | 
				
			||||||
		*(this->ndsec) * 0.1;
 | 
					 | 
				
			||||||
	//	stime = stime - ((double)delay / (double)(this->output_sample_rate));
 | 
					 | 
				
			||||||
	*(this->Tsec) = stime;
 | 
					 | 
				
			||||||
	ib=*(this->ibuf);
 | 
					 | 
				
			||||||
	this->tbuf[ib] = stime;
 | 
					 | 
				
			||||||
	//printf("CAP:TIME, %d, %lf, %ld, %ld, %d\n",ib, stime, delay, this->output_sample_rate, *this->ndsec);
 | 
					 | 
				
			||||||
	ib++;
 | 
					 | 
				
			||||||
	if(ib>=1024)
 | 
					 | 
				
			||||||
		ib = 0;
 | 
					 | 
				
			||||||
	*(this->ibuf) = ib;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	alsa_capture_buffers[0]=this->app_buffer_y1 + *(this->app_buffer_offset);
 | 
					 | 
				
			||||||
	alsa_capture_buffers[1]=this->app_buffer_y2 + *(this->app_buffer_offset);
 | 
					 | 
				
			||||||
	result = snd_pcm_readn(this->audio_fd, alsa_capture_buffers, this->period_size);
 | 
					 | 
				
			||||||
	*(this->app_buffer_offset) += this->period_size;
 | 
					 | 
				
			||||||
	if ( *(this->app_buffer_offset) >= this->app_buffer_length )
 | 
					 | 
				
			||||||
		*(this->app_buffer_offset)=0;  /* FIXME: implement proper wrapping */
 | 
					 | 
				
			||||||
#ifdef ALSA_CAPTURE_LOG
 | 
					 | 
				
			||||||
	printf("result=%d\n",result);
 | 
					 | 
				
			||||||
	snd_pcm_status(this->audio_fd, pcm_stat);
 | 
					 | 
				
			||||||
        snd_pcm_status_dump(pcm_stat, jcd_out);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
	fivehz_();                             //Call fortran routine
 | 
					 | 
				
			||||||
	return result;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int playback_xrun(alsa_driver_t *alsa_driver_playback) {
 | 
					 | 
				
			||||||
	alsa_driver_t *this = alsa_driver_playback;
 | 
					 | 
				
			||||||
	snd_pcm_status_t *pcm_stat;
 | 
					 | 
				
			||||||
	snd_pcm_status_alloca(&pcm_stat);
 | 
					 | 
				
			||||||
	printf("playback xrun\n");
 | 
					 | 
				
			||||||
	snd_pcm_status(this->audio_fd, pcm_stat);
 | 
					 | 
				
			||||||
        snd_pcm_status_dump(pcm_stat, jcd_out);
 | 
					 | 
				
			||||||
	snd_pcm_prepare(this->audio_fd);
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int capture_xrun(alsa_driver_t *alsa_driver_capture) {
 | 
					 | 
				
			||||||
	alsa_driver_t *this = alsa_driver_capture;
 | 
					 | 
				
			||||||
	snd_pcm_status_t *pcm_stat;
 | 
					 | 
				
			||||||
	snd_pcm_status_alloca(&pcm_stat);
 | 
					 | 
				
			||||||
	printf("capture xrun\n");
 | 
					 | 
				
			||||||
	snd_pcm_status(this->audio_fd, pcm_stat);
 | 
					 | 
				
			||||||
        snd_pcm_status_dump(pcm_stat, jcd_out);
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void ao_alsa_loop(void *iarg) {
 | 
					 | 
				
			||||||
	int playback_nfds;
 | 
					 | 
				
			||||||
	int capture_nfds;
 | 
					 | 
				
			||||||
	struct pollfd *pfd;
 | 
					 | 
				
			||||||
	int nfds;
 | 
					 | 
				
			||||||
	int capture_index;
 | 
					 | 
				
			||||||
	unsigned short playback_revents;
 | 
					 | 
				
			||||||
	unsigned short capture_revents;
 | 
					 | 
				
			||||||
	playback_nfds = snd_pcm_poll_descriptors_count (
 | 
					 | 
				
			||||||
				alsa_driver_playback.audio_fd);
 | 
					 | 
				
			||||||
	capture_nfds = snd_pcm_poll_descriptors_count (
 | 
					 | 
				
			||||||
				alsa_driver_capture.audio_fd);
 | 
					 | 
				
			||||||
	pfd = (struct pollfd *) malloc (sizeof (struct pollfd) * 
 | 
					 | 
				
			||||||
		(playback_nfds + capture_nfds));
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	nfds=0;	
 | 
					 | 
				
			||||||
	snd_pcm_poll_descriptors (alsa_driver_playback.audio_fd,
 | 
					 | 
				
			||||||
		&pfd[0],
 | 
					 | 
				
			||||||
		playback_nfds);
 | 
					 | 
				
			||||||
	nfds += playback_nfds;
 | 
					 | 
				
			||||||
	snd_pcm_poll_descriptors (alsa_driver_capture.audio_fd,
 | 
					 | 
				
			||||||
		&pfd[nfds],
 | 
					 | 
				
			||||||
		capture_nfds);
 | 
					 | 
				
			||||||
	capture_index = nfds;
 | 
					 | 
				
			||||||
	nfds += capture_nfds;
 | 
					 | 
				
			||||||
	while(1) {
 | 
					 | 
				
			||||||
		if (poll (pfd, nfds, 200000) < 0) {
 | 
					 | 
				
			||||||
			printf("poll failed\n");
 | 
					 | 
				
			||||||
			continue;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		snd_pcm_poll_descriptors_revents(alsa_driver_playback.audio_fd, &pfd[0], playback_nfds, &playback_revents);
 | 
					 | 
				
			||||||
		snd_pcm_poll_descriptors_revents(alsa_driver_capture.audio_fd, &pfd[capture_index], capture_nfds, &capture_revents);
 | 
					 | 
				
			||||||
		//if ((playback_revents & POLLERR) || ((capture_revents) & POLLERR)) {
 | 
					 | 
				
			||||||
		if (((capture_revents) & POLLERR)) {
 | 
					 | 
				
			||||||
			printf("pollerr\n");
 | 
					 | 
				
			||||||
			capture_xrun(&alsa_driver_capture);
 | 
					 | 
				
			||||||
			return;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if (((playback_revents) & POLLERR)) {
 | 
					 | 
				
			||||||
			printf("pollerr\n");
 | 
					 | 
				
			||||||
			playback_xrun(&alsa_driver_capture);
 | 
					 | 
				
			||||||
			return;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if (playback_revents & POLLOUT) {
 | 
					 | 
				
			||||||
			playback_callback(&alsa_driver_playback);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if (capture_revents & POLLIN) {
 | 
					 | 
				
			||||||
			capture_callback(&alsa_driver_capture);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
	return;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void decode1_(void *iarg);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int start_threads_(int *ndevin, int *ndevout, short y1[], short y2[],
 | 
					 | 
				
			||||||
	int *nbuflen, int *iwrite, short iwave[],
 | 
					 | 
				
			||||||
	int *nwave, int *nfsample, int *nsamperbuf,
 | 
					 | 
				
			||||||
	int *TRPeriod, int *TxOK, int *ndebug,
 | 
					 | 
				
			||||||
	int *Transmitting, double *Tsec, int *ngo, int *nmode,
 | 
					 | 
				
			||||||
	double tbuf[], int *ibuf, int *ndsec)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  pthread_t thread1,thread2;
 | 
					 | 
				
			||||||
  int iret1,iret2;
 | 
					 | 
				
			||||||
  int iarg1 = 1;
 | 
					 | 
				
			||||||
  //int32_t rate=11025;
 | 
					 | 
				
			||||||
  int32_t rate=*nfsample;
 | 
					 | 
				
			||||||
  alsa_driver_capture.app_buffer_y1 = y1;
 | 
					 | 
				
			||||||
  alsa_driver_capture.app_buffer_y2 = y2;
 | 
					 | 
				
			||||||
  alsa_driver_capture.app_buffer_offset = iwrite;
 | 
					 | 
				
			||||||
  alsa_driver_capture.app_buffer_length = *nbuflen;
 | 
					 | 
				
			||||||
  alsa_driver_capture.Tsec = Tsec;
 | 
					 | 
				
			||||||
  alsa_driver_capture.tbuf = tbuf;
 | 
					 | 
				
			||||||
  alsa_driver_capture.ibuf = ibuf;
 | 
					 | 
				
			||||||
  alsa_driver_capture.ndsec = ndsec;
 | 
					 | 
				
			||||||
  alsa_driver_playback.Tsec = Tsec;
 | 
					 | 
				
			||||||
  alsa_driver_playback.app_buffer_y1 = iwave;
 | 
					 | 
				
			||||||
  alsa_driver_playback.tx_ok = TxOK;
 | 
					 | 
				
			||||||
  alsa_driver_playback.tr_period = TRPeriod;
 | 
					 | 
				
			||||||
  alsa_driver_playback.nwave = nwave;
 | 
					 | 
				
			||||||
  alsa_driver_playback.nmode = nmode;
 | 
					 | 
				
			||||||
  alsa_driver_playback.transmitting = Transmitting;
 | 
					 | 
				
			||||||
  alsa_driver_playback.ndsec = ndsec;
 | 
					 | 
				
			||||||
  //  printf("start_threads: creating thread for decode1\n");
 | 
					 | 
				
			||||||
  iret1 = pthread_create(&thread1,NULL,(void*)&decode1_,&iarg1);
 | 
					 | 
				
			||||||
/* Open audio card. */
 | 
					 | 
				
			||||||
  printf("Using ALSA sound.\n");
 | 
					 | 
				
			||||||
  ao_alsa_open(&alsa_driver_playback, &rate, SND_PCM_STREAM_PLAYBACK);
 | 
					 | 
				
			||||||
  ao_alsa_open(&alsa_driver_capture, &rate, SND_PCM_STREAM_CAPTURE);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Start audio io thread
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
  iret2 = pthread_create(&thread2, NULL, (void *)&ao_alsa_loop, NULL);
 | 
					 | 
				
			||||||
  snd_pcm_prepare(alsa_driver_capture.audio_fd);
 | 
					 | 
				
			||||||
  snd_pcm_start(alsa_driver_capture.audio_fd);
 | 
					 | 
				
			||||||
  snd_pcm_prepare(alsa_driver_playback.audio_fd);
 | 
					 | 
				
			||||||
  //snd_pcm_start(alsa_driver_playback.audio_fd);
 | 
					 | 
				
			||||||
  return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										306
									
								
								start_oss.c
									
									
									
									
									
								
							
							
						
						
									
										306
									
								
								start_oss.c
									
									
									
									
									
								
							@ -1,306 +0,0 @@
 | 
				
			|||||||
#include <stdio.h>
 | 
					 | 
				
			||||||
#include <stdlib.h>
 | 
					 | 
				
			||||||
#include <pthread.h>
 | 
					 | 
				
			||||||
#include <inttypes.h>
 | 
					 | 
				
			||||||
#include <time.h>
 | 
					 | 
				
			||||||
#include <sys/time.h>
 | 
					 | 
				
			||||||
#include <fcntl.h>
 | 
					 | 
				
			||||||
#include <sys/soundcard.h>
 | 
					 | 
				
			||||||
#include <string.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define AUDIOBUFSIZE	4096
 | 
					 | 
				
			||||||
#define FRAMESPERBUFFER 1024
 | 
					 | 
				
			||||||
#define TIMEOUT 1000L		/* select time out for audio device */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* XXX probably safer to use a local buffer due to the wsjt threaded nature. */
 | 
					 | 
				
			||||||
static char rcv_buf[AUDIOBUFSIZE];	
 | 
					 | 
				
			||||||
static char tx_buf[AUDIOBUFSIZE];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define MAXDSPNAME 16
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
extern void decode1_(int *iarg);
 | 
					 | 
				
			||||||
void oss_loop(int *iarg);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * local state data referencing some gcom common fortran variables as well
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static struct audio_data {
 | 
					 | 
				
			||||||
  int fd_in;		/* Audio fd in; used only locally in this function  */
 | 
					 | 
				
			||||||
  int fd_out;		/* Audio fd out; used only locally in this function */
 | 
					 | 
				
			||||||
  double *Tsec;		/* Present time                       SoundIn,SoundOut */
 | 
					 | 
				
			||||||
  double *tbuf;		/* Tsec at time of input callback          SoundIn  */
 | 
					 | 
				
			||||||
  int *iwrite;		/* Write pointer to Rx ring buffer         SoundIn  */
 | 
					 | 
				
			||||||
  int *ibuf;		/* Most recent input buffer#               SoundIn  */
 | 
					 | 
				
			||||||
  int *TxOK;		/* OK to transmit?                         SoundIn  */
 | 
					 | 
				
			||||||
  int *ndebug;		/* Write debugging info?                   GUI      */
 | 
					 | 
				
			||||||
  int *ndsec;		/* Dsec in units of 0.1 s                  GUI      */
 | 
					 | 
				
			||||||
  int *Transmitting;	/* Actually transmitting?                  SoundOut */
 | 
					 | 
				
			||||||
  int *nwave;		/* Number of samples in iwave              SoundIn  */
 | 
					 | 
				
			||||||
  int *nmode;		/* Which WSJT mode?                        GUI      */
 | 
					 | 
				
			||||||
  int *trperiod;	/* Tx or Rx period in seconds              GUI      */
 | 
					 | 
				
			||||||
  int nbuflen;
 | 
					 | 
				
			||||||
  int nfs;
 | 
					 | 
				
			||||||
  int16_t *y1;		/* Ring buffer for audio channel 0         SoundIn  */
 | 
					 | 
				
			||||||
  int16_t *y2;		/* Ring buffer for audio channel 1         SoundIn  */
 | 
					 | 
				
			||||||
  short  *iwave;
 | 
					 | 
				
			||||||
}data;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * start_threads()
 | 
					 | 
				
			||||||
 * inputs	- ndevin  device number for input
 | 
					 | 
				
			||||||
 *		- ndevout device number for output
 | 
					 | 
				
			||||||
 *		- y1 short int array for channel 0
 | 
					 | 
				
			||||||
 *		- y2 short int array for channel 1
 | 
					 | 
				
			||||||
 * 		- nmax
 | 
					 | 
				
			||||||
 *		- iwrite
 | 
					 | 
				
			||||||
 *		- iwave
 | 
					 | 
				
			||||||
 *		- nwave
 | 
					 | 
				
			||||||
 *		- rate 
 | 
					 | 
				
			||||||
 *		- NSPB
 | 
					 | 
				
			||||||
 *		- TRPeriod
 | 
					 | 
				
			||||||
 *		- TxOK
 | 
					 | 
				
			||||||
 *		- ndebug debug output or not?
 | 
					 | 
				
			||||||
 *		- Transmitting
 | 
					 | 
				
			||||||
 *		- Tsec
 | 
					 | 
				
			||||||
 *		- ngo
 | 
					 | 
				
			||||||
 *		- nmode
 | 
					 | 
				
			||||||
 *		- tbuf
 | 
					 | 
				
			||||||
 *		- ibuf
 | 
					 | 
				
			||||||
 *		- ndsec
 | 
					 | 
				
			||||||
 * output	- ?
 | 
					 | 
				
			||||||
 * side effects - Called from audio_init.f90 to start audio decode and
 | 
					 | 
				
			||||||
 *		  OSS thread.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int
 | 
					 | 
				
			||||||
start_threads_(int *ndevin, int *ndevout, short y1[], short y2[],
 | 
					 | 
				
			||||||
	       int *nbuflen, int *iwrite, short iwave[],
 | 
					 | 
				
			||||||
	       int *nwave, int *nfsample, int *nsamperbuf,
 | 
					 | 
				
			||||||
	       int *TRPeriod, int *TxOK, int *ndebug,
 | 
					 | 
				
			||||||
	       int *Transmitting, double *Tsec, int *ngo, int *nmode,
 | 
					 | 
				
			||||||
	       double tbuf[], int *ibuf, int *ndsec,
 | 
					 | 
				
			||||||
	       char *PttPort, char *devin_name, char *devout_name)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  pthread_t thread1,thread2;
 | 
					 | 
				
			||||||
  int iret1,iret2;
 | 
					 | 
				
			||||||
  int iarg1 = 1,iarg2 = 2;
 | 
					 | 
				
			||||||
  int32_t rate=*nfsample;
 | 
					 | 
				
			||||||
  int samplesize;
 | 
					 | 
				
			||||||
  int format;
 | 
					 | 
				
			||||||
  int channels;
 | 
					 | 
				
			||||||
  double dnfs;
 | 
					 | 
				
			||||||
  int i;
 | 
					 | 
				
			||||||
  char *p;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /* Remove space if present */
 | 
					 | 
				
			||||||
  p = strchr(devin_name, ' ');
 | 
					 | 
				
			||||||
  if(p != NULL)
 | 
					 | 
				
			||||||
    *p = '\0';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  p = strchr(devout_name, ' ');
 | 
					 | 
				
			||||||
  if(p != NULL)
 | 
					 | 
				
			||||||
    *p = '\0';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  data.fd_in = open(devin_name, O_RDONLY, 0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if(data.fd_in < 0) { 
 | 
					 | 
				
			||||||
	fprintf(stderr, "Cannot open %s for input.\n", devin_name);
 | 
					 | 
				
			||||||
	return (-1);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (*devout_name == '\0') {
 | 
					 | 
				
			||||||
    close(data.fd_in);
 | 
					 | 
				
			||||||
    data.fd_in = open(devin_name, O_RDWR, 0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if(data.fd_in < 0) { 
 | 
					 | 
				
			||||||
      fprintf(stderr, "Cannot open %s for input.\n", devin_name);
 | 
					 | 
				
			||||||
      return (-1);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    data.fd_out = data.fd_in;
 | 
					 | 
				
			||||||
    if(ioctl(data.fd_in, SNDCTL_DSP_SETDUPLEX, 0) < 0) {
 | 
					 | 
				
			||||||
      fprintf(stderr, "Cannot use %s for full duplex.\n", devin_name);
 | 
					 | 
				
			||||||
      return(-1);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  } else {
 | 
					 | 
				
			||||||
    data.fd_out = open(devout_name, O_WRONLY, 0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if(data.fd_out < 0) { 
 | 
					 | 
				
			||||||
      fprintf(stderr, "Cannot open %s for output.\n", devout_name);
 | 
					 | 
				
			||||||
      return (-1);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  data.Tsec = Tsec;
 | 
					 | 
				
			||||||
  data.tbuf = tbuf;
 | 
					 | 
				
			||||||
  data.iwrite = iwrite;
 | 
					 | 
				
			||||||
  data.ibuf = ibuf;
 | 
					 | 
				
			||||||
  data.TxOK = TxOK;
 | 
					 | 
				
			||||||
  data.ndebug = ndebug;
 | 
					 | 
				
			||||||
  data.ndsec = ndsec;
 | 
					 | 
				
			||||||
  data.Transmitting = Transmitting;
 | 
					 | 
				
			||||||
  data.y1 = y1;
 | 
					 | 
				
			||||||
  data.y2 = y2;
 | 
					 | 
				
			||||||
  data.nbuflen = *nbuflen;
 | 
					 | 
				
			||||||
  data.nmode = nmode;
 | 
					 | 
				
			||||||
  data.nwave = nwave;
 | 
					 | 
				
			||||||
  data.iwave = iwave;
 | 
					 | 
				
			||||||
  data.nfs = *nfsample;
 | 
					 | 
				
			||||||
  data.trperiod = TRPeriod;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  dnfs=(double)*nfsample;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  channels = 2;
 | 
					 | 
				
			||||||
  if(ioctl (data.fd_in, SNDCTL_DSP_CHANNELS, &channels) == -1) {
 | 
					 | 
				
			||||||
	fprintf (stderr, "Unable to set 2 channels for input.\n");
 | 
					 | 
				
			||||||
	return (-1);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if(channels != 2) {
 | 
					 | 
				
			||||||
    fprintf (stderr, "Unable to set 2 channels.\n");
 | 
					 | 
				
			||||||
    return (-1);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  format = AFMT_S16_NE;
 | 
					 | 
				
			||||||
  if(ioctl (data.fd_in, SNDCTL_DSP_SETFMT, &format) == -1) {
 | 
					 | 
				
			||||||
	fprintf (stderr, "Unable to set format for input.\n");
 | 
					 | 
				
			||||||
	return (-1);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if(ioctl (data.fd_in, SNDCTL_DSP_SPEED, &rate) == -1) {
 | 
					 | 
				
			||||||
	fprintf (stderr, "Unable to set rate for input\n");
 | 
					 | 
				
			||||||
	return (-1);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  printf("Audio OSS streams running normally.\n");
 | 
					 | 
				
			||||||
  printf("******************************************************************\n");
 | 
					 | 
				
			||||||
  printf("Opened %s for input.\n", devin_name);
 | 
					 | 
				
			||||||
  if (*devout_name != '\0')
 | 
					 | 
				
			||||||
    printf("Opened %s for output.\n", devout_name);
 | 
					 | 
				
			||||||
  else
 | 
					 | 
				
			||||||
    printf("Opened %s for output.\n", devin_name);
 | 
					 | 
				
			||||||
  printf("Rate set = %d\n", rate);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  //  printf("start_threads: creating thread for oss_loop\n");
 | 
					 | 
				
			||||||
  iret1 = pthread_create(&thread1, NULL,
 | 
					 | 
				
			||||||
			 (void *(*)(void *))oss_loop, &iarg1);
 | 
					 | 
				
			||||||
  // printf("start_threads: creating thread for decode1_\n");
 | 
					 | 
				
			||||||
  iret2 = pthread_create(&thread2, NULL,
 | 
					 | 
				
			||||||
			 (void *(*)(void *))decode1_,&iarg2);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * oss_loop
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * inputs	- int pointer NOT USED
 | 
					 | 
				
			||||||
 * output	- none
 | 
					 | 
				
			||||||
 * side effects	-
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void
 | 
					 | 
				
			||||||
oss_loop(int *iarg)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  fd_set readfds, writefds;
 | 
					 | 
				
			||||||
  int nfds = 0;
 | 
					 | 
				
			||||||
  struct timeval timeout = {0, 0};
 | 
					 | 
				
			||||||
  struct timeval tv;
 | 
					 | 
				
			||||||
  int nread;
 | 
					 | 
				
			||||||
  unsigned int i;
 | 
					 | 
				
			||||||
  static int n=0;
 | 
					 | 
				
			||||||
  static int n2=0;
 | 
					 | 
				
			||||||
  static int ia=0;
 | 
					 | 
				
			||||||
  static int ib=0;
 | 
					 | 
				
			||||||
  static int ic=0;
 | 
					 | 
				
			||||||
  static int16_t *in;
 | 
					 | 
				
			||||||
  static int16_t *wptr;
 | 
					 | 
				
			||||||
  static int TxOKz=0;
 | 
					 | 
				
			||||||
  static int ncall=0;
 | 
					 | 
				
			||||||
  static int nsec=0;
 | 
					 | 
				
			||||||
  static double stime;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  for (;;) {
 | 
					 | 
				
			||||||
    FD_ZERO(&readfds );
 | 
					 | 
				
			||||||
    FD_ZERO(&writefds );
 | 
					 | 
				
			||||||
    FD_SET(data.fd_in, &readfds);
 | 
					 | 
				
			||||||
    FD_SET(data.fd_out, &writefds);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    timeout.tv_usec = TIMEOUT;
 | 
					 | 
				
			||||||
    if(select(FD_SETSIZE, &readfds, &writefds, NULL, &timeout) > 0) {
 | 
					 | 
				
			||||||
      if(FD_ISSET(data.fd_in, &readfds)) {
 | 
					 | 
				
			||||||
	    nread = read (data.fd_in, rcv_buf, AUDIOBUFSIZE);
 | 
					 | 
				
			||||||
	    if(nread <= 0) {
 | 
					 | 
				
			||||||
	      fprintf(stderr, "Read error %d\n", nread);
 | 
					 | 
				
			||||||
	      return;
 | 
					 | 
				
			||||||
	    }
 | 
					 | 
				
			||||||
	    if(nread == AUDIOBUFSIZE) {
 | 
					 | 
				
			||||||
	      /* Get System time */
 | 
					 | 
				
			||||||
	      gettimeofday(&tv, NULL);
 | 
					 | 
				
			||||||
	      stime = (double) tv.tv_sec + ((double)tv.tv_usec / 1000000.0) +
 | 
					 | 
				
			||||||
		*(data.ndsec) * 0.1;
 | 
					 | 
				
			||||||
	      *(data.Tsec) = stime;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	      ncall++;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	      /* increment buffer pointers only if data available */
 | 
					 | 
				
			||||||
	      ia=*(data.iwrite);
 | 
					 | 
				
			||||||
	      ib=*(data.ibuf);
 | 
					 | 
				
			||||||
	      data.tbuf[ib-1] = stime;	/* convert to c index to store */
 | 
					 | 
				
			||||||
	      ib++;
 | 
					 | 
				
			||||||
	      if(ib>FRAMESPERBUFFER)
 | 
					 | 
				
			||||||
		ib=1; 
 | 
					 | 
				
			||||||
	      *(data.ibuf) = ib;
 | 
					 | 
				
			||||||
	      in = (int16_t *)rcv_buf;	/* XXX */
 | 
					 | 
				
			||||||
	      for(i=0; i<FRAMESPERBUFFER; i++) {
 | 
					 | 
				
			||||||
		data.y1[ia] = (*in++);
 | 
					 | 
				
			||||||
		data.y2[ia] = (*in++);
 | 
					 | 
				
			||||||
		ia++;
 | 
					 | 
				
			||||||
	      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	      if(ia >= data.nbuflen)
 | 
					 | 
				
			||||||
		ia=0;  //Wrap buffer pointer if necessary
 | 
					 | 
				
			||||||
	      *(data.iwrite) = ia;            /* Save buffer pointer */
 | 
					 | 
				
			||||||
	      fivehz_();                      /* Call fortran routine */
 | 
					 | 
				
			||||||
	    }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      if(FD_ISSET(data.fd_in, &writefds)) {
 | 
					 | 
				
			||||||
	/* Get System time */
 | 
					 | 
				
			||||||
	gettimeofday(&tv, NULL);
 | 
					 | 
				
			||||||
	stime = (double) tv.tv_sec + ((double)tv.tv_usec / 1000000.0) +
 | 
					 | 
				
			||||||
	  *(data.ndsec) * 0.1;
 | 
					 | 
				
			||||||
	*(data.Tsec) = stime;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if(*(data.TxOK) && (!TxOKz)) {
 | 
					 | 
				
			||||||
	  nsec = (int)stime;
 | 
					 | 
				
			||||||
	  n = nsec / *(data.trperiod);
 | 
					 | 
				
			||||||
	  ic = (int)(stime - *(data.trperiod) * n) * data.nfs;
 | 
					 | 
				
			||||||
	  ic = ic % *(data.nwave);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	TxOKz = *(data.TxOK);
 | 
					 | 
				
			||||||
	*(data.Transmitting) = *(data.TxOK);
 | 
					 | 
				
			||||||
	wptr = (int16_t *)tx_buf;		/* XXX */
 | 
					 | 
				
			||||||
	if(*(data.TxOK))  {
 | 
					 | 
				
			||||||
	  for(i=0 ; i<FRAMESPERBUFFER; i++)  {
 | 
					 | 
				
			||||||
	    n2 = data.iwave[ic];
 | 
					 | 
				
			||||||
	    addnoise_(&n2);
 | 
					 | 
				
			||||||
	    *wptr++ = n2;			/* left */
 | 
					 | 
				
			||||||
	    *wptr++ = n2;			/* right */
 | 
					 | 
				
			||||||
	    ic++;
 | 
					 | 
				
			||||||
	    if(ic >= *(data.nwave)) {
 | 
					 | 
				
			||||||
	      ic = ic % *(data.nwave);	/* Wrap buffer pointer if necessary */
 | 
					 | 
				
			||||||
	      if(*(data.nmode) == 2)
 | 
					 | 
				
			||||||
		*(data.TxOK) = 0;
 | 
					 | 
				
			||||||
	    }
 | 
					 | 
				
			||||||
	  }
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
	  memset(tx_buf, 0, AUDIOBUFSIZE);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if(write(data.fd_out, tx_buf, AUDIOBUFSIZE) < 0) {
 | 
					 | 
				
			||||||
	  fprintf(stderr, "Can't write to soundcard.\n");
 | 
					 | 
				
			||||||
	  return;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	fivehztx_();                             /* Call fortran routine */
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										19
									
								
								wfile3.c
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								wfile3.c
									
									
									
									
									
								
							@ -1,19 +0,0 @@
 | 
				
			|||||||
#include <stdio.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void wfile3_(char *outfile, char buf[], int *nbytes0)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  int n,nbytes;
 | 
					 | 
				
			||||||
  static int first=1;
 | 
					 | 
				
			||||||
  static FILE *fp=NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  nbytes=*nbytes0;
 | 
					 | 
				
			||||||
  fp = fopen(outfile,"wb");
 | 
					 | 
				
			||||||
  if(fp == NULL) {
 | 
					 | 
				
			||||||
    printf("Cannot create %s\n",outfile);
 | 
					 | 
				
			||||||
    exit(0);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  n=fwrite(buf,1,nbytes,fp);
 | 
					 | 
				
			||||||
  fclose(fp);
 | 
					 | 
				
			||||||
  return(n);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user