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

bfio_file.c

/*
 * (c) Copyright 2001 - 2004 -- Anders Torger
 *
 * This program is open source. For license terms, see the LICENSE file.
 *
 */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <inttypes.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#ifndef O_LARGEFILE
#define O_LARGEFILE 0
#endif

#define IS_BFIO_MODULE
#include "bfmod.h"
#include "bit.h"

struct readstate {
    off_t filesize;
    off_t skipbytes;
    off_t curpos;
    bool_t loop;
};

static struct readstate *readstate[FD_SETSIZE];
static fd_set fds[2];
static int fdmax[2] = { -1, -1 };
static bool_t debug = false;

struct settings {
    off_t skipbytes;
    bool_t append;
    bool_t loop;
    char *path;
};

#define GET_TOKEN(token, errstr)                                               \
    if (get_config_token(&lexval) != token) {                                  \
        fprintf(stderr, "File I/O: Parse error: " errstr);                     \
        return NULL;                                                           \
    }

void *
bfio_preinit(int *version_major,
             int *version_minor,
             int (*get_config_token)(union bflexval *lexval),
             int io,
             int *sample_format,
             int sample_rate,
             int open_channels,
             int *uses_sample_clock,
             int *callback_sched_policy,
             struct sched_param *callback_sched,
             int _debug)
{
    struct settings *settings;
    union bflexval lexval;
    int token, ver;

    ver = *version_major;
    *version_major = BF_VERSION_MAJOR;
    *version_minor = BF_VERSION_MINOR;
    if (ver != BF_VERSION_MAJOR) {
        return NULL;
    }
    debug = !!_debug;
    settings = malloc(sizeof(struct settings));
    memset(settings, 0, sizeof(struct settings));
    while ((token = get_config_token(&lexval)) > 0) {
        if (token == BF_LEXVAL_FIELD) {
            if (strcmp(lexval.field, "path") == 0) {
                if (settings->path != NULL) {
                    fprintf(stderr, "File I/O: Parse error: path "
                            "already set.\n");
                    return NULL;
                }
                GET_TOKEN(BF_LEXVAL_STRING, "expected string.\n");
                settings->path = strdup(lexval.string);                
            } else if (strcmp(lexval.field, "skip") == 0) {
                GET_TOKEN(BF_LEXVAL_REAL, "expected integer.\n");
                settings->skipbytes = (off_t)lexval.real;
            } else if (strcmp(lexval.field, "append") == 0) {
                if (io == BF_IN) {
                    fprintf(stderr, "File I/O: Append on input makes "
                            "no sense.\n");
                    return NULL;
                }
                GET_TOKEN(BF_LEXVAL_BOOLEAN, "expected boolean value.\n");
                settings->append = lexval.boolean;
            } else if (strcmp(lexval.field, "loop") == 0) {
                if (io == BF_OUT) {
                    fprintf(stderr, "File I/O: Loop on output makes "
                            "no sense.\n");
                    return NULL;
                }
                GET_TOKEN(BF_LEXVAL_BOOLEAN, "expected boolean value.\n");
                settings->loop = lexval.boolean;
            } else {
                fprintf(stderr, "File I/O: Parse error: unknown field.\n");
                return NULL;
            }
            GET_TOKEN(BF_LEX_EOS, "expected end of statement (;).\n");
        } else {
            fprintf(stderr, "File I/O: Parse error: expected field.\n");
            return NULL;
        }
    }
    if (settings->path == NULL) {
        fprintf(stderr, "File I/O: Parse error: path not set.\n");
        return NULL;
    }
    if (*sample_format == BF_SAMPLE_FORMAT_AUTO) {
        fprintf(stderr, "File I/O: No support for AUTO sample format.\n");
        return NULL;
    }
    *uses_sample_clock = 0;
    return settings;
}

