Logo Search packages:      
Sourcecode: tucnak2 version File versions  Download package

oss.c

/*
    Tucnak - VHF contest log
    Copyright (C) 2002-2006  Ladislav Vaiz <ok1zia@nagano.cz>

    This program is free software; you can redistribute it and/or                                                        
    modify it under the terms of the GNU General Public License                                                          
    version 2 as published by the Free Software Foundation.

*/

#include "header.h"
    
static const char *clabels[] = SOUND_DEVICE_LABELS;

int oss_open(struct dsp *dsp, int rec){
    int tmp;
      char errbuf[1024];

    CONDGFREE(dsp->filename);
    dsp->filename=g_strdup(cfg->ssbd_dsp);

    dbg("open_dsp('%s',%s)\n", dsp->filename, rec?"record":"playback");
    CONDGFREE(dsp->name);
    dsp->name=g_strdup(cfg->ssbd_dsp);
    dsp->fd = open (cfg->ssbd_dsp, rec?O_RDONLY:O_WRONLY, 0);
    if (dsp->fd < 0){
        log_addf("Can't open file '%s': %s", dsp->name, strerror_r(errno, errbuf, sizeof(errbuf)) );
        goto err;
    }

    if (cfg->ssbd_maxfrag>=2 && cfg->ssbd_maxfrag<16384){
        dsp->fragment = (cfg->ssbd_maxfrag<<16)|0x000a;
        dbg("setting fragment to 0x%08x\n", dsp->fragment);
        if (ioctl (dsp->fd, SNDCTL_DSP_SETFRAGMENT, &dsp->fragment)){
            log_addf("Can't set fragment size to 0x%x: %s", dsp->fragment, strerror_r(errno, errbuf, sizeof(errbuf)) );
            goto err;
        }
    }   
        
    if (ioctl(dsp->fd, SNDCTL_DSP_GETFMTS, &dsp->fmt_mask)){
        log_addf("Can't get supported audio formats: %s", strerror_r(errno, errbuf, sizeof(errbuf)) );
        goto err;
    }
    
    tmp=dsp->oss_format;
    if (ioctl (dsp->fd, SNDCTL_DSP_SETFMT, &dsp->oss_format)){
        log_addf("Can't set audio format %d, recommended %d: %s", tmp, dsp->oss_format, strerror_r(errno, errbuf, sizeof(errbuf)) );
        
        tmp=dsp->oss_format;
        if (ioctl (dsp->fd, SNDCTL_DSP_SETFMT, &dsp->oss_format)){
            log_addf("Can't set recommended audio format %d, return %d: %s", tmp, dsp->oss_format, strerror_r(errno, errbuf, sizeof(errbuf)) );
            
            tmp = dsp->oss_format = AFMT_S16_NE;
            if (ioctl (dsp->fd, SNDCTL_DSP_SETFMT, &dsp->oss_format)){
                log_addf("Can't set fallback audio %d, return %d: %s", tmp, dsp->oss_format, strerror_r(errno, errbuf, sizeof(errbuf)) );
                
                dsp->oss_format = AFMT_S8;
                if (ioctl (dsp->fd, SNDCTL_DSP_SETFMT, &dsp->oss_format)){
                    log_addf("Can't set fallback audio format %d, return %d: %s", tmp, dsp->oss_format, strerror_r(errno, errbuf, sizeof(errbuf)) );
                    
                    dsp->oss_format = AFMT_U8;
                    if (ioctl (dsp->fd, SNDCTL_DSP_SETFMT, &dsp->oss_format)){
                        log_addf("Can't set fallback audio format %d, return %d: %s", tmp, dsp->oss_format, strerror_r(errno, errbuf, sizeof(errbuf)) );
                        goto err;
                    }
                }
            }
        }
        /* fallback ok */
    }
    

    tmp=dsp->channels;
    if (ioctl (dsp->fd, SNDCTL_DSP_CHANNELS, &dsp->channels)){
        log_addf("Can't set channels %d, recommended %d: %s", tmp, dsp->channels, strerror_r(errno, errbuf, sizeof(errbuf)) );
        
        tmp=dsp->channels;
        if (ioctl (dsp->fd, SNDCTL_DSP_CHANNELS, &dsp->channels)){
            log_addf("Can't set recommended channels %d, return %d: %s", tmp, dsp->channels, strerror_r(errno, errbuf, sizeof(errbuf)) );
            goto err;
        }
        /* fallback ok */
    }

    tmp=dsp->speed;
    if (ioctl (dsp->fd, SNDCTL_DSP_SPEED, &dsp->speed)){
        log_addf("Can't set samplerate %d, recommended %d: %s", tmp, dsp->speed, strerror_r(errno, errbuf, sizeof(errbuf)) );
        
        tmp=dsp->speed;
        if (ioctl (dsp->fd, SNDCTL_DSP_SPEED, &dsp->speed)){
            log_addf("Can't set recommended samplerate %d, return %d: %s", tmp, dsp->speed, strerror_r(errno, errbuf, sizeof(errbuf)) );
            goto err;
        }
        /* fallback ok */
    }

    if (ioctl (dsp->fd, SNDCTL_DSP_GETBLKSIZE, &dsp->blksize)){
        log_addf("Can't set block size %d: %s", tmp, dsp->blksize, strerror_r(errno, errbuf, sizeof(errbuf)) );
        goto err;
    }   
    goto x;
    
err:;
    if (dsp->fd>=0) close(dsp->fd);
    dsp->fd = -1;

x:;
   /* dbg(" dsp->fd=%d\n", dsp->fd);*/
    return dsp->fd;
} 