int
bfio_init(void *params,
        int io,
        int sample_format,
        int sample_rate,
        int open_channels,
        int used_channels,
        const int channel_selection[],
        int period_size,
        int *device_period_size,
        int *isinterleaved,
          void *callback_state,
          int (*process_callback)(void **callback_states[2],
                                  int callback_state_count[2],
                                  void **buffers[2],
                                  int frame_count,
                                  int event))
{
    struct settings *settings;
    struct stat buf;
    int fd, mode;

    settings = (struct settings *)params;
    *device_period_size = 0; 
    *isinterleaved = 1;
    if (io == BF_IN) {
      if ((fd = open(settings->path, O_RDONLY | O_NONBLOCK |
                   O_LARGEFILE)) == -1)
      {
          fprintf(stderr, "File I/O: Could not open file \"%s\" for "
                    "reading: %s.\n", settings->path, strerror(errno));
          return -1;
      }
        readstate[fd] = malloc(sizeof(struct readstate));
        memset(readstate[fd], 0, sizeof(struct readstate));
        readstate[fd]->filesize = 0;
        if (settings->loop) {
            if (stat(settings->path, &buf) != 0) {
                fprintf(stderr, "File I/O: Could not stat file \"%s\": %s.\n",
                        settings->path, strerror(errno));
                return -1;
            }
            readstate[fd]->filesize = buf.st_size;
        }
        readstate[fd]->curpos = 0;
        readstate[fd]->skipbytes = settings->skipbytes;
        readstate[fd]->loop = settings->loop;
      if (settings->skipbytes > 0) {
          if (lseek(fd, settings->skipbytes, SEEK_SET) == -1) {
            fprintf(stderr, "File seek failed.\n");
            return -1;
          }
            readstate[fd]->curpos = settings->skipbytes;
      }
    } else {
      if (settings->append) {
          mode = O_APPEND;
      } else {
          mode = O_TRUNC;
      }
      if ((fd = open(settings->path, O_WRONLY | O_CREAT | mode |
                   O_NONBLOCK | O_LARGEFILE, S_IRUSR | S_IWUSR |
                   S_IRGRP | S_IROTH)) == -1)
      {
          fprintf(stderr, "File I/O: Could not create file \"%s\" for "
                    "writing: %s.\n", settings->path, strerror(errno));
          return -1;
      }
    }
    FD_SET(fd, &fds[io]);
    if (fd > fdmax[io]) {
        fdmax[io] = fd;
    }
    free(settings->path);
    free(settings);
    return fd;
}

int
bfio_read(int fd,
        void *buf,
        int offset,
        int count)
{
    int retval;

    if ((retval = read(fd, &((uint8_t *)buf)[offset], count)) == -1) {
      fprintf(stderr, "File I/O: Read failed: %s.\n", strerror(errno));
    }
    readstate[fd]->curpos += retval;
    if (readstate[fd]->loop &&
        readstate[fd]->curpos == readstate[fd]->filesize)
    {
        if (lseek(fd, readstate[fd]->skipbytes, SEEK_SET) == -1) {
            fprintf(stderr, "File I/O: seek failed: %s.\n", strerror(errno));
            return -1;
        }
        readstate[fd]->curpos = readstate[fd]->skipbytes;
    }
    return retval;
}

int
bfio_write(int fd,
         const void *buf,
         int offset,
         int count)
{
    int retval;

    if ((retval = write(fd, &((const uint8_t *)buf)[offset], count)) == -1) {
      fprintf(stderr, "File I/O: Write failed: %s.\n", strerror(errno));
    }
    return retval;
}

int
bfio_start(int io)
{
    /* do nothing */
    return 0;
}

void
bfio_stop(int io)
{
    int fd;
    
    for (fd = 0; fd <= fdmax[io]; fd++) {
        if (FD_ISSET(fd, &fds[io])) {
            close(fd);
        }
    }
}

void
_init(void);
void
_init(void)
{
    memset(readstate, 0, sizeof(readstate));
    memset(fds, 0, sizeof(fds));    
}

Generated by  Doxygen 1.6.0   Back to index