int oss_close(struct dsp *dsp){
    
    /*ST_START;*/
    dsp->reset(dsp);
    CONDGFREE(dsp->filename);
    if (dsp->fd >= 0) {
        /*dbg("close_dsp(fd=%d)\n",dsp->fd);*/
        close(dsp->fd);
    }   
    dsp->fd=-1;
/*    ST_STOP;*/
    return 0;
}


int oss_write(struct dsp *dsp, void *data, int len){
    return write(dsp->fd, data, len);    
}


int oss_read(struct dsp *dsp, void *data, int len){
    return read(dsp->fd, data, len);    
}


int oss_reset(struct dsp *dsp){
    if (!dsp || dsp->fd<0) return 0;
    return ioctl(dsp->fd, SNDCTL_DSP_RESET, NULL); 
}


int oss_sync(struct dsp *dsp){
    if (!dsp || dsp->fd<0) return 0;
    return ioctl(dsp->fd, SNDCTL_DSP_SYNC, NULL); 
}


int oss_set_format(struct dsp *dsp, SF_INFO *sfinfo){

    switch (sfinfo->format & SF_FORMAT_SUBMASK){
/*        case SF_FORMAT_PCM_U8:
            format=AFMT_U8;
            break;
        case SF_FORMAT_PCM_S8:
            format=AFMT_S8;
            break;*/
        case SF_FORMAT_ULAW:
            dsp->oss_format=AFMT_MU_LAW;
            break;            
        case SF_FORMAT_ALAW:
            dsp->oss_format=AFMT_A_LAW;
            break;            
        case SF_FORMAT_IMA_ADPCM:
            dsp->oss_format=AFMT_IMA_ADPCM;
            break;            
        default:
            dsp->oss_format=AFMT_S16_NE;    
    }
    dsp->channels=sfinfo->channels; 
    if (dsp->channels>MAX_CHANNELS) dsp->channels=MAX_CHANNELS;
    dsp->speed=sfinfo->samplerate;   
    return 0;
}    


int oss_get_sources(GString *labels){
      int fd, i, recmask;
    char s[16];
      
    g_string_truncate(labels, 0);
    if (!cfg->ssbd_mixer || strlen(cfg->ssbd_mixer)==0) return 0;

    fd=open(cfg->ssbd_mixer, O_RDWR, 0);
      if (fd<0){
            return -1;
      }

      if (ioctl(fd, SOUND_MIXER_READ_RECMASK, &recmask) <0){
            close(fd);
            return -1;
      }
      
    for (i=0; i<SOUND_MIXER_NRDEVICES; i++){
        if ((recmask & (1<<i))==0) continue;
        if (strlen(labels->str)>0) g_string_append_c(labels, ';');
        safe_strncpy(s, clabels[i], sizeof(s)); 
        stripr(s);
        g_string_append(labels, s);
    }
      close(fd);
    return 0;
}

int oss_set_source(struct dsp *dsp){
      int fd, i;
    char s[16];
    
    dbg("oss_set_source('%s')\n", dsp->source);
    if (!dsp->source || !*dsp->source){
        return 0;
    }

      
    fd=open(cfg->ssbd_mixer, O_RDWR, 0);
      if (fd<0){
            return -1;
      }

    for (i=0; i<SOUND_MIXER_NRDEVICES; i++){
        safe_strncpy(s, clabels[i], sizeof(s)); 
        stripr(s);
        if (strcasecmp(s, dsp->source)!=0) continue;

        dbg("oss_mixer_set_source('%s') setting 0x%x\n", dsp->source, i);
        if (ioctl(fd, SOUND_MIXER_WRITE_RECSRC, &i) <0){
            close(fd);
            return -1;
        }
        close(fd);
        return 0;
    }
    dbg("oss_mixer_set_source('%s') not found\n", dsp->source);
    
    close(fd);
    return -2;
}

char *oss_recsrc2source(int recsrc){
    int i;
    static char s[16];

    if (recsrc==0) return NULL;
    for (i=-1; recsrc; recsrc>>=1, i++);
    if (i<0) return NULL;
    if (i>=SOUND_MIXER_NRDEVICES) return NULL;

    safe_strncpy(s, clabels[i], sizeof(s)); 
    stripr(s);
    return s;
}

char *stripr(char *s){
    int i;

    i=strlen(s);
    if (!i) return s;

    for (i--;i>=0;i--){
        if (s[i]!=' ') break;
        s[i]='\0';
    }

    return s;
}

Generated by  Doxygen 1.6.0   Back to index